summaryrefslogtreecommitdiffstats
path: root/winsup/mingw/mingwex/dirent.c
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/mingw/mingwex/dirent.c')
-rw-r--r--winsup/mingw/mingwex/dirent.c468
1 files changed, 0 insertions, 468 deletions
diff --git a/winsup/mingw/mingwex/dirent.c b/winsup/mingw/mingwex/dirent.c
deleted file mode 100644
index a6b37408b..000000000
--- a/winsup/mingw/mingwex/dirent.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * dirent.c
- *
- * This file has no copyright assigned and is placed in the Public Domain.
- *
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
- *
- * Derived from DIRLIB.C by Matt J. Weinstein
- * This note appears in the DIRLIB.H
- * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
- *
- * Updated by Jeremy Bettis <jeremy@hksys.com>
- * Significantly revised and rewinddir, seekdir and telldir added
- * by Colin Peters <colin@fu.is.saga-u.ac.jp>
- * Further significantly revised for improved memory utilisation,
- * efficiency in operation, and better POSIX standards compliance
- * by Keith Marshall <keithmarshall@users.sourceforge.net>
- *
- */
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <io.h>
-#include <dirent.h>
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-
-#define DIRENT_RETURN_NOTHING
-#define DIRENT_REJECT( chk, err, rtn ) \
- do { if( chk ){ errno = (err); return rtn; }} while(0)
-
-union __dirstream_t
-{
- /* Actual (private) declaration for opaque data type "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:
- * (type is now int -- was short in older versions).
- * 0 = not started yet (next entry to read is first entry)
- * -1 = off the end
- * positive = 0 based index of next entry
- */
- int dd_stat;
-
- /* given path for dir with search pattern (struct is extended) */
- char dd_name[1];
-
- } dd_private;
-};
-
-union __wdirstream_t
-{
- /* Actual (private) declaration for opaque data type "_WDIR". */
-
- /* 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:
- * 0 = not started yet (next entry to read is first entry)
- * -1 = off the end
- * positive = 0 based index of next entry
- */
- int dd_stat;
-
- /* 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)
-
-#define DIRENT_OPEN(D) \
- ((D).dd_handle = _tfindfirst((D).dd_name, &((D).dd_dta)))
-
-#define DIRENT_UPDATE(D) \
- _tfindnext( (D).dd_handle, &(D).dd_dta )
-
-
-/*****
- *
- * opendir()
- *
- * Returns a pointer to a DIR structure appropriately filled in
- * to begin searching a directory.
- *
- */
-_TDIR *
-_topendir( const _TCHAR *path_name )
-{
- _TDIR *nd;
- _TCHAR abs_path[MAX_PATH];
-
- /* Reject any request which passes a NULL or an empty path name;
- * note that POSIX doesn't specify the handling for the NULL case,
- * and some implementations may simply fail with a segmentation
- * fault. We will fail more gracefully. Previous versions used
- * EFAULT here, but EINVAL seems more appropriate; however, POSIX
- * specifies neither of these for any opendir() failure.
- */
- DIRENT_REJECT( (path_name == NULL), EINVAL, (_TDIR *)(NULL) );
- /*
- * Conversely, POSIX *does* specify ENOENT for the empty path
- * name case, where we previously had ENOTDIR; here, we correct
- * this previous anomaly.
- */
- DIRENT_REJECT( (*path_name == _T('\0')), ENOENT, (_TDIR *)(NULL) );
-
- /* Identify the absolute path name corresponding to the (maybe
- * relative) path name we are to process; (this ensures that we
- * may always refer back to this same path name, e.g. to rewind
- * the "directory stream", even after an intervening change of
- * current working directory).
- */
- _tfullpath( abs_path, path_name, MAX_PATH );
-
- /* Ensure that the generated absolute path name ends with a
- * directory separator (backslash) character, so that we may
- * correctly append a wild-card matching pattern which will
- * cause _findfirst() and _findnext() to return every entry
- * in the specified directory; (note that, for now we may
- * simply assume that abs_path refers to a directory;
- * we will verify that when we call _findfirst() on it).
- */
- if( *abs_path != _T('\0') )
- {
- size_t offset = _tcslen( abs_path ) - 1;
- if( (abs_path[offset] != _T('/')) && (abs_path[offset] != _T('\\')) )
- _tcscat( abs_path, _T("\\") );
- }
-
- /* Now append the "match everything" wild-card pattern.
- */
- _tcscat( abs_path, _T("*") );
-
- /* Allocate space to store DIR structure. The size MUST be
- * adjusted to accommodate the complete absolute path name for
- * the specified directory, extended to include the wild-card
- * matching pattern, as above; (note that we DO NOT need any
- * special provision for the terminating NUL on the path name,
- * since the base size of the DIR structure includes it).
- */
- nd = (_TDIR *)(malloc(
- sizeof( _TDIR ) + (_tcslen( abs_path ) * sizeof( _TCHAR ))
- ));
-
- /* Bail out, if insufficient memory.
- */
- DIRENT_REJECT( (nd == NULL), ENOMEM, (_TDIR *)(NULL) );
-
- /* Copy the extended absolute path name string into place
- * within the allocated space for the DIR structure.
- */
- _tcscpy( nd->dd_private.dd_name, abs_path );
-
- /* Initialize the "directory stream", by calling _findfirst() on it;
- * this leaves the data for the first directory entry in the internal
- * dirent buffer, ready to be retrieved by readdir().
- */
- if( DIRENT_OPEN( nd->dd_private ) == (intptr_t)(-1) )
- {
- /* The _findfirst() call, (implied by DIRENT_OPEN), failed;
- * _findfirst() sets EINVAL where POSIX mandates ENOTDIR...
- */
- if( errno == EINVAL )
- errno = ENOTDIR;
-
- /* ...otherwise, while it may not be strictly POSIX conformant,
- * just accept whatever value _findfirst() assigned to errno. In
- * any event, prepare to return the NULL "directory stream"; since
- * this implies that we will lose our reference pointer to the
- * block of memory we allocated for the stream, free that
- * before we bail out.
- */
- free( nd );
- return (_TDIR *)(NULL);
- }
-
- /* Initialize the status, (i.e. the location index), so that
- * readdir() will simply return the first directory entry, which
- * has already been fetched by _findfirst(), without performing
- * an intervening _findnext() call.
- */
- nd->dd_private.dd_stat = 0;
-
- /* The d_ino and d_reclen fields have no relevance in MS-Windows;
- * initialize them to zero, as a one-time assignment for this DIR
- * instance, and henceforth forget them; (users should simply
- * ignore them).
- */
- nd->dd_dir.d_ino = 0;
- nd->dd_dir.d_reclen = 0;
-
- /* We've now completely initialized an instance of a DIR structure,
- * representing the requested "directory stream"; return a pointer
- * via which the caller may access it.
- */
- return nd;
-}
-
-
-/*****
- *
- * readdir()
- *
- * Return a pointer to a dirent structure filled in with information
- * on the next available entry, (if any), in the "directory stream".
- */
-struct _tdirent *
-_treaddir( _TDIR *dirp )
-{
- /* Check for a valid DIR stream reference; (we can't really
- * be certain until we try to read from it, except in the case
- * of a NULL pointer reference). Where we lack a valid reference,
- * POSIX mandates reporting EBADF; we previously had EFAULT, so
- * this version corrects the former anomaly.
- */
- DIRENT_REJECT( (dirp == NULL), EBADF, (struct _tdirent *)(NULL) );
-
- /* Okay to proceed. If this is the first readdir() request
- * following an opendir(), or a rewinddir(), then we already
- * have the requisite return information...
- */
- if( dirp->dd_private.dd_stat++ > 0 )
- {
- /* Otherwise...
- *
- * Get the next search entry. POSIX mandates that this must
- * return NULL after the last entry has been read, but that it
- * MUST NOT change errno in this case. MS-Windows _findnext()
- * DOES change errno (to ENOENT) after the last entry has been
- * read, so we must be prepared to restore it to its previous
- * value, when no actual error has occurred.
- */
- int prev_errno = errno;
- if( DIRENT_UPDATE( dirp->dd_private ) != 0 )
- {
- /* May be an error, or just the case described above...
- */
- if( GetLastError() == ERROR_NO_MORE_FILES )
- /*
- * ...which requires us to reset errno.
- */
- errno = prev_errno;
-
- /* In either case, there is no valid data to return.
- */
- return (struct _tdirent *)(NULL);
- }
- }
-
- /* Successfully got an entry. Everything about the file is
- * already appropriately filled in, except for the length of
- * the file name in the d_namlen field...
- */
- 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;
-}
-
-
-/*****
- *
- * closedir()
- *
- * Frees up resources allocated by opendir().
- *
- */
-int
-_tclosedir( _TDIR * dirp )
-{
- /* Attempting to reference a directory stream via a NULL pointer
- * would cause a segmentation fault; evade this. Since NULL can
- * never represent an open directory stream, set the EBADF errno
- * status, as mandated by POSIX, once again correcting previous
- * anomalous use of EFAULT in this context.
- */
- DIRENT_REJECT(
- ((dirp == NULL) || (_findclose( dirp->dd_private.dd_handle ) != 0)),
- EBADF, -1
- );
-
- /* If we didn't bail out above, we have a valid DIR structure
- * with which we have finished; release the memory allocated
- * to it, before returning "success".
- */
- free( dirp );
- return 0;
-}
-
-
-/*****
- *
- * rewinddir()
- *
- * Return to the beginning of the directory "stream". We simply call
- * _findclose(), to clear prior context, then _findfirst() to restart
- * the directory search, resetting the location index appropriately,
- * as it would be left by opendir().
- *
- */
-void
-_trewinddir( _TDIR * dirp )
-{
- /* This is an XSI extension to POSIX, which specifies no formal
- * error conditions; we will continue to check for and evade the
- * potential segmentation fault which would result from passing a
- * NULL reference pointer. For consistency with the core functions
- * implemented above, we will again report this as EBADF, rather
- * than the EFAULT of previous versions.
- */
- DIRENT_REJECT(
- ((dirp == NULL) || (_findclose( dirp->dd_private.dd_handle ) != 0)),
- EBADF, DIRENT_RETURN_NOTHING
- );
-
- /* We successfully closed the prior search context; reopen...
- */
- if( DIRENT_OPEN( dirp->dd_private ) != (intptr_t)(-1) )
- /*
- * ...and, on success, reset the location index.
- */
- dirp->dd_private.dd_stat = 0;
-}
-
-
-/*****
- *
- * telldir()
- *
- * Returns the "position" in the "directory stream" which can then
- * be passed to seekdir(), to return back to a previous entry. We
- * simply return the current location index from the dd_stat field.
- *
- */
-long
-_ttelldir( _TDIR * dirp )
-{
- /* This too is a POSIX-XSI extension, with no mandatory error
- * conditions. Once again, evade a potential segmentation fault
- * on passing a NULL reference pointer, again reporting it as
- * EBADF in preference to the EFAULT of previous versions.
- */
- DIRENT_REJECT( (dirp == NULL), EBADF, -1 );
-
- /* We didn't bail out; just assume dirp is valid, and return
- * the location index from the dd_stat field.
- */
- return dirp->dd_private.dd_stat;
-}
-
-
-/*****
- *
- * seekdir()
- *
- * Seek to an entry previously returned by telldir(). We rewind
- * the "directory stream", then repeatedly call _findnext() while
- * incrementing its internal location index until it matches the
- * position requested, or we reach the end of the stream. This is
- * not perfect, in that the directory may have changed while we
- * weren't looking, but it is the best we can achieve, and may
- * likely reproduce the behaviour of other implementations.
- *
- */
-void
-_tseekdir( _TDIR * dirp, long loc )
-{
- /* Another POSIX-XSI extension, with no specified mandatory
- * error conditions; we require a seek location of zero or
- * greater, and will reject less than zero as EINVAL...
- */
- DIRENT_REJECT( (loc < 0L), EINVAL, DIRENT_RETURN_NOTHING );
-
- /* Other than this, we simply accept any error condition
- * which arises as we "rewind" the "directory stream"...
- */
- _trewinddir( dirp );
-
- /* ...and, if this is successful...
- */
- if( (loc > 0) && (dirp->dd_private.dd_handle != (intptr_t)(-1)) )
- /*
- * ...seek forward until the location index within
- * the DIR structure matches the requested location.
- */
- while( (++dirp->dd_private.dd_stat < loc)
- && (DIRENT_UPDATE( dirp->dd_private ) == 0) )
- ;
-}
-
-/* $RCSfile$: end of file */