1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/dbm/src/dirent.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,348 @@ 1.4 +#ifdef OS2 1.5 + 1.6 +#include <stdio.h> 1.7 +#include <stdlib.h> 1.8 +#include <string.h> 1.9 +#include <ctype.h> 1.10 + 1.11 +#include <dirent.h> 1.12 +#include <errno.h> 1.13 + 1.14 +/*#ifndef __EMX__ 1.15 +#include <libx.h> 1.16 +#endif */ 1.17 + 1.18 +#define INCL_DOSFILEMGR 1.19 +#define INCL_DOSERRORS 1.20 +#include <os2.h> 1.21 + 1.22 +#if OS2 >= 2 1.23 +# define FFBUF FILEFINDBUF3 1.24 +# define Word ULONG 1.25 + /* 1.26 + * LS20 recommends a request count of 100, but according to the 1.27 + * APAR text it does not lead to missing files, just to funny 1.28 + * numbers of returned entries. 1.29 + * 1.30 + * LS30 HPFS386 requires a count greater than 2, or some files 1.31 + * are missing (those starting with a character less that '.'). 1.32 + * 1.33 + * Novell loses entries which overflow the buffer. In previous 1.34 + * versions of dirent2, this could have lead to missing files 1.35 + * when the average length of 100 directory entries was 40 bytes 1.36 + * or more (quite unlikely for files on a Novell server). 1.37 + * 1.38 + * Conclusion: Make sure that the entries all fit into the buffer 1.39 + * and that the buffer is large enough for more than 2 entries 1.40 + * (each entry is at most 300 bytes long). And ignore the LS20 1.41 + * effect. 1.42 + */ 1.43 +# define Count 25 1.44 +# define BufSz (25 * (sizeof(FILEFINDBUF3)+1)) 1.45 +#else 1.46 +# define FFBUF FILEFINDBUF 1.47 +# define Word USHORT 1.48 +# define BufSz 1024 1.49 +# define Count 3 1.50 +#endif 1.51 + 1.52 +#if defined(__IBMC__) || defined(__IBMCPP__) 1.53 + #define error(rc) _doserrno = rc, errno = EOS2ERR 1.54 +#elif defined(MICROSOFT) 1.55 + #define error(rc) _doserrno = rc, errno = 255 1.56 +#else 1.57 + #define error(rc) errno = 255 1.58 +#endif 1.59 + 1.60 +struct _dirdescr { 1.61 + HDIR handle; /* DosFindFirst handle */ 1.62 + char fstype; /* filesystem type */ 1.63 + Word count; /* valid entries in <ffbuf> */ 1.64 + long number; /* absolute number of next entry */ 1.65 + int index; /* relative number of next entry */ 1.66 + FFBUF * next; /* pointer to next entry */ 1.67 + char name[MAXPATHLEN+3]; /* directory name */ 1.68 + unsigned attrmask; /* attribute mask for seekdir */ 1.69 + struct dirent entry; /* buffer for directory entry */ 1.70 + BYTE ffbuf[BufSz]; 1.71 +}; 1.72 + 1.73 +/* 1.74 + * Return first char of filesystem type, or 0 if unknown. 1.75 + */ 1.76 +static char 1.77 +getFSType(const char *path) 1.78 +{ 1.79 + static char cache[1+26]; 1.80 + char drive[3], info[512]; 1.81 + Word unit, infolen; 1.82 + char r; 1.83 + 1.84 + if (isalpha(path[0]) && path[1] == ':') { 1.85 + unit = toupper(path[0]) - '@'; 1.86 + path += 2; 1.87 + } else { 1.88 + ULONG driveMap; 1.89 +#if OS2 >= 2 1.90 + if (DosQueryCurrentDisk(&unit, &driveMap)) 1.91 +#else 1.92 + if (DosQCurDisk(&unit, &driveMap)) 1.93 +#endif 1.94 + return 0; 1.95 + } 1.96 + 1.97 + if ((path[0] == '\\' || path[0] == '/') 1.98 + && (path[1] == '\\' || path[1] == '/')) 1.99 + return 0; 1.100 + 1.101 + if (cache [unit]) 1.102 + return cache [unit]; 1.103 + 1.104 + drive[0] = '@' + unit; 1.105 + drive[1] = ':'; 1.106 + drive[2] = '\0'; 1.107 + infolen = sizeof info; 1.108 +#if OS2 >= 2 1.109 + if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen)) 1.110 + return 0; 1.111 + if (infolen >= sizeof(FSQBUFFER2)) { 1.112 + FSQBUFFER2 *p = (FSQBUFFER2 *)info; 1.113 + r = p->szFSDName[p->cbName]; 1.114 + } else 1.115 +#else 1.116 + if (DosQFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen, 0)) 1.117 + return 0; 1.118 + if (infolen >= 9) { 1.119 + char *p = info + sizeof(USHORT); 1.120 + p += sizeof(USHORT) + *(USHORT *)p + 1 + sizeof(USHORT); 1.121 + r = *p; 1.122 + } else 1.123 +#endif 1.124 + r = 0; 1.125 + return cache [unit] = r; 1.126 +} 1.127 + 1.128 +char * 1.129 +abs_path(const char *name, char *buffer, int len) 1.130 +{ 1.131 + char buf[4]; 1.132 + if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') { 1.133 + buf[0] = name[0]; 1.134 + buf[1] = name[1]; 1.135 + buf[2] = '.'; 1.136 + buf[3] = '\0'; 1.137 + name = buf; 1.138 + } 1.139 +#if OS2 >= 2 1.140 + if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len)) 1.141 +#else 1.142 + if (DosQPathInfo((PSZ)name, FIL_QUERYFULLNAME, (PBYTE)buffer, len, 0L)) 1.143 +#endif 1.144 + return NULL; 1.145 + return buffer; 1.146 +} 1.147 + 1.148 +DIR * 1.149 +openxdir(const char *path, unsigned att_mask) 1.150 +{ 1.151 + DIR *dir; 1.152 + char name[MAXPATHLEN+3]; 1.153 + Word rc; 1.154 + 1.155 + dir = malloc(sizeof(DIR)); 1.156 + if (dir == NULL) { 1.157 + errno = ENOMEM; 1.158 + return NULL; 1.159 + } 1.160 + 1.161 + strncpy(name, path, MAXPATHLEN); 1.162 + name[MAXPATHLEN] = '\0'; 1.163 + switch (name[strlen(name)-1]) { 1.164 + default: 1.165 + strcat(name, "\\"); 1.166 + case '\\': 1.167 + case '/': 1.168 + case ':': 1.169 + ; 1.170 + } 1.171 + strcat(name, "."); 1.172 + if (!abs_path(name, dir->name, MAXPATHLEN+1)) 1.173 + strcpy(dir->name, name); 1.174 + if (dir->name[strlen(dir->name)-1] == '\\') 1.175 + strcat(dir->name, "*"); 1.176 + else 1.177 + strcat(dir->name, "\\*"); 1.178 + 1.179 + dir->fstype = getFSType(dir->name); 1.180 + dir->attrmask = att_mask | A_DIR; 1.181 + 1.182 + dir->handle = HDIR_CREATE; 1.183 + dir->count = 100; 1.184 +#if OS2 >= 2 1.185 + rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask, 1.186 + dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); 1.187 +#else 1.188 + rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask, 1.189 + (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0); 1.190 +#endif 1.191 + switch (rc) { 1.192 + default: 1.193 + free(dir); 1.194 + error(rc); 1.195 + return NULL; 1.196 + case NO_ERROR: 1.197 + case ERROR_NO_MORE_FILES: 1.198 + ; 1.199 + } 1.200 + 1.201 + dir->number = 0; 1.202 + dir->index = 0; 1.203 + dir->next = (FFBUF *)dir->ffbuf; 1.204 + 1.205 + return (DIR *)dir; 1.206 +} 1.207 + 1.208 +DIR * 1.209 +opendir(const char *pathname) 1.210 +{ 1.211 + return openxdir(pathname, 0); 1.212 +} 1.213 + 1.214 +struct dirent * 1.215 +readdir(DIR *dir) 1.216 +{ 1.217 + static int dummy_ino = 2; 1.218 + 1.219 + if (dir->index == dir->count) { 1.220 + Word rc; 1.221 + dir->count = 100; 1.222 +#if OS2 >= 2 1.223 + rc = DosFindNext(dir->handle, dir->ffbuf, 1.224 + sizeof dir->ffbuf, &dir->count); 1.225 +#else 1.226 + rc = DosFindNext(dir->handle, (PFILEFINDBUF)dir->ffbuf, 1.227 + sizeof dir->ffbuf, &dir->count); 1.228 +#endif 1.229 + if (rc) { 1.230 + error(rc); 1.231 + return NULL; 1.232 + } 1.233 + 1.234 + dir->index = 0; 1.235 + dir->next = (FFBUF *)dir->ffbuf; 1.236 + } 1.237 + 1.238 + if (dir->index == dir->count) 1.239 + return NULL; 1.240 + 1.241 + memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName); 1.242 + dir->entry.d_name[dir->next->cchName] = '\0'; 1.243 + dir->entry.d_ino = dummy_ino++; 1.244 + dir->entry.d_reclen = dir->next->cchName; 1.245 + dir->entry.d_namlen = dir->next->cchName; 1.246 + dir->entry.d_size = dir->next->cbFile; 1.247 + dir->entry.d_attribute = dir->next->attrFile; 1.248 + dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite; 1.249 + dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite; 1.250 + 1.251 + switch (dir->fstype) { 1.252 + case 'F': /* FAT */ 1.253 + case 'C': /* CDFS */ 1.254 + if (dir->next->attrFile & FILE_DIRECTORY) 1.255 + strupr(dir->entry.d_name); 1.256 + else 1.257 + strlwr(dir->entry.d_name); 1.258 + } 1.259 + 1.260 +#if OS2 >= 2 1.261 + dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset); 1.262 +#else 1.263 + dir->next = (FFBUF *)((BYTE *)dir->next->achName + dir->next->cchName + 1); 1.264 +#endif 1.265 + ++dir->number; 1.266 + ++dir->index; 1.267 + 1.268 + return &dir->entry; 1.269 +} 1.270 + 1.271 +long 1.272 +telldir(DIR *dir) 1.273 +{ 1.274 + return dir->number; 1.275 +} 1.276 + 1.277 +void 1.278 +seekdir(DIR *dir, long off) 1.279 +{ 1.280 + if (dir->number > off) { 1.281 + char name[MAXPATHLEN+2]; 1.282 + Word rc; 1.283 + 1.284 + DosFindClose(dir->handle); 1.285 + 1.286 + strcpy(name, dir->name); 1.287 + strcat(name, "*"); 1.288 + 1.289 + dir->handle = HDIR_CREATE; 1.290 + dir->count = 32767; 1.291 +#if OS2 >= 2 1.292 + rc = DosFindFirst(name, &dir->handle, dir->attrmask, 1.293 + dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD); 1.294 +#else 1.295 + rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask, 1.296 + (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0); 1.297 +#endif 1.298 + switch (rc) { 1.299 + default: 1.300 + error(rc); 1.301 + return; 1.302 + case NO_ERROR: 1.303 + case ERROR_NO_MORE_FILES: 1.304 + ; 1.305 + } 1.306 + 1.307 + dir->number = 0; 1.308 + dir->index = 0; 1.309 + dir->next = (FFBUF *)dir->ffbuf; 1.310 + } 1.311 + 1.312 + while (dir->number < off && readdir(dir)) 1.313 + ; 1.314 +} 1.315 + 1.316 +void 1.317 +closedir(DIR *dir) 1.318 +{ 1.319 + DosFindClose(dir->handle); 1.320 + free(dir); 1.321 +} 1.322 + 1.323 +/*****************************************************************************/ 1.324 + 1.325 +#ifdef TEST 1.326 + 1.327 +main(int argc, char **argv) 1.328 +{ 1.329 + int i; 1.330 + DIR *dir; 1.331 + struct dirent *ep; 1.332 + 1.333 + for (i = 1; i < argc; ++i) { 1.334 + dir = opendir(argv[i]); 1.335 + if (!dir) 1.336 + continue; 1.337 + while (ep = readdir(dir)) 1.338 + if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1])) 1.339 + printf("%s%s\n", argv[i], ep->d_name); 1.340 + else 1.341 + printf("%s/%s\n", argv[i], ep->d_name); 1.342 + closedir(dir); 1.343 + } 1.344 + 1.345 + return 0; 1.346 +} 1.347 + 1.348 +#endif 1.349 + 1.350 +#endif /* OS2 */ 1.351 +