* cygwin.din: Export fdopendir.

* dir.cc (opendir): Call fhandler's opendir with fd set to -1.
	(fdopendir): New function.
	(seekdir64): Use dirent_info_mask.
	(rewinddir): Ditto.
	(closedir): Only release underlying file descriptor if it has been
	reserved by opendir itself.
	* fhandler.cc (fhandler_base::opendir): Accommodate new parameter.
	* fhandler.h (dirent_states): Add dirent_valid_fd and dirent_info_mask.
	(fhander_XXX::opendir): Add file descriptor parameter.  Use regparms.
	(fhandler_procnet::opendir): Drop declaration.
	* fhandler_disk_file.cc (fhandler_disk_file::opendir): Ditto.
	If called from fdopendir, use existing handle to re-open directory
	with valid flags.  Rename fd to cfd.  Use only if no valid incoming fd.
	(fhandler_cygdrive::opendir): Accommodate new parameter.
	* fhandler_process.cc (fhandler_process::opendir): Ditto.
	* fhandler_procnet.cc (fhandler_procnet::opendir): Drop definition.
	* fhandler_virtual.cc (fhandler_virtual::opendir): Accommodate new
	parameter.  Only create new file descriptor entry if called from
	opendir.  Remove duplicated setting of dir->__flags.
	* posix.sgml: Add fdopendir to list of implemented Solaris functions.
	* include/cygwin/version.h: Bump API minor number.
	* include/sys/dirent.h: Declare fdopendir.
This commit is contained in:
Corinna Vinschen
2007-06-29 15:13:01 +00:00
parent 8931495a14
commit 40570a828e
11 changed files with 128 additions and 62 deletions

View File

@@ -1514,7 +1514,7 @@ struct __DIR_cache
#define d_mounts(d) ((__DIR_mounts *) (d)->__d_internal)
DIR *
fhandler_disk_file::opendir ()
fhandler_disk_file::opendir (int fd)
{
DIR *dir;
DIR *res = NULL;
@@ -1542,9 +1542,9 @@ fhandler_disk_file::opendir ()
{
strcpy (d_dirname (dir), get_win32_name ());
dir->__d_dirent->__d_version = __DIRENT_VERSION;
cygheap_fdnew fd;
cygheap_fdnew cfd;
if (fd < 0)
if (cfd < 0 && fd < 0)
goto free_dirent;
/* FindFirstFile doesn't seem to like duplicate /'s.
@@ -1569,15 +1569,28 @@ fhandler_disk_file::opendir ()
if (!pc.iscygdrive ())
{
OBJECT_ATTRIBUTES attr;
WCHAR wpath[CYG_MAX_PATH + 10];
UNICODE_STRING upath = {0, sizeof (wpath), wpath};
IO_STATUS_BLOCK io;
NTSTATUS status;
IO_STATUS_BLOCK io;
WCHAR wpath[CYG_MAX_PATH + 10] = { 0 };
UNICODE_STRING upath = {0, sizeof (wpath), wpath};
SECURITY_ATTRIBUTES sa = sec_none;
pc.get_nt_native_path (upath);
InitializeObjectAttributes (&attr, &upath,
OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL, sa.lpSecurityDescriptor);
if (fd >= 0 && get_handle ())
{
/* fdopendir() case. Just initialize with the emtpy upath
and reuse the exisiting handle. */
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
get_handle (), NULL);
}
else
{
/* opendir() case. Initialize with given directory name and
NULL directory handle. */
pc.get_nt_native_path (upath);
InitializeObjectAttributes (&attr, &upath,
OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL, sa.lpSecurityDescriptor);
}
status = NtOpenFile (&dir->__handle,
SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,
@@ -1605,13 +1618,22 @@ fhandler_disk_file::opendir ()
dir->__flags |= dirent_get_d_ino;
}
}
/* Filling fd with `this' (aka storing this in the file descriptor table
should only happen after it's clear that opendir doesn't fail,
otherwise we end up cfree'ing the fhandler twice, once in opendir()
in dir.cc, the second time on exit. Nasty, nasty... */
fd = this;
fd->nohandle (true);
dir->__d_fd = fd;
if (fd >= 0)
{
dir->__flags |= dirent_valid_fd;
dir->__d_fd = fd;
}
else
{
/* Filling cfd with `this' (aka storing this in the file
descriptor table should only happen after it's clear that
opendir doesn't fail, otherwise we end up cfree'ing the
fhandler twice, once in opendir() in dir.cc, the second
time on exit. Nasty, nasty... */
cfd = this;
cfd->nohandle (true);
dir->__d_fd = cfd;
}
dir->__fh = this;
res = dir;
}
@@ -2011,11 +2033,11 @@ fhandler_cygdrive::fstat (struct __stat64 *buf)
}
DIR *
fhandler_cygdrive::opendir ()
fhandler_cygdrive::opendir (int fd)
{
DIR *dir;
dir = fhandler_disk_file::opendir ();
dir = fhandler_disk_file::opendir (fd);
if (dir && !ndrives)
set_drives ();