Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2022-08-04 17:58:50 +0300
committerCorinna Vinschen <corinna@vinschen.de>2022-08-05 13:02:11 +0300
commit007e23d6390af11582e55453269b7a51c723d2dd (patch)
tree8e8cff3ca23f5e56d9766a5ee6c6abb366611b07 /winsup/cygwin/fhandler/cygdrive.cc
parent1e428bee1c5ef7c76ba4e46e6693b913edc9bbf3 (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.cc158
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;
+}