common/msvc_dirent.cc

Go to the documentation of this file.
00001 
00004 /*
00005     Implementation of POSIX directory browsing functions and types for Win32.
00006 
00007     Author:  Kevlin Henney ([email protected], [email protected])
00008     History: Created March 1997. Updated June 2003.
00009     Fixes since importing into Xapian:
00010     2008-03-04 Fixed readdir() not to set errno to ENOENT when the
00011                end of the directory is reached.
00012 
00013     Copyright Kevlin Henney, 1997, 2003. All rights reserved.
00014 
00015     Permission to use, copy, modify, and distribute this software and its
00016     documentation for any purpose is hereby granted without fee, provided
00017     that this copyright and permissions notice appear in all copies and
00018     derivatives.
00019     
00020     This software is supplied "as is" without express or implied warranty.
00021 
00022     But that said, if there are any problems please get in touch.
00023 */
00024 
00025 #include <config.h>
00026 #ifdef __WIN32__
00027 
00028 #include "msvc_dirent.h"
00029 #include <errno.h>
00030 #include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #ifdef __cplusplus
00035 extern "C"
00036 {
00037 #endif
00038 
00039 struct DIR
00040 {
00041     long                handle; /* -1 for failed rewind */
00042     struct _finddata_t  info;
00043     struct dirent       result; /* d_name null iff first time */
00044     char                *name;  /* null-terminated char string */
00045 };
00046 
00047 DIR *opendir(const char *name)
00048 {
00049     DIR *dir = 0;
00050 
00051     if(name && name[0])
00052     {
00053         size_t base_length = strlen(name);
00054         const char *all = /* search pattern must end with suitable wildcard */
00055             strchr("/\\", name[base_length - 1]) ? "*" : "/*";
00056 
00057         if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
00058            (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
00059         {
00060             strcat(strcpy(dir->name, name), all);
00061 
00062             if((dir->handle = (long) _findfirst(dir->name, &dir->info)) != -1)
00063             {
00064                 dir->result.d_name = 0;
00065             }
00066             else /* rollback */
00067             {
00068                 free(dir->name);
00069                 free(dir);
00070                 dir = 0;
00071             }
00072         }
00073         else /* rollback */
00074         {
00075             free(dir);
00076             dir   = 0;
00077             errno = ENOMEM;
00078         }
00079     }
00080     else
00081     {
00082         errno = EINVAL;
00083     }
00084 
00085     return dir;
00086 }
00087 
00088 int closedir(DIR *dir)
00089 {
00090     int result = -1;
00091 
00092     if(dir)
00093     {
00094         if(dir->handle != -1)
00095         {
00096             result = _findclose(dir->handle);
00097         }
00098 
00099         free(dir->name);
00100         free(dir);
00101     }
00102 
00103     if(result == -1) /* map all errors to EBADF */
00104     {
00105         errno = EBADF;
00106     }
00107 
00108     return result;
00109 }
00110 
00111 struct dirent *readdir(DIR *dir)
00112 {
00113     struct dirent *result = 0;
00114 
00115     if(dir && dir->handle != -1)
00116     {
00117         if(!dir->result.d_name) {
00118             result = &dir->result;
00119             result->d_name = dir->info.name;
00120         } else {
00121             int orig_errno = errno;
00122             if (_findnext(dir->handle, &dir->info) != -1) {
00123                 result = &dir->result;
00124                 result->d_name = dir->info.name;
00125             } else if (errno == ENOENT) {
00126                 // _findnext sets errno to ENOENT when the end of the directory
00127                 // is reached.  However, according to POSIX, the value of errno
00128                 // should not be changed by this condition.  Therefore, we have
00129                 // to set it back to the original value.
00130                 errno = orig_errno;
00131             }
00132         }
00133     }
00134     else
00135     {
00136         errno = EBADF;
00137     }
00138 
00139     return result;
00140 }
00141 
00142 void rewinddir(DIR *dir)
00143 {
00144     if(dir && dir->handle != -1)
00145     {
00146         _findclose(dir->handle);
00147         dir->handle = (long) _findfirst(dir->name, &dir->info);
00148         dir->result.d_name = 0;
00149     }
00150     else
00151     {
00152         errno = EBADF;
00153     }
00154 }
00155 
00156 #ifdef __cplusplus
00157 }
00158 #endif
00159 
00160 #endif

Documentation for Xapian (version 1.0.10).
Generated on 24 Dec 2008 by Doxygen 1.5.2.