]> sourceware.org Git - newlib-cygwin.git/commitdiff
Rationalise structure layout; add dirent.d_type field.
authorKeith Marshall <keithmarshall@@users.sf.net>
Sat, 1 Oct 2011 20:18:10 +0000 (20:18 +0000)
committerKeith Marshall <keithmarshall@@users.sf.net>
Sat, 1 Oct 2011 20:18:10 +0000 (20:18 +0000)
winsup/mingw/ChangeLog
winsup/mingw/include/dirent.h
winsup/mingw/mingwex/dirent.c

index d8a9d4e1aab27c0c0dc712267429c4c179bba7f6..5f1e9a59f693581ff66f2948bc8ee9459ee50985 100644 (file)
@@ -1,3 +1,29 @@
+2011-10-01  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       Rationalise structure layout; add dirent.d_type field.
+
+       * include/dirent.h (struct dirent): Rearrange; add d_type field.
+       Add extra padding fields between d_type and d_name, to represent a
+       union with a _finddata_t struct, aligned at the d_type field.
+       (struct _wdirent): Likewise, with _wfinddata_t aligned at d_type.
+       (DT_REG, DT_DIR): New macros; define them to be equivalent to...
+       (_A_NORMAL, _A_SUBDIR): ...these Microsoft attributes respectively.
+       (DT_BLK, DT_CHR, DT_FIFO, DT_LNK, DT_SOCK): New macros; define them.
+       They have little relevance on Win32, so don't use them, substitute...
+       (DT_UNKNOWN): ...this new catch-all macro instead; define it.
+       (struct __dirstream_t): Change declaration; replace by opaque union.
+       (struct __wdirstream_t): Likewise.
+
+       * mingwex/dirent.c (struct __dirstream_t): Redefine as union; map...
+       (struct dirent, struct __dirstream_private_t): ...these to a common
+       address; the latter encapsulates the private data into...
+       (dd_private): ...this new member; update all references accordingly.
+       Adjust field layout to align with corresponding dirent fields.
+       (struct __wdirstream_t): Similarly redefine as union, mapping...
+       (struct _wdirent, struct __wdirstream_private_t): ...these.
+       (_treaddir): Set dirent.d_type to appropriate selection from...
+       (DT_REG, DT_DIR, DT_UNKNOWN): ...these.
+
 2011-08-27  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Don't expose implementation detail for opaque DIRENT structures.
 2002-09-17 Danny Smith <dannysmith@users.sourceforge.net>
 
        * include/time.h (__need_NULL): Define before including
-       stddef.h. Thanks to: Rüdiger Dehmel <de@lmnet.de>.
+       stddef.h. Thanks to: Rüdiger Dehmel <de@lmnet.de>.
 
 2002-09-16 Ranjit Matthew <rmathew@hotmail.com>
 
index 7d2af2b1951f84b7a70c9e89d1a81140851eb483..3abedfafc45e9b5b1e65ae042374a7c527c18ad1 100644 (file)
@@ -24,6 +24,20 @@ struct dirent
        long            d_ino;          /* Always zero. */
        unsigned short  d_reclen;       /* Always zero. */
        unsigned short  d_namlen;       /* Length of name in d_name. */
+
+       /* The following exactly mimic the layout of _finddata_t ...
+        */
+       unsigned        d_type;         /* File attributes */
+       time_t          d_time_create;
+       time_t          d_time_access;  /* always midnight local time */
+       time_t          d_time_write;
+       _fsize_t        d_size;
+       /*
+        * ...so that we may map a union of _finddata_t at the
+        * location of d_type (corresponding to _finddata_t.attrib),
+        * and thus map this directly to the _findfirst/_findnext
+        * returned field.
+        */
        char            d_name[FILENAME_MAX]; /* File name. */
 };
 
@@ -31,7 +45,7 @@ struct dirent
  * This opaque data type represents the private structure
  * through which a directory stream is referenced.
  */
-typedef struct __dirstream_t DIR;
+typedef union __dirstream_t DIR;
 
 DIR* __cdecl __MINGW_NOTHROW opendir (const char*);
 struct dirent* __cdecl __MINGW_NOTHROW readdir (DIR*);
@@ -48,6 +62,20 @@ struct _wdirent
        long            d_ino;          /* Always zero. */
        unsigned short  d_reclen;       /* Always zero. */
        unsigned short  d_namlen;       /* Length of name in d_name. */
+
+       /* The following exactly mimic the layout of _wfinddata_t ...
+        */
+       unsigned        d_type;         /* File attributes */
+       time_t          d_time_create;  /* -1 for FAT file systems */
+       time_t          d_time_access;  /* -1 for FAT file systems */
+       time_t          d_time_write;
+       _fsize_t        d_size;
+       /*
+        * ...so that we may map a union of _wfinddata_t at the
+        * location of d_type (corresponding to _wfinddata_t.attrib),
+        * and thus map this directly to the _wfindfirst/_wfindnext
+        * returned field.
+        */
        wchar_t         d_name[FILENAME_MAX]; /* File name. */
 };
 
@@ -55,7 +83,7 @@ struct _wdirent
  * This opaque data type represents the private structure
  * through which a wide directory stream is referenced.
  */
-typedef struct __wdirstream_t _WDIR;
+typedef union __wdirstream_t _WDIR;
 
 _WDIR* __cdecl __MINGW_NOTHROW _wopendir (const wchar_t*);
 struct _wdirent*  __cdecl __MINGW_NOTHROW _wreaddir (_WDIR*);
@@ -69,6 +97,47 @@ void __cdecl __MINGW_NOTHROW _wseekdir (_WDIR*, long);
 }
 #endif
 
-#endif /* Not RC_INVOKED */
+#if defined(_BSD_SOURCE) || defined(_WIN32)
+/*
+ * BSD-ish systems define manifest constants for the d_type field;
+ * although probably only DT_REG and DT_DIR are useful on Win32, we
+ * try to map them as best we can from the _finddata.attrib field.
+ *
+ * The relevant Microsoft manifest values are:
+ *
+ *   _A_NORMAL (0x0000)        normal file: best fit for DT_REG
+ *   _A_RDONLY (0x0001)        read-only: no BSD d_type equivalent
+ *   _A_HIDDEN (0x0002)        hidden entity: no BSD equivalent
+ *   _A_SYSTEM (0x0004)        system entity: no BSD equivalent
+ *   _A_VOLID  (0x0008)        volume label: no BSD equivalent
+ *   _A_SUBDIR (0x0010)        directory: best fit for DT_DIR
+ *   _A_ARCH   (0x0020)        "dirty": no BSD equivalent
+ *
+ * Thus, we may immediately define:
+ */
+#define DT_REG         _A_NORMAL
+#define DT_DIR         _A_SUBDIR
+
+/* The remaining BSD d_type manifest values have no Win32 equivalents;
+ * we will define them artificially, and then we will ensure that our
+ * opendir()/readdir() implementation will never assign them; (we will
+ * substitute DT_UNKNOWN, but it would be unwise to simply make these
+ * equivalent to that, since an application is likely to simply check
+ * for d_type equal to any one of these defined types, and thus could
+ * mistakenly identify DT_UNKNOWN as being of the tested type):
+ */
+#define DT_BLK         (((_A_SUBDIR) << 4) | DT_UNKNOWN)
+#define DT_CHR         (((_A_SUBDIR) << 5) | DT_UNKNOWN)
+#define DT_FIFO        (((_A_SUBDIR) << 6) | DT_UNKNOWN)
+#define DT_LNK         (((_A_SUBDIR) << 7) | DT_UNKNOWN)
+#define DT_SOCK        (((_A_SUBDIR) << 8) | DT_UNKNOWN)
+
+/* No file system entity can ever be simultaneously a volume label
+ * and a directory; we will exploit this to unambiguously define:
+ */
+#define DT_UNKNOWN     (_A_VOLID | _A_SUBDIR)
+
+#endif  /* _BSD_SOURCE */
+#endif /* ! RC_INVOKED */
 
-#endif /* Not _DIRENT_H_ */
+#endif /* !defined _DIRENT_H_ */
index 0d3e54a09f03228f6f694e997a171082852c5d68..f35a88db7f8c687b7827d647ad849035287904be 100644 (file)
 #define SUFFIX _T("*")
 #define        SLASH   _T("\\")
 
-struct __dirstream_t
+union __dirstream_t
 {
   /* Actual (private) declaration for opaque data type "DIR". */
 
-    /* disk transfer area for this dir */
-    struct _finddata_t dd_dta;
+  /* dirent struct to return from dir (NOTE: this makes this thread
+   * safe as long as only one thread uses a particular DIR struct at
+   * a time) */
+  struct dirent        dd_dir;
+
+  struct __dirstream_private_t
+  {
+    /* Three padding fields, matching the head of dd_dir...
+     */
+    long               dd_ino;         /* Always zero. */
+    unsigned short     dd_reclen;      /* Always zero. */
+    unsigned short     dd_namlen;      /* Length of name in d_name. */
 
-    /* dirent struct to return from dir (NOTE: this makes this thread
-     * safe as long as only one thread uses a particular DIR struct at
-     * a time) */
-    struct dirent      dd_dir;
+    /* ...to keep the start of this disk transfer area for this dir
+     * aligned at the offset of the dd_dir.d_type field
+     */
+    struct _finddata_t dd_dta;
 
     /* _findnext handle */
     intptr_t           dd_handle;
 
-    /*
-     * Status of search:
+    /* Status of search:
      *   (type is now int -- was short in older versions).
      *   0 = not started yet (next entry to read is first entry)
      *  -1 = off the end
@@ -54,25 +63,36 @@ struct __dirstream_t
 
     /* given path for dir with search pattern (struct is extended) */
     char               dd_name[1];
+
+  } dd_private;
 };
 
-struct __wdirstream_t
+union __wdirstream_t
 {
   /* Actual (private) declaration for opaque data type "_WDIR". */
 
-    /* disk transfer area for this dir */
-    struct _wfinddata_t        dd_dta;
+  /* dirent struct to return from dir (NOTE: this makes this thread
+   * safe as long as only one thread uses a particular DIR struct at
+   * a time) */
+  struct _wdirent      dd_dir;
+
+  struct __wdirstream_private_t
+  {
+    /* Three padding fields, matching the head of dd_dir...
+     */
+    long               dd_ino;         /* Always zero. */
+    unsigned short     dd_reclen;      /* Always zero. */
+    unsigned short     dd_namlen;      /* Length of name in d_name. */
 
-    /* dirent struct to return from dir (NOTE: this makes this thread
-     * safe as long as only one thread uses a particular DIR struct at
-     * a time) */
-    struct _wdirent    dd_dir;
+    /* ...to keep the start of this disk transfer area for this dir
+     * aligned at the offset of the dd_dir.d_type field
+     */
+    struct _wfinddata_t        dd_dta;
 
     /* _findnext handle */
     intptr_t           dd_handle;
 
-    /*
-     * Status of search:
+    /* Status of search:
      *   0 = not started yet (next entry to read is first entry)
      *  -1 = off the end
      *   positive = 0 based index of next entry
@@ -81,8 +101,27 @@ struct __wdirstream_t
 
     /* given path for dir with search pattern (struct is extended) */
     wchar_t            dd_name[1];
+
+  } dd_private;
 };
 
+/* We map the BSD d_type field in the returned dirent structure
+ * from the Microsoft _finddata_t dd_dta.attrib bits, which are:
+ *
+ *   _A_NORMAL (0x0000)        normal file: best fit for DT_REG
+ *   _A_RDONLY (0x0001)        read-only: no BSD d_type equivalent
+ *   _A_HIDDEN (0x0002)        hidden entity: no BSD equivalent
+ *   _A_SYSTEM (0x0004)        system entity: no BSD equivalent
+ *   _A_VOLID  (0x0008)        volume label: no BSD equivalent
+ *   _A_SUBDIR (0x0010)        directory: best fit for DT_DIR
+ *   _A_ARCH   (0x0020)        "dirty": no BSD equivalent
+ *
+ * Of these, _A_RDONLY, _A_HIDDEN, _A_SYSTEM, and _A_ARCH are
+ * modifier bits, rather than true entity type specifiers; we
+ * will ignore them in the mapping, by applying this mask:
+ */
+#define DT_IGNORED     (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH)
+
 /* Helper for opendir().  */
 static inline unsigned _tGetFileAttributes (const _TCHAR * tPath)
 {
@@ -161,27 +200,27 @@ _topendir (const _TCHAR *szPath)
     }
 
   /* Create the search expression. */
-  _tcscpy (nd->dd_name, szFullPath);
+  _tcscpy (nd->dd_private.dd_name, szFullPath);
 
   /* Add on a slash if the path does not end with one. */
-  if (nd->dd_name[0] != _T('\0')
-      && _tcsrchr (nd->dd_name, _T('/')) != nd->dd_name
-                                           + _tcslen (nd->dd_name) - 1
-      && _tcsrchr (nd->dd_name, _T('\\')) != nd->dd_name
-                                            + _tcslen (nd->dd_name) - 1)
+  if (nd->dd_private.dd_name[0] != _T('\0')
+      && _tcsrchr (nd->dd_private.dd_name, _T('/')) != nd->dd_private.dd_name
+                                           + _tcslen (nd->dd_private.dd_name) - 1
+      && _tcsrchr (nd->dd_private.dd_name, _T('\\')) != nd->dd_private.dd_name
+                                            + _tcslen (nd->dd_private.dd_name) - 1)
     {
-      _tcscat (nd->dd_name, SLASH);
+      _tcscat (nd->dd_private.dd_name, SLASH);
     }
 
   /* Add on the search pattern */
-  _tcscat (nd->dd_name, SUFFIX);
+  _tcscat (nd->dd_private.dd_name, SUFFIX);
 
   /* Initialize handle to -1 so that a premature closedir doesn't try
    * to call _findclose on it. */
-  nd->dd_handle = -1;
+  nd->dd_private.dd_handle = -1;
 
   /* Initialize the status. */
-  nd->dd_stat = 0;
+  nd->dd_private.dd_stat = 0;
 
   /* Initialize the dirent structure. ino and reclen are invalid under
    * Win32, and name simply points at the appropriate part of the
@@ -213,33 +252,33 @@ _treaddir (_TDIR * dirp)
       return (struct _tdirent *) 0;
     }
 
-  if (dirp->dd_stat < 0)
+  if (dirp->dd_private.dd_stat < 0)
     {
       /* We have already returned all files in the directory
        * (or the structure has an invalid dd_stat). */
       return (struct _tdirent *) 0;
     }
-  else if (dirp->dd_stat == 0)
+  else if (dirp->dd_private.dd_stat == 0)
     {
       /* We haven't started the search yet. */
       /* Start the search */
-      dirp->dd_handle = _tfindfirst (dirp->dd_name, &(dirp->dd_dta));
+      dirp->dd_private.dd_handle = _tfindfirst (dirp->dd_private.dd_name, &(dirp->dd_private.dd_dta));
 
-      if (dirp->dd_handle == -1)
+      if (dirp->dd_private.dd_handle == -1)
        {
          /* Whoops! Seems there are no files in that
           * directory. */
-         dirp->dd_stat = -1;
+         dirp->dd_private.dd_stat = -1;
        }
       else
        {
-         dirp->dd_stat = 1;
+         dirp->dd_private.dd_stat = 1;
        }
     }
   else
     {
       /* Get the next search entry. */
-      if (_tfindnext (dirp->dd_handle, &(dirp->dd_dta)))
+      if (_tfindnext (dirp->dd_private.dd_handle, &(dirp->dd_private.dd_dta)))
        {
          /* We are off the end or otherwise error.     
             _findnext sets errno to ENOENT if no more file
@@ -247,25 +286,46 @@ _treaddir (_TDIR * dirp)
          DWORD winerr = GetLastError ();
          if (winerr == ERROR_NO_MORE_FILES)
            errno = 0;  
-         _findclose (dirp->dd_handle);
-         dirp->dd_handle = -1;
-         dirp->dd_stat = -1;
+         _findclose (dirp->dd_private.dd_handle);
+         dirp->dd_private.dd_handle = -1;
+         dirp->dd_private.dd_stat = -1;
        }
       else
        {
          /* Update the status to indicate the correct
           * number. */
-         dirp->dd_stat++;
+         dirp->dd_private.dd_stat++;
        }
     }
 
-  if (dirp->dd_stat > 0)
+  if (dirp->dd_private.dd_stat > 0)
     {
       /* Successfully got an entry. Everything about the file is
        * already appropriately filled in except the length of the
-       * file name. */
-      dirp->dd_dir.d_namlen = _tcslen (dirp->dd_dta.name);
-      _tcscpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
+       * file name...
+       */
+      dirp->dd_dir.d_namlen = _tcslen (dirp->dd_dir.d_name);
+      /*
+       * ...and the attributes returned in the dd_dta.attrib field;
+       * these require adjustment to their BSD equivalents, which are
+       * returned via the union with the dd_dir.d_type field:
+       */
+      switch( dirp->dd_dir.d_type &= ~DT_IGNORED )
+       {
+         case DT_REG:
+         case DT_DIR:
+           /* After stripping out the modifier bits in DT_IGNORED,
+            * (which we ALWAYS ignore), this pair require no further
+            * adjustment...
+            */
+           break;
+
+         default:
+           /* ...while nothing else has an appropriate equivalent
+            * in the BSD d_type identification model.
+            */
+           dirp->dd_dir.d_type = DT_UNKNOWN;
+       }
       return &dirp->dd_dir;
     }
 
@@ -292,9 +352,9 @@ _tclosedir (_TDIR * dirp)
       return -1;
     }
 
-  if (dirp->dd_handle != -1)
+  if (dirp->dd_private.dd_handle != -1)
     {
-      rc = _findclose (dirp->dd_handle);
+      rc = _findclose (dirp->dd_private.dd_handle);
     }
 
   /* Delete the dir structure. */
@@ -320,13 +380,13 @@ _trewinddir (_TDIR * dirp)
       return;
     }
 
-  if (dirp->dd_handle != -1)
+  if (dirp->dd_private.dd_handle != -1)
     {
-      _findclose (dirp->dd_handle);
+      _findclose (dirp->dd_private.dd_handle);
     }
 
-  dirp->dd_handle = -1;
-  dirp->dd_stat = 0;
+  dirp->dd_private.dd_handle = -1;
+  dirp->dd_private.dd_stat = 0;
 }
 
 /*
@@ -345,7 +405,7 @@ _ttelldir (_TDIR * dirp)
       errno = EFAULT;
       return -1;
     }
-  return dirp->dd_stat;
+  return dirp->dd_private.dd_stat;
 }
 
 /*
@@ -377,19 +437,19 @@ _tseekdir (_TDIR * dirp, long lPos)
   else if (lPos == -1)
     {
       /* Seek past end. */
-      if (dirp->dd_handle != -1)
+      if (dirp->dd_private.dd_handle != -1)
        {
-         _findclose (dirp->dd_handle);
+         _findclose (dirp->dd_private.dd_handle);
        }
-      dirp->dd_handle = -1;
-      dirp->dd_stat = -1;
+      dirp->dd_private.dd_handle = -1;
+      dirp->dd_private.dd_stat = -1;
     }
   else
     {
       /* Rewind and read forward to the appropriate index. */
       _trewinddir (dirp);
 
-      while ((dirp->dd_stat < lPos) && _treaddir (dirp))
+      while ((dirp->dd_private.dd_stat < lPos) && _treaddir (dirp))
        ;
     }
 }
This page took 0.049118 seconds and 5 git commands to generate.