Back to index

lightning-sunbird  0.9+nobinonly
prfile.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "primpl.h"
00039 
00040 #include <string.h>
00041 #include <fcntl.h>
00042 
00043 #ifdef XP_UNIX
00044 #if defined(AIX) || defined(QNX)
00045 /* To pick up sysconf */
00046 #include <unistd.h>
00047 #else
00048 /* To pick up getrlimit, setrlimit */
00049 #include <sys/time.h>
00050 #include <sys/resource.h>
00051 #endif
00052 #endif /* XP_UNIX */
00053 
00054 extern PRLock *_pr_flock_lock;
00055 extern PRCondVar *_pr_flock_cv;
00056 
00057 static PRInt32 PR_CALLBACK FileRead(PRFileDesc *fd, void *buf, PRInt32 amount)
00058 {
00059     PRInt32 rv = 0;
00060     PRThread *me = _PR_MD_CURRENT_THREAD();
00061 
00062     if (_PR_PENDING_INTERRUPT(me)) {
00063               me->flags &= ~_PR_INTERRUPT;
00064               PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
00065               rv = -1;
00066     }
00067     if (_PR_IO_PENDING(me)) {
00068         PR_SetError(PR_IO_PENDING_ERROR, 0);
00069        rv = -1;
00070     }
00071     if (rv == -1)
00072        return rv;
00073 
00074        rv = _PR_MD_READ(fd, buf, amount);
00075        if (rv < 0) {
00076               PR_ASSERT(rv == -1);
00077        }
00078     PR_LOG(_pr_io_lm, PR_LOG_MAX, ("read -> %d", rv));
00079     return rv;
00080 }
00081 
00082 static PRInt32 PR_CALLBACK FileWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
00083 {
00084     PRInt32 rv = 0;
00085     PRInt32 temp, count;
00086     PRThread *me = _PR_MD_CURRENT_THREAD();
00087 
00088     if (_PR_PENDING_INTERRUPT(me)) {
00089         me->flags &= ~_PR_INTERRUPT;
00090         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
00091            rv = -1;
00092     }
00093     if (_PR_IO_PENDING(me)) {
00094         PR_SetError(PR_IO_PENDING_ERROR, 0);
00095            rv = -1;
00096     }
00097     if (rv != 0)
00098        return rv;
00099 
00100     count = 0;
00101 #if !defined(_PR_HAVE_O_APPEND)  /* Bugzilla: 4090, 276330 */
00102     if (fd->secret->appendMode) {
00103         if (PR_Seek64(fd, 0, PR_SEEK_END) == -1) {
00104             return -1;
00105         }
00106     } /* if (fd->secret->appendMode...) */
00107 #endif /* _PR_HAVE_O_APPEND */
00108     while (amount > 0) {
00109               temp = _PR_MD_WRITE(fd, buf, amount);
00110               if (temp < 0) {
00111                      count = -1;
00112                      break;
00113               }
00114               count += temp;
00115               if (fd->secret->nonblocking) {
00116                      break;
00117               }
00118               buf = (const void*) ((const char*)buf + temp);
00119               amount -= temp;
00120     }
00121     PR_LOG(_pr_io_lm, PR_LOG_MAX, ("write -> %d", count));
00122     return count;
00123 }
00124 
00125 static PROffset32 PR_CALLBACK FileSeek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
00126 {
00127     PROffset32 result;
00128 
00129     result = _PR_MD_LSEEK(fd, offset, whence);
00130     return result;
00131 }
00132 
00133 static PROffset64 PR_CALLBACK FileSeek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
00134 {
00135 #ifdef XP_MAC
00136 #pragma unused( fd, offset, whence )
00137 #endif
00138     PROffset64 result;
00139 
00140     result = _PR_MD_LSEEK64(fd, offset, whence);
00141     return result;
00142 }
00143 
00144 static PRInt32 PR_CALLBACK FileAvailable(PRFileDesc *fd)
00145 {
00146     PRInt32 result, cur, end;
00147 
00148     cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR);
00149 
00150        if (cur >= 0)
00151        end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END);
00152 
00153     if ((cur < 0) || (end < 0)) {
00154         return -1;
00155     }
00156 
00157     result = end - cur;
00158     _PR_MD_LSEEK(fd, cur, PR_SEEK_SET);
00159 
00160     return result;
00161 }
00162 
00163 static PRInt64 PR_CALLBACK FileAvailable64(PRFileDesc *fd)
00164 {
00165 #ifdef XP_MAC
00166 #pragma unused( fd )
00167 #endif
00168     PRInt64 result, cur, end;
00169     PRInt64 minus_one;
00170 
00171     LL_I2L(minus_one, -1);
00172     cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR);
00173 
00174     if (LL_GE_ZERO(cur))
00175        end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END);
00176 
00177     if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one;
00178 
00179     LL_SUB(result, end, cur);
00180     (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET);
00181 
00182     return result;
00183 }
00184 
00185 static PRInt32 PR_CALLBACK PipeAvailable(PRFileDesc *fd)
00186 {
00187        PRInt32 rv;
00188        rv =  _PR_MD_PIPEAVAILABLE(fd);
00189        return rv;           
00190 }
00191 
00192 static PRInt64 PR_CALLBACK PipeAvailable64(PRFileDesc *fd)
00193 {
00194     PRInt64 rv;
00195     LL_I2L(rv, _PR_MD_PIPEAVAILABLE(fd));
00196        return rv;           
00197 }
00198 
00199 static PRStatus PR_CALLBACK PipeSync(PRFileDesc *fd)
00200 {
00201 #if defined(XP_MAC)
00202 #pragma unused (fd)
00203 #endif
00204 
00205        return PR_SUCCESS;
00206 }
00207 
00208 static PRStatus PR_CALLBACK FileGetInfo(PRFileDesc *fd, PRFileInfo *info)
00209 {
00210        PRInt32 rv;
00211 
00212     rv = _PR_MD_GETOPENFILEINFO(fd, info);
00213     if (rv < 0) {
00214        return PR_FAILURE;
00215     } else
00216        return PR_SUCCESS;
00217 }
00218 
00219 static PRStatus PR_CALLBACK FileGetInfo64(PRFileDesc *fd, PRFileInfo64 *info)
00220 {
00221 #ifdef XP_MAC
00222 #pragma unused( fd, info )
00223 #endif
00224     /* $$$$ NOT YET IMPLEMENTED */
00225        PRInt32 rv;
00226 
00227     rv = _PR_MD_GETOPENFILEINFO64(fd, info);
00228     if (rv < 0) return PR_FAILURE;
00229     else return PR_SUCCESS;
00230 }
00231 
00232 static PRStatus PR_CALLBACK FileSync(PRFileDesc *fd)
00233 {
00234     PRInt32 result;
00235     result = _PR_MD_FSYNC(fd);
00236     if (result < 0) {
00237               return PR_FAILURE;
00238     }
00239     return PR_SUCCESS;
00240 }
00241 
00242 static PRStatus PR_CALLBACK FileClose(PRFileDesc *fd)
00243 {
00244     if (!fd || !fd->secret
00245             || (fd->secret->state != _PR_FILEDESC_OPEN
00246             && fd->secret->state != _PR_FILEDESC_CLOSED)) {
00247         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
00248         return PR_FAILURE;
00249     }
00250 
00251     if (fd->secret->state == _PR_FILEDESC_OPEN) {
00252         if (_PR_MD_CLOSE_FILE(fd->secret->md.osfd) < 0) {
00253             return PR_FAILURE;
00254         }
00255         fd->secret->state = _PR_FILEDESC_CLOSED;
00256     }
00257     PR_FreeFileDesc(fd);
00258     return PR_SUCCESS;
00259 }
00260 
00261 static PRInt16 PR_CALLBACK FilePoll(
00262     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
00263 {
00264 #ifdef XP_MAC
00265 #pragma unused( fd, in_flags )
00266 #endif
00267     *out_flags = 0;
00268     return in_flags;
00269 }  /* FilePoll */
00270 
00271 static PRIOMethods _pr_fileMethods = {
00272     PR_DESC_FILE,
00273     FileClose,
00274     FileRead,
00275     FileWrite,
00276     FileAvailable,
00277     FileAvailable64,
00278     FileSync,
00279     FileSeek,
00280     FileSeek64,
00281     FileGetInfo,
00282     FileGetInfo64,
00283     (PRWritevFN)_PR_InvalidInt,           
00284     (PRConnectFN)_PR_InvalidStatus,              
00285     (PRAcceptFN)_PR_InvalidDesc,          
00286     (PRBindFN)_PR_InvalidStatus,          
00287     (PRListenFN)_PR_InvalidStatus,        
00288     (PRShutdownFN)_PR_InvalidStatus,      
00289     (PRRecvFN)_PR_InvalidInt,             
00290     (PRSendFN)_PR_InvalidInt,             
00291     (PRRecvfromFN)_PR_InvalidInt,  
00292     (PRSendtoFN)_PR_InvalidInt,           
00293     FilePoll,         
00294     (PRAcceptreadFN)_PR_InvalidInt,   
00295     (PRTransmitfileFN)_PR_InvalidInt, 
00296     (PRGetsocknameFN)_PR_InvalidStatus,   
00297     (PRGetpeernameFN)_PR_InvalidStatus,   
00298     (PRReservedFN)_PR_InvalidInt,  
00299     (PRReservedFN)_PR_InvalidInt,  
00300     (PRGetsocketoptionFN)_PR_InvalidStatus,      
00301     (PRSetsocketoptionFN)_PR_InvalidStatus,
00302     (PRSendfileFN)_PR_InvalidInt, 
00303     (PRConnectcontinueFN)_PR_InvalidStatus, 
00304     (PRReservedFN)_PR_InvalidInt, 
00305     (PRReservedFN)_PR_InvalidInt, 
00306     (PRReservedFN)_PR_InvalidInt, 
00307     (PRReservedFN)_PR_InvalidInt
00308 };
00309 
00310 PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)
00311 {
00312     return &_pr_fileMethods;
00313 }
00314 
00315 static PRIOMethods _pr_pipeMethods = {
00316     PR_DESC_PIPE,
00317     FileClose,
00318     FileRead,
00319     FileWrite,
00320     PipeAvailable,
00321     PipeAvailable64,
00322     PipeSync,
00323     (PRSeekFN)_PR_InvalidInt,
00324     (PRSeek64FN)_PR_InvalidInt64,
00325     (PRFileInfoFN)_PR_InvalidStatus,
00326     (PRFileInfo64FN)_PR_InvalidStatus,
00327     (PRWritevFN)_PR_InvalidInt,           
00328     (PRConnectFN)_PR_InvalidStatus,              
00329     (PRAcceptFN)_PR_InvalidDesc,          
00330     (PRBindFN)_PR_InvalidStatus,          
00331     (PRListenFN)_PR_InvalidStatus,        
00332     (PRShutdownFN)_PR_InvalidStatus,      
00333     (PRRecvFN)_PR_InvalidInt,             
00334     (PRSendFN)_PR_InvalidInt,             
00335     (PRRecvfromFN)_PR_InvalidInt,  
00336     (PRSendtoFN)_PR_InvalidInt,           
00337     FilePoll,         
00338     (PRAcceptreadFN)_PR_InvalidInt,   
00339     (PRTransmitfileFN)_PR_InvalidInt, 
00340     (PRGetsocknameFN)_PR_InvalidStatus,   
00341     (PRGetpeernameFN)_PR_InvalidStatus,   
00342     (PRReservedFN)_PR_InvalidInt,  
00343     (PRReservedFN)_PR_InvalidInt,  
00344     (PRGetsocketoptionFN)_PR_InvalidStatus,      
00345     (PRSetsocketoptionFN)_PR_InvalidStatus,
00346     (PRSendfileFN)_PR_InvalidInt, 
00347     (PRConnectcontinueFN)_PR_InvalidStatus, 
00348     (PRReservedFN)_PR_InvalidInt, 
00349     (PRReservedFN)_PR_InvalidInt, 
00350     (PRReservedFN)_PR_InvalidInt, 
00351     (PRReservedFN)_PR_InvalidInt
00352 };
00353 
00354 PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void)
00355 {
00356     return &_pr_pipeMethods;
00357 }
00358 
00359 PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
00360 {
00361     PRInt32 osfd;
00362     PRFileDesc *fd = 0;
00363 #if !defined(_PR_HAVE_O_APPEND)
00364     PRBool  appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
00365 #endif
00366 
00367     if (!_pr_initialized) _PR_ImplicitInitialization();
00368 
00369     /* Map pr open flags and mode to os specific flags */
00370 
00371     osfd = _PR_MD_OPEN(name, flags, mode);
00372     if (osfd != -1) {
00373         fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
00374         if (!fd) {
00375             (void) _PR_MD_CLOSE_FILE(osfd);
00376         } else {
00377 #if !defined(_PR_HAVE_O_APPEND)
00378             fd->secret->appendMode = appendMode;
00379 #endif
00380             _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
00381         }
00382     }
00383     return fd;
00384 }
00385 
00386 PR_IMPLEMENT(PRFileDesc*) PR_OpenFile(
00387     const char *name, PRIntn flags, PRIntn mode)
00388 {
00389     PRInt32 osfd;
00390     PRFileDesc *fd = 0;
00391 #if !defined(_PR_HAVE_O_APPEND)
00392     PRBool  appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
00393 #endif
00394 
00395     if (!_pr_initialized) _PR_ImplicitInitialization();
00396 
00397     /* Map pr open flags and mode to os specific flags */
00398 
00399     osfd = _PR_MD_OPEN_FILE(name, flags, mode);
00400     if (osfd != -1) {
00401         fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
00402         if (!fd) {
00403             (void) _PR_MD_CLOSE_FILE(osfd);
00404         } else {
00405 #if !defined(_PR_HAVE_O_APPEND)
00406             fd->secret->appendMode = appendMode;
00407 #endif
00408             _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
00409         }
00410     }
00411     return fd;
00412 }
00413 
00414 PR_IMPLEMENT(PRInt32) PR_GetSysfdTableMax(void)
00415 {
00416 #if defined(XP_UNIX) && !defined(AIX) && !defined(NEXTSTEP) && !defined(QNX)
00417     struct rlimit rlim;
00418 
00419     if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
00420        /* XXX need to call PR_SetError() */
00421        return -1;
00422     }
00423 
00424     return rlim.rlim_max;
00425 #elif defined(AIX) || defined(NEXTSTEP) || defined(QNX)
00426     return sysconf(_SC_OPEN_MAX);
00427 #elif defined(WIN32)
00428     /*
00429      * There is a systemwide limit of 65536 user handles.
00430      */
00431     return 16384;
00432 #elif defined (WIN16)
00433     return FOPEN_MAX;
00434 #elif defined(XP_OS2)
00435     ULONG ulReqCount = 0;
00436     ULONG ulCurMaxFH = 0;
00437     DosSetRelMaxFH(&ulReqCount, &ulCurMaxFH);
00438     return ulCurMaxFH;
00439 #elif defined (XP_MAC) || defined(XP_BEOS)
00440     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
00441    return -1;
00442 #else
00443     write me;
00444 #endif
00445 }
00446 
00447 PR_IMPLEMENT(PRInt32) PR_SetSysfdTableSize(int table_size)
00448 {
00449 #if defined(XP_UNIX) && !defined(AIX) && !defined(NEXTSTEP) && !defined(QNX)
00450     struct rlimit rlim;
00451     PRInt32 tableMax = PR_GetSysfdTableMax();
00452 
00453     if (tableMax < 0) 
00454         return -1;
00455 
00456     if (tableMax > FD_SETSIZE)
00457         tableMax = FD_SETSIZE;
00458 
00459     rlim.rlim_max = tableMax;
00460 
00461     /* Grow as much as we can; even if too big */
00462     if ( rlim.rlim_max < table_size )
00463         rlim.rlim_cur = rlim.rlim_max;
00464     else
00465         rlim.rlim_cur = table_size;
00466 
00467     if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
00468         /* XXX need to call PR_SetError() */
00469         return -1;
00470     }
00471 
00472     return rlim.rlim_cur;
00473 #elif defined(XP_OS2)
00474     PRInt32 tableMax = PR_GetSysfdTableMax();
00475     if (table_size > tableMax) {
00476       APIRET rc = NO_ERROR;
00477       rc = DosSetMaxFH(table_size);
00478       if (rc == NO_ERROR)
00479         return table_size;
00480       else
00481         return -1;
00482     } 
00483     return tableMax;
00484 #elif defined(AIX) || defined(NEXTSTEP) || defined(QNX) \
00485         || defined(WIN32) || defined(WIN16) || defined(XP_BEOS)
00486     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
00487     return -1;
00488 #elif defined (XP_MAC)
00489 #pragma unused (table_size)
00490     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
00491    return -1;
00492 #else
00493     write me;
00494 #endif
00495 }
00496 
00497 PR_IMPLEMENT(PRStatus) PR_Delete(const char *name)
00498 {
00499        PRInt32 rv;
00500 
00501        rv = _PR_MD_DELETE(name);
00502        if (rv < 0) {
00503               return PR_FAILURE;
00504        } else
00505               return PR_SUCCESS;
00506 }
00507 
00508 PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)
00509 {
00510        PRInt32 rv;
00511 
00512        rv = _PR_MD_GETFILEINFO(fn, info);
00513        if (rv < 0) {
00514               return PR_FAILURE;
00515        } else
00516               return PR_SUCCESS;
00517 }
00518 
00519 PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
00520 {
00521 #ifdef XP_MAC
00522 #pragma unused (fn, info)
00523 #endif
00524     PRInt32 rv;
00525 
00526     if (!_pr_initialized) _PR_ImplicitInitialization();
00527     rv = _PR_MD_GETFILEINFO64(fn, info);
00528     if (rv < 0) {
00529         return PR_FAILURE;
00530     } else {
00531         return PR_SUCCESS;
00532     }
00533 }
00534 
00535 PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to)
00536 {
00537        PRInt32 rv;
00538 
00539        rv = _PR_MD_RENAME(from, to);
00540        if (rv < 0) {
00541               return PR_FAILURE;
00542        } else
00543               return PR_SUCCESS;
00544 }
00545 
00546 PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how)
00547 {
00548 PRInt32 rv;
00549 
00550        rv = _PR_MD_ACCESS(name, how);
00551        if (rv < 0) {
00552               return PR_FAILURE;
00553        } else
00554               return PR_SUCCESS;
00555 }
00556 
00557 /*
00558 ** Import an existing OS file to NSPR 
00559 */
00560 PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd)
00561 {
00562     PRFileDesc *fd = NULL;
00563 
00564     if (!_pr_initialized) _PR_ImplicitInitialization();
00565 
00566     fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
00567     if( !fd ) {
00568         (void) _PR_MD_CLOSE_FILE(osfd);
00569     } else {
00570         _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
00571     }
00572 
00573     return fd;
00574 }
00575 
00576 /*
00577 ** Import an existing OS pipe to NSPR 
00578 */
00579 PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PRInt32 osfd)
00580 {
00581     PRFileDesc *fd = NULL;
00582 
00583     if (!_pr_initialized) _PR_ImplicitInitialization();
00584 
00585     fd = PR_AllocFileDesc(osfd, &_pr_pipeMethods);
00586     if( !fd ) {
00587         (void) _PR_MD_CLOSE_FILE(osfd);
00588     } else {
00589         _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
00590 #ifdef WINNT
00591         fd->secret->md.sync_file_io = PR_TRUE;
00592 #endif
00593     }
00594 
00595     return fd;
00596 }
00597 
00598 #ifndef NO_NSPR_10_SUPPORT
00599 /*
00600 ** PR_Stat() for Win16 is defined in w16io.c
00601 ** it is a hack to circumvent problems in Gromit and Java
00602 ** See also: BugSplat: 98516.
00603 */
00604 #if !defined(WIN16)
00605 /*
00606  * This function is supposed to be for backward compatibility with
00607  * nspr 1.0.  Therefore, it still uses the nspr 1.0 error-reporting
00608  * mechanism -- returns a PRInt32, which is the error code when the call
00609  * fails.
00610  * 
00611  * If we need this function in nspr 2.0, it should be changed to
00612  * return PRStatus, as follows:
00613  *
00614  * PR_IMPLEMENT(PRStatus) PR_Stat(const char *name, struct stat *buf)
00615  * {
00616  *     PRInt32 rv;
00617  *
00618  *     rv = _PR_MD_STAT(name, buf);
00619  *     if (rv < 0)
00620  *         return PR_FAILURE;
00621  *     else
00622  *         return PR_SUCCESS;
00623  * }
00624  *
00625  * -- wtc, 2/14/97.
00626  */
00627 PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
00628 {
00629     PRInt32 rv;
00630 
00631     rv = _PR_MD_STAT(name, buf);
00632        return rv;
00633 }
00634 
00635 #endif /* !defined(WIN16)  */
00636 #endif /* ! NO_NSPR_10_SUPPORT */
00637 
00638 PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
00639 {
00640     PRStatus status = PR_SUCCESS;
00641 
00642 #ifdef WINNT
00643     if (!fd->secret->md.io_model_committed) {
00644         PRInt32 rv;
00645         rv = _md_Associate((HANDLE)fd->secret->md.osfd);
00646         PR_ASSERT(0 != rv);
00647         fd->secret->md.io_model_committed = PR_TRUE;
00648     }
00649 #endif
00650 
00651     PR_Lock(_pr_flock_lock);
00652     while (fd->secret->lockCount == -1)
00653         PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT);
00654     if (fd->secret->lockCount == 0) {
00655         fd->secret->lockCount = -1;
00656         PR_Unlock(_pr_flock_lock);
00657         status = _PR_MD_LOCKFILE(fd->secret->md.osfd);
00658         PR_Lock(_pr_flock_lock);
00659         fd->secret->lockCount = (status == PR_SUCCESS) ? 1 : 0;
00660         PR_NotifyAllCondVar(_pr_flock_cv);
00661     } else {
00662         fd->secret->lockCount++;
00663     }
00664     PR_Unlock(_pr_flock_lock);
00665  
00666     return status;
00667 }
00668 
00669 PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)
00670 {
00671     PRStatus status = PR_SUCCESS;
00672 
00673 #ifdef WINNT
00674     if (!fd->secret->md.io_model_committed) {
00675         PRInt32 rv;
00676         rv = _md_Associate((HANDLE)fd->secret->md.osfd);
00677         PR_ASSERT(0 != rv);
00678         fd->secret->md.io_model_committed = PR_TRUE;
00679     }
00680 #endif
00681 
00682     PR_Lock(_pr_flock_lock);
00683     if (fd->secret->lockCount == 0) {
00684         status = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
00685         PR_ASSERT(status == PR_SUCCESS || fd->secret->lockCount == 0);
00686         if (status == PR_SUCCESS)
00687             fd->secret->lockCount = 1;
00688     } else {
00689         fd->secret->lockCount++;
00690     }
00691     PR_Unlock(_pr_flock_lock);
00692 
00693     return status;
00694 }
00695 
00696 PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)
00697 {
00698     PRStatus rv = PR_SUCCESS;
00699 
00700     PR_Lock(_pr_flock_lock);
00701     if (fd->secret->lockCount == 1) {
00702         rv = _PR_MD_UNLOCKFILE(fd->secret->md.osfd);
00703         if (rv == PR_SUCCESS) 
00704             fd->secret->lockCount = 0;
00705     } else {
00706         fd->secret->lockCount--;
00707     }
00708     PR_Unlock(_pr_flock_lock);
00709 
00710     return rv;
00711 }
00712 
00713 PR_IMPLEMENT(PRStatus) PR_CreatePipe(
00714     PRFileDesc **readPipe,
00715     PRFileDesc **writePipe
00716 )
00717 {
00718 #if defined(XP_MAC)
00719 #pragma unused (readPipe, writePipe)
00720 #endif
00721 
00722 #ifdef WIN32
00723     HANDLE readEnd, writeEnd;
00724     SECURITY_ATTRIBUTES pipeAttributes;
00725 
00726     if (!_pr_initialized) _PR_ImplicitInitialization();
00727 
00728     ZeroMemory(&pipeAttributes, sizeof(pipeAttributes));
00729     pipeAttributes.nLength = sizeof(pipeAttributes);
00730     pipeAttributes.bInheritHandle = TRUE;
00731     if (CreatePipe(&readEnd, &writeEnd, &pipeAttributes, 0) == 0) {
00732         PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
00733         return PR_FAILURE;
00734     }
00735     *readPipe = PR_AllocFileDesc((PRInt32)readEnd, &_pr_pipeMethods);
00736     if (NULL == *readPipe) {
00737         CloseHandle(readEnd);
00738         CloseHandle(writeEnd);
00739         return PR_FAILURE;
00740     }
00741     *writePipe = PR_AllocFileDesc((PRInt32)writeEnd, &_pr_pipeMethods);
00742     if (NULL == *writePipe) {
00743         PR_Close(*readPipe);
00744         CloseHandle(writeEnd);
00745         return PR_FAILURE;
00746     }
00747 #ifdef WINNT
00748     (*readPipe)->secret->md.sync_file_io = PR_TRUE;
00749     (*writePipe)->secret->md.sync_file_io = PR_TRUE;
00750 #endif
00751     (*readPipe)->secret->inheritable = _PR_TRI_TRUE;
00752     (*writePipe)->secret->inheritable = _PR_TRI_TRUE;
00753     return PR_SUCCESS;
00754 #elif defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
00755 #ifdef XP_OS2
00756     HFILE pipefd[2];
00757 #else
00758     int pipefd[2];
00759 #endif
00760 
00761     if (!_pr_initialized) _PR_ImplicitInitialization();
00762 
00763 #ifdef XP_OS2
00764     if (DosCreatePipe(&pipefd[0], &pipefd[1], 4096) != 0) {
00765 #else
00766     if (pipe(pipefd) == -1) {
00767 #endif
00768         /* XXX map pipe error */
00769         PR_SetError(PR_UNKNOWN_ERROR, errno);
00770         return PR_FAILURE;
00771     }
00772     *readPipe = PR_AllocFileDesc(pipefd[0], &_pr_pipeMethods);
00773     if (NULL == *readPipe) {
00774         close(pipefd[0]);
00775         close(pipefd[1]);
00776         return PR_FAILURE;
00777     }
00778     *writePipe = PR_AllocFileDesc(pipefd[1], &_pr_pipeMethods);
00779     if (NULL == *writePipe) {
00780         PR_Close(*readPipe);
00781         close(pipefd[1]);
00782         return PR_FAILURE;
00783     }
00784 #ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
00785     _PR_MD_MAKE_NONBLOCK(*readPipe);
00786 #endif
00787     _PR_MD_INIT_FD_INHERITABLE(*readPipe, PR_FALSE);
00788 #ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
00789     _PR_MD_MAKE_NONBLOCK(*writePipe);
00790 #endif
00791     _PR_MD_INIT_FD_INHERITABLE(*writePipe, PR_FALSE);
00792     return PR_SUCCESS;
00793 #else
00794     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
00795     return PR_FAILURE;
00796 #endif
00797 }
00798 
00799 #ifdef MOZ_UNICODE
00800 /* ================ UTF16 Interfaces ================================ */
00801 PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16(
00802     const PRUnichar *name, PRIntn flags, PRIntn mode)
00803 { 
00804     PRInt32 osfd;
00805     PRFileDesc *fd = 0;
00806 #if !defined(_PR_HAVE_O_APPEND)
00807     PRBool  appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
00808 #endif
00809    
00810     if (!_pr_initialized) _PR_ImplicitInitialization();
00811   
00812     /* Map pr open flags and mode to os specific flags */
00813     osfd = _PR_MD_OPEN_FILE_UTF16(name, flags, mode);
00814     if (osfd != -1) {
00815         fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
00816         if (!fd) {
00817             (void) _PR_MD_CLOSE_FILE(osfd);
00818         } else {
00819 #if !defined(_PR_HAVE_O_APPEND)
00820             fd->secret->appendMode = appendMode;
00821 #endif
00822             _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
00823         }
00824     }
00825     return fd;
00826 }
00827  
00828 PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info)
00829 {
00830 #ifdef XP_MAC
00831 #pragma unused (fn, info)
00832 #endif
00833     PRInt32 rv;
00834 
00835     if (!_pr_initialized) _PR_ImplicitInitialization();
00836     rv = _PR_MD_GETFILEINFO64_UTF16(fn, info);
00837     if (rv < 0) {
00838         return PR_FAILURE;
00839     } else {
00840         return PR_SUCCESS;
00841     }
00842 }
00843 
00844 /* ================ UTF16 Interfaces ================================ */
00845 #endif /* MOZ_UNICODE */