diff options
Diffstat (limited to 'security/nss/lib/dbm/src/dirent.c')
-rw-r--r-- | security/nss/lib/dbm/src/dirent.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/security/nss/lib/dbm/src/dirent.c b/security/nss/lib/dbm/src/dirent.c new file mode 100644 index 0000000000..da3e83e5c8 --- /dev/null +++ b/security/nss/lib/dbm/src/dirent.c @@ -0,0 +1,344 @@ +#ifdef OS2 + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include <dirent.h> +#include <errno.h> + +/*#ifndef __EMX__ +#include <libx.h> +#endif */ + +#define INCL_DOSFILEMGR +#define INCL_DOSERRORS +#include <os2.h> + +#if OS2 >= 2 +#define FFBUF FILEFINDBUF3 +#define Word ULONG +/* + * LS20 recommends a request count of 100, but according to the + * APAR text it does not lead to missing files, just to funny + * numbers of returned entries. + * + * LS30 HPFS386 requires a count greater than 2, or some files + * are missing (those starting with a character less that '.'). + * + * Novell loses entries which overflow the buffer. In previous + * versions of dirent2, this could have lead to missing files + * when the average length of 100 directory entries was 40 bytes + * or more (quite unlikely for files on a Novell server). + * + * Conclusion: Make sure that the entries all fit into the buffer + * and that the buffer is large enough for more than 2 entries + * (each entry is at most 300 bytes long). And ignore the LS20 + * effect. + */ +#define Count 25 +#define BufSz (25 * (sizeof(FILEFINDBUF3) + 1)) +#else +#define FFBUF FILEFINDBUF +#define Word USHORT +#define BufSz 1024 +#define Count 3 +#endif + +#if defined(__IBMC__) || defined(__IBMCPP__) +#define error(rc) _doserrno = rc, errno = EOS2ERR +#elif defined(MICROSOFT) +#define error(rc) _doserrno = rc, errno = 255 +#else +#define error(rc) errno = 255 +#endif + +struct _dirdescr { + HDIR handle; /* DosFindFirst handle */ + char fstype; /* filesystem type */ + Word count; /* valid entries in <ffbuf> */ + long number; /* absolute number of next entry */ + int index; /* relative number of next entry */ + FFBUF *next; /* pointer to next entry */ + char name[MAXPATHLEN + 3]; /* directory name */ + unsigned attrmask; /* attribute mask for seekdir */ + struct dirent entry; /* buffer for directory entry */ + BYTE ffbuf[BufSz]; +}; + +/* + * Return first char of filesystem type, or 0 if unknown. + */ +static char +getFSType(const char *path) +{ + static char cache[1 + 26]; + char drive[3], info[512]; + Word unit, infolen; + char r; + + if (isalpha(path[0]) && path[1] == ':') { + unit = toupper(path[0]) - '@'; + path += 2; + } else { + ULONG driveMap; +#if OS2 >= 2 + if (DosQueryCurrentDisk(&unit, &driveMap)) +#else + if (DosQCurDisk(&unit, &driveMap)) +#endif + 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'; + infolen = sizeof info; +#if OS2 >= 2 + if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen)) + return 0; + if (infolen >= sizeof(FSQBUFFER2)) { + FSQBUFFER2 *p = (FSQBUFFER2 *)info; + r = p->szFSDName[p->cbName]; + } else +#else + if (DosQFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen, 0)) + return 0; + if (infolen >= 9) { + char *p = info + sizeof(USHORT); + p += sizeof(USHORT) + *(USHORT *)p + 1 + sizeof(USHORT); + r = *p; + } else +#endif + r = 0; + 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 OS2 >= 2 + if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len)) +#else + if (DosQPathInfo((PSZ)name, FIL_QUERYFULLNAME, (PBYTE)buffer, len, 0L)) +#endif + return NULL; + return buffer; +} + +DIR * +openxdir(const char *path, unsigned att_mask) +{ + DIR *dir; + char name[MAXPATHLEN + 3]; + Word rc; + + 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->handle = HDIR_CREATE; + dir->count = 100; +#if OS2 >= 2 + rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask, + dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); +#else + rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask, + (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0); +#endif + switch (rc) { + default: + free(dir); + error(rc); + return NULL; + case NO_ERROR: + case ERROR_NO_MORE_FILES:; + } + + dir->number = 0; + dir->index = 0; + dir->next = (FFBUF *)dir->ffbuf; + + return (DIR *)dir; +} + +DIR * +opendir(const char *pathname) +{ + return openxdir(pathname, 0); +} + +struct dirent * +readdir(DIR *dir) +{ + static int dummy_ino = 2; + + if (dir->index == dir->count) { + Word rc; + dir->count = 100; +#if OS2 >= 2 + rc = DosFindNext(dir->handle, dir->ffbuf, + sizeof dir->ffbuf, &dir->count); +#else + rc = DosFindNext(dir->handle, (PFILEFINDBUF)dir->ffbuf, + sizeof dir->ffbuf, &dir->count); +#endif + if (rc) { + error(rc); + return NULL; + } + + dir->index = 0; + dir->next = (FFBUF *)dir->ffbuf; + } + + if (dir->index == dir->count) + return NULL; + + memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName); + dir->entry.d_name[dir->next->cchName] = '\0'; + dir->entry.d_ino = dummy_ino++; + dir->entry.d_reclen = dir->next->cchName; + dir->entry.d_namlen = dir->next->cchName; + dir->entry.d_size = dir->next->cbFile; + dir->entry.d_attribute = dir->next->attrFile; + dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite; + dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite; + + switch (dir->fstype) { + case 'F': /* FAT */ + case 'C': /* CDFS */ + if (dir->next->attrFile & FILE_DIRECTORY) + strupr(dir->entry.d_name); + else + strlwr(dir->entry.d_name); + } + +#if OS2 >= 2 + dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset); +#else + dir->next = (FFBUF *)((BYTE *)dir->next->achName + dir->next->cchName + 1); +#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]; + Word rc; + + DosFindClose(dir->handle); + + strcpy(name, dir->name); + strcat(name, "*"); + + dir->handle = HDIR_CREATE; + dir->count = 32767; +#if OS2 >= 2 + rc = DosFindFirst(name, &dir->handle, dir->attrmask, + dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); +#else + rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask, + (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0); +#endif + switch (rc) { + default: + error(rc); + return; + case NO_ERROR: + case ERROR_NO_MORE_FILES:; + } + + dir->number = 0; + dir->index = 0; + dir->next = (FFBUF *)dir->ffbuf; + } + + while (dir->number < off && readdir(dir)) + ; +} + +void +closedir(DIR *dir) +{ + DosFindClose(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 + +#endif /* OS2 */ |