From: Gurusamy Sarathy Date: Fri, 15 Oct 1999 04:49:09 +0000 (+0000) Subject: win32_*dir() cleanup; win32_readdir() iterates as necessary X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=95136addeff6f7c87c13a96a62f5eaafb9bafdcf;p=p5sagit%2Fp5-mst-13.2.git win32_*dir() cleanup; win32_readdir() iterates as necessary rather than win32_opendir() reading all files up front (untested) p4raw-id: //depot/perl@4385 --- diff --git a/win32/include/dirent.h b/win32/include/dirent.h index d2ef6d5..d6eb7ea 100644 --- a/win32/include/dirent.h +++ b/win32/include/dirent.h @@ -1,41 +1,44 @@ -// dirent.h +/* dirent.h */ -// djl -// Provide UNIX compatibility +/* djl + * Provide UNIX compatibility + */ #ifndef _INC_DIRENT #define _INC_DIRENT -// -// NT versions of readdir(), etc -// From the MSDOS implementation -// +/* + * NT versions of readdir(), etc + * From the MSDOS implementation + */ -// Directory entry size +/* Directory entry size */ #ifdef DIRSIZ #undef DIRSIZ #endif #define DIRSIZ(rp) (sizeof(struct direct)) -// needed to compile directory stuff +/* needed to compile directory stuff */ #define DIRENT direct -// structure of a directory entry +/* structure of a directory entry */ typedef struct direct { - long d_ino; // inode number (not used by MS-DOS) - int d_namlen; // Name length - char d_name[257]; // file name + long d_ino; /* inode number (not used by MS-DOS) */ + long d_namlen; /* name length */ + char *d_name; /* file name */ } _DIRECT; -// structure for dir operations +/* structure for dir operations */ typedef struct _dir_struc { - char *start; // Starting position - char *curr; // Current position - long size; // Size of string table - long nfiles; // number if filenames in table - struct direct dirstr; // Directory structure to return + char *start; /* starting position */ + char *curr; /* current position */ + long size; /* allocated size of string table */ + long nfiles; /* number of filenames in table */ + struct direct dirstr; /* directory structure to return */ + void* handle; /* system handle */ + char *end; /* position after last filename */ } DIR; #if 0 /* these have moved to win32iop.h */ @@ -47,4 +50,4 @@ void win32_rewinddir(DIR *dirp); int win32_closedir(DIR *dirp); #endif -#endif //_INC_DIRENT +#endif /* _INC_DIRENT */ diff --git a/win32/win32.c b/win32/win32.c index a2a6502..71a959a 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -672,7 +672,7 @@ DllExport DIR * win32_opendir(char *filename) { dTHXo; - DIR *p; + DIR *dirp; long len; long idx; char scanname[MAX_PATH+3]; @@ -682,7 +682,7 @@ win32_opendir(char *filename) HANDLE fh; char buffer[MAX_PATH*2]; WCHAR wbuffer[MAX_PATH]; - char* ptr; + char* ptr; len = strlen(filename); if (len > MAX_PATH) @@ -693,9 +693,7 @@ win32_opendir(char *filename) return NULL; /* Get us a DIR structure */ - Newz(1303, p, 1, DIR); - if (p == NULL) - return NULL; + Newz(1303, dirp, 1, DIR); /* Create the search pattern */ strcpy(scanname, filename); @@ -719,11 +717,25 @@ win32_opendir(char *filename) else { fh = FindFirstFileA(scanname, &aFindData); } + dirp->handle = fh; if (fh == INVALID_HANDLE_VALUE) { + DWORD err = GetLastError(); /* FindFirstFile() fails on empty drives! */ - if (GetLastError() == ERROR_FILE_NOT_FOUND) - return p; - Safefree( p); + switch (err) { + case ERROR_FILE_NOT_FOUND: + return dirp; + case ERROR_NO_MORE_FILES: + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; + break; + case ERROR_NOT_ENOUGH_MEMORY: + errno = ENOMEM; + break; + default: + errno = EINVAL; + break; + } + Safefree(dirp); return NULL; } @@ -738,39 +750,16 @@ win32_opendir(char *filename) ptr = aFindData.cFileName; } idx = strlen(ptr)+1; - New(1304, p->start, idx, char); - if (p->start == NULL) - Perl_croak_nocontext("opendir: malloc failed!\n"); - strcpy(p->start, ptr); - p->nfiles++; - - /* loop finding all the files that match the wildcard - * (which should be all of them in this directory!). - * the variable idx should point one past the null terminator - * of the previous string found. - */ - while (USING_WIDE() - ? FindNextFileW(fh, &wFindData) - : FindNextFileA(fh, &aFindData)) { - if (USING_WIDE()) { - W2AHELPER(wFindData.cFileName, buffer, sizeof(buffer)); - } - /* ptr is set above to the correct area */ - len = strlen(ptr); - /* bump the string table size by enough for the - * new name and it's null terminator - */ - Renew(p->start, idx+len+1, char); - if (p->start == NULL) - Perl_croak_nocontext("opendir: malloc failed!\n"); - strcpy(&p->start[idx], ptr); - p->nfiles++; - idx += len+1; - } - FindClose(fh); - p->size = idx; - p->curr = p->start; - return p; + if (idx < 256) + dirp->size = 128; + else + dirp->size = idx; + New(1304, dirp->start, dirp->size, char); + strcpy(dirp->start, ptr); + dirp->nfiles++; + dirp->end = dirp->curr = dirp->start; + dirp->end += idx; + return dirp; } @@ -780,24 +769,59 @@ win32_opendir(char *filename) DllExport struct direct * win32_readdir(DIR *dirp) { - int len; - static int dummy = 0; + long len; if (dirp->curr) { /* first set up the structure to return */ len = strlen(dirp->curr); - strcpy(dirp->dirstr.d_name, dirp->curr); + dirp->dirstr.d_name = dirp->curr; dirp->dirstr.d_namlen = len; /* Fake an inode */ - dirp->dirstr.d_ino = dummy++; + dirp->dirstr.d_ino = (long)dirp->curr; - /* Now set up for the nDllExport call to readdir */ + /* Now set up for the next call to readdir */ dirp->curr += len + 1; - if (dirp->curr >= (dirp->start + dirp->size)) { - dirp->curr = NULL; + if (dirp->curr >= dirp->end) { + dTHXo; + char* ptr; + BOOL res; + WIN32_FIND_DATAW wFindData; + WIN32_FIND_DATAA aFindData; + char buffer[MAX_PATH*2]; + + /* finding the next file that matches the wildcard + * (which should be all of them in this directory!). + * the variable idx should point one past the null terminator + * of the previous string found. + */ + if (USING_WIDE()) { + res = FindNextFileW(dirp->handle, &wFindData); + if (res) { + W2AHELPER(wFindData.cFileName, buffer, sizeof(buffer)); + ptr = buffer; + } + } + else { + res = FindNextFileA(dirp->handle, &aFindData); + if (res) + ptr = aFindData.cFileName; + } + if (res) { + len = strlen(ptr)+1; + /* bump the string table size by enough for the + * new name and it's null terminator */ + while (dirp->end + len > dirp->start + dirp->size) { + dirp->size *= 2; + Renew(dirp->start, dirp->size, char); + } + strcpy(dirp->end, ptr); + dirp->end += idx; + dirp->nfiles++; + } + else + dirp->curr = NULL; } - return &(dirp->dirstr); } else @@ -808,17 +832,17 @@ win32_readdir(DIR *dirp) DllExport long win32_telldir(DIR *dirp) { - return (long) dirp->curr; + return (dirp->curr - dirp->start); } /* Seekdir moves the string pointer to a previously saved position - *(Saved by telldir). + * (returned by telldir). */ DllExport void win32_seekdir(DIR *dirp, long loc) { - dirp->curr = (char *)loc; + dirp->curr = dirp->start + loc; } /* Rewinddir resets the string pointer to the start */ @@ -833,6 +857,8 @@ DllExport int win32_closedir(DIR *dirp) { dTHXo; + if (dirp->handle != INVALID_HANDLE_VALUE) + FindClose(p->handle); Safefree(dirp->start); Safefree(dirp); return 1;