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
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-03-02 01:37:25 +0300
committerCorinna Vinschen <corinna@vinschen.de>2006-03-02 01:37:25 +0300
commitc115f31ff26e621befc3bad4e020b3663a66ab2c (patch)
tree064d785b2fb50b6dd8985d3da8e91f5f9f3d721c /winsup
parent8d0f58ef3724fc248b8e26be1a84ceffd93039fe (diff)
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/fhandler.h9
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc245
3 files changed, 159 insertions, 117 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 09d756145..5cea69b07 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,25 @@
+2006-03-01 Corinna Vinschen <corinna@vinschen.de>
+
+ * 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 <cgf@timesys.com>
* cygwin.din: Fix some erroneous SIGFE/NOSIGFE settings.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 37b7699c8..bd068a88d 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 2eede10da..84234c4a3 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -34,6 +34,97 @@ details. */
#define _COMPILING_NEWLIB
#include <dirent.h>
+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;