home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / os2 / os2io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  15.6 KB  |  621 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* OS2 IO module
  20.  *
  21.  * Assumes synchronous I/O.
  22.  *
  23.  */
  24.  
  25. #include "primpl.h"
  26. #include <direct.h>
  27.  
  28. struct _MDLock               _pr_ioq_lock;
  29.  
  30. PR_IMPLEMENT(PRStatus)
  31. _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
  32. {
  33.     PRInt32 rv;
  34.     ULONG count;
  35.  
  36.     PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
  37.         SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks);
  38.     rv = DosWaitEventSem(thread->md.blocked_sema.sem, msecs);
  39.     DosResetEventSem(thread->md.blocked_sema.sem, &count); 
  40.     switch(rv) 
  41.     {
  42.         case NO_ERROR:
  43.             return PR_SUCCESS;
  44.             break;
  45.         case ERROR_TIMEOUT:
  46.             _PR_THREAD_LOCK(thread);
  47.             if (thread->state == _PR_IO_WAIT) {
  48.               ;
  49.             } else {
  50.                 if (thread->wait.cvar != NULL) {
  51.                     thread->wait.cvar = NULL;
  52.                     _PR_THREAD_UNLOCK(thread);
  53.                 } else {
  54.                     /* The CVAR was notified just as the timeout
  55.                      * occurred.  This led to us being notified twice.
  56.                      * call SemRequest() to clear the semaphore.
  57.                      */
  58.                     _PR_THREAD_UNLOCK(thread);
  59.                     rv = DosWaitEventSem(thread->md.blocked_sema.sem, 0);
  60.                     DosResetEventSem(thread->md.blocked_sema.sem, &count); 
  61.                     PR_ASSERT(rv == NO_ERROR);
  62.                 }
  63.             }
  64.             return PR_SUCCESS;
  65.             break;
  66.         default:
  67.             break;
  68.     }
  69.     return PR_FAILURE;
  70. }
  71. PR_IMPLEMENT(PRStatus)
  72. _PR_MD_WAKEUP_WAITER(PRThread *thread)
  73. {
  74.     if ( _PR_IS_NATIVE_THREAD(thread) ) 
  75.     {
  76.         if (DosPostEventSem(thread->md.blocked_sema.sem) != NO_ERROR)
  77.             return PR_FAILURE;
  78.         else
  79.             return PR_SUCCESS;
  80.     }
  81. }
  82.  
  83.  
  84. /* --- FILE IO ----------------------------------------------------------- */
  85. /*
  86.  *  _PR_MD_OPEN() -- Open a file
  87.  *
  88.  *  returns: a fileHandle
  89.  *
  90.  *  The NSPR open flags (osflags) are translated into flags for OS/2
  91.  *
  92.  *  Mode seems to be passed in as a unix style file permissions argument
  93.  *  as in 0666, in the case of opening the logFile. 
  94.  *
  95.  */
  96. PRInt32
  97. _PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
  98. {
  99.     HFILE file;
  100.     PRInt32 access = OPEN_SHARE_DENYNONE;
  101.     PRInt32 flags = OPEN_ACTION_OPEN_IF_EXISTS;
  102.     PRInt32 rc;
  103.     PRUword actionTaken;
  104.  
  105.     ULONG CurMaxFH = 0;
  106.     LONG ReqCount = 1;
  107.  
  108.     if (osflags & PR_RDONLY)
  109.         access |= OPEN_ACCESS_READONLY;
  110.     else if (osflags & PR_WRONLY)
  111.         access |= OPEN_ACCESS_WRITEONLY;
  112.     else if(osflags & PR_RDWR)
  113.         access |= OPEN_ACCESS_READWRITE;
  114.     if (osflags & PR_CREATE_FILE)
  115.         flags |= OPEN_ACTION_CREATE_IF_NEW;
  116.     else if (osflags & PR_TRUNCATE){
  117.         flags &= ~OPEN_ACTION_OPEN_IF_EXISTS;
  118.         flags |= OPEN_ACTION_REPLACE_IF_EXISTS;
  119.     }
  120.         
  121.     /* OS/2 sets the Max file handles per process to 20 by default */
  122.     DosSetRelMaxFH(&ReqCount, &CurMaxFH);
  123.  
  124.     rc = DosOpen((char*)name,
  125.                  &file,            /* file handle if successful */
  126.                  &actionTaken,     /* reason for failure        */
  127.                  0,                /* initial size of new file  */
  128.                  FILE_NORMAL,      /* file system attributes    */
  129.                  flags,            /* Open flags                */
  130.                  access,           /* Open mode and rights      */
  131.                  0);               /* OS/2 Extended Attributes  */
  132.     if (rc != NO_ERROR) {
  133.         _PR_MD_MAP_OPEN_ERROR(rc);
  134.       return -1; 
  135.     }
  136.  
  137.     return (PRInt32)file;
  138. }
  139.  
  140. PRInt32
  141. _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
  142. {
  143.     PRUword bytes;
  144.     int rv;
  145.  
  146.     rv = DosRead((HFILE)fd->secret->md.osfd,
  147.                  (PVOID)buf,
  148.                  len,
  149.                  &bytes);
  150.     
  151.     if (rv != NO_ERROR) 
  152.     {
  153.         /* ERROR_HANDLE_EOF can only be returned by async io */
  154.         PR_ASSERT(rv != ERROR_HANDLE_EOF);
  155.         if (rv == ERROR_BROKEN_PIPE)
  156.             return 0;
  157.         else {
  158.             _PR_MD_MAP_READ_ERROR(rv);
  159.         return -1;
  160.     }
  161.     }
  162.     return bytes;
  163. }
  164.  
  165. PRInt32
  166. _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
  167. {
  168.     PRUword bytes;
  169.     int rv; 
  170.  
  171.     /* No longer using DosWrite since it doesn't convert \n to \n\r like C runtime does */
  172. #if 0
  173.     rv = DosWrite((HFILE)fd->secret->md.osfd,
  174.                   (PVOID)buf,
  175.                   len,
  176.                   &bytes);
  177.  
  178.     if (rv != NO_ERROR) 
  179.     {
  180.         _PR_MD_MAP_WRITE_ERROR(rv);
  181.         return -1;
  182.     }
  183. #else
  184.     bytes = write(fd->secret->md.osfd, buf, len);
  185.     if (rv == -1) 
  186.        _PR_MD_MAP_WRITE_ERROR(errno);
  187. #endif
  188.  
  189.     return bytes;
  190. } /* --- end _PR_MD_WRITE() --- */
  191.  
  192. PRInt32
  193. _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, int whence)
  194. {
  195.     PRInt32 rv;
  196.     PRUword newLocation;
  197.  
  198.     rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation);
  199.  
  200.     if (rv != NO_ERROR) {
  201.         _PR_MD_MAP_LSEEK_ERROR(rv);
  202.         return -1;
  203.     } else
  204.         return newLocation;
  205. }
  206.  
  207. PRInt64
  208. _PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, int whence)
  209. {
  210.     PRInt64 result;
  211.     PRInt32 rv, low = offset.lo, hi = offset.hi;
  212.     PRUword newLocation;
  213.  
  214.     rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation);
  215.     rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation);
  216.  
  217.       if (rv != NO_ERROR) {
  218.         _PR_MD_MAP_LSEEK_ERROR(rv);
  219.         hi = newLocation = -1;
  220.    }
  221.  
  222.     result.lo = hi;
  223.     result.hi = newLocation;
  224.     return result;
  225. }
  226.  
  227. PRInt32
  228. _PR_MD_FSYNC(PRFileDesc *fd)
  229. {
  230.     PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd);
  231.  
  232.     if (rc != NO_ERROR) {
  233.        if (rc != ERROR_ACCESS_DENIED) {    
  234.                _PR_MD_MAP_FSYNC_ERROR(rc);
  235.            return -1;
  236.        }
  237.     }
  238.     return 0;
  239. }
  240.  
  241. PRInt32
  242. _MD_CloseFile(PRInt32 osfd)
  243. {
  244.     PRInt32 rv;
  245.     
  246.     rv = DosClose((HFILE)osfd);
  247.      if (rv != NO_ERROR)
  248.         _PR_MD_MAP_CLOSE_ERROR(rv);
  249.     return rv;
  250. }
  251.  
  252.  
  253. /* --- DIR IO ------------------------------------------------------------ */
  254. #define GetFileFromDIR(d)       (d)->d_entry.achName
  255.  
  256. void FlipSlashes(char *cp, int len)
  257. {
  258.     while (--len >= 0) {
  259.     if (cp[0] == '/') {
  260.         cp[0] = PR_DIRECTORY_SEPARATOR;
  261.     }
  262.     cp++;
  263.     }
  264. }
  265.  
  266. /*
  267. **
  268. ** Local implementations of standard Unix RTL functions which are not provided
  269. ** by the VAC RTL.
  270. **
  271. */
  272.  
  273. PRInt32
  274. _PR_MD_CLOSE_DIR(_MDDir *d)
  275. {
  276.    PRInt32 rc;
  277.  
  278.     if ( d ) {
  279.       rc = DosFindClose(d->d_hdl);
  280.       if(rc == NO_ERROR){
  281.         d->magic = (PRUint32)-1;
  282.         return PR_SUCCESS;
  283.         } else {
  284.             _PR_MD_MAP_CLOSEDIR_ERROR(rc);
  285.             return PR_FAILURE;
  286.         }
  287.     }
  288.     PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  289.     return PR_FAILURE;
  290. }
  291.  
  292.  
  293. PRStatus
  294. _PR_MD_OPEN_DIR(_MDDir *d, const char *name)
  295. {
  296.     char filename[ CCHMAXPATH ];
  297.     PRUword numEntries, rc;
  298.  
  299.     PR_snprintf(filename, CCHMAXPATH, "%s%s%s",
  300.                 name, PR_DIRECTORY_SEPARATOR_STR, "*.*");
  301.     FlipSlashes( filename, strlen(filename) );
  302.  
  303.     d->d_hdl = HDIR_CREATE;
  304.  
  305.     rc = DosFindFirst( filename, &d->d_hdl, FILE_DIRECTORY, &(d->d_entry), sizeof(d->d_entry), &numEntries, FIL_STANDARD); 
  306.     if ( rc != NO_ERROR ) {
  307.         _PR_MD_MAP_OPENDIR_ERROR(rc);
  308.         return PR_FAILURE;
  309.     }
  310.     d->firstEntry = PR_TRUE;
  311.     d->magic = _MD_MAGIC_DIR;
  312.     return PR_SUCCESS;
  313. }
  314.  
  315. char *
  316. _PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
  317. {
  318.     PRUword numFiles = 1;
  319.     BOOL rv;
  320.     char *fileName;
  321.  
  322.     if ( d ) {
  323.        while (1) {
  324.            if (d->firstEntry) {
  325.                d->firstEntry = PR_FALSE;
  326.                rv = NO_ERROR;
  327.            } else {
  328.                rv = DosFindNext(d->d_hdl, &(d->d_entry), sizeof(d->d_entry), &numFiles);
  329.            }
  330.            if (rv != NO_ERROR) {
  331.                break;
  332.            }
  333.            fileName = GetFileFromDIR(d);
  334.            if ( (flags & PR_SKIP_DOT) &&
  335.                 (fileName[0] == '.') && (fileName[1] == '\0'))
  336.                 continue;
  337.            if ( (flags & PR_SKIP_DOT_DOT) &&
  338.                 (fileName[0] == '.') && (fileName[1] == '.') &&
  339.                 (fileName[2] == '\0'))
  340.                 continue;
  341.             /*
  342.              * XXX
  343.              * Is this the correct definition of a hidden file on OS/2?
  344.              */
  345.            if ( (flags & PR_SKIP_HIDDEN) && (fileName[0] == '.'))
  346.                 continue;
  347.            return fileName;
  348.         }
  349.         PR_ASSERT(NO_ERROR != rv);
  350.             _PR_MD_MAP_READDIR_ERROR(rv);
  351.         return NULL;
  352.         }
  353.     PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  354.     return NULL;
  355. }
  356.  
  357. PRInt32
  358. _PR_MD_DELETE(const char *name)
  359. {
  360.     PRInt32 rc = DosDelete((char*)name);
  361.     if(rc == NO_ERROR) {
  362.         return 0;
  363.     } else {
  364.         _PR_MD_MAP_DELETE_ERROR(rc);
  365.         return -1;
  366.     }
  367. }
  368.  
  369. PRInt32
  370. _PR_MD_STAT(const char *fn, struct stat *info)
  371. {
  372.     PRInt32 rv;
  373.  
  374.     rv = _stat((char*)fn, info);
  375.     if (-1 == rv) {
  376.         /*
  377.          * Check for MSVC runtime library _stat() bug.
  378.          * (It's really a bug in FindFirstFile().)
  379.          * If a pathname ends in a backslash or slash,
  380.          * e.g., c:\temp\ or c:/temp/, _stat() will fail.
  381.          * Note: a pathname ending in a slash (e.g., c:/temp/)
  382.          * can be handled by _stat() on NT but not on Win95.
  383.          *
  384.          * We remove the backslash or slash at the end and
  385.          * try again.  
  386.          *
  387.          * Not sure if this happens on OS/2 or not,
  388.          * but it doesn't hurt to be careful.
  389.          */
  390.  
  391.         int len = strlen(fn);
  392.         if (len > 0 && len <= _MAX_PATH
  393.                 && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
  394.             char newfn[_MAX_PATH + 1];
  395.  
  396.             strcpy(newfn, fn);
  397.             newfn[len - 1] = '\0';
  398.             rv = _stat(newfn, info);
  399.         }
  400.     }
  401.  
  402.     if (-1 == rv) {
  403.         _PR_MD_MAP_STAT_ERROR(errno);
  404.     }
  405.     return rv;
  406. }
  407.  
  408. PRInt32
  409. _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
  410. {
  411.     struct stat sb;
  412.     PRInt32 rv;
  413.  
  414.     if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) {
  415.         if (info) {
  416.             if (S_IFREG & sb.st_mode)
  417.                 info->type = PR_FILE_FILE ;
  418.             else if (S_IFDIR & sb.st_mode)
  419.                 info->type = PR_FILE_DIRECTORY;
  420.             else
  421.                 info->type = PR_FILE_OTHER;
  422.             info->size = sb.st_size;
  423.             info->modifyTime.lo = sb.st_mtime;
  424.             info->creationTime.lo = sb.st_ctime;
  425.         }
  426.     }
  427.     return rv;
  428. }
  429.  
  430. PRInt32
  431. _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
  432. {
  433.     PRFileInfo info32;
  434.     PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
  435.     if (0 == rv)
  436.     {
  437.         info->type = info32.type;
  438.         info->size.lo = info32.size;
  439.         info->modifyTime = info32.modifyTime;
  440.         info->creationTime = info32.creationTime;
  441.     }
  442.     return rv;
  443. }
  444.  
  445. PRInt32
  446. _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
  447. {
  448.    /* For once, the VAC compiler/library did a nice thing.
  449.     * The file handle used by the C runtime is the same one
  450.     * returned by the OS when you call DosOpen().  This means
  451.     * that you can take an OS HFILE and use it with C file
  452.     * functions.  The only caveat is that you have to call
  453.     * _setmode() first to initialize some junk.  This is
  454.     * immensely useful because I did not have a clue how to
  455.     * implement this function otherwise.  The windows folks
  456.     * took the source from the Microsoft C library source, but
  457.     * IBM wasn't kind enough to ship the source with VAC.
  458.     * On second thought, the needed function could probably
  459.     * be gotten from the OS/2 GNU library source, but the
  460.     * point is now moot.
  461.     */
  462.    struct stat hinfo;
  463.  
  464.     _setmode(fd->secret->md.osfd, O_BINARY);
  465.     if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) {
  466.         _PR_MD_MAP_FSTAT_ERROR(errno);
  467.         return -1;
  468.     }
  469.  
  470.     if (hinfo.st_mode & S_IFDIR)
  471.         info->type = PR_FILE_DIRECTORY;
  472.     else
  473.         info->type = PR_FILE_FILE;
  474.  
  475.     info->size = hinfo.st_size;
  476.     info->modifyTime.lo = hinfo.st_mtime;
  477.     info->creationTime.lo = hinfo.st_ctime;
  478.  
  479.     return 0;
  480. }
  481.  
  482. PRInt32
  483. _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
  484. {
  485.    PRFileInfo info32;
  486.    PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32);
  487.    if (0 == rv)
  488.    {
  489.        info->type = info32.type;
  490.        info->size.lo = info32.size;
  491.        info->modifyTime = info32.modifyTime;
  492.        info->creationTime = info32.creationTime;
  493.    }
  494.    return rv;
  495. }
  496.  
  497.  
  498. PRInt32
  499. _PR_MD_RENAME(const char *from, const char *to)
  500. {
  501.    PRInt32 rc;
  502.     /* Does this work with dot-relative pathnames? */
  503.     if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) {
  504.         return 0;
  505.     } else {
  506.         _PR_MD_MAP_RENAME_ERROR(rc);
  507.         return -1;
  508.     }
  509. }
  510.  
  511. PRInt32
  512. _PR_MD_ACCESS(const char *name, PRIntn how)
  513. {
  514. PRInt32 rv;
  515.     switch (how) {
  516.       case PR_ACCESS_WRITE_OK:
  517.         rv = access(name, 02);
  518.         break;
  519.       case PR_ACCESS_READ_OK:
  520.         rv = access(name, 04);
  521.         break;
  522.       case PR_ACCESS_EXISTS:
  523.         return access(name, 00);
  524.           break;
  525.       default:
  526.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  527.         return -1;
  528.     }
  529.     if (rv < 0)
  530.         _PR_MD_MAP_ACCESS_ERROR(errno);
  531.     return rv;
  532. }
  533.  
  534. PRInt32
  535. _PR_MD_MKDIR(const char *name, PRIntn mode)
  536. {
  537.    PRInt32 rc;
  538.     /* XXXMB - how to translate the "mode"??? */
  539.     if ((rc = DosCreateDir((char *)name, NULL)) == NO_ERROR) {
  540.         return 0;
  541.     } else {
  542.         _PR_MD_MAP_MKDIR_ERROR(rc);
  543.         return -1;
  544.     }
  545. }
  546.  
  547. PRInt32
  548. _PR_MD_RMDIR(const char *name)
  549. {
  550.    PRInt32 rc;
  551.     if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) {
  552.         return 0;
  553.     } else {
  554.         _PR_MD_MAP_RMDIR_ERROR(rc);
  555.         return -1;
  556.     }
  557. }
  558.  
  559. PR_IMPLEMENT(PRStatus)
  560. _PR_MD_LOCKFILE(PRInt32 f)
  561. {
  562.     PRInt32   rv;
  563.    FILELOCK lock, unlock;
  564.  
  565.    lock.lOffset = 0;
  566.    lock.lRange = 0xffffffff;
  567.    unlock.lOffset = 0;
  568.    unlock.lRange = 0;
  569.  
  570.     /*
  571.      * loop trying to DosSetFileLocks(),
  572.      * pause for a few miliseconds when can't get the lock
  573.      * and try again
  574.      */
  575.     for( rv = FALSE; rv == FALSE; /* do nothing */ )
  576.     {
  577.     
  578.         rv = DosSetFileLocks( (HFILE) f,
  579.                                 &unlock, &lock,
  580.                                 0, 0); 
  581.         if ( rv != NO_ERROR )
  582.         {
  583.             DosSleep( 50 );  /* Sleep() a few milisecs and try again. */
  584.         }            
  585.     } /* end for() */
  586.     return PR_SUCCESS;
  587. } /* end _PR_MD_LOCKFILE() */
  588.  
  589. PR_IMPLEMENT(PRStatus)
  590. _PR_MD_TLOCKFILE(PRInt32 f)
  591. {
  592.     return _PR_MD_LOCKFILE(f);
  593. } /* end _PR_MD_TLOCKFILE() */
  594.  
  595.  
  596. PR_IMPLEMENT(PRStatus)
  597. _PR_MD_UNLOCKFILE(PRInt32 f)
  598. {
  599.     PRInt32   rv;
  600.    FILELOCK lock, unlock;
  601.  
  602.    lock.lOffset = 0;
  603.    lock.lRange = 0;
  604.    unlock.lOffset = 0;
  605.    unlock.lRange = 0xffffffff;
  606.     
  607.    rv = DosSetFileLocks( (HFILE) f,
  608.                           &unlock, &lock,
  609.                           0, 0); 
  610.             
  611.     if ( rv != NO_ERROR )
  612.     {
  613.         return PR_SUCCESS;
  614.     }
  615.     else
  616.     {
  617.         return PR_FAILURE;
  618.     }
  619. } /* end _PR_MD_UNLOCKFILE() */
  620.  
  621.