* include/sys/dirent.h (struct __DIR): Rename __d_unused to

__d_internal.
	* fhandler_disk_file.cc (struct __DIR_cache): Remove useless "typedef".
	(d_dirname): Remove useless "struct".
	(d_cachepos): Ditto.
	(d_cache): Ditto.
	(class __DIR_mounts): New class, implementing mount point tracking
	for readdir.
	(d_mounts): New macro for easy access to __DIR_mounts structure.
	(fhandler_disk_file::opendir): Allocate __DIR_mounts structure and
	let __d_internal element of dir point to it.
	(fhandler_disk_file::readdir_helper): Add mount points in the current
	directory, which don't have a real directory backing them.
	Don't generate an inode number for /dev.  Add comment, why.
	(fhandler_disk_file::readdir): Move filling fname to an earlier point.
	Check if current entry is a mount point and evaluate correct inode
	number for it.
	(fhandler_disk_file::readdir_9x): Ditto.
	(fhandler_disk_file::rewinddir): Set all mount points in this directory
	to "not found" so that they are listed again after calling rewinddir().
	(fhandler_disk_file::closedir): Deallocate __DIR_mounts structure.
	* path.cc (mount_info::get_mounts_here): New method to evaluate a list
	of mount points in a given parent directory.
	* shared_info.h (class mount_info): Declare get_mounts_here.
This commit is contained in:
Corinna Vinschen 2006-03-01 13:47:49 +00:00
parent 0e3befd678
commit e817fd3c8b
5 changed files with 131 additions and 8 deletions

View File

@ -1,3 +1,30 @@
2006-03-01 Corinna Vinschen <corinna@vinschen.de>
* include/sys/dirent.h (struct __DIR): Rename __d_unused to
__d_internal.
* fhandler_disk_file.cc (struct __DIR_cache): Remove useless "typedef".
(d_dirname): Remove useless "struct".
(d_cachepos): Ditto.
(d_cache): Ditto.
(class __DIR_mounts): New class, implementing mount point tracking
for readdir.
(d_mounts): New macro for easy access to __DIR_mounts structure.
(fhandler_disk_file::opendir): Allocate __DIR_mounts structure and
let __d_internal element of dir point to it.
(fhandler_disk_file::readdir_helper): Add mount points in the current
directory, which don't have a real directory backing them.
Don't generate an inode number for /dev. Add comment, why.
(fhandler_disk_file::readdir): Move filling fname to an earlier point.
Check if current entry is a mount point and evaluate correct inode
number for it.
(fhandler_disk_file::readdir_9x): Ditto.
(fhandler_disk_file::rewinddir): Set all mount points in this directory
to "not found" so that they are listed again after calling rewinddir().
(fhandler_disk_file::closedir): Deallocate __DIR_mounts structure.
* path.cc (mount_info::get_mounts_here): New method to evaluate a list
of mount points in a given parent directory.
* shared_info.h (class mount_info): Declare get_mounts_here.
2006-02-28 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::opendir): Use iscygdrive

View File

@ -1392,16 +1392,74 @@ fhandler_disk_file::rmdir ()
* (sizeof (FILE_ID_BOTH_DIR_INFORMATION) \
+ 2 * CYG_MAX_PATH))
typedef struct __DIR_cache
struct __DIR_cache
{
char __name[CYG_MAX_PATH];
ULONG __pos;
char __cache[DIR_BUF_SIZE];
};
#define d_dirname(d) (((struct __DIR_cache *) (d)->__d_dirname)->__name)
#define d_cachepos(d) (((struct __DIR_cache *) (d)->__d_dirname)->__pos)
#define d_cache(d) (((struct __DIR_cache *) (d)->__d_dirname)->__cache)
#define d_dirname(d) (((__DIR_cache *) (d)->__d_dirname)->__name)
#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 *
fhandler_disk_file::opendir ()
@ -1458,6 +1516,7 @@ fhandler_disk_file::opendir ()
dir->__d_position = 0;
dir->__flags = (pc.normalized_path[0] == '/' && pc.normalized_path[1] == '\0') ? dirent_isroot : 0;
dir->__d_internal = (unsigned) new __DIR_mounts (pc.normalized_path);
if (wincap.is_winnt ())
{
d_cachepos (dir) = 0;
@ -1521,7 +1580,9 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
if (w32_err)
{
bool added = false;
if (!(dir->__flags & dirent_isroot))
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))
{
@ -1574,7 +1635,13 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
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"))
{
@ -1697,7 +1764,9 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
}
else
FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
sys_wcstombs (fname, CYG_MAX_PATH - 1, FileName, buf->FileNameLength / 2);
de->d_ino = d_mounts (dir)->check_mount (fname, de->d_ino);
if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
{
OBJECT_ATTRIBUTES attr;
@ -1723,7 +1792,6 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
}
}
}
sys_wcstombs (fname, CYG_MAX_PATH - 1, FileName, buf->FileNameLength / 2);
}
if (!(res = readdir_helper (dir, de, RtlNtStatusToDosError (status),
@ -1783,7 +1851,8 @@ fhandler_disk_file::readdir_9x (DIR *dir, dirent *de)
goto out;
}
}
if (!lasterr)
de->d_ino = d_mounts (dir)->check_mount (buf.cFileName, de->d_ino);
if (!(res = readdir_helper (dir, de, lasterr, buf.dwFileAttributes,
buf.cFileName)))
dir->__d_position++;
@ -1825,12 +1894,14 @@ fhandler_disk_file::rewinddir (DIR *dir)
dir->__handle = INVALID_HANDLE_VALUE;
}
dir->__d_position = 0;
d_mounts (dir)->rewind ();
}
int
fhandler_disk_file::closedir (DIR *dir)
{
int res = 0;
delete d_mounts (dir);
if (!dir->__handle)
/* ignore */;
else if (dir->__handle == INVALID_HANDLE_VALUE)

View File

@ -48,7 +48,7 @@ typedef struct __DIR
char *__d_dirname; /* directory name with trailing '*' */
_off_t __d_position; /* used by telldir/seekdir */
int __d_fd;
unsigned __d_unused;
unsigned __d_internal;
void *__handle;
void *__fh;
unsigned __flags;

View File

@ -1718,6 +1718,30 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
return rc;
}
int
mount_info::get_mounts_here (const char *parent_dir, int parent_dir_len,
char **mount_points)
{
int n_mounts = 0;
for (int i = 0; i < nmounts; i++)
{
mount_item *mi = mount + posix_sorted[i];
char *last_slash = strrchr (mi->posix_path, '/');
if (!last_slash)
continue;
if (last_slash == mi->posix_path)
{
if (parent_dir_len == 1 && mi->posix_pathlen > 1)
mount_points[n_mounts++] = last_slash + 1;
}
else if (parent_dir_len == last_slash - mi->posix_path
&& strncasematch (parent_dir, mi->posix_path, parent_dir_len))
mount_points[n_mounts++] = last_slash + 1;
}
return n_mounts;
}
/* cygdrive_posix_path: Build POSIX path used as the
mount point for cygdrives created when there is no other way to
obtain a POSIX path from a Win32 one. */

View File

@ -91,6 +91,7 @@ class mount_info
int get_cygdrive_info (char *user, char *system, char* user_flags,
char* system_flags);
void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p);
int get_mounts_here (const char *parent_dir, int, char **mount_points);
private: