diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2022-08-04 17:58:50 +0300 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2022-08-05 13:02:11 +0300 |
commit | 007e23d6390af11582e55453269b7a51c723d2dd (patch) | |
tree | 8e8cff3ca23f5e56d9766a5ee6c6abb366611b07 /winsup/cygwin/fhandler/cygdrive.cc | |
parent | 1e428bee1c5ef7c76ba4e46e6693b913edc9bbf3 (diff) |
Cygwin: Reorganize cygwin source dir
Create subdirs and move files accordingly:
- DevDocs: doc files
- fhandler: fhandler sources, split fhandler.cc into base.cc and null.cc
- local_includes: local include files
- scripts: scripts called during build
- sec: security sources
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup/cygwin/fhandler/cygdrive.cc')
-rw-r--r-- | winsup/cygwin/fhandler/cygdrive.cc | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/winsup/cygwin/fhandler/cygdrive.cc b/winsup/cygwin/fhandler/cygdrive.cc new file mode 100644 index 000000000..1ac1d5d4f --- /dev/null +++ b/winsup/cygwin/fhandler/cygdrive.cc @@ -0,0 +1,158 @@ +/* fhandler_cygdrive.cc + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "winsup.h" +#include <lm.h> +#include <sys/statvfs.h> +#include "cygerrno.h" +#include "security.h" +#include "path.h" +#include "fhandler.h" +#include "dtable.h" +#include "cygheap.h" +#include "shared_info.h" + +#define _LIBC +#include <dirent.h> + +fhandler_cygdrive::fhandler_cygdrive () : + fhandler_disk_file () +{ +} + +int +fhandler_cygdrive::open (int flags, mode_t mode) +{ + if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + { + set_errno (EEXIST); + return 0; + } + if (flags & O_WRONLY) + { + set_errno (EISDIR); + return 0; + } + /* Open a fake handle to \\Device\\Null */ + return open_null (flags); +} + +int +fhandler_cygdrive::fstat (struct stat *buf) +{ + fhandler_base::fstat (buf); + buf->st_ino = 2; + buf->st_mode = S_IFDIR | STD_RBITS | STD_XBITS; + buf->st_nlink = 1; + return 0; +} + +int +fhandler_cygdrive::fstatvfs (struct statvfs *sfs) +{ + /* Virtual file system. Just return an empty buffer with a few values + set to something useful. Just as on Linux. */ + memset (sfs, 0, sizeof (*sfs)); + sfs->f_bsize = sfs->f_frsize = 4096; + sfs->f_flag = ST_RDONLY; + sfs->f_namemax = NAME_MAX; + return 0; +} + +#define MAX_DRIVE_BUF_LEN (sizeof ("x:\\") * 26 + 2) + +struct __DIR_drives +{ + char *pdrive; + char pbuf[MAX_DRIVE_BUF_LEN]; +}; + +#define d_drives(d) ((__DIR_drives *) (d)->__d_internal) + +DIR * +fhandler_cygdrive::opendir (int fd) +{ + DIR *dir; + + dir = fhandler_disk_file::opendir (fd); + if (dir) + { + dir->__d_internal = (uintptr_t) new __DIR_drives; + GetLogicalDriveStrings (MAX_DRIVE_BUF_LEN, d_drives(dir)->pbuf); + d_drives(dir)->pdrive = d_drives(dir)->pbuf; + } + + return dir; +} + +int +fhandler_cygdrive::readdir (DIR *dir, dirent *de) +{ + WCHAR drive[] = L"X:"; + + while (true) + { + if (!d_drives(dir)->pdrive || !*d_drives(dir)->pdrive) + { + if (!(dir->__flags & dirent_saw_dot)) + { + de->d_name[0] = '.'; + de->d_name[1] = '\0'; + de->d_ino = 2; + } + return ENMFILE; + } + disk_type dt = get_disk_type ((drive[0] = *d_drives(dir)->pdrive, drive)); + if (dt == DT_SHARE_SMB) + { + /* Calling NetUseGetInfo on SMB drives allows to fetch the + current state of the drive without trying to open a file + descriptor on the share (GetFileAttributes). This avoids + waiting for SMB timeouts. Of course, there's a downside: + If a drive becomes availabe again, it can take a couple of + minutes to recognize it. As long as this didn't happen, + the drive will not show up in the cygdrive dir. */ + PUSE_INFO_1 pui1; + DWORD status; + + if (NetUseGetInfo (NULL, drive, 1, (PBYTE *) &pui1) == NERR_Success) + { + status = pui1->ui1_status; + NetApiBufferFree (pui1); + if (status == USE_OK) + break; + } + } + else if (dt != DT_FLOPPY + && GetFileAttributes (d_drives(dir)->pdrive) != INVALID_FILE_ATTRIBUTES) + break; + d_drives(dir)->pdrive = strchr (d_drives(dir)->pdrive, '\0') + 1; + } + *de->d_name = cyg_tolower (*d_drives(dir)->pdrive); + de->d_name[1] = '\0'; + user_shared->warned_msdos = true; + de->d_ino = readdir_get_ino (d_drives(dir)->pdrive, false); + dir->__d_position++; + d_drives(dir)->pdrive = strchr (d_drives(dir)->pdrive, '\0') + 1; + syscall_printf ("%p = readdir (%p) (%s)", &de, dir, de->d_name); + return 0; +} + +void +fhandler_cygdrive::rewinddir (DIR *dir) +{ + d_drives(dir)->pdrive = d_drives(dir)->pbuf; + dir->__d_position = 0; +} + +int +fhandler_cygdrive::closedir (DIR *dir) +{ + delete d_drives(dir); + return 0; +} |