Mercurial > dwindows
diff win/dirent.c @ 3:67a643a734d9
Import
author | ktk@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Tue, 03 Jul 2001 07:50:39 +0000 |
parents | |
children | 4ec906d40ce2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/win/dirent.c Tue Jul 03 07:50:39 2001 +0000 @@ -0,0 +1,226 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include <windows.h> + +#include "dirent.h" +#include <errno.h> + +#define error(rc) errno = 255 + +struct _dirdescr { + HANDLE handle; /* DosFindFirst handle */ + char fstype; /* filesystem type */ + long count; /* valid entries in <ffbuf> */ + long number; /* absolute number of next entry */ + int index; /* relative number of next entry */ + char name[MAXPATHLEN+3]; /* directory name */ + unsigned attrmask; /* attribute mask for seekdir */ + struct dirent entry; /* buffer for directory entry */ + WIN32_FIND_DATA data; +}; + +/* + * Return first char of filesystem type, or 0 if unknown. + */ +static char +getFSType(const char *path) +{ + static char cache[1+26]; + char drive[3]; + ULONG unit; + char r; + + if (isalpha(path[0]) && path[1] == ':') { + unit = toupper(path[0]) - '@'; + path += 2; + } else { + return 0; + } + + if ((path[0] == '\\' || path[0] == '/') + && (path[1] == '\\' || path[1] == '/')) + return 0; + + if (cache [unit]) + return cache [unit]; + + drive[0] = '@' + unit; + drive[1] = ':'; + drive[2] = '\0'; + + r = GetDriveType(drive); + + return cache [unit] = r; +} + +char * +abs_path(const char *name, char *buffer, int len) +{ + char buf[4]; + if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') { + buf[0] = name[0]; + buf[1] = name[1]; + buf[2] = '.'; + buf[3] = '\0'; + name = buf; + } + if (GetLongPathName(name, buffer, len)) + return NULL; + return buffer; +} + +DIR * +openxdir(const char *path, unsigned att_mask) +{ + DIR *dir; + char name[MAXPATHLEN+3]; + + dir = malloc(sizeof(DIR)); + if (dir == NULL) { + errno = ENOMEM; + return NULL; + } + + strncpy(name, path, MAXPATHLEN); + name[MAXPATHLEN] = '\0'; + switch (name[strlen(name)-1]) { + default: + strcat(name, "\\"); + case '\\': + case '/': + case ':': + ; + } + strcat(name, "."); + if (!abs_path(name, dir->name, MAXPATHLEN+1)) + strcpy(dir->name, name); + if (dir->name[strlen(dir->name)-1] == '\\') + strcat(dir->name, "*"); + else + strcat(dir->name, "\\*"); + + dir->fstype = getFSType(dir->name); + dir->attrmask = att_mask | A_DIR; + + dir->count = 100; + if((dir->handle = FindFirstFile(dir->name, &dir->data))==NULL) + { + free(dir); + error(rc); + return NULL; + } + + dir->number = 0; + dir->index = 0; + + return (DIR *)dir; +} + +DIR * +opendir(const char *pathname) +{ + return openxdir(pathname, 0); +} + +struct dirent * +readdir(DIR *dir) +{ + static int dummy_ino = 2; + + if (dir->number) + { + ULONG rc; + dir->count = 100; + if(!FindNextFile(dir->handle, &(dir->data))) + { + error(rc); + return NULL; + } + + dir->index = 0; + } + + strcpy(dir->entry.d_name, dir->data.cFileName); + dir->entry.d_ino = dummy_ino++; + dir->entry.d_reclen = strlen(dir->data.cFileName); + dir->entry.d_namlen = strlen(dir->data.cFileName); + dir->entry.d_size = dir->data.nFileSizeLow; + dir->entry.d_attribute = dir->data.dwFileAttributes; +#if 0 + dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite; + dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite; +#endif + + dir->number++; + dir->index++; + return &dir->entry; +} + +long +telldir(DIR *dir) +{ + return dir->number; +} + +void +seekdir(DIR *dir, long off) +{ + if (dir->number > off) { + char name[MAXPATHLEN+2]; + ULONG rc; + + FindClose(dir->handle); + + strcpy(name, dir->name); + strcat(name, "*"); + + if((dir->handle = FindFirstFile(name, &(dir->data)))==NULL) + { + error(rc); + return; + } + + dir->number = 0; + dir->index = 0; + } + + while (dir->number < off && readdir(dir)) + ; +} + +void +closedir(DIR *dir) +{ + FindClose(dir->handle); + free(dir); +} + +/*****************************************************************************/ + +#ifdef TEST + +main(int argc, char **argv) +{ + int i; + DIR *dir; + struct dirent *ep; + + for (i = 1; i < argc; ++i) { + dir = opendir(argv[i]); + if (!dir) + continue; + while (ep = readdir(dir)) + if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1])) + printf("%s%s\n", argv[i], ep->d_name); + else + printf("%s/%s\n", argv[i], ep->d_name); + closedir(dir); + } + + return 0; +} + +#endif