1 /* fhandler_cygdrive.cc
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 #include <sys/statvfs.h>
18 #include "shared_info.h"
23 fhandler_cygdrive::fhandler_cygdrive () :
29 fhandler_cygdrive::open (int flags
, mode_t mode
)
31 if ((flags
& (O_CREAT
| O_EXCL
)) == (O_CREAT
| O_EXCL
))
41 /* Open a fake handle to \\Device\\Null */
42 return open_null (flags
);
46 fhandler_cygdrive::fstat (struct stat
*buf
)
48 fhandler_base::fstat (buf
);
50 buf
->st_mode
= S_IFDIR
| STD_RBITS
| STD_XBITS
;
56 fhandler_cygdrive::fstatvfs (struct statvfs
*sfs
)
58 /* Virtual file system. Just return an empty buffer with a few values
59 set to something useful. Just as on Linux. */
60 memset (sfs
, 0, sizeof (*sfs
));
61 sfs
->f_bsize
= sfs
->f_frsize
= 4096;
62 sfs
->f_flag
= ST_RDONLY
;
63 sfs
->f_namemax
= NAME_MAX
;
67 #define MAX_DRIVE_BUF_LEN (sizeof ("x:\\") * 26 + 2)
72 char pbuf
[MAX_DRIVE_BUF_LEN
];
75 #define d_drives(d) ((__DIR_drives *) (d)->__d_internal)
78 fhandler_cygdrive::opendir (int fd
)
82 dir
= fhandler_disk_file::opendir (fd
);
85 dir
->__d_internal
= (uintptr_t) new __DIR_drives
;
86 GetLogicalDriveStrings (MAX_DRIVE_BUF_LEN
, d_drives(dir
)->pbuf
);
87 d_drives(dir
)->pdrive
= d_drives(dir
)->pbuf
;
94 fhandler_cygdrive::readdir (DIR *dir
, dirent
*de
)
96 WCHAR drive
[] = L
"X:";
100 if (!d_drives(dir
)->pdrive
|| !*d_drives(dir
)->pdrive
)
102 if (!(dir
->__flags
& dirent_saw_dot
))
105 de
->d_name
[1] = '\0';
110 disk_type dt
= get_disk_type ((drive
[0] = *d_drives(dir
)->pdrive
, drive
));
111 if (dt
== DT_SHARE_SMB
)
113 /* Calling NetUseGetInfo on SMB drives allows to fetch the
114 current state of the drive without trying to open a file
115 descriptor on the share (GetFileAttributes). This avoids
116 waiting for SMB timeouts. Of course, there's a downside:
117 If a drive becomes availabe again, it can take a couple of
118 minutes to recognize it. As long as this didn't happen,
119 the drive will not show up in the cygdrive dir. */
123 if (NetUseGetInfo (NULL
, drive
, 1, (PBYTE
*) &pui1
) == NERR_Success
)
125 status
= pui1
->ui1_status
;
126 NetApiBufferFree (pui1
);
127 if (status
== USE_OK
)
131 else if (dt
!= DT_FLOPPY
132 && GetFileAttributes (d_drives(dir
)->pdrive
) != INVALID_FILE_ATTRIBUTES
)
134 d_drives(dir
)->pdrive
= strchr (d_drives(dir
)->pdrive
, '\0') + 1;
136 *de
->d_name
= cyg_tolower (*d_drives(dir
)->pdrive
);
137 de
->d_name
[1] = '\0';
138 user_shared
->warned_msdos
= true;
139 de
->d_ino
= readdir_get_ino (d_drives(dir
)->pdrive
, false);
141 d_drives(dir
)->pdrive
= strchr (d_drives(dir
)->pdrive
, '\0') + 1;
142 syscall_printf ("%p = readdir (%p) (%s)", &de
, dir
, de
->d_name
);
147 fhandler_cygdrive::rewinddir (DIR *dir
)
149 d_drives(dir
)->pdrive
= d_drives(dir
)->pbuf
;
150 dir
->__d_position
= 0;
154 fhandler_cygdrive::closedir (DIR *dir
)
156 delete d_drives(dir
);