1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/md/os2/os2io.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,942 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* OS2 IO module 1.10 + * 1.11 + * Assumes synchronous I/O. 1.12 + * 1.13 + */ 1.14 + 1.15 +#include "primpl.h" 1.16 +#include "prio.h" 1.17 +#include <ctype.h> 1.18 +#include <string.h> 1.19 +#include <limits.h> 1.20 +#include <dirent.h> 1.21 +#include <fcntl.h> 1.22 +#include <io.h> 1.23 + 1.24 +struct _MDLock _pr_ioq_lock; 1.25 + 1.26 +static PRBool isWSEB = PR_FALSE; /* whether we are using an OS/2 kernel that supports large files */ 1.27 + 1.28 +typedef APIRET (*DosOpenLType)(PSZ pszFileName, PHFILE pHf, PULONG pulAction, 1.29 + LONGLONG cbFile, ULONG ulAttribute, 1.30 + ULONG fsOpenFlags, ULONG fsOpenMode, 1.31 + PEAOP2 peaop2); 1.32 + 1.33 +typedef APIRET (*DosSetFileLocksLType)(HFILE hFile, PFILELOCKL pflUnlock, 1.34 + PFILELOCKL pflLock, ULONG timeout, 1.35 + ULONG flags); 1.36 + 1.37 +typedef APIRET (*DosSetFilePtrLType)(HFILE hFile, LONGLONG ib, ULONG method, 1.38 + PLONGLONG ibActual); 1.39 + 1.40 +DosOpenLType myDosOpenL; 1.41 +DosSetFileLocksLType myDosSetFileLocksL; 1.42 +DosSetFilePtrLType myDosSetFilePtrL; 1.43 + 1.44 +void 1.45 +_PR_MD_INIT_IO() 1.46 +{ 1.47 + APIRET rc; 1.48 + HMODULE module; 1.49 + 1.50 + sock_init(); 1.51 + 1.52 + rc = DosLoadModule(NULL, 0, "DOSCALL1", &module); 1.53 + if (rc != NO_ERROR) 1.54 + { 1.55 + return; 1.56 + } 1.57 + rc = DosQueryProcAddr(module, 981, NULL, (PFN*) &myDosOpenL); 1.58 + if (rc != NO_ERROR) 1.59 + { 1.60 + return; 1.61 + } 1.62 + rc = DosQueryProcAddr(module, 986, NULL, (PFN*) &myDosSetFileLocksL); 1.63 + if (rc != NO_ERROR) 1.64 + { 1.65 + return; 1.66 + } 1.67 + rc = DosQueryProcAddr(module, 988, NULL, (PFN*) &myDosSetFilePtrL); 1.68 + if (rc != NO_ERROR) 1.69 + { 1.70 + return; 1.71 + } 1.72 + isWSEB = PR_TRUE; 1.73 +} 1.74 + 1.75 +PRStatus 1.76 +_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks) 1.77 +{ 1.78 + PRInt32 rv; 1.79 + ULONG count; 1.80 + 1.81 + PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? 1.82 + SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks); 1.83 + rv = DosWaitEventSem(thread->md.blocked_sema, msecs); 1.84 + DosResetEventSem(thread->md.blocked_sema, &count); 1.85 + switch(rv) 1.86 + { 1.87 + case NO_ERROR: 1.88 + return PR_SUCCESS; 1.89 + break; 1.90 + case ERROR_TIMEOUT: 1.91 + _PR_THREAD_LOCK(thread); 1.92 + if (thread->state == _PR_IO_WAIT) { 1.93 + ; 1.94 + } else { 1.95 + if (thread->wait.cvar != NULL) { 1.96 + thread->wait.cvar = NULL; 1.97 + _PR_THREAD_UNLOCK(thread); 1.98 + } else { 1.99 + /* The CVAR was notified just as the timeout 1.100 + * occurred. This led to us being notified twice. 1.101 + * call SemRequest() to clear the semaphore. 1.102 + */ 1.103 + _PR_THREAD_UNLOCK(thread); 1.104 + rv = DosWaitEventSem(thread->md.blocked_sema, 0); 1.105 + DosResetEventSem(thread->md.blocked_sema, &count); 1.106 + PR_ASSERT(rv == NO_ERROR); 1.107 + } 1.108 + } 1.109 + return PR_SUCCESS; 1.110 + break; 1.111 + default: 1.112 + break; 1.113 + } 1.114 + return PR_FAILURE; 1.115 +} 1.116 +PRStatus 1.117 +_PR_MD_WAKEUP_WAITER(PRThread *thread) 1.118 +{ 1.119 + if ( _PR_IS_NATIVE_THREAD(thread) ) 1.120 + { 1.121 + if (DosPostEventSem(thread->md.blocked_sema) != NO_ERROR) 1.122 + return PR_FAILURE; 1.123 + else 1.124 + return PR_SUCCESS; 1.125 + } 1.126 +} 1.127 + 1.128 + 1.129 +/* --- FILE IO ----------------------------------------------------------- */ 1.130 +/* 1.131 + * _PR_MD_OPEN() -- Open a file 1.132 + * 1.133 + * returns: a fileHandle 1.134 + * 1.135 + * The NSPR open flags (osflags) are translated into flags for OS/2 1.136 + * 1.137 + * Mode seems to be passed in as a unix style file permissions argument 1.138 + * as in 0666, in the case of opening the logFile. 1.139 + * 1.140 + */ 1.141 +PRInt32 1.142 +_PR_MD_OPEN(const char *name, PRIntn osflags, int mode) 1.143 +{ 1.144 + HFILE file; 1.145 + PRInt32 access = OPEN_SHARE_DENYNONE; 1.146 + PRInt32 flags = 0L; 1.147 + APIRET rc = 0; 1.148 + PRUword actionTaken; 1.149 + 1.150 +#ifdef MOZ_OS2_HIGH_MEMORY 1.151 + /* 1.152 + * All the pointer arguments (&file, &actionTaken and name) have to be in 1.153 + * low memory for DosOpen to use them. 1.154 + * The following moves name to low memory. 1.155 + */ 1.156 + if ((ULONG)name >= 0x20000000) 1.157 + { 1.158 + size_t len = strlen(name) + 1; 1.159 + char *copy = (char *)alloca(len); 1.160 + memcpy(copy, name, len); 1.161 + name = copy; 1.162 + } 1.163 +#endif 1.164 + 1.165 + if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH; 1.166 + 1.167 + if (osflags & PR_RDONLY) 1.168 + access |= OPEN_ACCESS_READONLY; 1.169 + else if (osflags & PR_WRONLY) 1.170 + access |= OPEN_ACCESS_WRITEONLY; 1.171 + else if(osflags & PR_RDWR) 1.172 + access |= OPEN_ACCESS_READWRITE; 1.173 + 1.174 + if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) 1.175 + { 1.176 + flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS; 1.177 + } 1.178 + else if (osflags & PR_CREATE_FILE) 1.179 + { 1.180 + if (osflags & PR_TRUNCATE) 1.181 + flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS; 1.182 + else 1.183 + flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; 1.184 + } 1.185 + else 1.186 + { 1.187 + if (osflags & PR_TRUNCATE) 1.188 + flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS; 1.189 + else 1.190 + flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; 1.191 + } 1.192 + 1.193 + do { 1.194 + if (isWSEB) 1.195 + { 1.196 + rc = myDosOpenL((char*)name, 1.197 + &file, /* file handle if successful */ 1.198 + &actionTaken, /* reason for failure */ 1.199 + 0, /* initial size of new file */ 1.200 + FILE_NORMAL, /* file system attributes */ 1.201 + flags, /* Open flags */ 1.202 + access, /* Open mode and rights */ 1.203 + 0); /* OS/2 Extended Attributes */ 1.204 + } 1.205 + else 1.206 + { 1.207 + rc = DosOpen((char*)name, 1.208 + &file, /* file handle if successful */ 1.209 + &actionTaken, /* reason for failure */ 1.210 + 0, /* initial size of new file */ 1.211 + FILE_NORMAL, /* file system attributes */ 1.212 + flags, /* Open flags */ 1.213 + access, /* Open mode and rights */ 1.214 + 0); /* OS/2 Extended Attributes */ 1.215 + }; 1.216 + if (rc == ERROR_TOO_MANY_OPEN_FILES) { 1.217 + ULONG CurMaxFH = 0; 1.218 + LONG ReqCount = 20; 1.219 + APIRET rc2; 1.220 + rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH); 1.221 + if (rc2 != NO_ERROR) { 1.222 + break; 1.223 + } 1.224 + } 1.225 + } while (rc == ERROR_TOO_MANY_OPEN_FILES); 1.226 + 1.227 + if (rc != NO_ERROR) { 1.228 + _PR_MD_MAP_OPEN_ERROR(rc); 1.229 + return -1; 1.230 + } 1.231 + 1.232 + return (PRInt32)file; 1.233 +} 1.234 + 1.235 +PRInt32 1.236 +_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) 1.237 +{ 1.238 + ULONG bytes; 1.239 + int rv; 1.240 + 1.241 + rv = DosRead((HFILE)fd->secret->md.osfd, 1.242 + (PVOID)buf, 1.243 + len, 1.244 + &bytes); 1.245 + 1.246 + if (rv != NO_ERROR) 1.247 + { 1.248 + /* ERROR_HANDLE_EOF can only be returned by async io */ 1.249 + PR_ASSERT(rv != ERROR_HANDLE_EOF); 1.250 + if (rv == ERROR_BROKEN_PIPE) 1.251 + return 0; 1.252 + else { 1.253 + _PR_MD_MAP_READ_ERROR(rv); 1.254 + return -1; 1.255 + } 1.256 + } 1.257 + return (PRInt32)bytes; 1.258 +} 1.259 + 1.260 +PRInt32 1.261 +_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) 1.262 +{ 1.263 + PRInt32 bytes; 1.264 + int rv; 1.265 + 1.266 + rv = DosWrite((HFILE)fd->secret->md.osfd, 1.267 + (PVOID)buf, 1.268 + len, 1.269 + (PULONG)&bytes); 1.270 + 1.271 + if (rv != NO_ERROR) 1.272 + { 1.273 + _PR_MD_MAP_WRITE_ERROR(rv); 1.274 + return -1; 1.275 + } 1.276 + 1.277 + if (len != bytes) { 1.278 + rv = ERROR_DISK_FULL; 1.279 + _PR_MD_MAP_WRITE_ERROR(rv); 1.280 + return -1; 1.281 + } 1.282 + 1.283 + return bytes; 1.284 +} /* --- end _PR_MD_WRITE() --- */ 1.285 + 1.286 +PRInt32 1.287 +_PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) 1.288 +{ 1.289 + PRInt32 rv; 1.290 + PRUword newLocation; 1.291 + 1.292 + rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation); 1.293 + 1.294 + if (rv != NO_ERROR) { 1.295 + _PR_MD_MAP_LSEEK_ERROR(rv); 1.296 + return -1; 1.297 + } else 1.298 + return newLocation; 1.299 +} 1.300 + 1.301 +PRInt64 1.302 +_PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence) 1.303 +{ 1.304 +#ifdef NO_LONG_LONG 1.305 + PRInt64 result; 1.306 + PRInt32 rv, low = offset.lo, hi = offset.hi; 1.307 + PRUword newLocation; 1.308 + 1.309 + rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation); 1.310 + rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation); 1.311 + 1.312 + if (rv != NO_ERROR) { 1.313 + _PR_MD_MAP_LSEEK_ERROR(rv); 1.314 + hi = newLocation = -1; 1.315 + } 1.316 + 1.317 + result.lo = newLocation; 1.318 + result.hi = hi; 1.319 + return result; 1.320 + 1.321 +#else 1.322 + PRInt32 where, rc, lo = (PRInt32)offset, hi = (PRInt32)(offset >> 32); 1.323 + PRUint64 rv; 1.324 + PRUint32 newLocation, uhi; 1.325 + PRUint64 newLocationL; 1.326 + 1.327 + switch (whence) 1.328 + { 1.329 + case PR_SEEK_SET: 1.330 + where = FILE_BEGIN; 1.331 + break; 1.332 + case PR_SEEK_CUR: 1.333 + where = FILE_CURRENT; 1.334 + break; 1.335 + case PR_SEEK_END: 1.336 + where = FILE_END; 1.337 + break; 1.338 + default: 1.339 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.340 + return -1; 1.341 + } 1.342 + if (isWSEB) 1.343 + { 1.344 + rc = myDosSetFilePtrL((HFILE)fd->secret->md.osfd, offset, where, (PLONGLONG)&newLocationL); 1.345 + } 1.346 + else 1.347 + { 1.348 + rc = DosSetFilePtr((HFILE)fd->secret->md.osfd, lo, where, (PULONG)&newLocation); 1.349 + } 1.350 + 1.351 + if (rc != NO_ERROR) { 1.352 + _PR_MD_MAP_LSEEK_ERROR(rc); 1.353 + return -1; 1.354 + } 1.355 + 1.356 + if (isWSEB) 1.357 + { 1.358 + return newLocationL; 1.359 + } 1.360 + 1.361 + uhi = (PRUint32)hi; 1.362 + PR_ASSERT((PRInt32)uhi >= 0); 1.363 + rv = uhi; 1.364 + PR_ASSERT((PRInt64)rv >= 0); 1.365 + rv = (rv << 32); 1.366 + PR_ASSERT((PRInt64)rv >= 0); 1.367 + rv += newLocation; 1.368 + PR_ASSERT((PRInt64)rv >= 0); 1.369 + return (PRInt64)rv; 1.370 +#endif 1.371 +} 1.372 + 1.373 +PRInt32 1.374 +_PR_MD_FSYNC(PRFileDesc *fd) 1.375 +{ 1.376 + PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd); 1.377 + 1.378 + if (rc != NO_ERROR) { 1.379 + if (rc != ERROR_ACCESS_DENIED) { 1.380 + _PR_MD_MAP_FSYNC_ERROR(rc); 1.381 + return -1; 1.382 + } 1.383 + } 1.384 + return 0; 1.385 +} 1.386 + 1.387 +PRInt32 1.388 +_MD_CloseFile(PRInt32 osfd) 1.389 +{ 1.390 + PRInt32 rv; 1.391 + 1.392 + rv = DosClose((HFILE)osfd); 1.393 + if (rv != NO_ERROR) 1.394 + _PR_MD_MAP_CLOSE_ERROR(rv); 1.395 + return rv; 1.396 +} 1.397 + 1.398 + 1.399 +/* --- DIR IO ------------------------------------------------------------ */ 1.400 +#define GetFileFromDIR(d) (isWSEB?(d)->d_entry.large.achName:(d)->d_entry.small.achName) 1.401 +#define GetFileAttr(d) (isWSEB?(d)->d_entry.large.attrFile:(d)->d_entry.small.attrFile) 1.402 + 1.403 +void FlipSlashes(char *cp, int len) 1.404 +{ 1.405 + while (--len >= 0) { 1.406 + if (cp[0] == '/') { 1.407 + cp[0] = PR_DIRECTORY_SEPARATOR; 1.408 + } 1.409 + cp++; 1.410 + } 1.411 +} 1.412 + 1.413 +/* 1.414 +** 1.415 +** Local implementations of standard Unix RTL functions which are not provided 1.416 +** by the VAC RTL. 1.417 +** 1.418 +*/ 1.419 + 1.420 +PRInt32 1.421 +_PR_MD_CLOSE_DIR(_MDDir *d) 1.422 +{ 1.423 + PRInt32 rc; 1.424 + 1.425 + if ( d ) { 1.426 + rc = DosFindClose(d->d_hdl); 1.427 + if(rc == NO_ERROR){ 1.428 + d->magic = (PRUint32)-1; 1.429 + return PR_SUCCESS; 1.430 + } else { 1.431 + _PR_MD_MAP_CLOSEDIR_ERROR(rc); 1.432 + return PR_FAILURE; 1.433 + } 1.434 + } 1.435 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.436 + return PR_FAILURE; 1.437 +} 1.438 + 1.439 + 1.440 +PRStatus 1.441 +_PR_MD_OPEN_DIR(_MDDir *d, const char *name) 1.442 +{ 1.443 + char filename[ CCHMAXPATH ]; 1.444 + PRUword numEntries, rc; 1.445 + 1.446 + numEntries = 1; 1.447 + 1.448 + PR_snprintf(filename, CCHMAXPATH, "%s%s%s", 1.449 + name, PR_DIRECTORY_SEPARATOR_STR, "*.*"); 1.450 + FlipSlashes( filename, strlen(filename) ); 1.451 + 1.452 + d->d_hdl = HDIR_CREATE; 1.453 + 1.454 + if (isWSEB) 1.455 + { 1.456 + rc = DosFindFirst( filename, 1.457 + &d->d_hdl, 1.458 + FILE_DIRECTORY | FILE_HIDDEN, 1.459 + &(d->d_entry.large), 1.460 + sizeof(d->d_entry.large), 1.461 + &numEntries, 1.462 + FIL_STANDARDL); 1.463 + } 1.464 + else 1.465 + { 1.466 + rc = DosFindFirst( filename, 1.467 + &d->d_hdl, 1.468 + FILE_DIRECTORY | FILE_HIDDEN, 1.469 + &(d->d_entry.small), 1.470 + sizeof(d->d_entry.small), 1.471 + &numEntries, 1.472 + FIL_STANDARD); 1.473 + } 1.474 + if ( rc != NO_ERROR ) { 1.475 + _PR_MD_MAP_OPENDIR_ERROR(rc); 1.476 + return PR_FAILURE; 1.477 + } 1.478 + d->firstEntry = PR_TRUE; 1.479 + d->magic = _MD_MAGIC_DIR; 1.480 + return PR_SUCCESS; 1.481 +} 1.482 + 1.483 +char * 1.484 +_PR_MD_READ_DIR(_MDDir *d, PRIntn flags) 1.485 +{ 1.486 + PRUword numFiles = 1; 1.487 + BOOL rv; 1.488 + char *fileName; 1.489 + USHORT fileAttr; 1.490 + 1.491 + if ( d ) { 1.492 + while (1) { 1.493 + if (d->firstEntry) { 1.494 + d->firstEntry = PR_FALSE; 1.495 + rv = NO_ERROR; 1.496 + } else { 1.497 + rv = DosFindNext(d->d_hdl, 1.498 + &(d->d_entry), 1.499 + sizeof(d->d_entry), 1.500 + &numFiles); 1.501 + } 1.502 + if (rv != NO_ERROR) { 1.503 + break; 1.504 + } 1.505 + fileName = GetFileFromDIR(d); 1.506 + fileAttr = GetFileAttr(d); 1.507 + if ( (flags & PR_SKIP_DOT) && 1.508 + (fileName[0] == '.') && (fileName[1] == '\0')) 1.509 + continue; 1.510 + if ( (flags & PR_SKIP_DOT_DOT) && 1.511 + (fileName[0] == '.') && (fileName[1] == '.') && 1.512 + (fileName[2] == '\0')) 1.513 + continue; 1.514 + /* 1.515 + * XXX 1.516 + * Is this the correct definition of a hidden file on OS/2? 1.517 + */ 1.518 + if ((flags & PR_SKIP_NONE) && (fileAttr & FILE_HIDDEN)) 1.519 + return fileName; 1.520 + else if ((flags & PR_SKIP_HIDDEN) && (fileAttr & FILE_HIDDEN)) 1.521 + continue; 1.522 + return fileName; 1.523 + } 1.524 + PR_ASSERT(NO_ERROR != rv); 1.525 + _PR_MD_MAP_READDIR_ERROR(rv); 1.526 + return NULL; 1.527 + } 1.528 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.529 + return NULL; 1.530 +} 1.531 + 1.532 +PRInt32 1.533 +_PR_MD_DELETE(const char *name) 1.534 +{ 1.535 + PRInt32 rc = DosDelete((char*)name); 1.536 + if(rc == NO_ERROR) { 1.537 + return 0; 1.538 + } else { 1.539 + _PR_MD_MAP_DELETE_ERROR(rc); 1.540 + return -1; 1.541 + } 1.542 +} 1.543 + 1.544 +PRInt32 1.545 +_PR_MD_STAT(const char *fn, struct stat *info) 1.546 +{ 1.547 + PRInt32 rv; 1.548 + char filename[CCHMAXPATH]; 1.549 + 1.550 + PR_snprintf(filename, CCHMAXPATH, "%s", fn); 1.551 + FlipSlashes(filename, strlen(filename)); 1.552 + 1.553 + rv = _stat((char*)filename, info); 1.554 + if (-1 == rv) { 1.555 + /* 1.556 + * Check for MSVC runtime library _stat() bug. 1.557 + * (It's really a bug in FindFirstFile().) 1.558 + * If a pathname ends in a backslash or slash, 1.559 + * e.g., c:\temp\ or c:/temp/, _stat() will fail. 1.560 + * Note: a pathname ending in a slash (e.g., c:/temp/) 1.561 + * can be handled by _stat() on NT but not on Win95. 1.562 + * 1.563 + * We remove the backslash or slash at the end and 1.564 + * try again. 1.565 + * 1.566 + * Not sure if this happens on OS/2 or not, 1.567 + * but it doesn't hurt to be careful. 1.568 + */ 1.569 + 1.570 + int len = strlen(fn); 1.571 + if (len > 0 && len <= _MAX_PATH 1.572 + && (fn[len - 1] == '\\' || fn[len - 1] == '/')) { 1.573 + char newfn[_MAX_PATH + 1]; 1.574 + 1.575 + strcpy(newfn, fn); 1.576 + newfn[len - 1] = '\0'; 1.577 + rv = _stat(newfn, info); 1.578 + } 1.579 + } 1.580 + 1.581 + if (-1 == rv) { 1.582 + _PR_MD_MAP_STAT_ERROR(errno); 1.583 + } 1.584 + return rv; 1.585 +} 1.586 + 1.587 +PRInt32 1.588 +_PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info) 1.589 +{ 1.590 + struct stat sb; 1.591 + PRInt32 rv; 1.592 + PRInt64 s, s2us; 1.593 + 1.594 + if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) { 1.595 + if (info) { 1.596 + if (S_IFREG & sb.st_mode) 1.597 + info->type = PR_FILE_FILE ; 1.598 + else if (S_IFDIR & sb.st_mode) 1.599 + info->type = PR_FILE_DIRECTORY; 1.600 + else 1.601 + info->type = PR_FILE_OTHER; 1.602 + info->size = sb.st_size; 1.603 + LL_I2L(s2us, PR_USEC_PER_SEC); 1.604 + LL_I2L(s, sb.st_mtime); 1.605 + LL_MUL(s, s, s2us); 1.606 + info->modifyTime = s; 1.607 + LL_I2L(s, sb.st_ctime); 1.608 + LL_MUL(s, s, s2us); 1.609 + info->creationTime = s; 1.610 + } 1.611 + } 1.612 + return rv; 1.613 +} 1.614 + 1.615 +PRInt32 1.616 +_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) 1.617 +{ 1.618 + PRFileInfo info32; 1.619 + PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32); 1.620 + if (rv != 0) 1.621 + { 1.622 + return rv; 1.623 + } 1.624 + info->type = info32.type; 1.625 + LL_UI2L(info->size,info32.size); 1.626 + info->modifyTime = info32.modifyTime; 1.627 + info->creationTime = info32.creationTime; 1.628 + 1.629 + if (isWSEB) 1.630 + { 1.631 + APIRET rc ; 1.632 + FILESTATUS3L fstatus; 1.633 + 1.634 + rc = DosQueryPathInfo(fn, FIL_STANDARDL, &fstatus, sizeof(fstatus)); 1.635 + 1.636 + if (NO_ERROR != rc) 1.637 + { 1.638 + _PR_MD_MAP_OPEN_ERROR(rc); 1.639 + return -1; 1.640 + } 1.641 + 1.642 + if (! (fstatus.attrFile & FILE_DIRECTORY)) 1.643 + { 1.644 + info->size = fstatus.cbFile; 1.645 + } 1.646 + } 1.647 + 1.648 + return rv; 1.649 +} 1.650 + 1.651 +PRInt32 1.652 +_PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info) 1.653 +{ 1.654 + /* For once, the VAC compiler/library did a nice thing. 1.655 + * The file handle used by the C runtime is the same one 1.656 + * returned by the OS when you call DosOpen(). This means 1.657 + * that you can take an OS HFILE and use it with C file 1.658 + * functions. The only caveat is that you have to call 1.659 + * _setmode() first to initialize some junk. This is 1.660 + * immensely useful because I did not have a clue how to 1.661 + * implement this function otherwise. The windows folks 1.662 + * took the source from the Microsoft C library source, but 1.663 + * IBM wasn't kind enough to ship the source with VAC. 1.664 + * On second thought, the needed function could probably 1.665 + * be gotten from the OS/2 GNU library source, but the 1.666 + * point is now moot. 1.667 + */ 1.668 + struct stat hinfo; 1.669 + PRInt64 s, s2us; 1.670 + 1.671 + _setmode(fd->secret->md.osfd, O_BINARY); 1.672 + if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) { 1.673 + _PR_MD_MAP_FSTAT_ERROR(errno); 1.674 + return -1; 1.675 + } 1.676 + 1.677 + if (hinfo.st_mode & S_IFDIR) 1.678 + info->type = PR_FILE_DIRECTORY; 1.679 + else 1.680 + info->type = PR_FILE_FILE; 1.681 + 1.682 + info->size = hinfo.st_size; 1.683 + LL_I2L(s2us, PR_USEC_PER_SEC); 1.684 + LL_I2L(s, hinfo.st_mtime); 1.685 + LL_MUL(s, s, s2us); 1.686 + info->modifyTime = s; 1.687 + LL_I2L(s, hinfo.st_ctime); 1.688 + LL_MUL(s, s, s2us); 1.689 + info->creationTime = s; 1.690 + 1.691 + return 0; 1.692 +} 1.693 + 1.694 +PRInt32 1.695 +_PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info) 1.696 +{ 1.697 + PRFileInfo info32; 1.698 + PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32); 1.699 + if (0 == rv) 1.700 + { 1.701 + info->type = info32.type; 1.702 + LL_UI2L(info->size,info32.size); 1.703 + 1.704 + info->modifyTime = info32.modifyTime; 1.705 + info->creationTime = info32.creationTime; 1.706 + } 1.707 + 1.708 + if (isWSEB) 1.709 + { 1.710 + APIRET rc ; 1.711 + FILESTATUS3L fstatus; 1.712 + 1.713 + rc = DosQueryFileInfo(fd->secret->md.osfd, FIL_STANDARDL, &fstatus, sizeof(fstatus)); 1.714 + 1.715 + if (NO_ERROR != rc) 1.716 + { 1.717 + _PR_MD_MAP_OPEN_ERROR(rc); 1.718 + return -1; 1.719 + } 1.720 + 1.721 + if (! (fstatus.attrFile & FILE_DIRECTORY)) 1.722 + { 1.723 + info->size = fstatus.cbFile; 1.724 + } 1.725 + } 1.726 + 1.727 + return rv; 1.728 +} 1.729 + 1.730 + 1.731 +PRInt32 1.732 +_PR_MD_RENAME(const char *from, const char *to) 1.733 +{ 1.734 + PRInt32 rc; 1.735 + /* Does this work with dot-relative pathnames? */ 1.736 + if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) { 1.737 + return 0; 1.738 + } else { 1.739 + _PR_MD_MAP_RENAME_ERROR(rc); 1.740 + return -1; 1.741 + } 1.742 +} 1.743 + 1.744 +PRInt32 1.745 +_PR_MD_ACCESS(const char *name, PRAccessHow how) 1.746 +{ 1.747 + PRInt32 rv; 1.748 + switch (how) { 1.749 + case PR_ACCESS_WRITE_OK: 1.750 + rv = access(name, 02); 1.751 + break; 1.752 + case PR_ACCESS_READ_OK: 1.753 + rv = access(name, 04); 1.754 + break; 1.755 + case PR_ACCESS_EXISTS: 1.756 + return access(name, 00); 1.757 + break; 1.758 + default: 1.759 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.760 + return -1; 1.761 + } 1.762 + if (rv < 0) 1.763 + _PR_MD_MAP_ACCESS_ERROR(errno); 1.764 + return rv; 1.765 +} 1.766 + 1.767 +PRInt32 1.768 +_PR_MD_MKDIR(const char *name, PRIntn mode) 1.769 +{ 1.770 + PRInt32 rc; 1.771 + /* XXXMB - how to translate the "mode"??? */ 1.772 + if ((rc = DosCreateDir((char *)name, NULL))== NO_ERROR) { 1.773 + return 0; 1.774 + } else { 1.775 + _PR_MD_MAP_MKDIR_ERROR(rc); 1.776 + return -1; 1.777 + } 1.778 +} 1.779 + 1.780 +PRInt32 1.781 +_PR_MD_RMDIR(const char *name) 1.782 +{ 1.783 + PRInt32 rc; 1.784 + if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) { 1.785 + return 0; 1.786 + } else { 1.787 + _PR_MD_MAP_RMDIR_ERROR(rc); 1.788 + return -1; 1.789 + } 1.790 +} 1.791 + 1.792 +PRStatus 1.793 +_PR_MD_LOCKFILE(PRInt32 f) 1.794 +{ 1.795 + PRInt32 rv; 1.796 + FILELOCK lock, unlock; 1.797 + FILELOCKL lockL, unlockL; 1.798 + 1.799 + lock.lOffset = 0; 1.800 + lockL.lOffset = 0; 1.801 + lock.lRange = 0xffffffff; 1.802 + lockL.lRange = 0xffffffffffffffff; 1.803 + unlock.lOffset = 0; 1.804 + unlock.lRange = 0; 1.805 + unlockL.lOffset = 0; 1.806 + unlockL.lRange = 0; 1.807 + 1.808 + /* 1.809 + * loop trying to DosSetFileLocks(), 1.810 + * pause for a few miliseconds when can't get the lock 1.811 + * and try again 1.812 + */ 1.813 + for( rv = FALSE; rv == FALSE; /* do nothing */ ) 1.814 + { 1.815 + if (isWSEB) 1.816 + { 1.817 + rv = myDosSetFileLocksL( (HFILE) f, 1.818 + &unlockL, &lockL, 1.819 + 0, 0); 1.820 + } 1.821 + else 1.822 + { 1.823 + rv = DosSetFileLocks( (HFILE) f, 1.824 + &unlock, &lock, 1.825 + 0, 0); 1.826 + } 1.827 + if ( rv != NO_ERROR ) 1.828 + { 1.829 + DosSleep( 50 ); /* Sleep() a few milisecs and try again. */ 1.830 + } 1.831 + } /* end for() */ 1.832 + return PR_SUCCESS; 1.833 +} /* end _PR_MD_LOCKFILE() */ 1.834 + 1.835 +PRStatus 1.836 +_PR_MD_TLOCKFILE(PRInt32 f) 1.837 +{ 1.838 + return _PR_MD_LOCKFILE(f); 1.839 +} /* end _PR_MD_TLOCKFILE() */ 1.840 + 1.841 + 1.842 +PRStatus 1.843 +_PR_MD_UNLOCKFILE(PRInt32 f) 1.844 +{ 1.845 + PRInt32 rv; 1.846 + FILELOCK lock, unlock; 1.847 + FILELOCKL lockL, unlockL; 1.848 + 1.849 + lock.lOffset = 0; 1.850 + lockL.lOffset = 0; 1.851 + lock.lRange = 0; 1.852 + lockL.lRange = 0; 1.853 + unlock.lOffset = 0; 1.854 + unlockL.lOffset = 0; 1.855 + unlock.lRange = 0xffffffff; 1.856 + unlockL.lRange = 0xffffffffffffffff; 1.857 + 1.858 + if (isWSEB) 1.859 + { 1.860 + rv = myDosSetFileLocksL( (HFILE) f, 1.861 + &unlockL, &lockL, 1.862 + 0, 0); 1.863 + } 1.864 + else 1.865 + { 1.866 + rv = DosSetFileLocks( (HFILE) f, 1.867 + &unlock, &lock, 1.868 + 0, 0); 1.869 + } 1.870 + 1.871 + if ( rv != NO_ERROR ) 1.872 + { 1.873 + return PR_SUCCESS; 1.874 + } 1.875 + else 1.876 + { 1.877 + return PR_FAILURE; 1.878 + } 1.879 +} /* end _PR_MD_UNLOCKFILE() */ 1.880 + 1.881 +PRStatus 1.882 +_PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) 1.883 +{ 1.884 + APIRET rc = 0; 1.885 + ULONG flags; 1.886 + switch (fd->methods->file_type) 1.887 + { 1.888 + case PR_DESC_PIPE: 1.889 + case PR_DESC_FILE: 1.890 + rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags); 1.891 + if (rc != NO_ERROR) { 1.892 + PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); 1.893 + return PR_FAILURE; 1.894 + } 1.895 + 1.896 + if (inheritable) 1.897 + flags &= ~OPEN_FLAGS_NOINHERIT; 1.898 + else 1.899 + flags |= OPEN_FLAGS_NOINHERIT; 1.900 + 1.901 + /* Mask off flags DosSetFHState don't want. */ 1.902 + flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); 1.903 + rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags); 1.904 + if (rc != NO_ERROR) { 1.905 + PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); 1.906 + return PR_FAILURE; 1.907 + } 1.908 + break; 1.909 + 1.910 + case PR_DESC_LAYERED: 1.911 + /* what to do here? */ 1.912 + PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/); 1.913 + return PR_FAILURE; 1.914 + 1.915 + case PR_DESC_SOCKET_TCP: 1.916 + case PR_DESC_SOCKET_UDP: 1.917 + /* These are global on OS/2. */ 1.918 + break; 1.919 + } 1.920 + 1.921 + return PR_SUCCESS; 1.922 +} 1.923 + 1.924 +void 1.925 +_PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported) 1.926 +{ 1.927 + /* XXX this function needs to be implemented */ 1.928 + fd->secret->inheritable = _PR_TRI_UNKNOWN; 1.929 +} 1.930 + 1.931 +void 1.932 +_PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd) 1.933 +{ 1.934 + /* XXX this function needs to be reviewed */ 1.935 + ULONG flags; 1.936 + 1.937 + PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); 1.938 + if (DosQueryFHState((HFILE)fd->secret->md.osfd, &flags) == 0) { 1.939 + if (flags & OPEN_FLAGS_NOINHERIT) { 1.940 + fd->secret->inheritable = _PR_TRI_FALSE; 1.941 + } else { 1.942 + fd->secret->inheritable = _PR_TRI_TRUE; 1.943 + } 1.944 + } 1.945 +}