Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 |