mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-06 07:41:17 +00:00
dirent.c and dirent.h brought in from cygwin for win32 builds
This commit is contained in:
parent
d0a95aba9d
commit
0d755a0dd6
3 changed files with 252 additions and 100 deletions
|
@ -161,6 +161,9 @@ if test "x$mingw" = xyes; then
|
||||||
AC_MSG_CHECKING(for fnmatch.h)
|
AC_MSG_CHECKING(for fnmatch.h)
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_FNMATCH_H, 1, [Define this if you have fnmatch.h])
|
AC_DEFINE(HAVE_FNMATCH_H, 1, [Define this if you have fnmatch.h])
|
||||||
|
AC_MSG_CHECKING(for tchar.h)
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_TCHAR_H, 1, [Define this if you have tchar.h])
|
||||||
else
|
else
|
||||||
AC_CHECK_HEADERS(fnmatch.h)
|
AC_CHECK_HEADERS(fnmatch.h)
|
||||||
fi
|
fi
|
||||||
|
|
138
include/win32/dirent.h
Normal file
138
include/win32/dirent.h
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* DIRENT.H (formerly DIRLIB.H)
|
||||||
|
*
|
||||||
|
* by M. J. Weinstein Released to public domain 1-Jan-89
|
||||||
|
*
|
||||||
|
* Because I have heard that this feature (opendir, readdir, closedir)
|
||||||
|
* it so useful for programmers coming from UNIX or attempting to port
|
||||||
|
* UNIX code, and because it is reasonably light weight, I have included
|
||||||
|
* it in the Mingw32 package. I have also added an implementation of
|
||||||
|
* rewinddir, seekdir and telldir.
|
||||||
|
* - Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that is will be useful but
|
||||||
|
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
|
||||||
|
* DISCLAIMED. This includeds but is not limited to warranties of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* $Revision$
|
||||||
|
* $Author$
|
||||||
|
* $Date$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __STRICT_ANSI__
|
||||||
|
|
||||||
|
#ifndef _DIRENT_H_
|
||||||
|
#define _DIRENT_H_
|
||||||
|
|
||||||
|
/* All the headers include this file. */
|
||||||
|
#include <_mingw.h>
|
||||||
|
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#ifndef RC_INVOKED
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct dirent {
|
||||||
|
long d_ino; /* Always zero. */
|
||||||
|
unsigned short d_reclen; /* Always zero. */
|
||||||
|
unsigned short d_namlen; /* Length of name in d_name. */
|
||||||
|
char d_name[FILENAME_MAX]; /* File name. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an internal data structure. Good programmers will not use it
|
||||||
|
* except as an argument to one of the functions below.
|
||||||
|
* dd_stat field is now int (was short in older versions).
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* _findnext handle */
|
||||||
|
long 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) */
|
||||||
|
char dd_name[1];
|
||||||
|
} DIR;
|
||||||
|
|
||||||
|
DIR *__cdecl opendir (const char *);
|
||||||
|
struct dirent *__cdecl readdir (DIR *);
|
||||||
|
int __cdecl closedir (DIR *);
|
||||||
|
void __cdecl rewinddir (DIR *);
|
||||||
|
long __cdecl telldir (DIR *);
|
||||||
|
void __cdecl seekdir (DIR *, long);
|
||||||
|
|
||||||
|
|
||||||
|
/* wide char versions */
|
||||||
|
|
||||||
|
struct _wdirent {
|
||||||
|
long d_ino; /* Always zero. */
|
||||||
|
unsigned short d_reclen; /* Always zero. */
|
||||||
|
unsigned short d_namlen; /* Length of name in d_name. */
|
||||||
|
wchar_t d_name[FILENAME_MAX]; /* File name. */
|
||||||
|
/* NOTE: The name in the dirent structure points to the name in
|
||||||
|
the * wfinddata_t structure in the _WDIR. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an internal data structure. Good programmers will not use it
|
||||||
|
* except as an argument to one of the functions below.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* _findnext handle */
|
||||||
|
long 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];
|
||||||
|
} _WDIR;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_WDIR *__cdecl _wopendir (const wchar_t *);
|
||||||
|
struct _wdirent *__cdecl _wreaddir (_WDIR *);
|
||||||
|
int __cdecl _wclosedir (_WDIR *);
|
||||||
|
void __cdecl _wrewinddir (_WDIR *);
|
||||||
|
long __cdecl _wtelldir (_WDIR *);
|
||||||
|
void __cdecl _wseekdir (_WDIR *, long);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* Not RC_INVOKED */
|
||||||
|
#endif /* Not _DIRENT_H_ */
|
||||||
|
#endif /* Not __STRICT_ANSI__ */
|
|
@ -9,8 +9,12 @@
|
||||||
* Significantly revised and rewinddir, seekdir and telldir added by Colin
|
* Significantly revised and rewinddir, seekdir and telldir added by Colin
|
||||||
* Peters <colin@fu.is.saga-u.ac.jp>
|
* Peters <colin@fu.is.saga-u.ac.jp>
|
||||||
*
|
*
|
||||||
|
* $Revision$
|
||||||
|
* $Author$
|
||||||
|
* $Date$
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,168 +22,175 @@
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
static __attribute__ ((unused)) const char rcsid[] =
|
||||||
"$Id$";
|
"$Id$";
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <io.h>
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#define SUFFIX "*"
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define SLASH "\\"
|
#include <windows.h> /* for GetFileAttributes */
|
||||||
|
|
||||||
#ifndef S_ISDIR
|
|
||||||
#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) /* is a directory */
|
|
||||||
#endif//S_ISDIR
|
|
||||||
|
|
||||||
|
#include <tchar.h>
|
||||||
|
#define SUFFIX _T("*")
|
||||||
|
#define SLASH _T("\\")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
opendir
|
* opendir
|
||||||
|
*
|
||||||
Returns a pointer to a DIR structure appropriately filled in to begin
|
* Returns a pointer to a DIR structure appropriately filled in to begin
|
||||||
searching a directory.
|
* searching a directory.
|
||||||
*/
|
*/
|
||||||
DIR *
|
_TDIR *
|
||||||
opendir (const char *szPath)
|
_topendir (const _TCHAR * szPath)
|
||||||
{
|
{
|
||||||
DIR *nd;
|
_TDIR *nd;
|
||||||
struct _stat statDir;
|
unsigned int rc;
|
||||||
|
_TCHAR szFullPath[MAX_PATH];
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if (!szPath) {
|
if (!szPath) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
return (DIR *) 0;
|
return (_TDIR *) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szPath[0] == '\0') {
|
if (szPath[0] == _T ('\0')) {
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
return (DIR *) 0;
|
return (_TDIR *) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to determine if the given path really is a directory. */
|
/* Attempt to determine if the given path really is a directory. */
|
||||||
if (_stat (szPath, &statDir)) {
|
rc = GetFileAttributes (szPath);
|
||||||
/* Error, stat should have set an error value. */
|
if (rc == (unsigned int) -1) {
|
||||||
return (DIR *) 0;
|
/* call GetLastError for more error info */
|
||||||
|
errno = ENOENT;
|
||||||
|
return (_TDIR *) 0;
|
||||||
}
|
}
|
||||||
|
if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
if (!S_ISDIR (statDir.st_mode)) {
|
/* Error, entry exists but not a directory. */
|
||||||
/* Error, stat reports not a directory. */
|
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
return (DIR *) 0;
|
return (_TDIR *) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate enough space to store DIR structure and the complete *
|
/* Make an absolute pathname. */
|
||||||
|
_tfullpath (szFullPath, szPath, MAX_PATH);
|
||||||
|
|
||||||
|
/* Allocate enough space to store DIR structure and the complete
|
||||||
directory path given. */
|
directory path given. */
|
||||||
nd = (DIR *) calloc (1, sizeof (DIR) + strlen (szPath) + strlen (SLASH) +
|
nd = (_TDIR *) malloc (sizeof (_TDIR) +
|
||||||
strlen (SUFFIX));
|
(_tcslen (szFullPath) + _tcslen (SLASH) +
|
||||||
|
_tcslen (SUFFIX) + 1) * sizeof (_TCHAR));
|
||||||
|
|
||||||
if (!nd) {
|
if (!nd) {
|
||||||
/* Error, out of memory. */
|
/* Error, out of memory. */
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return (DIR *) 0;
|
return (_TDIR *) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the search expression. */
|
/* Create the search expression. */
|
||||||
strcpy (nd->dd_name, szPath);
|
_tcscpy (nd->dd_name, szFullPath);
|
||||||
|
|
||||||
/* Add on a slash if the path does not end with one. */
|
/* Add on a slash if the path does not end with one. */
|
||||||
if (nd->dd_name[0] != '\0' &&
|
if (nd->dd_name[0] != _T ('\0') &&
|
||||||
nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
|
nd->dd_name[_tcslen (nd->dd_name) - 1] != _T ('/') &&
|
||||||
nd->dd_name[strlen (nd->dd_name) - 1] != '\\') {
|
nd->dd_name[_tcslen (nd->dd_name) - 1] != _T ('\\')) {
|
||||||
strcat (nd->dd_name, SLASH);
|
_tcscat (nd->dd_name, SLASH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add on the search pattern */
|
/* Add on the search pattern */
|
||||||
strcat (nd->dd_name, SUFFIX);
|
_tcscat (nd->dd_name, SUFFIX);
|
||||||
|
|
||||||
/* Initialize handle to -1 so that a premature closedir doesn't try * to
|
/* Initialize handle to -1 so that a premature closedir doesn't try to
|
||||||
call _findclose on it. */
|
call _findclose on it. */
|
||||||
nd->dd_handle = -1;
|
nd->dd_handle = -1;
|
||||||
|
|
||||||
/* Initialize the status. */
|
/* Initialize the status. */
|
||||||
nd->dd_stat = 0;
|
nd->dd_stat = 0;
|
||||||
|
|
||||||
/* Initialize the dirent structure. ino and reclen are invalid under *
|
/* Initialize the dirent structure. ino and reclen are invalid under
|
||||||
Win32, and name simply points at the appropriate part of the *
|
Win32, and name simply points at the appropriate part of the
|
||||||
findfirst_t structure. */
|
findfirst_t structure. */
|
||||||
nd->dd_dir.d_ino = 0;
|
nd->dd_dir.d_ino = 0;
|
||||||
nd->dd_dir.d_reclen = 0;
|
nd->dd_dir.d_reclen = 0;
|
||||||
nd->dd_dir.d_namlen = 0;
|
nd->dd_dir.d_namlen = 0;
|
||||||
nd->dd_dir.d_name = nd->dd_dta.name;
|
memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
|
||||||
|
|
||||||
return nd;
|
return nd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
readdir
|
|
||||||
|
|
||||||
Return a pointer to a dirent structure filled with the information on the
|
/*
|
||||||
next entry in the directory.
|
* readdir
|
||||||
|
*
|
||||||
|
* Return a pointer to a dirent structure filled with the information on the
|
||||||
|
* next entry in the directory.
|
||||||
*/
|
*/
|
||||||
struct dirent *
|
struct _tdirent *
|
||||||
readdir (DIR * dirp)
|
_treaddir (_TDIR * dirp)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
/* Check for valid DIR struct. */
|
/* Check for valid DIR struct. */
|
||||||
if (!dirp) {
|
if (!dirp) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
return (struct dirent *) 0;
|
return (struct _tdirent *) 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (dirp->dd_dir.d_name != dirp->dd_dta.name) {
|
|
||||||
/* The structure does not seem to be set up correctly. */
|
|
||||||
errno = EINVAL;
|
|
||||||
return (struct dirent *) 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirp->dd_stat < 0) {
|
if (dirp->dd_stat < 0) {
|
||||||
/* We have already returned all files in the directory * (or the
|
/* We have already returned all files in the directory (or the
|
||||||
structure has an invalid dd_stat). */
|
structure has an invalid dd_stat). */
|
||||||
return (struct dirent *) 0;
|
return (struct _tdirent *) 0;
|
||||||
} else if (dirp->dd_stat == 0) {
|
} else if (dirp->dd_stat == 0) {
|
||||||
/* We haven't started the search yet. */
|
/* We haven't started the search yet. */
|
||||||
/* Start the search */
|
/* Start the search */
|
||||||
dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta));
|
dirp->dd_handle = _tfindfirst (dirp->dd_name, &(dirp->dd_dta));
|
||||||
|
|
||||||
if (dirp->dd_handle == -1) {
|
if (dirp->dd_handle == -1) {
|
||||||
/* Whoops! Seems there are no files in that * directory. */
|
/* Whoops! Seems there are no files in that directory. */
|
||||||
dirp->dd_stat = -1;
|
dirp->dd_stat = -1;
|
||||||
} else {
|
} else {
|
||||||
dirp->dd_stat = 1;
|
dirp->dd_stat = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Get the next search entry. */
|
/* Get the next search entry. */
|
||||||
if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) {
|
if (_tfindnext (dirp->dd_handle, &(dirp->dd_dta))) {
|
||||||
/* We are off the end or otherwise error. */
|
/* We are off the end or otherwise error. _findnext
|
||||||
|
sets errno to ENOENT if no more file Undo this. */
|
||||||
|
DWORD winerr = GetLastError ();
|
||||||
|
|
||||||
|
if (winerr == ERROR_NO_MORE_FILES)
|
||||||
|
errno = 0;
|
||||||
_findclose (dirp->dd_handle);
|
_findclose (dirp->dd_handle);
|
||||||
dirp->dd_handle = -1;
|
dirp->dd_handle = -1;
|
||||||
dirp->dd_stat = -1;
|
dirp->dd_stat = -1;
|
||||||
} else {
|
} else {
|
||||||
/* Update the status to indicate the correct * number. */
|
/* Update the status to indicate the correct number. */
|
||||||
dirp->dd_stat++;
|
dirp->dd_stat++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirp->dd_stat > 0) {
|
if (dirp->dd_stat > 0) {
|
||||||
/* Successfully got an entry. Everything about the file is * already
|
/* Successfully got an entry. Everything about the file is
|
||||||
appropriately filled in except the length of the * file name. */
|
already appropriately filled in except the length of the
|
||||||
dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
|
file name. */
|
||||||
|
dirp->dd_dir.d_namlen = _tcslen (dirp->dd_dta.name);
|
||||||
|
_tcscpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
|
||||||
return &dirp->dd_dir;
|
return &dirp->dd_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct dirent *) 0;
|
return (struct _tdirent *) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
closedir
|
|
||||||
|
|
||||||
Frees up resources allocated by opendir.
|
/*
|
||||||
|
* closedir
|
||||||
|
*
|
||||||
|
* Frees up resources allocated by opendir.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
closedir (DIR * dirp)
|
_tclosedir (_TDIR * dirp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -202,13 +213,13 @@ closedir (DIR * dirp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
rewinddir
|
* rewinddir
|
||||||
|
*
|
||||||
Return to the beginning of the directory "stream". We simply call findclose
|
* Return to the beginning of the directory "stream". We simply call findclose
|
||||||
and then reset things like an opendir.
|
* and then reset things like an opendir.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
rewinddir (DIR * dirp)
|
_trewinddir (_TDIR * dirp)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
@ -226,13 +237,13 @@ rewinddir (DIR * dirp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
telldir
|
* telldir
|
||||||
|
*
|
||||||
Returns the "position" in the "directory stream" which can be used with
|
* Returns the "position" in the "directory stream" which can be used with
|
||||||
seekdir to go back to an old entry. We simply return the value in stat.
|
* seekdir to go back to an old entry. We simply return the value in stat.
|
||||||
*/
|
*/
|
||||||
long
|
long
|
||||||
telldir (DIR * dirp)
|
_ttelldir (_TDIR * dirp)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
@ -244,16 +255,16 @@ telldir (DIR * dirp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
seekdir
|
* seekdir
|
||||||
|
*
|
||||||
Seek to an entry previously returned by telldir. We rewind the directory
|
* Seek to an entry previously returned by telldir. We rewind the directory
|
||||||
and call readdir repeatedly until either dd_stat is the position number
|
* and call readdir repeatedly until either dd_stat is the position number
|
||||||
or -1 (off the end). This is not perfect, in that the directory may
|
* or -1 (off the end). This is not perfect, in that the directory may
|
||||||
have changed while we weren't looking. But that is probably the case with
|
* have changed while we weren't looking. But that is probably the case with
|
||||||
any such system.
|
* any such system.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
seekdir (DIR * dirp, long lPos)
|
_tseekdir (_TDIR * dirp, long lPos)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
@ -275,8 +286,8 @@ seekdir (DIR * dirp, long lPos)
|
||||||
dirp->dd_stat = -1;
|
dirp->dd_stat = -1;
|
||||||
} else {
|
} else {
|
||||||
/* Rewind and read forward to the appropriate index. */
|
/* Rewind and read forward to the appropriate index. */
|
||||||
rewinddir (dirp);
|
_trewinddir (dirp);
|
||||||
|
|
||||||
while ((dirp->dd_stat < lPos) && readdir (dirp));
|
while ((dirp->dd_stat < lPos) && _treaddir (dirp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue