Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2007-06-29 19:13:01 +0400
committerCorinna Vinschen <corinna@vinschen.de>2007-06-29 19:13:01 +0400
commit40570a828e0ed00cf570a2d7fa41ddae887c1367 (patch)
tree86f1a9e5322b57c1b2567a1e85b308e0ff932816 /winsup
parent8931495a1417c7dc1b6c56d0120efb40a1fa030b (diff)
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog26
-rw-r--r--winsup/cygwin/dir.cc23
-rw-r--r--winsup/cygwin/fhandler.cc2
-rw-r--r--winsup/cygwin/fhandler.h17
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc60
-rw-r--r--winsup/cygwin/fhandler_process.cc12
-rw-r--r--winsup/cygwin/fhandler_procnet.cc9
-rw-r--r--winsup/cygwin/fhandler_virtual.cc32
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/sys/dirent.h3
-rw-r--r--winsup/cygwin/posix.sgml1
11 files changed, 127 insertions, 61 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 5ad9aae7d..5f092f7ae 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index 3d0dbae7b..2ce0488c5 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -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);
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 4348b8792..6cabe912a 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1444,7 +1444,7 @@ fhandler_base::rmdir ()
}
DIR *
-fhandler_base::opendir ()
+fhandler_base::opendir (int fd)
{
set_errno (ENOTDIR);
return NULL;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 814054399..b41838c5a 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -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)));
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 353c45ba5..d693a9ddb 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -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 ();
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index 1abb99dfd..6ba9fd4cc 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -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;
}
diff --git a/winsup/cygwin/fhandler_procnet.cc b/winsup/cygwin/fhandler_procnet.cc
index 8201a0d1d..82c5f0a84 100644
--- a/winsup/cygwin/fhandler_procnet.cc
+++ b/winsup/cygwin/fhandler_procnet.cc
@@ -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)
{
diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc
index 13f8e1fd4..4045c2d5e 100644
--- a/winsup/cygwin/fhandler_virtual.cc
+++ b/winsup/cygwin/fhandler_virtual.cc
@@ -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;
+ res = dir;
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;
+ }
+ else
+ {
+ cygheap_fdnew cfd;
+ if (cfd >= 0)
+ {
+ cfd = this;
+ cfd->nohandle (true);
+ dir->__d_fd = cfd;
+ dir->__fh = this;
+ res = dir;
+ }
}
}
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 9059ecdec..478387517 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -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
diff --git a/winsup/cygwin/include/sys/dirent.h b/winsup/cygwin/include/sys/dirent.h
index d4e5e1333..24cde06d6 100644
--- a/winsup/cygwin/include/sys/dirent.h
+++ b/winsup/cygwin/include/sys/dirent.h
@@ -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 *);
diff --git a/winsup/cygwin/posix.sgml b/winsup/cygwin/posix.sgml
index 2567195e7..28717eb21 100644
--- a/winsup/cygwin/posix.sgml
+++ b/winsup/cygwin/posix.sgml
@@ -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