From f5360746dca74b3876743743161b69d118e4b9d6 Mon Sep 17 00:00:00 2001 From: corinna Date: Wed, 1 Mar 2006 22:37:25 +0000 Subject: [PATCH] * fhandler.h (enum dirent_states): Remove dirent_saw_cygdrive, dirent_saw_dev and dirent_saw_proc. (fhandler_cygdrive::open): Declare. (fhandler_cygdrive::close): Declare. * fhandler_disk_file.cc (class __DIR_mounts): Move to beginning of file. (__DIR_mounts::check_mount): New parameter to indicate if inode number is needed in calling function or not. Add /proc and /cygdrive handling. (__DIR_mounts::check_missing_mount): Ditto. (path_conv::ndisk_links): Use __DIR_mounts class to create correct hardlink count for directories with mount points in them. (fhandler_disk_file::readdir_helper): Remove /dev, /proc and /cygdrive handling. (fhandler_cygdrive::open): New method. (fhandler_cygdrive::close): New method. (fhandler_cygdrive::fstat): Always return fixed inode number 2 and fixed link count of 1. Drop call to set_drives. (fhandler_cygdrive::opendir): Drop call to get_namehash. (fhandler_cygdrive::readdir): Handle "." entry to return fixed inode number 2. --- winsup/cygwin/ChangeLog | 22 ++++ winsup/cygwin/fhandler.h | 9 +- winsup/cygwin/fhandler_disk_file.cc | 245 +++++++++++++++++++----------------- 3 files changed, 159 insertions(+), 117 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 09d7561458..5cea69b076 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,25 @@ +2006-03-01 Corinna Vinschen + + * fhandler.h (enum dirent_states): Remove dirent_saw_cygdrive, + dirent_saw_dev and dirent_saw_proc. + (fhandler_cygdrive::open): Declare. + (fhandler_cygdrive::close): Declare. + * fhandler_disk_file.cc (class __DIR_mounts): Move to beginning of file. + (__DIR_mounts::check_mount): New parameter to indicate if inode number + is needed in calling function or not. Add /proc and /cygdrive handling. + (__DIR_mounts::check_missing_mount): Ditto. + (path_conv::ndisk_links): Use __DIR_mounts class to create correct + hardlink count for directories with mount points in them. + (fhandler_disk_file::readdir_helper): Remove /dev, /proc and /cygdrive + handling. + (fhandler_cygdrive::open): New method. + (fhandler_cygdrive::close): New method. + (fhandler_cygdrive::fstat): Always return fixed inode number 2 and + fixed link count of 1. Drop call to set_drives. + (fhandler_cygdrive::opendir): Drop call to get_namehash. + (fhandler_cygdrive::readdir): Handle "." entry to return fixed inode + number 2. + 2006-03-01 Christopher Faylor * cygwin.din: Fix some erroneous SIGFE/NOSIGFE settings. diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 37b7699c8f..bd068a88d7 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -45,11 +45,8 @@ enum dirent_states dirent_saw_dot_dot = 0x0002, dirent_saw_eof = 0x0004, dirent_isroot = 0x0008, - dirent_saw_cygdrive = 0x0010, - dirent_saw_dev = 0x0020, - dirent_saw_proc = 0x0040, - dirent_set_d_ino = 0x0080, - dirent_get_d_ino = 0x0100 + dirent_set_d_ino = 0x0010, + dirent_get_d_ino = 0x0020 }; enum conn_state @@ -697,6 +694,8 @@ class fhandler_cygdrive: public fhandler_disk_file void set_drives (); public: fhandler_cygdrive (); + int open (int flags, mode_t mode); + int close (); DIR *opendir (); int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); void rewinddir (DIR *); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 2eede10dae..84234c4a30 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -34,6 +34,97 @@ details. */ #define _COMPILING_NEWLIB #include +class __DIR_mounts +{ + int count; + const char *parent_dir; + int parent_dir_len; + char *mounts[MAX_MOUNTS]; + bool found[MAX_MOUNTS + 2]; + +#define __DIR_PROC (MAX_MOUNTS) +#define __DIR_CYGDRIVE (MAX_MOUNTS+1) + + __ino64_t eval_ino (int idx) + { + __ino64_t ino = 0; + char fname[CYG_MAX_PATH]; + struct __stat64 st; + int len = parent_dir_len; + + strcpy (fname, parent_dir); + if (fname[len - 1] != '/') + fname[len++] = '/'; + strcpy (fname + len, mounts[idx]); + if (!lstat64 (fname, &st)) + ino = st.st_ino; + return ino; + } + +public: + __DIR_mounts (const char *posix_path) + : parent_dir (posix_path) + { + parent_dir_len = strlen (parent_dir); + count = mount_table->get_mounts_here (parent_dir, parent_dir_len, mounts); + rewind (); + } + __ino64_t check_mount (const char *name, __ino64_t ino, bool eval = true) + { + if (parent_dir_len == 1) /* root dir */ + { + if (strcasematch (name, "proc")) + { + found[__DIR_PROC] = true; + return hash_path_name (0, "/proc"); + } + if (strlen (name) == mount_table->cygdrive_len - 2 + && strncasematch (name, mount_table->cygdrive + 1, + mount_table->cygdrive_len - 2)) + { + found[__DIR_CYGDRIVE] = true; + return 2; + } + } + for (int i = 0; i < count; ++i) + if (strcasematch (name, mounts[i])) + { + found[i] = true; + return eval ? eval_ino (i) : 1; + } + return ino; + } + __ino64_t check_missing_mount (char *ret_name, bool eval = true) + { + for (int i = 0; i < count; ++i) + if (!found[i]) + { + found[i] = true; + strcpy (ret_name, mounts[i]); + return eval ? eval_ino (i) : 1; + } + if (parent_dir_len == 1) /* root dir */ + { + if (!found[__DIR_PROC]) + { + found[__DIR_PROC] = true; + strcpy (ret_name, "proc"); + return hash_path_name (0, "/proc"); + } + if (!found[__DIR_CYGDRIVE]) + { + found[__DIR_CYGDRIVE] = true; + strncpy (ret_name, mount_table->cygdrive + 1, + mount_table->cygdrive_len - 2); + ret_name[mount_table->cygdrive_len - 2] = '\0'; + return 2; + } + } + return 0; + } + void rewind () { memset (found, 0, sizeof found); } +}; + unsigned __stdcall path_conv::ndisk_links (DWORD nNumberOfLinks) { @@ -46,6 +137,7 @@ path_conv::ndisk_links (DWORD nNumberOfLinks) const char *s; unsigned count; + __DIR_mounts *dir = new __DIR_mounts (normalized_path); if (nNumberOfLinks <= 1) { s = "/*"; @@ -79,6 +171,7 @@ path_conv::ndisk_links (DWORD nNumberOfLinks) && (buf.cFileName[1] == '\0' || (buf.cFileName[1] == '.' && buf.cFileName[2] == '\0'))) saw_dot--; + dir->check_mount (buf.cFileName, 0, false); } while (FindNextFileA (h, &buf)); FindClose (h); @@ -92,6 +185,10 @@ path_conv::ndisk_links (DWORD nNumberOfLinks) saw_dot--; FindClose (h); } + while (dir->check_missing_mount (buf.cFileName, false)) + ++count; + + delete dir; return count + saw_dot; } @@ -1403,62 +1500,6 @@ struct __DIR_cache #define d_cachepos(d) (((__DIR_cache *) (d)->__d_dirname)->__pos) #define d_cache(d) (((__DIR_cache *) (d)->__d_dirname)->__cache) -class __DIR_mounts -{ - int count; - const char *parent_dir; - int parent_dir_len; - char *mounts[MAX_MOUNTS]; - bool found[MAX_MOUNTS]; - - __ino64_t eval_ino (int idx) - { - __ino64_t ino = 0; - char fname[CYG_MAX_PATH]; - struct __stat64 st; - int len = parent_dir_len; - - strcpy (fname, parent_dir); - if (fname[len - 1] != '/') - fname[len++] = '/'; - strcpy (fname + len, mounts[idx]); - if (!lstat64 (fname, &st)) - ino = st.st_ino; - return ino; - } - -public: - __DIR_mounts (const char *posix_path) - : parent_dir (posix_path) - { - parent_dir_len = strlen (parent_dir); - count = mount_table->get_mounts_here (parent_dir, parent_dir_len, mounts); - rewind (); - } - __ino64_t check_mount (const char *name, __ino64_t ino) - { - for (int i = 0; i < count; ++i) - if (strcasematch (name, mounts[i])) - { - found[i] = true; - return eval_ino (i); - } - return ino; - } - __ino64_t check_missing_mount (char *ret_name) - { - for (int i = 0; i < count; ++i) - if (!found[i]) - { - found[i] = true; - strcpy (ret_name, mounts[i]); - return eval_ino (i); - } - return 0; - } - void rewind () { memset (found, 0, sizeof found); } -}; - #define d_mounts(d) ((__DIR_mounts *) (d)->__d_internal) DIR * @@ -1582,26 +1623,6 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err, bool added = false; if ((de->d_ino = d_mounts (dir)->check_missing_mount (fname))) added = true; - else if (!(dir->__flags & dirent_isroot)) - /* nothing */; - else if (0 && !(dir->__flags & dirent_saw_dev)) - { - strcpy (fname, "dev"); - added = true; - } - else if (!(dir->__flags & dirent_saw_proc)) - { - strcpy (fname, "proc"); - added = true; - } - else if (!(dir->__flags & dirent_saw_cygdrive) - && mount_table->cygdrive_len > 1) - { - strcpy (fname, mount_table->cygdrive + 1); - fname[mount_table->cygdrive_len - 2] = '\0'; - added = true; - } - if (!added) return geterrno_from_win_error (w32_err); @@ -1630,32 +1651,6 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err, fnunmunge (de->d_name, fname); else strcpy (de->d_name, fname); - if (dir->__flags & dirent_isroot) - { - if (strcasematch (de->d_name, "dev")) - { - dir->__flags |= dirent_saw_dev; - /* In contrast to /proc, /dev has no own fhandler which cares - for inode numbers. So, if the directory exists physically, - its "real" inode number should be used. Otherwise it must - not be faked until we add a /dev fhandler to Cygwin. */ -#if 0 - de->d_ino = hash_path_name (0, "/dev"); -#endif - } - else if (strcasematch (de->d_name, "proc")) - { - dir->__flags |= dirent_saw_proc; - de->d_ino = hash_path_name (0, "/proc"); - } - if (strlen (de->d_name) == mount_table->cygdrive_len - 2 - && strncasematch (de->d_name, mount_table->cygdrive + 1, - mount_table->cygdrive_len - 2)) - { - dir->__flags |= dirent_saw_cygdrive; - de->d_ino = 0; - } - } if (dir->__d_position == 0 && !strcmp (fname, ".")) dir->__flags |= dirent_saw_dot; else if (dir->__d_position == 1 && !strcmp (fname, "..")) @@ -1931,6 +1926,31 @@ fhandler_cygdrive::fhandler_cygdrive () : { } +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; + } + flags |= O_DIROPEN; + set_flags (flags); + nohandle (true); + return 1; +} + +int +fhandler_cygdrive::close () +{ + return 0; +} + #define DRVSZ sizeof ("x:\\") void fhandler_cygdrive::set_drives () @@ -1945,12 +1965,8 @@ int fhandler_cygdrive::fstat (struct __stat64 *buf) { buf->st_mode = S_IFDIR | 0555; - /* Call get_namehash before calling set_drives, otherwise the namehash - is broken due to overwriting the win32 path in set_drives. */ - buf->st_ino = get_namehash (); - if (!ndrives) - set_drives (); - buf->st_nlink = ndrives + 2; + buf->st_ino = 2; + buf->st_nlink = 1; return 0; } @@ -1960,9 +1976,6 @@ fhandler_cygdrive::opendir () DIR *dir; dir = fhandler_disk_file::opendir (); - /* Call get_namehash before calling set_drives, otherwise the namehash - is broken due to overwriting the win32 path in set_drives. */ - get_namehash (); if (dir && !ndrives) set_drives (); @@ -1975,7 +1988,15 @@ fhandler_cygdrive::readdir (DIR *dir, dirent *de) while (true) { if (!pdrive || !*pdrive) - return ENMFILE; + { + if (!(dir->__flags & dirent_saw_dot)) + { + de->d_name[0] = '.'; + de->d_name[1] = '\0'; + de->d_ino = 2; + } + return ENMFILE; + } if (GetFileAttributes (pdrive) != INVALID_FILE_ATTRIBUTES) break; pdrive = strchr (pdrive, '\0') + 1; -- 2.11.0