home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / io / prfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  13.0 KB  |  555 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. #include "primpl.h"
  20.  
  21. #include <string.h>
  22. #include <fcntl.h>
  23.  
  24. #ifdef XP_UNIX
  25. #ifdef AIX
  26. /* To pick up sysconf */
  27. #include <unistd.h>
  28. #else
  29. /* To pick up getrlimit, setrlimit */
  30. #include <sys/time.h>
  31. #include <sys/resource.h>
  32. #endif
  33. #endif /* XP_UNIX */
  34.  
  35. extern PRLock *_pr_flock_lock;
  36.  
  37. static PRInt32 PR_CALLBACK FileRead(PRFileDesc *fd, void *buf, PRInt32 amount)
  38. {
  39.     PRInt32 rv = 0;
  40.     PRThread *me = _PR_MD_CURRENT_THREAD();
  41.  
  42.     if (_PR_PENDING_INTERRUPT(me)) {
  43.          me->flags &= ~_PR_INTERRUPT;
  44.         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  45.         rv = -1;
  46.     }
  47.     if (_PR_IO_PENDING(me)) {
  48.         PR_SetError(PR_IO_PENDING_ERROR, 0);
  49.     rv = -1;
  50.     }
  51.     if (rv == -1)
  52.         return rv;
  53.  
  54.     rv = _PR_MD_READ(fd, buf, amount);
  55.     if (rv < 0) {
  56.         PR_ASSERT(rv == -1);
  57.     }
  58.     PR_LOG(_pr_io_lm, PR_LOG_MAX, ("read -> %d", rv));
  59.     return rv;
  60. }
  61.  
  62. static PRInt32 PR_CALLBACK FileWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
  63. {
  64.     PRInt32 rv = 0;
  65.     PRInt32 temp, count;
  66.     PRThread *me = _PR_MD_CURRENT_THREAD();
  67.  
  68.     if (_PR_PENDING_INTERRUPT(me)) {
  69.         me->flags &= ~_PR_INTERRUPT;
  70.         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
  71.     rv = -1;
  72.     }
  73.     if (_PR_IO_PENDING(me)) {
  74.         PR_SetError(PR_IO_PENDING_ERROR, 0);
  75.     rv = -1;
  76.     }
  77.     if (rv != 0)
  78.         return rv;
  79.  
  80.     count = 0;
  81.     while (amount > 0) {
  82.         temp = _PR_MD_WRITE(fd, buf, amount);
  83.         if (temp < 0) {
  84.             count = -1;
  85.             break;
  86.         }
  87.         count += temp;
  88.         if (fd->secret->nonblocking) {
  89.             break;
  90.         }
  91.         buf = (const void*) ((const char*)buf + temp);
  92.         amount -= temp;
  93.     }
  94.     PR_LOG(_pr_io_lm, PR_LOG_MAX, ("write -> %d", count));
  95.     return count;
  96. }
  97.  
  98. static PRInt32 PR_CALLBACK FileSeek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
  99. {
  100.     PRInt32 result;
  101.  
  102.     result = _PR_MD_LSEEK(fd, offset, whence);
  103.     return result;
  104. }
  105.  
  106. static PRInt64 PR_CALLBACK FileSeek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
  107. {
  108.     PRInt64 result;
  109.  
  110.     result = _PR_MD_LSEEK64(fd, offset, whence);
  111.     return result;
  112. }
  113.  
  114. static PRInt32 PR_CALLBACK FileAvailable(PRFileDesc *fd)
  115. {
  116.     PRInt32 result, cur, end;
  117.  
  118.     cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR);
  119.  
  120.     if (cur >= 0)
  121.         end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END);
  122.  
  123.     if ((cur < 0) || (end < 0)) {
  124.         return -1;
  125.     }
  126.  
  127.     result = end - cur;
  128.     _PR_MD_LSEEK(fd, cur, PR_SEEK_SET);
  129.  
  130.     return result;
  131. }
  132.  
  133. static PRInt64 PR_CALLBACK FileAvailable64(PRFileDesc *fd)
  134. {
  135.     PRInt64 result, cur, end;
  136.     PRInt64 minus_one;
  137.  
  138.     LL_I2L(minus_one, -1);
  139.     cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR);
  140.  
  141.     if (LL_GE_ZERO(cur))
  142.         end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END);
  143.  
  144.     if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one;
  145.  
  146.     LL_SUB(result, end, cur);
  147.     (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET);
  148.  
  149.     return result;
  150. }
  151.  
  152. static PRStatus PR_CALLBACK FileInfo(PRFileDesc *fd, PRFileInfo *info)
  153. {
  154.     PRInt32 rv;
  155.  
  156.     rv = _PR_MD_GETOPENFILEINFO(fd, info);
  157.     if (rv < 0) {
  158.     return PR_FAILURE;
  159.     } else
  160.     return PR_SUCCESS;
  161. }
  162.  
  163. static PRStatus PR_CALLBACK FileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
  164. {
  165.     /* $$$$ NOT YET IMPLEMENTED */
  166.     PRInt32 rv;
  167.  
  168.     rv = _PR_MD_GETOPENFILEINFO64(fd, info);
  169.     if (rv < 0) return PR_FAILURE;
  170.     else return PR_SUCCESS;
  171. }
  172.  
  173. static PRStatus PR_CALLBACK FileSync(PRFileDesc *fd)
  174. {
  175.     PRInt32 result;
  176.     result = _PR_MD_FSYNC(fd);
  177.     if (result < 0) {
  178.         return PR_FAILURE;
  179.     }
  180.     return PR_SUCCESS;
  181. }
  182.  
  183. static PRStatus PR_CALLBACK FileClose(PRFileDesc *fd)
  184. {
  185.     PRInt32 rv;
  186.  
  187.     if (!fd || fd->secret->state != _PR_FILEDESC_OPEN) {
  188.         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
  189.         return PR_FAILURE;
  190.     }
  191.  
  192.     fd->secret->state = _PR_FILEDESC_CLOSED;
  193.  
  194.     rv =  _PR_MD_CLOSE_FILE(fd->secret->md.osfd);
  195.     PR_FreeFileDesc(fd);
  196.     if (rv < 0) {
  197.         return PR_FAILURE;
  198.     } else {
  199.         return PR_SUCCESS;
  200.     }
  201. }
  202.  
  203. PRIOMethods _pr_fileMethods = {
  204.     PR_DESC_FILE,
  205.     FileClose,
  206.     FileRead,
  207.     FileWrite,
  208.     FileAvailable,
  209.     FileAvailable64,
  210.     FileSync,
  211.     FileSeek,
  212.     FileSeek64,
  213.     FileInfo,
  214.     FileInfo64,
  215.     (PRWritevFN)_PR_InvalidInt,        
  216.     (PRConnectFN)_PR_InvalidStatus,        
  217.     (PRAcceptFN)_PR_InvalidDesc,        
  218.     (PRBindFN)_PR_InvalidStatus,        
  219.     (PRListenFN)_PR_InvalidStatus,        
  220.     (PRShutdownFN)_PR_InvalidStatus,    
  221.     (PRRecvFN)_PR_InvalidInt,        
  222.     (PRSendFN)_PR_InvalidInt,        
  223.     (PRRecvfromFN)_PR_InvalidInt,    
  224.     (PRSendtoFN)_PR_InvalidInt,        
  225.     (PRPollFN)0,         
  226.     (PRAcceptreadFN)_PR_InvalidInt,   
  227.     (PRTransmitfileFN)_PR_InvalidInt, 
  228.     (PRGetsocknameFN)_PR_InvalidStatus,    
  229.     (PRGetpeernameFN)_PR_InvalidStatus,    
  230.     (PRGetsockoptFN)_PR_InvalidStatus,    
  231.     (PRSetsockoptFN)_PR_InvalidStatus,    
  232.     (PRGetsocketoptionFN)_PR_InvalidStatus,    
  233.     (PRSetsocketoptionFN)_PR_InvalidStatus,    
  234. };
  235.  
  236. PR_IMPLEMENT(PRIOMethods*) PR_GetFileMethods(void)
  237. {
  238.     return &_pr_fileMethods;
  239. }
  240.  
  241. PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
  242. {
  243.     PRInt32 osfd;
  244.     PRFileDesc *fd = 0;
  245.  
  246.     if (!_pr_initialized) _PR_ImplicitInitialization();
  247.  
  248.     /* Map pr open flags and mode to os specific flags */
  249.  
  250.     osfd = _PR_MD_OPEN(name, flags, mode);
  251.     if (osfd != -1) {
  252.     fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
  253.         if (!fd) {
  254.             (void) _PR_MD_CLOSE_FILE(osfd);
  255.         }
  256.     }
  257.     return fd;
  258. }
  259.  
  260. PRInt32 PR_GetSysfdTableMax(void)
  261. {
  262. #if defined(XP_UNIX) && !defined(AIX)
  263.     struct rlimit rlim;
  264.  
  265.     if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
  266.        /* XXX need to call PR_SetError() */
  267.        return -1;
  268.     }
  269.  
  270.     return rlim.rlim_max;
  271. #elif defined(AIX)
  272.     return sysconf(_SC_OPEN_MAX);
  273. #elif defined(WIN32) || defined(OS2)
  274.     /*
  275.      * There is a systemwide limit of 65536 user handles.
  276.      * Not sure on OS/2, but sounds good.
  277.      */
  278.     return 16384;
  279. #elif defined (WIN16)
  280.     return FOPEN_MAX;
  281. #elif defined (XP_MAC)
  282.     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  283.    return -1;
  284. #else
  285.     write me;
  286. #endif
  287. }
  288.  
  289. PRInt32 PR_SetSysfdTableSize(int table_size)
  290. {
  291. #if defined(XP_UNIX) && !defined(AIX)
  292.     struct rlimit rlim;
  293.     PRInt32 tableMax = PR_GetSysfdTableMax();
  294.  
  295.     if (tableMax < 0) 
  296.         return -1;
  297.  
  298.     if (tableMax > FD_SETSIZE)
  299.         tableMax = FD_SETSIZE;
  300.  
  301.     rlim.rlim_max = tableMax;
  302.  
  303.     /* Grow as much as we can; even if too big */
  304.     if ( rlim.rlim_max < table_size )
  305.         rlim.rlim_cur = rlim.rlim_max;
  306.     else
  307.         rlim.rlim_cur = table_size;
  308.  
  309.     if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
  310.         /* XXX need to call PR_SetError() */
  311.         return -1;
  312.     }
  313.  
  314.     return rlim.rlim_cur;
  315. #elif defined(AIX) || defined(WIN32) || defined(WIN16) || defined(OS2)
  316.     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  317.     return -1;
  318. #elif defined (XP_MAC)
  319. #pragma unused (table_size)
  320.     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  321.    return -1;
  322. #else
  323.     write me;
  324. #endif
  325. }
  326.  
  327. PR_IMPLEMENT(PRStatus) PR_Delete(const char *name)
  328. {
  329.     PRInt32 rv;
  330.  
  331.     rv = _PR_MD_DELETE(name);
  332.     if (rv < 0) {
  333.         return PR_FAILURE;
  334.     } else
  335.         return PR_SUCCESS;
  336. }
  337.  
  338. PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)
  339. {
  340.     PRInt32 rv;
  341.  
  342.     rv = _PR_MD_GETFILEINFO(fn, info);
  343.     if (rv < 0) {
  344.         return PR_FAILURE;
  345.     } else
  346.         return PR_SUCCESS;
  347. }
  348.  
  349. PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
  350. {
  351.     PRInt32 rv;
  352.  
  353.     rv = _PR_MD_GETFILEINFO64(fn, info);
  354.     if (rv < 0) {
  355.         return PR_FAILURE;
  356.     } else {
  357.         return PR_SUCCESS;
  358.     }
  359. }
  360.  
  361. PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to)
  362. {
  363.     PRInt32 rv;
  364.  
  365.     rv = _PR_MD_RENAME(from, to);
  366.     if (rv < 0) {
  367.         return PR_FAILURE;
  368.     } else
  369.         return PR_SUCCESS;
  370. }
  371.  
  372. PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how)
  373. {
  374. PRInt32 rv;
  375.  
  376.     rv = _PR_MD_ACCESS(name, how);
  377.     if (rv < 0) {
  378.         return PR_FAILURE;
  379.     } else
  380.         return PR_SUCCESS;
  381. }
  382.  
  383. /*
  384. ** Import an existing OS file to NSPR 
  385. */
  386. PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd)
  387. {
  388.     PRFileDesc *fd = NULL;
  389.  
  390.     fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
  391.     if( !fd ) {
  392.         (void) _PR_MD_CLOSE_FILE(osfd);
  393.     }
  394.  
  395.     return fd;
  396. }
  397.  
  398. #ifndef NO_NSPR_10_SUPPORT
  399. /*
  400. ** PR_Stat() for Win16 is defined in w16io.c
  401. ** it is a hack to circumvent problems in Gromit and Java
  402. ** See also: BugSplat: 98516.
  403. */
  404. #if !defined(WIN16)
  405. /*
  406.  * This function is supposed to be for backward compatibility with
  407.  * nspr 1.0.  Therefore, it still uses the nspr 1.0 error-reporting
  408.  * mechanism -- returns a PRInt32, which is the error code when the call
  409.  * fails.
  410.  * 
  411.  * If we need this function in nspr 2.0, it should be changed to
  412.  * return PRStatus, as follows:
  413.  *
  414.  * PR_IMPLEMENT(PRStatus) PR_Stat(const char *name, struct stat *buf)
  415.  * {
  416.  *     PRInt32 rv;
  417.  *
  418.  *     rv = _PR_MD_STAT(name, buf);
  419.  *     if (rv < 0)
  420.  *         return PR_FAILURE;
  421.  *     else
  422.  *         return PR_SUCCESS;
  423.  * }
  424.  *
  425.  * -- wtc, 2/14/97.
  426.  */
  427. PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
  428. {
  429.     PRInt32 rv;
  430.  
  431.     rv = _PR_MD_STAT(name, buf);
  432.     return rv;
  433. }
  434.  
  435. #endif /* !defined(WIN16)  */
  436. #endif /* ! NO_NSPR_10_SUPPORT */
  437.  
  438. PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
  439. {
  440.     PRStatus rv = PR_SUCCESS;
  441.  
  442.     PR_Lock(_pr_flock_lock);
  443.     if (fd->secret->lockCount == 0) {
  444.         rv = _PR_MD_LOCKFILE(fd->secret->md.osfd);
  445.         if (rv == PR_SUCCESS)
  446.             fd->secret->lockCount = 1;
  447.     } else {
  448.         fd->secret->lockCount++;
  449.     }
  450.     PR_Unlock(_pr_flock_lock);
  451.  
  452.     return rv;
  453. }
  454.  
  455. PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)
  456. {
  457.     PRStatus rv = PR_SUCCESS;
  458.  
  459.     PR_Lock(_pr_flock_lock);
  460.     if (fd->secret->lockCount == 0) {
  461.         rv = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
  462.         PR_ASSERT(rv == PR_SUCCESS || fd->secret->lockCount == 0);
  463.         if (rv == PR_SUCCESS)
  464.             fd->secret->lockCount = 1;
  465.     } else {
  466.         fd->secret->lockCount++;
  467.     }
  468.     PR_Unlock(_pr_flock_lock);
  469.  
  470.     return rv;
  471. }
  472.  
  473. PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)
  474. {
  475.     PRStatus rv = PR_SUCCESS;
  476.  
  477.     PR_Lock(_pr_flock_lock);
  478.     if (fd->secret->lockCount == 1) {
  479.         rv = _PR_MD_UNLOCKFILE(fd->secret->md.osfd);
  480.         if (rv == PR_SUCCESS) 
  481.             fd->secret->lockCount = 0;
  482.     } else {
  483.         fd->secret->lockCount--;
  484.     }
  485.     PR_Unlock(_pr_flock_lock);
  486.  
  487.     return rv;
  488. }
  489.  
  490. PR_IMPLEMENT(PRStatus) PR_CreatePipe(
  491.     PRFileDesc **readPipe,
  492.     PRFileDesc **writePipe
  493. )
  494. {
  495. #if defined(XP_MAC)
  496. #pragma unused (readPipe, writePipe)
  497. #endif
  498.  
  499. #ifdef WIN32
  500.     HANDLE readEnd, writeEnd;
  501.     SECURITY_ATTRIBUTES pipeAttributes;
  502.  
  503.     ZeroMemory(&pipeAttributes, sizeof(pipeAttributes));
  504.     pipeAttributes.nLength = sizeof(pipeAttributes);
  505.     pipeAttributes.bInheritHandle = TRUE;
  506.     if (CreatePipe(&readEnd, &writeEnd, &pipeAttributes, 0) == 0) {
  507.         PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
  508.         return PR_FAILURE;
  509.     }
  510.     *readPipe = PR_AllocFileDesc((PRInt32)readEnd, &_pr_fileMethods);
  511.     if (NULL == *readPipe) {
  512.         CloseHandle(readEnd);
  513.         CloseHandle(writeEnd);
  514.         return PR_FAILURE;
  515.     }
  516.     *writePipe = PR_AllocFileDesc((PRInt32)writeEnd, &_pr_fileMethods);
  517.     if (NULL == *writePipe) {
  518.         PR_Close(*readPipe);
  519.         CloseHandle(writeEnd);
  520.         return PR_FAILURE;
  521.     }
  522. #ifdef WINNT
  523.     (*readPipe)->secret->md.nonoverlapped = PR_TRUE;
  524.     (*writePipe)->secret->md.nonoverlapped = PR_TRUE;
  525. #endif
  526.     return PR_SUCCESS;
  527. #elif defined(XP_UNIX)
  528.     int pipefd[2];
  529.  
  530.     if (pipe(pipefd) == -1) {
  531.         /* XXX map pipe error */
  532.         PR_SetError(PR_UNKNOWN_ERROR, errno);
  533.         return PR_FAILURE;
  534.     }
  535.     *readPipe = PR_AllocFileDesc(pipefd[0], &_pr_fileMethods);
  536.     if (NULL == *readPipe) {
  537.         close(pipefd[0]);
  538.         close(pipefd[1]);
  539.         return PR_FAILURE;
  540.     }
  541.     *writePipe = PR_AllocFileDesc(pipefd[1], &_pr_fileMethods);
  542.     if (NULL == *writePipe) {
  543.         PR_Close(*readPipe);
  544.         close(pipefd[1]);
  545.         return PR_FAILURE;
  546.     }
  547.     _MD_MakeNonblock(*readPipe);
  548.     _MD_MakeNonblock(*writePipe);
  549.     return PR_SUCCESS;
  550. #else
  551.     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  552.     return PR_FAILURE;
  553. #endif
  554. }
  555.