/* dir.c - wrapper for Windows to support opendir/readdir/closedir api */ /* telldir(), seekdir() and scandir() are not supported. but scandir() would be * easy to add. */ /* August 10, 2007 - Jon Mayo - PUBLIC DOMAIN */ /** start of dir.h **/ #include struct dirent { char d_name[PATH_MAX]; }; typedef struct _dir_c DIR; void rewinddir(DIR *dir); DIR *opendir(const char *name); struct dirent *readdir(DIR *dir); int closedir(DIR *dir); /** end of dir.h **/ /** start of dir.c **/ #include #include #define _WIN32_WINNT 0x0400 #include /* #include "dir.h" */ struct _dir_c { char name[PATH_MAX]; struct dirent curr; WIN32_FIND_DATA ff_data; int result; HANDLE h; }; void rewinddir(DIR *dir) { DWORD dwError; assert(dir!=NULL); if(dir->h!=INVALID_HANDLE_VALUE) FindClose(dir->h); dir->h=FindFirstFileA(dir->name, &dir->ff_data); dir->result=dir->h!=INVALID_HANDLE_VALUE; if(!dir->result) { dwError=GetLastError(); switch(dwError) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: printf(TEXT("FindFirstFile(): File/Path not found.\n")); break; default: printf(TEXT("FindFirstFile() error. error=%u\n"), dwError); break; case ERROR_NO_MORE_FILES: /* do nothing */ ; } } } /* note: don't use backslashes in the name. windows supports forward slash just * fine. this will make your programs easier to port and have fewer bugs from * porting. */ DIR *opendir(const char *name) { DIR *ret; size_t len; assert(name!=NULL); ret=malloc(sizeof *ret); if(!ret) return 0; ret->h=INVALID_HANDLE_VALUE; /* copy name - truncate it if too long */ strncpy(ret->name, name, sizeof ret->name-1-2); ret->name[sizeof ret->name-1]=0; /* TODO: handle truncation as an error */ /* put "/*" on the end of the string */ len=strlen(ret->name); if(len && (ret->name[len-1]!='/' && ret->name[len-1]!='\\')) { ret->name[len++]='/'; ret->name[len]=0; } ret->name[len++]='*'; ret->name[len]=0; printf("name='%s'", ret->name); rewinddir(ret); /* initialize with FindFirstFile() */ return ret; } struct dirent *readdir(DIR *dir) { assert(dir!=NULL); if(!dir->result) { return 0; /* no more results */ } /* store previous result and return it */ strcpy(dir->curr.d_name, dir->ff_data.cFileName); /* load future result */ dir->result=FindNextFile(dir->h, &dir->ff_data); if(!dir->result && GetLastError()!=ERROR_NO_MORE_FILES) { printf(TEXT("FindNextFile() error.\n")); /* we'll still return the previous result even if we have an error */ } return &dir->curr; } int closedir(DIR *dir) { assert(dir!=NULL); if(dir->h!=INVALID_HANDLE_VALUE) { FindClose(dir->h); } free(dir); } /** end of dir.c **/ /** Test/Example code **/ #define STAND_ALONE #ifdef STAND_ALONE #include int main() { DIR *d; struct dirent *de; d=opendir(".."); while((de=readdir(d))) { printf("%s\n", de->d_name); } closedir(d); } #endif