From b7b6625e9c773bf5078369e7aa3b0a278d9bc949 Mon Sep 17 00:00:00 2001 From: sezero Date: Mon, 30 Aug 2010 13:50:28 +0000 Subject: [PATCH] updated dirent.[ch] from mingw-w64. git-svn-id: svn+ssh://svn.code.sf.net/p/quakespasm/code/trunk@316 af15c1b1-3010-417e-b628-4374ebc0bcbd --- quakespasm/Windows/VisualStudio/dirent.c | 459 ++++++++++++++++------- quakespasm/Windows/VisualStudio/dirent.h | 150 ++++++-- 2 files changed, 448 insertions(+), 161 deletions(-) diff --git a/quakespasm/Windows/VisualStudio/dirent.c b/quakespasm/Windows/VisualStudio/dirent.c index ef61c64f..9adec169 100644 --- a/quakespasm/Windows/VisualStudio/dirent.c +++ b/quakespasm/Windows/VisualStudio/dirent.c @@ -1,147 +1,342 @@ /* + * 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 + * Significantly revised and rewinddir, seekdir and telldir added by Colin + * Peters + * + */ - Implementation of POSIX directory browsing functions and types for Win32. +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif - Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) - History: Created March 1997. Updated June 2003. - Rights: See end of file. - -*/ - -#include /* for intptr_t under MSVC */ -/*#include */ -#include -#include -#include /* _findfirst and _findnext set errno if they return -1 */ #include +#include #include +#include +#include +#include -#ifdef __cplusplus -extern "C" +#include /* for GetFileAttributes */ + +#include +#define SUFFIX _T("*") +#define SLASH _T("\\") + + +/* Helper for opendir(). */ +static __inline DWORD _tGetFileAttributes (const _TCHAR * tPath) { +#ifdef _UNICODE + /* GetFileAttributesW does not work on W9x, so convert to ANSI */ + if (_osver & 0x8000) + { + char aPath [MAX_PATH]; + WideCharToMultiByte (CP_ACP, 0, tPath, -1, aPath, MAX_PATH, NULL, NULL); + return GetFileAttributesA (aPath); + } + return GetFileAttributesW (tPath); +#else + return GetFileAttributesA (tPath); #endif - -struct DIR -{ - intptr_t handle; /* -1 for failed rewind */ - struct _finddata_t info; - struct dirent result; /* d_name null iff first time */ - char *name; /* null-terminated char string */ -}; - -DIR *opendir(const char *name) -{ - DIR *dir = 0; - - if(name && name[0]) - { - size_t base_length = strlen(name); - const char *all = /* search pattern must end with suitable wildcard */ - strchr("/\\", name[base_length - 1]) ? "*" : "/*"; - - if((dir = (DIR *) malloc(sizeof *dir)) != 0 && - (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0) - { - strcat(strcpy(dir->name, name), all); - - if((dir->handle = _findfirst(dir->name, &dir->info)) != -1) - { - dir->result.d_name = 0; - } - else /* rollback */ - { - free(dir->name); - free(dir); - dir = 0; - } - } - else /* rollback */ - { - free(dir); - dir = 0; - errno = ENOMEM; - } - } - else - { - errno = EINVAL; - } - - return dir; } -int closedir(DIR *dir) -{ - int result = -1; - - if(dir) - { - if(dir->handle != -1) - { - result = _findclose(dir->handle); - } - - free(dir->name); - free(dir); - } - - if(result == -1) /* map all errors to EBADF */ - { - errno = EBADF; - } - - return result; -} - -struct dirent *readdir(DIR *dir) -{ - struct dirent *result = 0; - - if(dir && dir->handle != -1) - { - if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) - { - result = &dir->result; - result->d_name = dir->info.name; - } - } - else - { - errno = EBADF; - } - - return result; -} - -void rewinddir(DIR *dir) -{ - if(dir && dir->handle != -1) - { - _findclose(dir->handle); - dir->handle = _findfirst(dir->name, &dir->info); - dir->result.d_name = 0; - } - else - { - errno = EBADF; - } -} - -#ifdef __cplusplus -} -#endif - /* + * opendir + * + * Returns a pointer to a DIR structure appropriately filled in to begin + * searching a directory. + */ +_TDIR * +_topendir (const _TCHAR *szPath) +{ + _TDIR *nd; + unsigned int rc; + _TCHAR szFullPath[MAX_PATH]; - Copyright Kevlin Henney, 1997, 2003. All rights reserved. + errno = 0; - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that this copyright and permissions notice appear in all copies and - derivatives. - - This software is supplied "as is" without express or implied warranty. + if (!szPath) + { + errno = EFAULT; + return (_TDIR *) 0; + } - But that said, if there are any problems please get in touch. + if (szPath[0] == _T('\0')) + { + errno = ENOTDIR; + return (_TDIR *) 0; + } + + /* Attempt to determine if the given path really is a directory. */ + rc = _tGetFileAttributes (szPath); + if (rc == INVALID_FILE_ATTRIBUTES) + { + /* call GetLastError for more error info */ + errno = ENOENT; + return (_TDIR *) 0; + } + if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) + { + /* Error, entry exists but not a directory. */ + errno = ENOTDIR; + return (_TDIR *) 0; + } + + /* Make an absolute pathname. */ + _tfullpath (szFullPath, szPath, MAX_PATH); + + /* Allocate enough space to store DIR structure and the complete + * directory path given. */ + nd = (_TDIR *) malloc (sizeof (_TDIR) + (_tcslen (szFullPath) + + _tcslen (SLASH) + + _tcslen (SUFFIX) + 1) + * sizeof (_TCHAR)); + + if (!nd) + { + /* Error, out of memory. */ + errno = ENOMEM; + return (_TDIR *) 0; + } + + /* Create the search expression. */ + _tcscpy (nd->dd_name, szFullPath); + + /* Add on a slash if the path does not end with one. */ + if (nd->dd_name[0] != _T('\0') && + nd->dd_name[_tcslen (nd->dd_name) - 1] != _T('/') && + nd->dd_name[_tcslen (nd->dd_name) - 1] != _T('\\')) + { + _tcscat (nd->dd_name, SLASH); + } + + /* Add on the search pattern */ + _tcscat (nd->dd_name, SUFFIX); + + /* Initialize handle to -1 so that a premature closedir doesn't try + * to call _findclose on it. */ + nd->dd_handle = -1; + + /* Initialize the status. */ + nd->dd_stat = 0; + + /* Initialize the dirent structure. ino and reclen are invalid under + * Win32, and name simply points at the appropriate part of the + * findfirst_t structure. */ + nd->dd_dir.d_ino = 0; + nd->dd_dir.d_reclen = 0; + nd->dd_dir.d_namlen = 0; + memset (nd->dd_dir.d_name, 0, 260 /*FILENAME_MAX*/); + + return nd; +} + + +/* + * readdir + * + * Return a pointer to a dirent structure filled with the information on the + * next entry in the directory. + */ +struct _tdirent * +_treaddir (_TDIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return (struct _tdirent *) 0; + } + + if (dirp->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) + { + /* We haven't started the search yet. */ + /* Start the search */ + dirp->dd_handle = _tfindfirst (dirp->dd_name, &(dirp->dd_dta)); + + if (dirp->dd_handle == -1) + { + /* Whoops! Seems there are no files in that + * directory. */ + dirp->dd_stat = -1; + } + else + { + dirp->dd_stat = 1; + } + } + else + { + /* Get the next search entry. */ + if (_tfindnext (dirp->dd_handle, &(dirp->dd_dta))) + { + /* 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); + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Update the status to indicate the correct + * number. */ + dirp->dd_stat++; + } + } + + if (dirp->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); + return &dirp->dd_dir; + } + + return (struct _tdirent *) 0; +} + + +/* + * closedir + * + * Frees up resources allocated by opendir. + */ +int +_tclosedir (_TDIR * dirp) +{ + int rc; + + errno = 0; + rc = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + + if (dirp->dd_handle != -1) + { + rc = _findclose (dirp->dd_handle); + } + + /* Delete the dir structure. */ + free (dirp); + + return rc; +} + +/* + * rewinddir + * + * Return to the beginning of the directory "stream". We simply call findclose + * and then reset things like an opendir. + */ +void +_trewinddir (_TDIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + + dirp->dd_handle = -1; + dirp->dd_stat = 0; +} + +/* + * telldir + * + * 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. + */ +long +_ttelldir (_TDIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + return dirp->dd_stat; +} + +/* + * seekdir + * + * Seek to an entry previously returned by telldir. We rewind the directory + * 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 + * have changed while we weren't looking. But that is probably the case with + * any such system. + */ +void +_tseekdir (_TDIR * dirp, long lPos) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (lPos < -1) + { + /* Seeking to an invalid position. */ + errno = EINVAL; + return; + } + else if (lPos == -1) + { + /* Seek past end. */ + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Rewind and read forward to the appropriate index. */ + _trewinddir (dirp); + + while ((dirp->dd_stat < lPos) && _treaddir (dirp)) + ; + } +} -*/ diff --git a/quakespasm/Windows/VisualStudio/dirent.h b/quakespasm/Windows/VisualStudio/dirent.h index a02a0d82..2f9d2162 100644 --- a/quakespasm/Windows/VisualStudio/dirent.h +++ b/quakespasm/Windows/VisualStudio/dirent.h @@ -1,50 +1,142 @@ -#ifndef DIRENT_INCLUDED -#define DIRENT_INCLUDED - /* + * DIRENT.H (formerly DIRLIB.H) + * 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. + * + */ - Declaration of POSIX directory browsing functions and types for Win32. +#ifndef _DIRENT_H_ +#define _DIRENT_H_ - Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) - History: Created March 1997. Updated June 2003. - Rights: See end of file. - -*/ +#include +#include + +#ifndef RC_INVOKED #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif -typedef struct DIR DIR; - struct dirent { - char *d_name; + long d_ino; /* Always zero. */ + unsigned short d_reclen; /* Always zero. */ + unsigned short d_namlen; /* Length of name in d_name. */ + char d_name[260]; /* [FILENAME_MAX] */ /* File name. */ }; -DIR *opendir(const char *); -int closedir(DIR *); -struct dirent *readdir(DIR *); -void rewinddir(DIR *); +/* + * 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 */ + 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) */ + 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[260]; /* [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. + */ +typedef struct +{ + /* disk transfer area for this dir */ + struct _wfinddata_t dd_dta; - Copyright Kevlin Henney, 1997, 2003. All rights reserved. + /* 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; - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that this copyright and permissions notice appear in all copies and - derivatives. - - This software is supplied "as is" without express or implied warranty. + /* _findnext handle */ + intptr_t dd_handle; - But that said, if there are any problems please get in touch. + /* + * 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; -#ifdef __cplusplus +_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 _UNICODE +#define _tdirent _wdirent +#define _TDIR _WDIR +#define _topendir _wopendir +#define _tclosedir _wclosedir +#define _treaddir _wreaddir +#define _trewinddir _wrewinddir +#define _ttelldir _wtelldir +#define _tseekdir _wseekdir +#else +#define _tdirent dirent +#define _TDIR DIR +#define _topendir opendir +#define _tclosedir closedir +#define _treaddir readdir +#define _trewinddir rewinddir +#define _ttelldir telldir +#define _tseekdir seekdir +#endif + + +#ifdef __cplusplus } #endif -#endif +#endif /* Not RC_INVOKED */ + +#endif /* Not _DIRENT_H_ */ +