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

changeset 0
6474c204b198
     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 +}

mercurial