nsprpub/pr/src/md/os2/os2io.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /* OS2 IO module
michael@0 7 *
michael@0 8 * Assumes synchronous I/O.
michael@0 9 *
michael@0 10 */
michael@0 11
michael@0 12 #include "primpl.h"
michael@0 13 #include "prio.h"
michael@0 14 #include <ctype.h>
michael@0 15 #include <string.h>
michael@0 16 #include <limits.h>
michael@0 17 #include <dirent.h>
michael@0 18 #include <fcntl.h>
michael@0 19 #include <io.h>
michael@0 20
michael@0 21 struct _MDLock _pr_ioq_lock;
michael@0 22
michael@0 23 static PRBool isWSEB = PR_FALSE; /* whether we are using an OS/2 kernel that supports large files */
michael@0 24
michael@0 25 typedef APIRET (*DosOpenLType)(PSZ pszFileName, PHFILE pHf, PULONG pulAction,
michael@0 26 LONGLONG cbFile, ULONG ulAttribute,
michael@0 27 ULONG fsOpenFlags, ULONG fsOpenMode,
michael@0 28 PEAOP2 peaop2);
michael@0 29
michael@0 30 typedef APIRET (*DosSetFileLocksLType)(HFILE hFile, PFILELOCKL pflUnlock,
michael@0 31 PFILELOCKL pflLock, ULONG timeout,
michael@0 32 ULONG flags);
michael@0 33
michael@0 34 typedef APIRET (*DosSetFilePtrLType)(HFILE hFile, LONGLONG ib, ULONG method,
michael@0 35 PLONGLONG ibActual);
michael@0 36
michael@0 37 DosOpenLType myDosOpenL;
michael@0 38 DosSetFileLocksLType myDosSetFileLocksL;
michael@0 39 DosSetFilePtrLType myDosSetFilePtrL;
michael@0 40
michael@0 41 void
michael@0 42 _PR_MD_INIT_IO()
michael@0 43 {
michael@0 44 APIRET rc;
michael@0 45 HMODULE module;
michael@0 46
michael@0 47 sock_init();
michael@0 48
michael@0 49 rc = DosLoadModule(NULL, 0, "DOSCALL1", &module);
michael@0 50 if (rc != NO_ERROR)
michael@0 51 {
michael@0 52 return;
michael@0 53 }
michael@0 54 rc = DosQueryProcAddr(module, 981, NULL, (PFN*) &myDosOpenL);
michael@0 55 if (rc != NO_ERROR)
michael@0 56 {
michael@0 57 return;
michael@0 58 }
michael@0 59 rc = DosQueryProcAddr(module, 986, NULL, (PFN*) &myDosSetFileLocksL);
michael@0 60 if (rc != NO_ERROR)
michael@0 61 {
michael@0 62 return;
michael@0 63 }
michael@0 64 rc = DosQueryProcAddr(module, 988, NULL, (PFN*) &myDosSetFilePtrL);
michael@0 65 if (rc != NO_ERROR)
michael@0 66 {
michael@0 67 return;
michael@0 68 }
michael@0 69 isWSEB = PR_TRUE;
michael@0 70 }
michael@0 71
michael@0 72 PRStatus
michael@0 73 _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
michael@0 74 {
michael@0 75 PRInt32 rv;
michael@0 76 ULONG count;
michael@0 77
michael@0 78 PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
michael@0 79 SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks);
michael@0 80 rv = DosWaitEventSem(thread->md.blocked_sema, msecs);
michael@0 81 DosResetEventSem(thread->md.blocked_sema, &count);
michael@0 82 switch(rv)
michael@0 83 {
michael@0 84 case NO_ERROR:
michael@0 85 return PR_SUCCESS;
michael@0 86 break;
michael@0 87 case ERROR_TIMEOUT:
michael@0 88 _PR_THREAD_LOCK(thread);
michael@0 89 if (thread->state == _PR_IO_WAIT) {
michael@0 90 ;
michael@0 91 } else {
michael@0 92 if (thread->wait.cvar != NULL) {
michael@0 93 thread->wait.cvar = NULL;
michael@0 94 _PR_THREAD_UNLOCK(thread);
michael@0 95 } else {
michael@0 96 /* The CVAR was notified just as the timeout
michael@0 97 * occurred. This led to us being notified twice.
michael@0 98 * call SemRequest() to clear the semaphore.
michael@0 99 */
michael@0 100 _PR_THREAD_UNLOCK(thread);
michael@0 101 rv = DosWaitEventSem(thread->md.blocked_sema, 0);
michael@0 102 DosResetEventSem(thread->md.blocked_sema, &count);
michael@0 103 PR_ASSERT(rv == NO_ERROR);
michael@0 104 }
michael@0 105 }
michael@0 106 return PR_SUCCESS;
michael@0 107 break;
michael@0 108 default:
michael@0 109 break;
michael@0 110 }
michael@0 111 return PR_FAILURE;
michael@0 112 }
michael@0 113 PRStatus
michael@0 114 _PR_MD_WAKEUP_WAITER(PRThread *thread)
michael@0 115 {
michael@0 116 if ( _PR_IS_NATIVE_THREAD(thread) )
michael@0 117 {
michael@0 118 if (DosPostEventSem(thread->md.blocked_sema) != NO_ERROR)
michael@0 119 return PR_FAILURE;
michael@0 120 else
michael@0 121 return PR_SUCCESS;
michael@0 122 }
michael@0 123 }
michael@0 124
michael@0 125
michael@0 126 /* --- FILE IO ----------------------------------------------------------- */
michael@0 127 /*
michael@0 128 * _PR_MD_OPEN() -- Open a file
michael@0 129 *
michael@0 130 * returns: a fileHandle
michael@0 131 *
michael@0 132 * The NSPR open flags (osflags) are translated into flags for OS/2
michael@0 133 *
michael@0 134 * Mode seems to be passed in as a unix style file permissions argument
michael@0 135 * as in 0666, in the case of opening the logFile.
michael@0 136 *
michael@0 137 */
michael@0 138 PRInt32
michael@0 139 _PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
michael@0 140 {
michael@0 141 HFILE file;
michael@0 142 PRInt32 access = OPEN_SHARE_DENYNONE;
michael@0 143 PRInt32 flags = 0L;
michael@0 144 APIRET rc = 0;
michael@0 145 PRUword actionTaken;
michael@0 146
michael@0 147 #ifdef MOZ_OS2_HIGH_MEMORY
michael@0 148 /*
michael@0 149 * All the pointer arguments (&file, &actionTaken and name) have to be in
michael@0 150 * low memory for DosOpen to use them.
michael@0 151 * The following moves name to low memory.
michael@0 152 */
michael@0 153 if ((ULONG)name >= 0x20000000)
michael@0 154 {
michael@0 155 size_t len = strlen(name) + 1;
michael@0 156 char *copy = (char *)alloca(len);
michael@0 157 memcpy(copy, name, len);
michael@0 158 name = copy;
michael@0 159 }
michael@0 160 #endif
michael@0 161
michael@0 162 if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH;
michael@0 163
michael@0 164 if (osflags & PR_RDONLY)
michael@0 165 access |= OPEN_ACCESS_READONLY;
michael@0 166 else if (osflags & PR_WRONLY)
michael@0 167 access |= OPEN_ACCESS_WRITEONLY;
michael@0 168 else if(osflags & PR_RDWR)
michael@0 169 access |= OPEN_ACCESS_READWRITE;
michael@0 170
michael@0 171 if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
michael@0 172 {
michael@0 173 flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
michael@0 174 }
michael@0 175 else if (osflags & PR_CREATE_FILE)
michael@0 176 {
michael@0 177 if (osflags & PR_TRUNCATE)
michael@0 178 flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
michael@0 179 else
michael@0 180 flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
michael@0 181 }
michael@0 182 else
michael@0 183 {
michael@0 184 if (osflags & PR_TRUNCATE)
michael@0 185 flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
michael@0 186 else
michael@0 187 flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
michael@0 188 }
michael@0 189
michael@0 190 do {
michael@0 191 if (isWSEB)
michael@0 192 {
michael@0 193 rc = myDosOpenL((char*)name,
michael@0 194 &file, /* file handle if successful */
michael@0 195 &actionTaken, /* reason for failure */
michael@0 196 0, /* initial size of new file */
michael@0 197 FILE_NORMAL, /* file system attributes */
michael@0 198 flags, /* Open flags */
michael@0 199 access, /* Open mode and rights */
michael@0 200 0); /* OS/2 Extended Attributes */
michael@0 201 }
michael@0 202 else
michael@0 203 {
michael@0 204 rc = DosOpen((char*)name,
michael@0 205 &file, /* file handle if successful */
michael@0 206 &actionTaken, /* reason for failure */
michael@0 207 0, /* initial size of new file */
michael@0 208 FILE_NORMAL, /* file system attributes */
michael@0 209 flags, /* Open flags */
michael@0 210 access, /* Open mode and rights */
michael@0 211 0); /* OS/2 Extended Attributes */
michael@0 212 };
michael@0 213 if (rc == ERROR_TOO_MANY_OPEN_FILES) {
michael@0 214 ULONG CurMaxFH = 0;
michael@0 215 LONG ReqCount = 20;
michael@0 216 APIRET rc2;
michael@0 217 rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
michael@0 218 if (rc2 != NO_ERROR) {
michael@0 219 break;
michael@0 220 }
michael@0 221 }
michael@0 222 } while (rc == ERROR_TOO_MANY_OPEN_FILES);
michael@0 223
michael@0 224 if (rc != NO_ERROR) {
michael@0 225 _PR_MD_MAP_OPEN_ERROR(rc);
michael@0 226 return -1;
michael@0 227 }
michael@0 228
michael@0 229 return (PRInt32)file;
michael@0 230 }
michael@0 231
michael@0 232 PRInt32
michael@0 233 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
michael@0 234 {
michael@0 235 ULONG bytes;
michael@0 236 int rv;
michael@0 237
michael@0 238 rv = DosRead((HFILE)fd->secret->md.osfd,
michael@0 239 (PVOID)buf,
michael@0 240 len,
michael@0 241 &bytes);
michael@0 242
michael@0 243 if (rv != NO_ERROR)
michael@0 244 {
michael@0 245 /* ERROR_HANDLE_EOF can only be returned by async io */
michael@0 246 PR_ASSERT(rv != ERROR_HANDLE_EOF);
michael@0 247 if (rv == ERROR_BROKEN_PIPE)
michael@0 248 return 0;
michael@0 249 else {
michael@0 250 _PR_MD_MAP_READ_ERROR(rv);
michael@0 251 return -1;
michael@0 252 }
michael@0 253 }
michael@0 254 return (PRInt32)bytes;
michael@0 255 }
michael@0 256
michael@0 257 PRInt32
michael@0 258 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
michael@0 259 {
michael@0 260 PRInt32 bytes;
michael@0 261 int rv;
michael@0 262
michael@0 263 rv = DosWrite((HFILE)fd->secret->md.osfd,
michael@0 264 (PVOID)buf,
michael@0 265 len,
michael@0 266 (PULONG)&bytes);
michael@0 267
michael@0 268 if (rv != NO_ERROR)
michael@0 269 {
michael@0 270 _PR_MD_MAP_WRITE_ERROR(rv);
michael@0 271 return -1;
michael@0 272 }
michael@0 273
michael@0 274 if (len != bytes) {
michael@0 275 rv = ERROR_DISK_FULL;
michael@0 276 _PR_MD_MAP_WRITE_ERROR(rv);
michael@0 277 return -1;
michael@0 278 }
michael@0 279
michael@0 280 return bytes;
michael@0 281 } /* --- end _PR_MD_WRITE() --- */
michael@0 282
michael@0 283 PRInt32
michael@0 284 _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
michael@0 285 {
michael@0 286 PRInt32 rv;
michael@0 287 PRUword newLocation;
michael@0 288
michael@0 289 rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation);
michael@0 290
michael@0 291 if (rv != NO_ERROR) {
michael@0 292 _PR_MD_MAP_LSEEK_ERROR(rv);
michael@0 293 return -1;
michael@0 294 } else
michael@0 295 return newLocation;
michael@0 296 }
michael@0 297
michael@0 298 PRInt64
michael@0 299 _PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
michael@0 300 {
michael@0 301 #ifdef NO_LONG_LONG
michael@0 302 PRInt64 result;
michael@0 303 PRInt32 rv, low = offset.lo, hi = offset.hi;
michael@0 304 PRUword newLocation;
michael@0 305
michael@0 306 rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation);
michael@0 307 rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation);
michael@0 308
michael@0 309 if (rv != NO_ERROR) {
michael@0 310 _PR_MD_MAP_LSEEK_ERROR(rv);
michael@0 311 hi = newLocation = -1;
michael@0 312 }
michael@0 313
michael@0 314 result.lo = newLocation;
michael@0 315 result.hi = hi;
michael@0 316 return result;
michael@0 317
michael@0 318 #else
michael@0 319 PRInt32 where, rc, lo = (PRInt32)offset, hi = (PRInt32)(offset >> 32);
michael@0 320 PRUint64 rv;
michael@0 321 PRUint32 newLocation, uhi;
michael@0 322 PRUint64 newLocationL;
michael@0 323
michael@0 324 switch (whence)
michael@0 325 {
michael@0 326 case PR_SEEK_SET:
michael@0 327 where = FILE_BEGIN;
michael@0 328 break;
michael@0 329 case PR_SEEK_CUR:
michael@0 330 where = FILE_CURRENT;
michael@0 331 break;
michael@0 332 case PR_SEEK_END:
michael@0 333 where = FILE_END;
michael@0 334 break;
michael@0 335 default:
michael@0 336 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
michael@0 337 return -1;
michael@0 338 }
michael@0 339 if (isWSEB)
michael@0 340 {
michael@0 341 rc = myDosSetFilePtrL((HFILE)fd->secret->md.osfd, offset, where, (PLONGLONG)&newLocationL);
michael@0 342 }
michael@0 343 else
michael@0 344 {
michael@0 345 rc = DosSetFilePtr((HFILE)fd->secret->md.osfd, lo, where, (PULONG)&newLocation);
michael@0 346 }
michael@0 347
michael@0 348 if (rc != NO_ERROR) {
michael@0 349 _PR_MD_MAP_LSEEK_ERROR(rc);
michael@0 350 return -1;
michael@0 351 }
michael@0 352
michael@0 353 if (isWSEB)
michael@0 354 {
michael@0 355 return newLocationL;
michael@0 356 }
michael@0 357
michael@0 358 uhi = (PRUint32)hi;
michael@0 359 PR_ASSERT((PRInt32)uhi >= 0);
michael@0 360 rv = uhi;
michael@0 361 PR_ASSERT((PRInt64)rv >= 0);
michael@0 362 rv = (rv << 32);
michael@0 363 PR_ASSERT((PRInt64)rv >= 0);
michael@0 364 rv += newLocation;
michael@0 365 PR_ASSERT((PRInt64)rv >= 0);
michael@0 366 return (PRInt64)rv;
michael@0 367 #endif
michael@0 368 }
michael@0 369
michael@0 370 PRInt32
michael@0 371 _PR_MD_FSYNC(PRFileDesc *fd)
michael@0 372 {
michael@0 373 PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd);
michael@0 374
michael@0 375 if (rc != NO_ERROR) {
michael@0 376 if (rc != ERROR_ACCESS_DENIED) {
michael@0 377 _PR_MD_MAP_FSYNC_ERROR(rc);
michael@0 378 return -1;
michael@0 379 }
michael@0 380 }
michael@0 381 return 0;
michael@0 382 }
michael@0 383
michael@0 384 PRInt32
michael@0 385 _MD_CloseFile(PRInt32 osfd)
michael@0 386 {
michael@0 387 PRInt32 rv;
michael@0 388
michael@0 389 rv = DosClose((HFILE)osfd);
michael@0 390 if (rv != NO_ERROR)
michael@0 391 _PR_MD_MAP_CLOSE_ERROR(rv);
michael@0 392 return rv;
michael@0 393 }
michael@0 394
michael@0 395
michael@0 396 /* --- DIR IO ------------------------------------------------------------ */
michael@0 397 #define GetFileFromDIR(d) (isWSEB?(d)->d_entry.large.achName:(d)->d_entry.small.achName)
michael@0 398 #define GetFileAttr(d) (isWSEB?(d)->d_entry.large.attrFile:(d)->d_entry.small.attrFile)
michael@0 399
michael@0 400 void FlipSlashes(char *cp, int len)
michael@0 401 {
michael@0 402 while (--len >= 0) {
michael@0 403 if (cp[0] == '/') {
michael@0 404 cp[0] = PR_DIRECTORY_SEPARATOR;
michael@0 405 }
michael@0 406 cp++;
michael@0 407 }
michael@0 408 }
michael@0 409
michael@0 410 /*
michael@0 411 **
michael@0 412 ** Local implementations of standard Unix RTL functions which are not provided
michael@0 413 ** by the VAC RTL.
michael@0 414 **
michael@0 415 */
michael@0 416
michael@0 417 PRInt32
michael@0 418 _PR_MD_CLOSE_DIR(_MDDir *d)
michael@0 419 {
michael@0 420 PRInt32 rc;
michael@0 421
michael@0 422 if ( d ) {
michael@0 423 rc = DosFindClose(d->d_hdl);
michael@0 424 if(rc == NO_ERROR){
michael@0 425 d->magic = (PRUint32)-1;
michael@0 426 return PR_SUCCESS;
michael@0 427 } else {
michael@0 428 _PR_MD_MAP_CLOSEDIR_ERROR(rc);
michael@0 429 return PR_FAILURE;
michael@0 430 }
michael@0 431 }
michael@0 432 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
michael@0 433 return PR_FAILURE;
michael@0 434 }
michael@0 435
michael@0 436
michael@0 437 PRStatus
michael@0 438 _PR_MD_OPEN_DIR(_MDDir *d, const char *name)
michael@0 439 {
michael@0 440 char filename[ CCHMAXPATH ];
michael@0 441 PRUword numEntries, rc;
michael@0 442
michael@0 443 numEntries = 1;
michael@0 444
michael@0 445 PR_snprintf(filename, CCHMAXPATH, "%s%s%s",
michael@0 446 name, PR_DIRECTORY_SEPARATOR_STR, "*.*");
michael@0 447 FlipSlashes( filename, strlen(filename) );
michael@0 448
michael@0 449 d->d_hdl = HDIR_CREATE;
michael@0 450
michael@0 451 if (isWSEB)
michael@0 452 {
michael@0 453 rc = DosFindFirst( filename,
michael@0 454 &d->d_hdl,
michael@0 455 FILE_DIRECTORY | FILE_HIDDEN,
michael@0 456 &(d->d_entry.large),
michael@0 457 sizeof(d->d_entry.large),
michael@0 458 &numEntries,
michael@0 459 FIL_STANDARDL);
michael@0 460 }
michael@0 461 else
michael@0 462 {
michael@0 463 rc = DosFindFirst( filename,
michael@0 464 &d->d_hdl,
michael@0 465 FILE_DIRECTORY | FILE_HIDDEN,
michael@0 466 &(d->d_entry.small),
michael@0 467 sizeof(d->d_entry.small),
michael@0 468 &numEntries,
michael@0 469 FIL_STANDARD);
michael@0 470 }
michael@0 471 if ( rc != NO_ERROR ) {
michael@0 472 _PR_MD_MAP_OPENDIR_ERROR(rc);
michael@0 473 return PR_FAILURE;
michael@0 474 }
michael@0 475 d->firstEntry = PR_TRUE;
michael@0 476 d->magic = _MD_MAGIC_DIR;
michael@0 477 return PR_SUCCESS;
michael@0 478 }
michael@0 479
michael@0 480 char *
michael@0 481 _PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
michael@0 482 {
michael@0 483 PRUword numFiles = 1;
michael@0 484 BOOL rv;
michael@0 485 char *fileName;
michael@0 486 USHORT fileAttr;
michael@0 487
michael@0 488 if ( d ) {
michael@0 489 while (1) {
michael@0 490 if (d->firstEntry) {
michael@0 491 d->firstEntry = PR_FALSE;
michael@0 492 rv = NO_ERROR;
michael@0 493 } else {
michael@0 494 rv = DosFindNext(d->d_hdl,
michael@0 495 &(d->d_entry),
michael@0 496 sizeof(d->d_entry),
michael@0 497 &numFiles);
michael@0 498 }
michael@0 499 if (rv != NO_ERROR) {
michael@0 500 break;
michael@0 501 }
michael@0 502 fileName = GetFileFromDIR(d);
michael@0 503 fileAttr = GetFileAttr(d);
michael@0 504 if ( (flags & PR_SKIP_DOT) &&
michael@0 505 (fileName[0] == '.') && (fileName[1] == '\0'))
michael@0 506 continue;
michael@0 507 if ( (flags & PR_SKIP_DOT_DOT) &&
michael@0 508 (fileName[0] == '.') && (fileName[1] == '.') &&
michael@0 509 (fileName[2] == '\0'))
michael@0 510 continue;
michael@0 511 /*
michael@0 512 * XXX
michael@0 513 * Is this the correct definition of a hidden file on OS/2?
michael@0 514 */
michael@0 515 if ((flags & PR_SKIP_NONE) && (fileAttr & FILE_HIDDEN))
michael@0 516 return fileName;
michael@0 517 else if ((flags & PR_SKIP_HIDDEN) && (fileAttr & FILE_HIDDEN))
michael@0 518 continue;
michael@0 519 return fileName;
michael@0 520 }
michael@0 521 PR_ASSERT(NO_ERROR != rv);
michael@0 522 _PR_MD_MAP_READDIR_ERROR(rv);
michael@0 523 return NULL;
michael@0 524 }
michael@0 525 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
michael@0 526 return NULL;
michael@0 527 }
michael@0 528
michael@0 529 PRInt32
michael@0 530 _PR_MD_DELETE(const char *name)
michael@0 531 {
michael@0 532 PRInt32 rc = DosDelete((char*)name);
michael@0 533 if(rc == NO_ERROR) {
michael@0 534 return 0;
michael@0 535 } else {
michael@0 536 _PR_MD_MAP_DELETE_ERROR(rc);
michael@0 537 return -1;
michael@0 538 }
michael@0 539 }
michael@0 540
michael@0 541 PRInt32
michael@0 542 _PR_MD_STAT(const char *fn, struct stat *info)
michael@0 543 {
michael@0 544 PRInt32 rv;
michael@0 545 char filename[CCHMAXPATH];
michael@0 546
michael@0 547 PR_snprintf(filename, CCHMAXPATH, "%s", fn);
michael@0 548 FlipSlashes(filename, strlen(filename));
michael@0 549
michael@0 550 rv = _stat((char*)filename, info);
michael@0 551 if (-1 == rv) {
michael@0 552 /*
michael@0 553 * Check for MSVC runtime library _stat() bug.
michael@0 554 * (It's really a bug in FindFirstFile().)
michael@0 555 * If a pathname ends in a backslash or slash,
michael@0 556 * e.g., c:\temp\ or c:/temp/, _stat() will fail.
michael@0 557 * Note: a pathname ending in a slash (e.g., c:/temp/)
michael@0 558 * can be handled by _stat() on NT but not on Win95.
michael@0 559 *
michael@0 560 * We remove the backslash or slash at the end and
michael@0 561 * try again.
michael@0 562 *
michael@0 563 * Not sure if this happens on OS/2 or not,
michael@0 564 * but it doesn't hurt to be careful.
michael@0 565 */
michael@0 566
michael@0 567 int len = strlen(fn);
michael@0 568 if (len > 0 && len <= _MAX_PATH
michael@0 569 && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
michael@0 570 char newfn[_MAX_PATH + 1];
michael@0 571
michael@0 572 strcpy(newfn, fn);
michael@0 573 newfn[len - 1] = '\0';
michael@0 574 rv = _stat(newfn, info);
michael@0 575 }
michael@0 576 }
michael@0 577
michael@0 578 if (-1 == rv) {
michael@0 579 _PR_MD_MAP_STAT_ERROR(errno);
michael@0 580 }
michael@0 581 return rv;
michael@0 582 }
michael@0 583
michael@0 584 PRInt32
michael@0 585 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
michael@0 586 {
michael@0 587 struct stat sb;
michael@0 588 PRInt32 rv;
michael@0 589 PRInt64 s, s2us;
michael@0 590
michael@0 591 if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) {
michael@0 592 if (info) {
michael@0 593 if (S_IFREG & sb.st_mode)
michael@0 594 info->type = PR_FILE_FILE ;
michael@0 595 else if (S_IFDIR & sb.st_mode)
michael@0 596 info->type = PR_FILE_DIRECTORY;
michael@0 597 else
michael@0 598 info->type = PR_FILE_OTHER;
michael@0 599 info->size = sb.st_size;
michael@0 600 LL_I2L(s2us, PR_USEC_PER_SEC);
michael@0 601 LL_I2L(s, sb.st_mtime);
michael@0 602 LL_MUL(s, s, s2us);
michael@0 603 info->modifyTime = s;
michael@0 604 LL_I2L(s, sb.st_ctime);
michael@0 605 LL_MUL(s, s, s2us);
michael@0 606 info->creationTime = s;
michael@0 607 }
michael@0 608 }
michael@0 609 return rv;
michael@0 610 }
michael@0 611
michael@0 612 PRInt32
michael@0 613 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
michael@0 614 {
michael@0 615 PRFileInfo info32;
michael@0 616 PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
michael@0 617 if (rv != 0)
michael@0 618 {
michael@0 619 return rv;
michael@0 620 }
michael@0 621 info->type = info32.type;
michael@0 622 LL_UI2L(info->size,info32.size);
michael@0 623 info->modifyTime = info32.modifyTime;
michael@0 624 info->creationTime = info32.creationTime;
michael@0 625
michael@0 626 if (isWSEB)
michael@0 627 {
michael@0 628 APIRET rc ;
michael@0 629 FILESTATUS3L fstatus;
michael@0 630
michael@0 631 rc = DosQueryPathInfo(fn, FIL_STANDARDL, &fstatus, sizeof(fstatus));
michael@0 632
michael@0 633 if (NO_ERROR != rc)
michael@0 634 {
michael@0 635 _PR_MD_MAP_OPEN_ERROR(rc);
michael@0 636 return -1;
michael@0 637 }
michael@0 638
michael@0 639 if (! (fstatus.attrFile & FILE_DIRECTORY))
michael@0 640 {
michael@0 641 info->size = fstatus.cbFile;
michael@0 642 }
michael@0 643 }
michael@0 644
michael@0 645 return rv;
michael@0 646 }
michael@0 647
michael@0 648 PRInt32
michael@0 649 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
michael@0 650 {
michael@0 651 /* For once, the VAC compiler/library did a nice thing.
michael@0 652 * The file handle used by the C runtime is the same one
michael@0 653 * returned by the OS when you call DosOpen(). This means
michael@0 654 * that you can take an OS HFILE and use it with C file
michael@0 655 * functions. The only caveat is that you have to call
michael@0 656 * _setmode() first to initialize some junk. This is
michael@0 657 * immensely useful because I did not have a clue how to
michael@0 658 * implement this function otherwise. The windows folks
michael@0 659 * took the source from the Microsoft C library source, but
michael@0 660 * IBM wasn't kind enough to ship the source with VAC.
michael@0 661 * On second thought, the needed function could probably
michael@0 662 * be gotten from the OS/2 GNU library source, but the
michael@0 663 * point is now moot.
michael@0 664 */
michael@0 665 struct stat hinfo;
michael@0 666 PRInt64 s, s2us;
michael@0 667
michael@0 668 _setmode(fd->secret->md.osfd, O_BINARY);
michael@0 669 if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) {
michael@0 670 _PR_MD_MAP_FSTAT_ERROR(errno);
michael@0 671 return -1;
michael@0 672 }
michael@0 673
michael@0 674 if (hinfo.st_mode & S_IFDIR)
michael@0 675 info->type = PR_FILE_DIRECTORY;
michael@0 676 else
michael@0 677 info->type = PR_FILE_FILE;
michael@0 678
michael@0 679 info->size = hinfo.st_size;
michael@0 680 LL_I2L(s2us, PR_USEC_PER_SEC);
michael@0 681 LL_I2L(s, hinfo.st_mtime);
michael@0 682 LL_MUL(s, s, s2us);
michael@0 683 info->modifyTime = s;
michael@0 684 LL_I2L(s, hinfo.st_ctime);
michael@0 685 LL_MUL(s, s, s2us);
michael@0 686 info->creationTime = s;
michael@0 687
michael@0 688 return 0;
michael@0 689 }
michael@0 690
michael@0 691 PRInt32
michael@0 692 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
michael@0 693 {
michael@0 694 PRFileInfo info32;
michael@0 695 PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32);
michael@0 696 if (0 == rv)
michael@0 697 {
michael@0 698 info->type = info32.type;
michael@0 699 LL_UI2L(info->size,info32.size);
michael@0 700
michael@0 701 info->modifyTime = info32.modifyTime;
michael@0 702 info->creationTime = info32.creationTime;
michael@0 703 }
michael@0 704
michael@0 705 if (isWSEB)
michael@0 706 {
michael@0 707 APIRET rc ;
michael@0 708 FILESTATUS3L fstatus;
michael@0 709
michael@0 710 rc = DosQueryFileInfo(fd->secret->md.osfd, FIL_STANDARDL, &fstatus, sizeof(fstatus));
michael@0 711
michael@0 712 if (NO_ERROR != rc)
michael@0 713 {
michael@0 714 _PR_MD_MAP_OPEN_ERROR(rc);
michael@0 715 return -1;
michael@0 716 }
michael@0 717
michael@0 718 if (! (fstatus.attrFile & FILE_DIRECTORY))
michael@0 719 {
michael@0 720 info->size = fstatus.cbFile;
michael@0 721 }
michael@0 722 }
michael@0 723
michael@0 724 return rv;
michael@0 725 }
michael@0 726
michael@0 727
michael@0 728 PRInt32
michael@0 729 _PR_MD_RENAME(const char *from, const char *to)
michael@0 730 {
michael@0 731 PRInt32 rc;
michael@0 732 /* Does this work with dot-relative pathnames? */
michael@0 733 if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) {
michael@0 734 return 0;
michael@0 735 } else {
michael@0 736 _PR_MD_MAP_RENAME_ERROR(rc);
michael@0 737 return -1;
michael@0 738 }
michael@0 739 }
michael@0 740
michael@0 741 PRInt32
michael@0 742 _PR_MD_ACCESS(const char *name, PRAccessHow how)
michael@0 743 {
michael@0 744 PRInt32 rv;
michael@0 745 switch (how) {
michael@0 746 case PR_ACCESS_WRITE_OK:
michael@0 747 rv = access(name, 02);
michael@0 748 break;
michael@0 749 case PR_ACCESS_READ_OK:
michael@0 750 rv = access(name, 04);
michael@0 751 break;
michael@0 752 case PR_ACCESS_EXISTS:
michael@0 753 return access(name, 00);
michael@0 754 break;
michael@0 755 default:
michael@0 756 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
michael@0 757 return -1;
michael@0 758 }
michael@0 759 if (rv < 0)
michael@0 760 _PR_MD_MAP_ACCESS_ERROR(errno);
michael@0 761 return rv;
michael@0 762 }
michael@0 763
michael@0 764 PRInt32
michael@0 765 _PR_MD_MKDIR(const char *name, PRIntn mode)
michael@0 766 {
michael@0 767 PRInt32 rc;
michael@0 768 /* XXXMB - how to translate the "mode"??? */
michael@0 769 if ((rc = DosCreateDir((char *)name, NULL))== NO_ERROR) {
michael@0 770 return 0;
michael@0 771 } else {
michael@0 772 _PR_MD_MAP_MKDIR_ERROR(rc);
michael@0 773 return -1;
michael@0 774 }
michael@0 775 }
michael@0 776
michael@0 777 PRInt32
michael@0 778 _PR_MD_RMDIR(const char *name)
michael@0 779 {
michael@0 780 PRInt32 rc;
michael@0 781 if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) {
michael@0 782 return 0;
michael@0 783 } else {
michael@0 784 _PR_MD_MAP_RMDIR_ERROR(rc);
michael@0 785 return -1;
michael@0 786 }
michael@0 787 }
michael@0 788
michael@0 789 PRStatus
michael@0 790 _PR_MD_LOCKFILE(PRInt32 f)
michael@0 791 {
michael@0 792 PRInt32 rv;
michael@0 793 FILELOCK lock, unlock;
michael@0 794 FILELOCKL lockL, unlockL;
michael@0 795
michael@0 796 lock.lOffset = 0;
michael@0 797 lockL.lOffset = 0;
michael@0 798 lock.lRange = 0xffffffff;
michael@0 799 lockL.lRange = 0xffffffffffffffff;
michael@0 800 unlock.lOffset = 0;
michael@0 801 unlock.lRange = 0;
michael@0 802 unlockL.lOffset = 0;
michael@0 803 unlockL.lRange = 0;
michael@0 804
michael@0 805 /*
michael@0 806 * loop trying to DosSetFileLocks(),
michael@0 807 * pause for a few miliseconds when can't get the lock
michael@0 808 * and try again
michael@0 809 */
michael@0 810 for( rv = FALSE; rv == FALSE; /* do nothing */ )
michael@0 811 {
michael@0 812 if (isWSEB)
michael@0 813 {
michael@0 814 rv = myDosSetFileLocksL( (HFILE) f,
michael@0 815 &unlockL, &lockL,
michael@0 816 0, 0);
michael@0 817 }
michael@0 818 else
michael@0 819 {
michael@0 820 rv = DosSetFileLocks( (HFILE) f,
michael@0 821 &unlock, &lock,
michael@0 822 0, 0);
michael@0 823 }
michael@0 824 if ( rv != NO_ERROR )
michael@0 825 {
michael@0 826 DosSleep( 50 ); /* Sleep() a few milisecs and try again. */
michael@0 827 }
michael@0 828 } /* end for() */
michael@0 829 return PR_SUCCESS;
michael@0 830 } /* end _PR_MD_LOCKFILE() */
michael@0 831
michael@0 832 PRStatus
michael@0 833 _PR_MD_TLOCKFILE(PRInt32 f)
michael@0 834 {
michael@0 835 return _PR_MD_LOCKFILE(f);
michael@0 836 } /* end _PR_MD_TLOCKFILE() */
michael@0 837
michael@0 838
michael@0 839 PRStatus
michael@0 840 _PR_MD_UNLOCKFILE(PRInt32 f)
michael@0 841 {
michael@0 842 PRInt32 rv;
michael@0 843 FILELOCK lock, unlock;
michael@0 844 FILELOCKL lockL, unlockL;
michael@0 845
michael@0 846 lock.lOffset = 0;
michael@0 847 lockL.lOffset = 0;
michael@0 848 lock.lRange = 0;
michael@0 849 lockL.lRange = 0;
michael@0 850 unlock.lOffset = 0;
michael@0 851 unlockL.lOffset = 0;
michael@0 852 unlock.lRange = 0xffffffff;
michael@0 853 unlockL.lRange = 0xffffffffffffffff;
michael@0 854
michael@0 855 if (isWSEB)
michael@0 856 {
michael@0 857 rv = myDosSetFileLocksL( (HFILE) f,
michael@0 858 &unlockL, &lockL,
michael@0 859 0, 0);
michael@0 860 }
michael@0 861 else
michael@0 862 {
michael@0 863 rv = DosSetFileLocks( (HFILE) f,
michael@0 864 &unlock, &lock,
michael@0 865 0, 0);
michael@0 866 }
michael@0 867
michael@0 868 if ( rv != NO_ERROR )
michael@0 869 {
michael@0 870 return PR_SUCCESS;
michael@0 871 }
michael@0 872 else
michael@0 873 {
michael@0 874 return PR_FAILURE;
michael@0 875 }
michael@0 876 } /* end _PR_MD_UNLOCKFILE() */
michael@0 877
michael@0 878 PRStatus
michael@0 879 _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable)
michael@0 880 {
michael@0 881 APIRET rc = 0;
michael@0 882 ULONG flags;
michael@0 883 switch (fd->methods->file_type)
michael@0 884 {
michael@0 885 case PR_DESC_PIPE:
michael@0 886 case PR_DESC_FILE:
michael@0 887 rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags);
michael@0 888 if (rc != NO_ERROR) {
michael@0 889 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
michael@0 890 return PR_FAILURE;
michael@0 891 }
michael@0 892
michael@0 893 if (inheritable)
michael@0 894 flags &= ~OPEN_FLAGS_NOINHERIT;
michael@0 895 else
michael@0 896 flags |= OPEN_FLAGS_NOINHERIT;
michael@0 897
michael@0 898 /* Mask off flags DosSetFHState don't want. */
michael@0 899 flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
michael@0 900 rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags);
michael@0 901 if (rc != NO_ERROR) {
michael@0 902 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
michael@0 903 return PR_FAILURE;
michael@0 904 }
michael@0 905 break;
michael@0 906
michael@0 907 case PR_DESC_LAYERED:
michael@0 908 /* what to do here? */
michael@0 909 PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/);
michael@0 910 return PR_FAILURE;
michael@0 911
michael@0 912 case PR_DESC_SOCKET_TCP:
michael@0 913 case PR_DESC_SOCKET_UDP:
michael@0 914 /* These are global on OS/2. */
michael@0 915 break;
michael@0 916 }
michael@0 917
michael@0 918 return PR_SUCCESS;
michael@0 919 }
michael@0 920
michael@0 921 void
michael@0 922 _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported)
michael@0 923 {
michael@0 924 /* XXX this function needs to be implemented */
michael@0 925 fd->secret->inheritable = _PR_TRI_UNKNOWN;
michael@0 926 }
michael@0 927
michael@0 928 void
michael@0 929 _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd)
michael@0 930 {
michael@0 931 /* XXX this function needs to be reviewed */
michael@0 932 ULONG flags;
michael@0 933
michael@0 934 PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
michael@0 935 if (DosQueryFHState((HFILE)fd->secret->md.osfd, &flags) == 0) {
michael@0 936 if (flags & OPEN_FLAGS_NOINHERIT) {
michael@0 937 fd->secret->inheritable = _PR_TRI_FALSE;
michael@0 938 } else {
michael@0 939 fd->secret->inheritable = _PR_TRI_TRUE;
michael@0 940 }
michael@0 941 }
michael@0 942 }

mercurial