dirent_win.h
Go to the documentation of this file.
00001 /*****************************************************************************
00002  * dirent.h - dirent API for Microsoft Visual Studio
00003  *
00004  * Copyright (C) 2006 Toni Ronkko
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining
00007  * a copy of this software and associated documentation files (the
00008  * ``Software''), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sublicense, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00020  * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
00021  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00022  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00023  * OTHER DEALINGS IN THE SOFTWARE.
00024  *
00025  * Dec 15, 2009, John Cunningham
00026  * Added rewinddir member function
00027  *
00028  * Jan 18, 2008, Toni Ronkko
00029  * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
00030  * between multi-byte and unicode representations.  This makes the
00031  * code simpler and also allows the code to be compiled under MingW.  Thanks
00032  * to Azriel Fasten for the suggestion.
00033  *
00034  * Mar 4, 2007, Toni Ronkko
00035  * Bug fix: due to the strncpy_s() function this file only compiled in
00036  * Visual Studio 2005.  Using the new string functions only when the
00037  * compiler version allows.
00038  *
00039  * Nov  2, 2006, Toni Ronkko
00040  * Major update: removed support for Watcom C, MS-DOS and Turbo C to
00041  * simplify the file, updated the code to compile cleanly on Visual
00042  * Studio 2005 with both unicode and multi-byte character strings,
00043  * removed rewinddir() as it had a bug.
00044  *
00045  * Aug 20, 2006, Toni Ronkko
00046  * Removed all remarks about MSVC 1.0, which is antiqued now.  Simplified
00047  * comments by removing SGML tags.
00048  *
00049  * May 14 2002, Toni Ronkko
00050  * Embedded the function definitions directly to the header so that no
00051  * source modules need to be included in the Visual Studio project.  Removed
00052  * all the dependencies to other projects so that this very header can be
00053  * used independently.
00054  *
00055  * May 28 1998, Toni Ronkko
00056  * First version.
00057  *****************************************************************************/
00058 #ifndef DIRENT_H
00059 #define DIRENT_H
00060 
00061 #include <windows.h>
00062 #include <string.h>
00063 #include <assert.h>
00064 
00065 
00066 typedef struct dirent
00067 {
00068    char d_name[MAX_PATH + 1]; /* current dir entry (multi-byte char string) */
00069    WIN32_FIND_DATAA data;     /* file attributes */
00070 }  dirent;
00071 
00072 
00073 typedef struct DIR
00074 {
00075    dirent current;            /* Current directory entry */
00076    int    cached;             /* Indicates un-processed entry in memory */
00077    HANDLE search_handle;      /* File search handle */
00078    char   patt[MAX_PATH + 3]; /* search pattern (3 = pattern + "\\*\0") */
00079 } DIR;
00080 
00081 
00082 /* Forward declarations */
00083 static DIR *opendir (const char *dirname);
00084 static struct dirent *readdir (DIR *dirp);
00085 static int closedir (DIR *dirp);
00086 static void rewinddir(DIR* dirp);
00087 
00088 
00089 /* Use the new safe string functions introduced in Visual Studio 2005 */
00090 #if defined(_MSC_VER) && _MSC_VER >= 1400
00091 # define STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
00092 #else
00093 # define STRNCPY(dest,src,size) strncpy((dest),(src),(size))
00094 #endif
00095 
00096 
00097 /*****************************************************************************
00098  * Open directory stream DIRNAME for read and return a pointer to the
00099  * internal working area that is used to retrieve individual directory
00100  * entries.
00101  */
00102 static DIR *opendir(const char *dirname)
00103 {
00104    DIR *dirp;
00105    assert (dirname != NULL);
00106    assert (strlen (dirname) < MAX_PATH);
00107 
00108    /* construct new DIR structure */
00109    dirp = (DIR*) malloc (sizeof (struct DIR));
00110    if (dirp != NULL) {
00111       char *p;
00112 
00113       /* take directory name... */
00114       STRNCPY (dirp->patt, dirname, sizeof(dirp->patt));
00115       dirp->patt[MAX_PATH] = '\0';
00116 
00117       /* ... and append search pattern to it */
00118       p = strchr (dirp->patt, '\0');
00119       if (dirp->patt < p  &&  *(p-1) != '\\'  &&  *(p-1) != ':') {
00120          *p++ = '\\';
00121       }
00122       *p++ = '*';
00123       *p = '\0';
00124 
00125       /* open stream and retrieve first file */
00126       dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
00127       if (dirp->search_handle == INVALID_HANDLE_VALUE) {
00128          /* invalid search pattern? */
00129          free (dirp);
00130          return NULL;
00131       }
00132 
00133       /* there is an un-processed directory entry in memory now */
00134       dirp->cached = 1;
00135    }
00136 
00137    return dirp;
00138 }
00139 
00140 
00141 /*****************************************************************************
00142  * Read a directory entry, and return a pointer to a dirent structure
00143  * containing the name of the entry in d_name field.  Individual directory
00144  * entries returned by this very function include regular files,
00145  * sub-directories, pseudo-directories "." and "..", but also volume labels,
00146  * hidden files and system files may be returned.
00147  */
00148 static struct dirent *readdir(DIR *dirp)
00149 {
00150    assert (dirp != NULL);
00151 
00152    if (dirp->search_handle == INVALID_HANDLE_VALUE) {
00153       /* directory stream was opened/rewound incorrectly or ended normally */
00154       return NULL;
00155    }
00156 
00157    /* get next directory entry */
00158    if (dirp->cached != 0) {
00159       /* a valid directory entry already in memory */
00160       dirp->cached = 0;
00161    } else {
00162       /* read next directory entry from disk */
00163       if (FindNextFileA (dirp->search_handle, &dirp->current.data) == FALSE) {
00164          /* the very last file has been processed or an error occured */
00165          FindClose (dirp->search_handle);
00166          dirp->search_handle = INVALID_HANDLE_VALUE;
00167          return NULL;
00168       }
00169    }
00170 
00171    /* copy as a multibyte character string */
00172    STRNCPY ( dirp->current.d_name,
00173              dirp->current.data.cFileName,
00174              sizeof(dirp->current.d_name) );
00175    dirp->current.d_name[MAX_PATH] = '\0';
00176 
00177    return &dirp->current;
00178 }
00179 
00180 
00181 /*****************************************************************************
00182  * Close directory stream opened by opendir() function.  Close of the
00183  * directory stream invalidates the DIR structure as well as any previously
00184  * read directory entry.
00185  */
00186 static int closedir(DIR *dirp)
00187 {
00188    assert (dirp != NULL);
00189 
00190    /* release search handle */
00191    if (dirp->search_handle != INVALID_HANDLE_VALUE) {
00192       FindClose (dirp->search_handle);
00193       dirp->search_handle = INVALID_HANDLE_VALUE;
00194    }
00195 
00196    /* release directory handle */
00197    free (dirp);
00198    return 0;
00199 }
00200 
00201 
00202 /*****************************************************************************
00203  * Resets the position of the directory stream to which dirp refers to the
00204  * beginning of the directory. It also causes the directory stream to refer
00205  * to the current state of the corresponding directory, as a call to opendir()
00206  * would have done. If dirp does not refer to a directory stream, the effect
00207  * is undefined.
00208  */
00209 static void rewinddir(DIR* dirp)
00210 {
00211    /* release search handle */
00212    if (dirp->search_handle != INVALID_HANDLE_VALUE) {
00213       FindClose (dirp->search_handle);
00214       dirp->search_handle = INVALID_HANDLE_VALUE;
00215    }
00216 
00217    /* open new search handle and retrieve first file */
00218    dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
00219    if (dirp->search_handle == INVALID_HANDLE_VALUE) {
00220       /* invalid search pattern? */
00221       free (dirp);
00222       return;
00223    }
00224 
00225    /* there is an un-processed directory entry in memory now */
00226    dirp->cached = 1;
00227 }
00228 
00229 
00230 #endif /*DIRENT_H*/


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:31:02