security/nss/lib/dbm/src/dirent.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 #ifdef OS2
michael@0 2
michael@0 3 #include <stdio.h>
michael@0 4 #include <stdlib.h>
michael@0 5 #include <string.h>
michael@0 6 #include <ctype.h>
michael@0 7
michael@0 8 #include <dirent.h>
michael@0 9 #include <errno.h>
michael@0 10
michael@0 11 /*#ifndef __EMX__
michael@0 12 #include <libx.h>
michael@0 13 #endif */
michael@0 14
michael@0 15 #define INCL_DOSFILEMGR
michael@0 16 #define INCL_DOSERRORS
michael@0 17 #include <os2.h>
michael@0 18
michael@0 19 #if OS2 >= 2
michael@0 20 # define FFBUF FILEFINDBUF3
michael@0 21 # define Word ULONG
michael@0 22 /*
michael@0 23 * LS20 recommends a request count of 100, but according to the
michael@0 24 * APAR text it does not lead to missing files, just to funny
michael@0 25 * numbers of returned entries.
michael@0 26 *
michael@0 27 * LS30 HPFS386 requires a count greater than 2, or some files
michael@0 28 * are missing (those starting with a character less that '.').
michael@0 29 *
michael@0 30 * Novell loses entries which overflow the buffer. In previous
michael@0 31 * versions of dirent2, this could have lead to missing files
michael@0 32 * when the average length of 100 directory entries was 40 bytes
michael@0 33 * or more (quite unlikely for files on a Novell server).
michael@0 34 *
michael@0 35 * Conclusion: Make sure that the entries all fit into the buffer
michael@0 36 * and that the buffer is large enough for more than 2 entries
michael@0 37 * (each entry is at most 300 bytes long). And ignore the LS20
michael@0 38 * effect.
michael@0 39 */
michael@0 40 # define Count 25
michael@0 41 # define BufSz (25 * (sizeof(FILEFINDBUF3)+1))
michael@0 42 #else
michael@0 43 # define FFBUF FILEFINDBUF
michael@0 44 # define Word USHORT
michael@0 45 # define BufSz 1024
michael@0 46 # define Count 3
michael@0 47 #endif
michael@0 48
michael@0 49 #if defined(__IBMC__) || defined(__IBMCPP__)
michael@0 50 #define error(rc) _doserrno = rc, errno = EOS2ERR
michael@0 51 #elif defined(MICROSOFT)
michael@0 52 #define error(rc) _doserrno = rc, errno = 255
michael@0 53 #else
michael@0 54 #define error(rc) errno = 255
michael@0 55 #endif
michael@0 56
michael@0 57 struct _dirdescr {
michael@0 58 HDIR handle; /* DosFindFirst handle */
michael@0 59 char fstype; /* filesystem type */
michael@0 60 Word count; /* valid entries in <ffbuf> */
michael@0 61 long number; /* absolute number of next entry */
michael@0 62 int index; /* relative number of next entry */
michael@0 63 FFBUF * next; /* pointer to next entry */
michael@0 64 char name[MAXPATHLEN+3]; /* directory name */
michael@0 65 unsigned attrmask; /* attribute mask for seekdir */
michael@0 66 struct dirent entry; /* buffer for directory entry */
michael@0 67 BYTE ffbuf[BufSz];
michael@0 68 };
michael@0 69
michael@0 70 /*
michael@0 71 * Return first char of filesystem type, or 0 if unknown.
michael@0 72 */
michael@0 73 static char
michael@0 74 getFSType(const char *path)
michael@0 75 {
michael@0 76 static char cache[1+26];
michael@0 77 char drive[3], info[512];
michael@0 78 Word unit, infolen;
michael@0 79 char r;
michael@0 80
michael@0 81 if (isalpha(path[0]) && path[1] == ':') {
michael@0 82 unit = toupper(path[0]) - '@';
michael@0 83 path += 2;
michael@0 84 } else {
michael@0 85 ULONG driveMap;
michael@0 86 #if OS2 >= 2
michael@0 87 if (DosQueryCurrentDisk(&unit, &driveMap))
michael@0 88 #else
michael@0 89 if (DosQCurDisk(&unit, &driveMap))
michael@0 90 #endif
michael@0 91 return 0;
michael@0 92 }
michael@0 93
michael@0 94 if ((path[0] == '\\' || path[0] == '/')
michael@0 95 && (path[1] == '\\' || path[1] == '/'))
michael@0 96 return 0;
michael@0 97
michael@0 98 if (cache [unit])
michael@0 99 return cache [unit];
michael@0 100
michael@0 101 drive[0] = '@' + unit;
michael@0 102 drive[1] = ':';
michael@0 103 drive[2] = '\0';
michael@0 104 infolen = sizeof info;
michael@0 105 #if OS2 >= 2
michael@0 106 if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen))
michael@0 107 return 0;
michael@0 108 if (infolen >= sizeof(FSQBUFFER2)) {
michael@0 109 FSQBUFFER2 *p = (FSQBUFFER2 *)info;
michael@0 110 r = p->szFSDName[p->cbName];
michael@0 111 } else
michael@0 112 #else
michael@0 113 if (DosQFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen, 0))
michael@0 114 return 0;
michael@0 115 if (infolen >= 9) {
michael@0 116 char *p = info + sizeof(USHORT);
michael@0 117 p += sizeof(USHORT) + *(USHORT *)p + 1 + sizeof(USHORT);
michael@0 118 r = *p;
michael@0 119 } else
michael@0 120 #endif
michael@0 121 r = 0;
michael@0 122 return cache [unit] = r;
michael@0 123 }
michael@0 124
michael@0 125 char *
michael@0 126 abs_path(const char *name, char *buffer, int len)
michael@0 127 {
michael@0 128 char buf[4];
michael@0 129 if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') {
michael@0 130 buf[0] = name[0];
michael@0 131 buf[1] = name[1];
michael@0 132 buf[2] = '.';
michael@0 133 buf[3] = '\0';
michael@0 134 name = buf;
michael@0 135 }
michael@0 136 #if OS2 >= 2
michael@0 137 if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len))
michael@0 138 #else
michael@0 139 if (DosQPathInfo((PSZ)name, FIL_QUERYFULLNAME, (PBYTE)buffer, len, 0L))
michael@0 140 #endif
michael@0 141 return NULL;
michael@0 142 return buffer;
michael@0 143 }
michael@0 144
michael@0 145 DIR *
michael@0 146 openxdir(const char *path, unsigned att_mask)
michael@0 147 {
michael@0 148 DIR *dir;
michael@0 149 char name[MAXPATHLEN+3];
michael@0 150 Word rc;
michael@0 151
michael@0 152 dir = malloc(sizeof(DIR));
michael@0 153 if (dir == NULL) {
michael@0 154 errno = ENOMEM;
michael@0 155 return NULL;
michael@0 156 }
michael@0 157
michael@0 158 strncpy(name, path, MAXPATHLEN);
michael@0 159 name[MAXPATHLEN] = '\0';
michael@0 160 switch (name[strlen(name)-1]) {
michael@0 161 default:
michael@0 162 strcat(name, "\\");
michael@0 163 case '\\':
michael@0 164 case '/':
michael@0 165 case ':':
michael@0 166 ;
michael@0 167 }
michael@0 168 strcat(name, ".");
michael@0 169 if (!abs_path(name, dir->name, MAXPATHLEN+1))
michael@0 170 strcpy(dir->name, name);
michael@0 171 if (dir->name[strlen(dir->name)-1] == '\\')
michael@0 172 strcat(dir->name, "*");
michael@0 173 else
michael@0 174 strcat(dir->name, "\\*");
michael@0 175
michael@0 176 dir->fstype = getFSType(dir->name);
michael@0 177 dir->attrmask = att_mask | A_DIR;
michael@0 178
michael@0 179 dir->handle = HDIR_CREATE;
michael@0 180 dir->count = 100;
michael@0 181 #if OS2 >= 2
michael@0 182 rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask,
michael@0 183 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
michael@0 184 #else
michael@0 185 rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask,
michael@0 186 (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
michael@0 187 #endif
michael@0 188 switch (rc) {
michael@0 189 default:
michael@0 190 free(dir);
michael@0 191 error(rc);
michael@0 192 return NULL;
michael@0 193 case NO_ERROR:
michael@0 194 case ERROR_NO_MORE_FILES:
michael@0 195 ;
michael@0 196 }
michael@0 197
michael@0 198 dir->number = 0;
michael@0 199 dir->index = 0;
michael@0 200 dir->next = (FFBUF *)dir->ffbuf;
michael@0 201
michael@0 202 return (DIR *)dir;
michael@0 203 }
michael@0 204
michael@0 205 DIR *
michael@0 206 opendir(const char *pathname)
michael@0 207 {
michael@0 208 return openxdir(pathname, 0);
michael@0 209 }
michael@0 210
michael@0 211 struct dirent *
michael@0 212 readdir(DIR *dir)
michael@0 213 {
michael@0 214 static int dummy_ino = 2;
michael@0 215
michael@0 216 if (dir->index == dir->count) {
michael@0 217 Word rc;
michael@0 218 dir->count = 100;
michael@0 219 #if OS2 >= 2
michael@0 220 rc = DosFindNext(dir->handle, dir->ffbuf,
michael@0 221 sizeof dir->ffbuf, &dir->count);
michael@0 222 #else
michael@0 223 rc = DosFindNext(dir->handle, (PFILEFINDBUF)dir->ffbuf,
michael@0 224 sizeof dir->ffbuf, &dir->count);
michael@0 225 #endif
michael@0 226 if (rc) {
michael@0 227 error(rc);
michael@0 228 return NULL;
michael@0 229 }
michael@0 230
michael@0 231 dir->index = 0;
michael@0 232 dir->next = (FFBUF *)dir->ffbuf;
michael@0 233 }
michael@0 234
michael@0 235 if (dir->index == dir->count)
michael@0 236 return NULL;
michael@0 237
michael@0 238 memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName);
michael@0 239 dir->entry.d_name[dir->next->cchName] = '\0';
michael@0 240 dir->entry.d_ino = dummy_ino++;
michael@0 241 dir->entry.d_reclen = dir->next->cchName;
michael@0 242 dir->entry.d_namlen = dir->next->cchName;
michael@0 243 dir->entry.d_size = dir->next->cbFile;
michael@0 244 dir->entry.d_attribute = dir->next->attrFile;
michael@0 245 dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite;
michael@0 246 dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite;
michael@0 247
michael@0 248 switch (dir->fstype) {
michael@0 249 case 'F': /* FAT */
michael@0 250 case 'C': /* CDFS */
michael@0 251 if (dir->next->attrFile & FILE_DIRECTORY)
michael@0 252 strupr(dir->entry.d_name);
michael@0 253 else
michael@0 254 strlwr(dir->entry.d_name);
michael@0 255 }
michael@0 256
michael@0 257 #if OS2 >= 2
michael@0 258 dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset);
michael@0 259 #else
michael@0 260 dir->next = (FFBUF *)((BYTE *)dir->next->achName + dir->next->cchName + 1);
michael@0 261 #endif
michael@0 262 ++dir->number;
michael@0 263 ++dir->index;
michael@0 264
michael@0 265 return &dir->entry;
michael@0 266 }
michael@0 267
michael@0 268 long
michael@0 269 telldir(DIR *dir)
michael@0 270 {
michael@0 271 return dir->number;
michael@0 272 }
michael@0 273
michael@0 274 void
michael@0 275 seekdir(DIR *dir, long off)
michael@0 276 {
michael@0 277 if (dir->number > off) {
michael@0 278 char name[MAXPATHLEN+2];
michael@0 279 Word rc;
michael@0 280
michael@0 281 DosFindClose(dir->handle);
michael@0 282
michael@0 283 strcpy(name, dir->name);
michael@0 284 strcat(name, "*");
michael@0 285
michael@0 286 dir->handle = HDIR_CREATE;
michael@0 287 dir->count = 32767;
michael@0 288 #if OS2 >= 2
michael@0 289 rc = DosFindFirst(name, &dir->handle, dir->attrmask,
michael@0 290 dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
michael@0 291 #else
michael@0 292 rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask,
michael@0 293 (PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
michael@0 294 #endif
michael@0 295 switch (rc) {
michael@0 296 default:
michael@0 297 error(rc);
michael@0 298 return;
michael@0 299 case NO_ERROR:
michael@0 300 case ERROR_NO_MORE_FILES:
michael@0 301 ;
michael@0 302 }
michael@0 303
michael@0 304 dir->number = 0;
michael@0 305 dir->index = 0;
michael@0 306 dir->next = (FFBUF *)dir->ffbuf;
michael@0 307 }
michael@0 308
michael@0 309 while (dir->number < off && readdir(dir))
michael@0 310 ;
michael@0 311 }
michael@0 312
michael@0 313 void
michael@0 314 closedir(DIR *dir)
michael@0 315 {
michael@0 316 DosFindClose(dir->handle);
michael@0 317 free(dir);
michael@0 318 }
michael@0 319
michael@0 320 /*****************************************************************************/
michael@0 321
michael@0 322 #ifdef TEST
michael@0 323
michael@0 324 main(int argc, char **argv)
michael@0 325 {
michael@0 326 int i;
michael@0 327 DIR *dir;
michael@0 328 struct dirent *ep;
michael@0 329
michael@0 330 for (i = 1; i < argc; ++i) {
michael@0 331 dir = opendir(argv[i]);
michael@0 332 if (!dir)
michael@0 333 continue;
michael@0 334 while (ep = readdir(dir))
michael@0 335 if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1]))
michael@0 336 printf("%s%s\n", argv[i], ep->d_name);
michael@0 337 else
michael@0 338 printf("%s/%s\n", argv[i], ep->d_name);
michael@0 339 closedir(dir);
michael@0 340 }
michael@0 341
michael@0 342 return 0;
michael@0 343 }
michael@0 344
michael@0 345 #endif
michael@0 346
michael@0 347 #endif /* OS2 */
michael@0 348

mercurial