Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

dirent.c

00001 /*
00002  * dirent.c
00003  *
00004  * Derived from DIRLIB.C by Matt J. Weinstein 
00005  * This note appears in the DIRLIB.H
00006  * DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89
00007  *
00008  * Updated by Jeremy Bettis <[email protected]>
00009  * Significantly revised and rewinddir, seekdir and telldir added by Colin
00010  * Peters <[email protected]>
00011  *      
00012  * $Revision: 1.6 $
00013  * $Author: sam $
00014  * $Date: 2002/11/13 20:51:04 $
00015  *
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 
00023 #ifdef HAVE_ERRNO_H
00024 #   include <errno.h>
00025 #else
00026     static int errno;
00027     /* FIXME: anything clever to put here? */
00028 #   define EFAULT 12
00029 #   define ENOTDIR 12
00030 #   define ENOENT 12
00031 #   define ENOMEM 12
00032 #   define EINVAL 12
00033 #endif
00034 #include <string.h>
00035 #ifndef UNDER_CE
00036 #   include <io.h>
00037 #   include <direct.h>
00038 #else
00039 #   define FILENAME_MAX (260)
00040 #endif
00041 
00042 #define WIN32_LEAN_AND_MEAN
00043 #include <windows.h> /* for GetFileAttributes */
00044 
00045 #include <tchar.h>
00046 #define SUFFIX  "*"
00047 #define SLASH   "\\"
00048 
00049 struct dirent
00050 {
00051         long            d_ino;          /* Always zero. */
00052         unsigned short  d_reclen;       /* Always zero. */
00053         unsigned short  d_namlen;       /* Length of name in d_name. */
00054         char            d_name[FILENAME_MAX]; /* File name. */
00055 };
00056 
00057 typedef struct
00058 {
00059         /* disk transfer area for this dir */
00060         WIN32_FIND_DATA         dd_dta;
00061 
00062         /* dirent struct to return from dir (NOTE: this makes this thread
00063          * safe as long as only one thread uses a particular DIR struct at
00064          * a time) */
00065         struct dirent           dd_dir;
00066 
00067         /* findnext handle */
00068         HANDLE                  dd_handle;
00069 
00070         /*
00071          * Status of search:
00072          *   0 = not started yet (next entry to read is first entry)
00073          *  -1 = off the end
00074          *   positive = 0 based index of next entry
00075          */
00076         int                     dd_stat;
00077 
00078         /* given path for dir with search pattern (struct is extended) */
00079         char                    dd_name[1];
00080 } DIR;
00081 
00082 /*
00083  * opendir
00084  *
00085  * Returns a pointer to a DIR structure appropriately filled in to begin
00086  * searching a directory.
00087  */
00088 DIR * 
00089 vlc_opendir (const CHAR *szPath)
00090 {
00091   DIR *nd;
00092   unsigned int rc;
00093   CHAR szFullPath[MAX_PATH];
00094 
00095   errno = 0;
00096 
00097   if (!szPath)
00098     {
00099       errno = EFAULT;
00100       return (DIR *) 0;
00101     }
00102 
00103   if (szPath[0] == '\0')
00104     {
00105       errno = ENOTDIR;
00106       return (DIR *) 0;
00107     }
00108 
00109   /* Attempt to determine if the given path really is a directory. */
00110 #ifdef UNICODE
00111   {
00112     wchar_t szPathTmp[MAX_PATH];
00113     mbstowcs( szPathTmp, szPath, MAX_PATH );
00114     szPathTmp[MAX_PATH-1] = 0;
00115     rc = GetFileAttributes (szPathTmp);
00116   }
00117 #else
00118   rc = GetFileAttributes (szPath);
00119 #endif
00120   if (rc == (unsigned int)-1)
00121     {
00122       /* call GetLastError for more error info */
00123       errno = ENOENT;
00124       return (DIR *) 0;
00125     }
00126   if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
00127     {
00128       /* Error, entry exists but not a directory. */
00129       errno = ENOTDIR;
00130       return (DIR *) 0;
00131     }
00132 
00133   /* Make an absolute pathname.  */
00134 #if defined( UNDER_CE )
00135   if (szPath[0] == '\\' || szPath[0] == '/')
00136     {
00137       sprintf (szFullPath, "%s", szPath);
00138       szFullPath[0] = '\\';
00139     }
00140   else
00141     {
00142       wchar_t szFullPathTmp[MAX_PATH];
00143       if (GetModuleFileName( NULL, szFullPathTmp, MAX_PATH ) )
00144         {
00145           wcstombs( szFullPath, szFullPathTmp, MAX_PATH );
00146           szFullPath[MAX_PATH-1] = 0;
00147         }
00148       else
00149         {
00150           /* FIXME: if I wasn't lazy, I'd check for overflows here. */
00151           sprintf (szFullPath, "\\%s", szPath );
00152         }
00153     }
00154 #else
00155   _fullpath (szFullPath, szPath, MAX_PATH);
00156 #endif
00157 
00158   /* Allocate enough space to store DIR structure and the complete
00159    * directory path given. */
00160   nd = (DIR *) malloc (sizeof (DIR) + strlen (szFullPath) + sizeof (SLASH) +
00161                        sizeof (SUFFIX));
00162 
00163   if (!nd)
00164     {
00165       /* Error, out of memory. */
00166       errno = ENOMEM;
00167       return (DIR *) 0;
00168     }
00169 
00170   /* Create the search expression. */
00171   strcpy (nd->dd_name, szFullPath);
00172 
00173   /* Add on a slash if the path does not end with one. */
00174   if (nd->dd_name[0] != '\0' &&
00175       nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
00176       nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
00177     {
00178       strcat (nd->dd_name, SLASH);
00179     }
00180 
00181   /* Add on the search pattern */
00182   strcat (nd->dd_name, SUFFIX);
00183 
00184   /* Initialize handle so that a premature closedir doesn't try
00185    * to call FindClose on it. */
00186   nd->dd_handle = INVALID_HANDLE_VALUE;
00187 
00188   /* Initialize the status. */
00189   nd->dd_stat = 0;
00190 
00191   /* Initialize the dirent structure. ino and reclen are invalid under
00192    * Win32, and name simply points at the appropriate part of the
00193    * findfirst_t structure. */
00194   nd->dd_dir.d_ino = 0;
00195   nd->dd_dir.d_reclen = 0;
00196   nd->dd_dir.d_namlen = 0;
00197   memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
00198 
00199   return nd;
00200 }
00201 
00202 
00203 /*
00204  * readdir
00205  *
00206  * Return a pointer to a dirent structure filled with the information on the
00207  * next entry in the directory.
00208  */
00209 struct dirent *
00210 vlc_readdir (DIR * dirp)
00211 {
00212   errno = 0;
00213 
00214   /* Check for valid DIR struct. */
00215   if (!dirp)
00216     {
00217       errno = EFAULT;
00218       return (struct dirent *) 0;
00219     }
00220 
00221   if (dirp->dd_stat < 0)
00222     {
00223       /* We have already returned all files in the directory
00224        * (or the structure has an invalid dd_stat). */
00225       return (struct dirent *) 0;
00226     }
00227   else if (dirp->dd_stat == 0)
00228     {
00229 #ifdef UNICODE
00230         wchar_t dd_name[MAX_PATH];
00231         mbstowcs( dd_name, dirp->dd_name, MAX_PATH );
00232         dd_name[MAX_PATH-1] = 0;
00233 #else
00234         char *dd_name = dirp->dd_name;
00235 #endif
00236       /* We haven't started the search yet. */
00237       /* Start the search */
00238       dirp->dd_handle = FindFirstFile (dd_name, &(dirp->dd_dta));
00239 
00240           if (dirp->dd_handle == INVALID_HANDLE_VALUE)
00241         {
00242           /* Whoops! Seems there are no files in that
00243            * directory. */
00244           dirp->dd_stat = -1;
00245         }
00246       else
00247         {
00248           dirp->dd_stat = 1;
00249         }
00250     }
00251   else
00252     {
00253       /* Get the next search entry. */
00254       if (!FindNextFile ((HANDLE)dirp->dd_handle, &(dirp->dd_dta)))
00255         {
00256           /* We are off the end or otherwise error. */
00257           FindClose ((HANDLE)dirp->dd_handle);
00258           dirp->dd_handle = INVALID_HANDLE_VALUE;
00259           dirp->dd_stat = -1;
00260         }
00261       else
00262         {
00263           /* Update the status to indicate the correct
00264            * number. */
00265           dirp->dd_stat++;
00266         }
00267     }
00268 
00269   if (dirp->dd_stat > 0)
00270     {
00271       /* Successfully got an entry */
00272 
00273 #ifdef UNICODE
00274       char d_name[MAX_PATH];
00275       wcstombs( d_name, dirp->dd_dta.cFileName, MAX_PATH );
00276       d_name[MAX_PATH-1] = 0;
00277 #else
00278       char *d_name = dirp->dd_dta.cFileName;
00279 #endif
00280 
00281       strcpy (dirp->dd_dir.d_name, d_name);
00282       dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
00283       return &dirp->dd_dir;
00284     }
00285 
00286   return (struct dirent *) 0;
00287 }
00288 
00289 
00290 /*
00291  * closedir
00292  *
00293  * Frees up resources allocated by opendir.
00294  */
00295 int
00296 vlc_closedir (DIR * dirp)
00297 {
00298   int rc;
00299 
00300   errno = 0;
00301   rc = 0;
00302 
00303   if (!dirp)
00304     {
00305       errno = EFAULT;
00306       return -1;
00307     }
00308 
00309   if (dirp->dd_handle != INVALID_HANDLE_VALUE)
00310     {
00311       rc = FindClose ((HANDLE)dirp->dd_handle);
00312     }
00313 
00314   /* Delete the dir structure. */
00315   free (dirp);
00316 
00317   return rc;
00318 }
00319 
00320 /*
00321  * rewinddir
00322  *
00323  * Return to the beginning of the directory "stream". We simply call findclose
00324  * and then reset things like an opendir.
00325  */
00326 void
00327 vlc_rewinddir (DIR * dirp)
00328 {
00329   errno = 0;
00330 
00331   if (!dirp)
00332     {
00333       errno = EFAULT;
00334       return;
00335     }
00336 
00337   if (dirp->dd_handle != INVALID_HANDLE_VALUE)
00338     {
00339       FindClose ((HANDLE)dirp->dd_handle);
00340     }
00341 
00342   dirp->dd_handle = INVALID_HANDLE_VALUE;
00343   dirp->dd_stat = 0;
00344 }
00345 
00346 /*
00347  * telldir
00348  *
00349  * Returns the "position" in the "directory stream" which can be used with
00350  * seekdir to go back to an old entry. We simply return the value in stat.
00351  */
00352 long
00353 vlc_telldir (DIR * dirp)
00354 {
00355   errno = 0;
00356 
00357   if (!dirp)
00358     {
00359       errno = EFAULT;
00360       return -1;
00361     }
00362   return dirp->dd_stat;
00363 }
00364 
00365 /*
00366  * seekdir
00367  *
00368  * Seek to an entry previously returned by telldir. We rewind the directory
00369  * and call readdir repeatedly until either dd_stat is the position number
00370  * or -1 (off the end). This is not perfect, in that the directory may
00371  * have changed while we weren't looking. But that is probably the case with
00372  * any such system.
00373  */
00374 void
00375 vlc_seekdir (DIR * dirp, long lPos)
00376 {
00377   errno = 0;
00378 
00379   if (!dirp)
00380     {
00381       errno = EFAULT;
00382       return;
00383     }
00384 
00385   if (lPos < -1)
00386     {
00387       /* Seeking to an invalid position. */
00388       errno = EINVAL;
00389       return;
00390     }
00391   else if (lPos == -1)
00392     {
00393       /* Seek past end. */
00394       if (dirp->dd_handle != INVALID_HANDLE_VALUE)
00395         {
00396           FindClose ((HANDLE)dirp->dd_handle);
00397         }
00398       dirp->dd_handle = INVALID_HANDLE_VALUE;
00399       dirp->dd_stat = -1;
00400     }
00401   else
00402     {
00403       /* Rewind and read forward to the appropriate index. */
00404       vlc_rewinddir (dirp);
00405 
00406       while ((dirp->dd_stat < lPos) && vlc_readdir (dirp))
00407         ;
00408     }
00409 }

Generated on Tue Dec 20 10:14:59 2005 for vlc-0.8.4a by  doxygen 1.4.2