* 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

@ -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)