* 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:
		| @@ -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. | ||||
|   | ||||
| @@ -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,6 +260,10 @@ closedir (DIR *dir) | ||||
|  | ||||
|   int res = ((fhandler_base *) dir->__fh)->closedir (dir); | ||||
|  | ||||
|   /* 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); | ||||
|   | ||||
| @@ -1444,7 +1444,7 @@ fhandler_base::rmdir () | ||||
| } | ||||
|  | ||||
| DIR * | ||||
| fhandler_base::opendir () | ||||
| fhandler_base::opendir (int fd) | ||||
| { | ||||
|   set_errno (ENOTDIR); | ||||
|   return NULL; | ||||
|   | ||||
| @@ -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))); | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
| 	  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); | ||||
|       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 (); | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|   DIR *dir = fhandler_virtual::opendir (fd); | ||||
|   if (dir && fileid == PROCESS_FD) | ||||
|     fill_filebuf (); | ||||
|       dir->__flags = 0; | ||||
|     } | ||||
|   return dir; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
| { | ||||
|   | ||||
| @@ -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; | ||||
|       if (fd >= 0) | ||||
| 	{ | ||||
| 	  fd = this; | ||||
| 	  fd->nohandle (true); | ||||
| 	  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; | ||||
|       dir->__flags = 0; | ||||
|  | ||||
|       if (fd >= 0) | ||||
|         { | ||||
| 	  dir->__flags |= dirent_valid_fd; | ||||
| 	  dir->__d_fd = fd; | ||||
| 	  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; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 *); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user