Rationalise structure layout; add dirent.d_type field.
This commit is contained in:
parent
341bf73d6d
commit
35ddfc9e28
@ -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.
|
||||
@ -3071,7 +3097,7 @@
|
||||
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>
|
||||
|
||||
|
@ -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
|
||||
|
||||
#endif /* Not _DIRENT_H_ */
|
||||
/* 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 /* !defined _DIRENT_H_ */
|
||||
|
@ -28,23 +28,32 @@
|
||||
#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;
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* ...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;
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* ...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))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user