* 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

@ -1,3 +1,29 @@
2007-06-29 Corinna Vinschen <corinna@vinschen.de>
* 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.
2007-06-28 Brian Dessent <brian@dessent.net>
* include/cygwin/version.h: Fix comment typo.

View File

@ -61,7 +61,7 @@ opendir (const char *name)
if (!fh)
res = NULL;
else if (fh->exists ())
res = fh->opendir ();
res = fh->opendir (-1);
else
{
set_errno (ENOENT);
@ -73,6 +73,17 @@ opendir (const char *name)
return res;
}
extern "C" DIR *
fdopendir (int fd)
{
DIR *res = NULL;
cygheap_fdget cfd (fd);
if (cfd >= 0)
res = cfd->opendir (fd);
return res;
}
static int
readdir_worker (DIR *dir, dirent *de)
{
@ -204,7 +215,7 @@ seekdir64 (DIR *dir, _off64_t loc)
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
dir->__flags &= (dirent_isroot | dirent_get_d_ino | dirent_set_d_ino);
dir->__flags &= dirent_info_mask;
return ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
}
@ -225,7 +236,7 @@ rewinddir (DIR *dir)
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
dir->__flags &= (dirent_isroot | dirent_get_d_ino | dirent_set_d_ino);
dir->__flags &= dirent_info_mask;
return ((fhandler_base *) dir->__fh)->rewinddir (dir);
}
@ -249,7 +260,11 @@ closedir (DIR *dir)
int res = ((fhandler_base *) dir->__fh)->closedir (dir);
cygheap->fdtab.release (dir->__d_fd);
/* If the directory has been opened by fdopendir, the descriptor
entry is used elsewhere in the application and must not be removed
from the descriptor table. */
if (!(dir->__flags & dirent_valid_fd))
cygheap->fdtab.release (dir->__d_fd);
free (dir->__d_dirname);
free (dir->__d_dirent);

View File

@ -1444,7 +1444,7 @@ fhandler_base::rmdir ()
}
DIR *
fhandler_base::opendir ()
fhandler_base::opendir (int fd)
{
set_errno (ENOTDIR);
return NULL;

View File

@ -51,7 +51,11 @@ enum dirent_states
dirent_saw_eof = 0x0004,
dirent_isroot = 0x0008,
dirent_set_d_ino = 0x0010,
dirent_get_d_ino = 0x0020
dirent_get_d_ino = 0x0020,
dirent_valid_fd = 0x0040,
/* Global flags which must not be deleted on rewinddir or seekdir. */
dirent_info_mask = 0x0078
};
enum conn_state
@ -356,7 +360,7 @@ class fhandler_base
virtual void set_eof () {}
virtual int mkdir (mode_t mode);
virtual int rmdir ();
virtual DIR *opendir ();
virtual DIR *opendir (int fd) __attribute__ ((regparm (2)));
virtual int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
virtual _off64_t telldir (DIR *);
virtual void seekdir (DIR *, _off64_t);
@ -705,7 +709,7 @@ class fhandler_disk_file: public fhandler_base
_off64_t offset, DWORD size, void *address);
int mkdir (mode_t mode);
int rmdir ();
DIR *opendir ();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
_off64_t telldir (DIR *);
void seekdir (DIR *, _off64_t);
@ -725,7 +729,7 @@ class fhandler_cygdrive: public fhandler_disk_file
fhandler_cygdrive ();
int open (int flags, mode_t mode);
int close ();
DIR *opendir ();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
void rewinddir (DIR *);
int closedir (DIR *);
@ -1221,7 +1225,7 @@ class fhandler_virtual : public fhandler_base
virtual ~fhandler_virtual();
virtual int exists();
virtual DIR *opendir ();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
_off64_t telldir (DIR *);
void seekdir (DIR *, _off64_t);
void rewinddir (DIR *);
@ -1297,7 +1301,7 @@ class fhandler_process: public fhandler_proc
public:
fhandler_process ();
int exists();
DIR *opendir ();
DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
@ -1310,7 +1314,6 @@ class fhandler_procnet: public fhandler_proc
public:
fhandler_procnet ();
int exists();
DIR *opendir ();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));

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 ();

View File

@ -198,15 +198,11 @@ fhandler_process::fstat (struct __stat64 *buf)
}
DIR *
fhandler_process::opendir ()
fhandler_process::opendir (int fd)
{
DIR *dir = fhandler_virtual::opendir ();
if (dir)
{
if (fileid == PROCESS_FD)
fill_filebuf ();
dir->__flags = 0;
}
DIR *dir = fhandler_virtual::opendir (fd);
if (dir && fileid == PROCESS_FD)
fill_filebuf ();
return dir;
}

View File

@ -107,15 +107,6 @@ fhandler_procnet::fstat (struct __stat64 *buf)
}
}
DIR *
fhandler_procnet::opendir ()
{
DIR *dir = fhandler_virtual::opendir ();
if (dir)
dir->__flags = 0;
return dir;
}
int
fhandler_procnet::readdir (DIR *dir, dirent *de)
{

View File

@ -46,7 +46,7 @@ fhandler_virtual::fixup_after_exec ()
}
DIR *
fhandler_virtual::opendir ()
fhandler_virtual::opendir (int fd)
{
DIR *dir;
DIR *res = NULL;
@ -73,20 +73,30 @@ fhandler_virtual::opendir ()
{
strcpy (dir->__d_dirname, get_name ());
dir->__d_dirent->__d_version = __DIRENT_VERSION;
cygheap_fdnew fd;
dir->__d_cookie = __DIRENT_COOKIE;
dir->__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0;
dir->__flags = 0;
if (fd >= 0)
{
fd = this;
fd->nohandle (true);
{
dir->__flags |= dirent_valid_fd;
dir->__d_fd = fd;
dir->__fh = this;
dir->__d_cookie = __DIRENT_COOKIE;
dir->__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0;
// dir->__d_dirhash = get_namehash ();
dir->__flags = dirent_saw_dot | dirent_saw_dot_dot;
res = dir;
res->__flags = 0;
dir->__fh = this;
res = dir;
}
else
{
cygheap_fdnew cfd;
if (cfd >= 0)
{
cfd = this;
cfd->nohandle (true);
dir->__d_fd = cfd;
dir->__fh = this;
res = dir;
}
}
}

View File

@ -315,12 +315,13 @@ details. */
172: Export getifaddrs, freeifaddrs.
173: Export __assert_func.
174: Export stpcpy, stpncpy.
175: Export fdopendir.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 174
#define CYGWIN_VERSION_API_MINOR 175
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible

View File

@ -1,6 +1,6 @@
/* Posix dirent.h for WIN32.
Copyright 2001, 2002, 2003, 2005, 2006 Red Hat, Inc.
Copyright 2001, 2002, 2003, 2005, 2006, 2007 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
@ -56,6 +56,7 @@ typedef struct __DIR
#pragma pack(pop)
DIR *opendir (const char *);
DIR *fdopendir (int);
struct dirent *readdir (DIR *);
int readdir_r (DIR *, struct dirent *, struct dirent **);
void rewinddir (DIR *);

View File

@ -993,6 +993,7 @@ also ISO/IEC 9945:2003 and IEEE Std 1003.1-2001 (POSIX.1-2001).</para>
acltotext
endmntent
facl
fdopendir
getmntent
memalign
setmntent