* 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> 2007-06-28 Brian Dessent <brian@dessent.net>
* include/cygwin/version.h: Fix comment typo. * include/cygwin/version.h: Fix comment typo.

View File

@ -61,7 +61,7 @@ opendir (const char *name)
if (!fh) if (!fh)
res = NULL; res = NULL;
else if (fh->exists ()) else if (fh->exists ())
res = fh->opendir (); res = fh->opendir (-1);
else else
{ {
set_errno (ENOENT); set_errno (ENOENT);
@ -73,6 +73,17 @@ opendir (const char *name)
return res; 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 static int
readdir_worker (DIR *dir, dirent *de) readdir_worker (DIR *dir, dirent *de)
{ {
@ -204,7 +215,7 @@ seekdir64 (DIR *dir, _off64_t loc)
if (dir->__d_cookie != __DIRENT_COOKIE) if (dir->__d_cookie != __DIRENT_COOKIE)
return; 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); return ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
} }
@ -225,7 +236,7 @@ rewinddir (DIR *dir)
if (dir->__d_cookie != __DIRENT_COOKIE) if (dir->__d_cookie != __DIRENT_COOKIE)
return; 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); return ((fhandler_base *) dir->__fh)->rewinddir (dir);
} }
@ -249,7 +260,11 @@ closedir (DIR *dir)
int res = ((fhandler_base *) dir->__fh)->closedir (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_dirname);
free (dir->__d_dirent); free (dir->__d_dirent);

View File

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

View File

@ -51,7 +51,11 @@ enum dirent_states
dirent_saw_eof = 0x0004, dirent_saw_eof = 0x0004,
dirent_isroot = 0x0008, dirent_isroot = 0x0008,
dirent_set_d_ino = 0x0010, 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 enum conn_state
@ -356,7 +360,7 @@ class fhandler_base
virtual void set_eof () {} virtual void set_eof () {}
virtual int mkdir (mode_t mode); virtual int mkdir (mode_t mode);
virtual int rmdir (); virtual int rmdir ();
virtual DIR *opendir (); virtual DIR *opendir (int fd) __attribute__ ((regparm (2)));
virtual int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); virtual int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
virtual _off64_t telldir (DIR *); virtual _off64_t telldir (DIR *);
virtual void seekdir (DIR *, _off64_t); virtual void seekdir (DIR *, _off64_t);
@ -705,7 +709,7 @@ class fhandler_disk_file: public fhandler_base
_off64_t offset, DWORD size, void *address); _off64_t offset, DWORD size, void *address);
int mkdir (mode_t mode); int mkdir (mode_t mode);
int rmdir (); int rmdir ();
DIR *opendir (); DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
_off64_t telldir (DIR *); _off64_t telldir (DIR *);
void seekdir (DIR *, _off64_t); void seekdir (DIR *, _off64_t);
@ -725,7 +729,7 @@ class fhandler_cygdrive: public fhandler_disk_file
fhandler_cygdrive (); fhandler_cygdrive ();
int open (int flags, mode_t mode); int open (int flags, mode_t mode);
int close (); int close ();
DIR *opendir (); DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
void rewinddir (DIR *); void rewinddir (DIR *);
int closedir (DIR *); int closedir (DIR *);
@ -1221,7 +1225,7 @@ class fhandler_virtual : public fhandler_base
virtual ~fhandler_virtual(); virtual ~fhandler_virtual();
virtual int exists(); virtual int exists();
virtual DIR *opendir (); DIR *opendir (int fd) __attribute__ ((regparm (2)));
_off64_t telldir (DIR *); _off64_t telldir (DIR *);
void seekdir (DIR *, _off64_t); void seekdir (DIR *, _off64_t);
void rewinddir (DIR *); void rewinddir (DIR *);
@ -1297,7 +1301,7 @@ class fhandler_process: public fhandler_proc
public: public:
fhandler_process (); fhandler_process ();
int exists(); int exists();
DIR *opendir (); DIR *opendir (int fd) __attribute__ ((regparm (2)));
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0); int open (int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
@ -1310,7 +1314,6 @@ class fhandler_procnet: public fhandler_proc
public: public:
fhandler_procnet (); fhandler_procnet ();
int exists(); int exists();
DIR *opendir ();
int readdir (DIR *, dirent *) __attribute__ ((regparm (3))); int readdir (DIR *, dirent *) __attribute__ ((regparm (3)));
int open (int flags, mode_t mode = 0); int open (int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); 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) #define d_mounts(d) ((__DIR_mounts *) (d)->__d_internal)
DIR * DIR *
fhandler_disk_file::opendir () fhandler_disk_file::opendir (int fd)
{ {
DIR *dir; DIR *dir;
DIR *res = NULL; DIR *res = NULL;
@ -1542,9 +1542,9 @@ fhandler_disk_file::opendir ()
{ {
strcpy (d_dirname (dir), get_win32_name ()); strcpy (d_dirname (dir), get_win32_name ());
dir->__d_dirent->__d_version = __DIRENT_VERSION; dir->__d_dirent->__d_version = __DIRENT_VERSION;
cygheap_fdnew fd; cygheap_fdnew cfd;
if (fd < 0) if (cfd < 0 && fd < 0)
goto free_dirent; goto free_dirent;
/* FindFirstFile doesn't seem to like duplicate /'s. /* FindFirstFile doesn't seem to like duplicate /'s.
@ -1569,15 +1569,28 @@ fhandler_disk_file::opendir ()
if (!pc.iscygdrive ()) if (!pc.iscygdrive ())
{ {
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
WCHAR wpath[CYG_MAX_PATH + 10];
UNICODE_STRING upath = {0, sizeof (wpath), wpath};
IO_STATUS_BLOCK io;
NTSTATUS status; 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; SECURITY_ATTRIBUTES sa = sec_none;
pc.get_nt_native_path (upath);
InitializeObjectAttributes (&attr, &upath, if (fd >= 0 && get_handle ())
OBJ_CASE_INSENSITIVE | OBJ_INHERIT, {
NULL, sa.lpSecurityDescriptor); /* 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, status = NtOpenFile (&dir->__handle,
SYNCHRONIZE | FILE_LIST_DIRECTORY, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS, &attr, &io, FILE_SHARE_VALID_FLAGS,
@ -1605,13 +1618,22 @@ fhandler_disk_file::opendir ()
dir->__flags |= dirent_get_d_ino; dir->__flags |= dirent_get_d_ino;
} }
} }
/* Filling fd with `this' (aka storing this in the file descriptor table if (fd >= 0)
should only happen after it's clear that opendir doesn't fail, {
otherwise we end up cfree'ing the fhandler twice, once in opendir() dir->__flags |= dirent_valid_fd;
in dir.cc, the second time on exit. Nasty, nasty... */ dir->__d_fd = fd;
fd = this; }
fd->nohandle (true); else
dir->__d_fd = fd; {
/* 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; dir->__fh = this;
res = dir; res = dir;
} }
@ -2011,11 +2033,11 @@ fhandler_cygdrive::fstat (struct __stat64 *buf)
} }
DIR * DIR *
fhandler_cygdrive::opendir () fhandler_cygdrive::opendir (int fd)
{ {
DIR *dir; DIR *dir;
dir = fhandler_disk_file::opendir (); dir = fhandler_disk_file::opendir (fd);
if (dir && !ndrives) if (dir && !ndrives)
set_drives (); set_drives ();

View File

@ -198,15 +198,11 @@ fhandler_process::fstat (struct __stat64 *buf)
} }
DIR * DIR *
fhandler_process::opendir () fhandler_process::opendir (int fd)
{ {
DIR *dir = fhandler_virtual::opendir (); DIR *dir = fhandler_virtual::opendir (fd);
if (dir) if (dir && fileid == PROCESS_FD)
{ fill_filebuf ();
if (fileid == PROCESS_FD)
fill_filebuf ();
dir->__flags = 0;
}
return dir; 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 int
fhandler_procnet::readdir (DIR *dir, dirent *de) fhandler_procnet::readdir (DIR *dir, dirent *de)
{ {

View File

@ -46,7 +46,7 @@ fhandler_virtual::fixup_after_exec ()
} }
DIR * DIR *
fhandler_virtual::opendir () fhandler_virtual::opendir (int fd)
{ {
DIR *dir; DIR *dir;
DIR *res = NULL; DIR *res = NULL;
@ -73,20 +73,30 @@ fhandler_virtual::opendir ()
{ {
strcpy (dir->__d_dirname, get_name ()); strcpy (dir->__d_dirname, get_name ());
dir->__d_dirent->__d_version = __DIRENT_VERSION; 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) if (fd >= 0)
{ {
fd = this; dir->__flags |= dirent_valid_fd;
fd->nohandle (true);
dir->__d_fd = 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 = 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. 172: Export getifaddrs, freeifaddrs.
173: Export __assert_func. 173: Export __assert_func.
174: Export stpcpy, stpncpy. 174: Export stpcpy, stpncpy.
175: Export fdopendir.
*/ */
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0 #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 /* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible shared memory regions. It is incremented when incompatible

View File

@ -1,6 +1,6 @@
/* Posix dirent.h for WIN32. /* 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 This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for Cygwin license. Please consult the file "CYGWIN_LICENSE" for
@ -56,6 +56,7 @@ typedef struct __DIR
#pragma pack(pop) #pragma pack(pop)
DIR *opendir (const char *); DIR *opendir (const char *);
DIR *fdopendir (int);
struct dirent *readdir (DIR *); struct dirent *readdir (DIR *);
int readdir_r (DIR *, struct dirent *, struct dirent **); int readdir_r (DIR *, struct dirent *, struct dirent **);
void rewinddir (DIR *); 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 acltotext
endmntent endmntent
facl facl
fdopendir
getmntent getmntent
memalign memalign
setmntent setmntent