1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "primpl.h"
7 
8 #include <string.h>
9 #include <fcntl.h>
10 
11 #ifdef XP_UNIX
12 #if defined(AIX) || defined(QNX)
13 /* To pick up sysconf */
14 #include <unistd.h>
15 #else
16 /* To pick up getrlimit, setrlimit */
17 #include <sys/time.h>
18 #include <sys/resource.h>
19 #endif
20 #endif /* XP_UNIX */
21 
22 extern PRLock *_pr_flock_lock;
23 extern PRCondVar *_pr_flock_cv;
24 
FileRead(PRFileDesc * fd,void * buf,PRInt32 amount)25 static PRInt32 PR_CALLBACK FileRead(PRFileDesc *fd, void *buf, PRInt32 amount)
26 {
27     PRInt32 rv = 0;
28     PRThread *me = _PR_MD_CURRENT_THREAD();
29 
30     if (_PR_PENDING_INTERRUPT(me)) {
31  		me->flags &= ~_PR_INTERRUPT;
32 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
33 		rv = -1;
34     }
35     if (_PR_IO_PENDING(me)) {
36         PR_SetError(PR_IO_PENDING_ERROR, 0);
37 	rv = -1;
38     }
39     if (rv == -1)
40     	return rv;
41 
42 	rv = _PR_MD_READ(fd, buf, amount);
43 	if (rv < 0) {
44 		PR_ASSERT(rv == -1);
45 	}
46     PR_LOG(_pr_io_lm, PR_LOG_MAX, ("read -> %d", rv));
47     return rv;
48 }
49 
FileWrite(PRFileDesc * fd,const void * buf,PRInt32 amount)50 static PRInt32 PR_CALLBACK FileWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
51 {
52     PRInt32 rv = 0;
53     PRInt32 temp, count;
54     PRThread *me = _PR_MD_CURRENT_THREAD();
55 
56     if (_PR_PENDING_INTERRUPT(me)) {
57         me->flags &= ~_PR_INTERRUPT;
58         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
59 	    rv = -1;
60     }
61     if (_PR_IO_PENDING(me)) {
62         PR_SetError(PR_IO_PENDING_ERROR, 0);
63 	    rv = -1;
64     }
65     if (rv != 0)
66     	return rv;
67 
68     count = 0;
69 #if !defined(_PR_HAVE_O_APPEND)  /* Bugzilla: 4090, 276330 */
70     if (fd->secret->appendMode) {
71         if (PR_Seek64(fd, 0, PR_SEEK_END) == -1) {
72             return -1;
73         }
74     } /* if (fd->secret->appendMode...) */
75 #endif /* _PR_HAVE_O_APPEND */
76     while (amount > 0) {
77 		temp = _PR_MD_WRITE(fd, buf, amount);
78 		if (temp < 0) {
79 			count = -1;
80 			break;
81 		}
82 		count += temp;
83 		if (fd->secret->nonblocking) {
84 			break;
85 		}
86 		buf = (const void*) ((const char*)buf + temp);
87 		amount -= temp;
88     }
89     PR_LOG(_pr_io_lm, PR_LOG_MAX, ("write -> %d", count));
90     return count;
91 }
92 
FileSeek(PRFileDesc * fd,PROffset32 offset,PRSeekWhence whence)93 static PROffset32 PR_CALLBACK FileSeek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
94 {
95     PROffset32 result;
96 
97     result = _PR_MD_LSEEK(fd, offset, whence);
98     return result;
99 }
100 
FileSeek64(PRFileDesc * fd,PROffset64 offset,PRSeekWhence whence)101 static PROffset64 PR_CALLBACK FileSeek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
102 {
103     PROffset64 result;
104 
105     result = _PR_MD_LSEEK64(fd, offset, whence);
106     return result;
107 }
108 
FileAvailable(PRFileDesc * fd)109 static PRInt32 PR_CALLBACK FileAvailable(PRFileDesc *fd)
110 {
111     PRInt32 result, cur, end;
112 
113     cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR);
114 
115 	if (cur >= 0)
116     	end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END);
117 
118     if ((cur < 0) || (end < 0)) {
119         return -1;
120     }
121 
122     result = end - cur;
123     _PR_MD_LSEEK(fd, cur, PR_SEEK_SET);
124 
125     return result;
126 }
127 
FileAvailable64(PRFileDesc * fd)128 static PRInt64 PR_CALLBACK FileAvailable64(PRFileDesc *fd)
129 {
130     PRInt64 result, cur, end;
131     PRInt64 minus_one;
132 
133     LL_I2L(minus_one, -1);
134     cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR);
135 
136     if (LL_GE_ZERO(cur))
137     	end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END);
138 
139     if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one;
140 
141     LL_SUB(result, end, cur);
142     (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET);
143 
144     return result;
145 }
146 
PipeAvailable(PRFileDesc * fd)147 static PRInt32 PR_CALLBACK PipeAvailable(PRFileDesc *fd)
148 {
149 	PRInt32 rv;
150 	rv =  _PR_MD_PIPEAVAILABLE(fd);
151 	return rv;
152 }
153 
PipeAvailable64(PRFileDesc * fd)154 static PRInt64 PR_CALLBACK PipeAvailable64(PRFileDesc *fd)
155 {
156     PRInt64 rv;
157     LL_I2L(rv, _PR_MD_PIPEAVAILABLE(fd));
158 	return rv;
159 }
160 
PipeSync(PRFileDesc * fd)161 static PRStatus PR_CALLBACK PipeSync(PRFileDesc *fd)
162 {
163 	return PR_SUCCESS;
164 }
165 
FileGetInfo(PRFileDesc * fd,PRFileInfo * info)166 static PRStatus PR_CALLBACK FileGetInfo(PRFileDesc *fd, PRFileInfo *info)
167 {
168 	PRInt32 rv;
169 
170     rv = _PR_MD_GETOPENFILEINFO(fd, info);
171     if (rv < 0) {
172 	return PR_FAILURE;
173     } else
174 	return PR_SUCCESS;
175 }
176 
FileGetInfo64(PRFileDesc * fd,PRFileInfo64 * info)177 static PRStatus PR_CALLBACK FileGetInfo64(PRFileDesc *fd, PRFileInfo64 *info)
178 {
179     /* $$$$ NOT YET IMPLEMENTED */
180 	PRInt32 rv;
181 
182     rv = _PR_MD_GETOPENFILEINFO64(fd, info);
183     if (rv < 0) return PR_FAILURE;
184     else return PR_SUCCESS;
185 }
186 
FileSync(PRFileDesc * fd)187 static PRStatus PR_CALLBACK FileSync(PRFileDesc *fd)
188 {
189     PRInt32 result;
190     result = _PR_MD_FSYNC(fd);
191     if (result < 0) {
192 		return PR_FAILURE;
193     }
194     return PR_SUCCESS;
195 }
196 
FileClose(PRFileDesc * fd)197 static PRStatus PR_CALLBACK FileClose(PRFileDesc *fd)
198 {
199     if (!fd || !fd->secret
200             || (fd->secret->state != _PR_FILEDESC_OPEN
201             && fd->secret->state != _PR_FILEDESC_CLOSED)) {
202         PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
203         return PR_FAILURE;
204     }
205 
206     if (fd->secret->state == _PR_FILEDESC_OPEN) {
207         if (_PR_MD_CLOSE_FILE(fd->secret->md.osfd) < 0) {
208             return PR_FAILURE;
209         }
210         fd->secret->state = _PR_FILEDESC_CLOSED;
211     }
212     PR_FreeFileDesc(fd);
213     return PR_SUCCESS;
214 }
215 
FilePoll(PRFileDesc * fd,PRInt16 in_flags,PRInt16 * out_flags)216 static PRInt16 PR_CALLBACK FilePoll(
217     PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
218 {
219     *out_flags = 0;
220     return in_flags;
221 }  /* FilePoll */
222 
223 static PRIOMethods _pr_fileMethods = {
224     PR_DESC_FILE,
225     FileClose,
226     FileRead,
227     FileWrite,
228     FileAvailable,
229     FileAvailable64,
230     FileSync,
231     FileSeek,
232     FileSeek64,
233     FileGetInfo,
234     FileGetInfo64,
235     (PRWritevFN)_PR_InvalidInt,
236     (PRConnectFN)_PR_InvalidStatus,
237     (PRAcceptFN)_PR_InvalidDesc,
238     (PRBindFN)_PR_InvalidStatus,
239     (PRListenFN)_PR_InvalidStatus,
240     (PRShutdownFN)_PR_InvalidStatus,
241     (PRRecvFN)_PR_InvalidInt,
242     (PRSendFN)_PR_InvalidInt,
243     (PRRecvfromFN)_PR_InvalidInt,
244     (PRSendtoFN)_PR_InvalidInt,
245     FilePoll,
246     (PRAcceptreadFN)_PR_InvalidInt,
247     (PRTransmitfileFN)_PR_InvalidInt,
248     (PRGetsocknameFN)_PR_InvalidStatus,
249     (PRGetpeernameFN)_PR_InvalidStatus,
250     (PRReservedFN)_PR_InvalidInt,
251     (PRReservedFN)_PR_InvalidInt,
252     (PRGetsocketoptionFN)_PR_InvalidStatus,
253     (PRSetsocketoptionFN)_PR_InvalidStatus,
254     (PRSendfileFN)_PR_InvalidInt,
255     (PRConnectcontinueFN)_PR_InvalidStatus,
256     (PRReservedFN)_PR_InvalidInt,
257     (PRReservedFN)_PR_InvalidInt,
258     (PRReservedFN)_PR_InvalidInt,
259     (PRReservedFN)_PR_InvalidInt
260 };
261 
PR_GetFileMethods(void)262 PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)
263 {
264     return &_pr_fileMethods;
265 }
266 
267 static PRIOMethods _pr_pipeMethods = {
268     PR_DESC_PIPE,
269     FileClose,
270     FileRead,
271     FileWrite,
272     PipeAvailable,
273     PipeAvailable64,
274     PipeSync,
275     (PRSeekFN)_PR_InvalidInt,
276     (PRSeek64FN)_PR_InvalidInt64,
277     (PRFileInfoFN)_PR_InvalidStatus,
278     (PRFileInfo64FN)_PR_InvalidStatus,
279     (PRWritevFN)_PR_InvalidInt,
280     (PRConnectFN)_PR_InvalidStatus,
281     (PRAcceptFN)_PR_InvalidDesc,
282     (PRBindFN)_PR_InvalidStatus,
283     (PRListenFN)_PR_InvalidStatus,
284     (PRShutdownFN)_PR_InvalidStatus,
285     (PRRecvFN)_PR_InvalidInt,
286     (PRSendFN)_PR_InvalidInt,
287     (PRRecvfromFN)_PR_InvalidInt,
288     (PRSendtoFN)_PR_InvalidInt,
289     FilePoll,
290     (PRAcceptreadFN)_PR_InvalidInt,
291     (PRTransmitfileFN)_PR_InvalidInt,
292     (PRGetsocknameFN)_PR_InvalidStatus,
293     (PRGetpeernameFN)_PR_InvalidStatus,
294     (PRReservedFN)_PR_InvalidInt,
295     (PRReservedFN)_PR_InvalidInt,
296     (PRGetsocketoptionFN)_PR_InvalidStatus,
297     (PRSetsocketoptionFN)_PR_InvalidStatus,
298     (PRSendfileFN)_PR_InvalidInt,
299     (PRConnectcontinueFN)_PR_InvalidStatus,
300     (PRReservedFN)_PR_InvalidInt,
301     (PRReservedFN)_PR_InvalidInt,
302     (PRReservedFN)_PR_InvalidInt,
303     (PRReservedFN)_PR_InvalidInt
304 };
305 
PR_GetPipeMethods(void)306 PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void)
307 {
308     return &_pr_pipeMethods;
309 }
310 
PR_Open(const char * name,PRIntn flags,PRIntn mode)311 PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
312 {
313     PROsfd osfd;
314     PRFileDesc *fd = 0;
315 #if !defined(_PR_HAVE_O_APPEND)
316     PRBool  appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
317 #endif
318 
319     if (!_pr_initialized) _PR_ImplicitInitialization();
320 
321     /* Map pr open flags and mode to os specific flags */
322 
323     osfd = _PR_MD_OPEN(name, flags, mode);
324     if (osfd != -1) {
325         fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
326         if (!fd) {
327             (void) _PR_MD_CLOSE_FILE(osfd);
328         } else {
329 #if !defined(_PR_HAVE_O_APPEND)
330             fd->secret->appendMode = appendMode;
331 #endif
332             _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
333         }
334     }
335     return fd;
336 }
337 
PR_OpenFile(const char * name,PRIntn flags,PRIntn mode)338 PR_IMPLEMENT(PRFileDesc*) PR_OpenFile(
339     const char *name, PRIntn flags, PRIntn mode)
340 {
341     PROsfd osfd;
342     PRFileDesc *fd = 0;
343 #if !defined(_PR_HAVE_O_APPEND)
344     PRBool  appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
345 #endif
346 
347     if (!_pr_initialized) _PR_ImplicitInitialization();
348 
349     /* Map pr open flags and mode to os specific flags */
350 
351     osfd = _PR_MD_OPEN_FILE(name, flags, mode);
352     if (osfd != -1) {
353         fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
354         if (!fd) {
355             (void) _PR_MD_CLOSE_FILE(osfd);
356         } else {
357 #if !defined(_PR_HAVE_O_APPEND)
358             fd->secret->appendMode = appendMode;
359 #endif
360             _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
361         }
362     }
363     return fd;
364 }
365 
PR_GetSysfdTableMax(void)366 PR_IMPLEMENT(PRInt32) PR_GetSysfdTableMax(void)
367 {
368 #if defined(XP_UNIX) && !defined(AIX) && !defined(QNX)
369     struct rlimit rlim;
370 
371     if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
372        /* XXX need to call PR_SetError() */
373        return -1;
374     }
375 
376     return rlim.rlim_max;
377 #elif defined(AIX) || defined(QNX)
378     return sysconf(_SC_OPEN_MAX);
379 #elif defined(WIN32)
380     /*
381      * There is a systemwide limit of 65536 user handles.
382      */
383     return 16384;
384 #elif defined (WIN16)
385     return FOPEN_MAX;
386 #elif defined(XP_OS2)
387     ULONG ulReqCount = 0;
388     ULONG ulCurMaxFH = 0;
389     DosSetRelMaxFH(&ulReqCount, &ulCurMaxFH);
390     return ulCurMaxFH;
391 #elif defined(XP_BEOS)
392     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
393    return -1;
394 #else
395     write me;
396 #endif
397 }
398 
PR_SetSysfdTableSize(int table_size)399 PR_IMPLEMENT(PRInt32) PR_SetSysfdTableSize(int table_size)
400 {
401 #if defined(XP_UNIX) && !defined(AIX) && !defined(QNX)
402     struct rlimit rlim;
403     PRInt32 tableMax = PR_GetSysfdTableMax();
404 
405     if (tableMax < 0)
406         return -1;
407 
408     if (tableMax > FD_SETSIZE)
409         tableMax = FD_SETSIZE;
410 
411     rlim.rlim_max = tableMax;
412 
413     /* Grow as much as we can; even if too big */
414     if ( rlim.rlim_max < table_size )
415         rlim.rlim_cur = rlim.rlim_max;
416     else
417         rlim.rlim_cur = table_size;
418 
419     if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
420         /* XXX need to call PR_SetError() */
421         return -1;
422     }
423 
424     return rlim.rlim_cur;
425 #elif defined(XP_OS2)
426     PRInt32 tableMax = PR_GetSysfdTableMax();
427     if (table_size > tableMax) {
428       APIRET rc = NO_ERROR;
429       rc = DosSetMaxFH(table_size);
430       if (rc == NO_ERROR)
431         return table_size;
432       else
433         return -1;
434     }
435     return tableMax;
436 #elif defined(AIX) || defined(QNX) \
437         || defined(WIN32) || defined(WIN16) || defined(XP_BEOS)
438     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
439     return -1;
440 #else
441     write me;
442 #endif
443 }
444 
PR_Delete(const char * name)445 PR_IMPLEMENT(PRStatus) PR_Delete(const char *name)
446 {
447 	PRInt32 rv;
448 
449 	rv = _PR_MD_DELETE(name);
450 	if (rv < 0) {
451 		return PR_FAILURE;
452 	} else
453 		return PR_SUCCESS;
454 }
455 
PR_GetFileInfo(const char * fn,PRFileInfo * info)456 PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)
457 {
458 	PRInt32 rv;
459 
460 	rv = _PR_MD_GETFILEINFO(fn, info);
461 	if (rv < 0) {
462 		return PR_FAILURE;
463 	} else
464 		return PR_SUCCESS;
465 }
466 
PR_GetFileInfo64(const char * fn,PRFileInfo64 * info)467 PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
468 {
469     PRInt32 rv;
470 
471     if (!_pr_initialized) _PR_ImplicitInitialization();
472     rv = _PR_MD_GETFILEINFO64(fn, info);
473     if (rv < 0) {
474         return PR_FAILURE;
475     } else {
476         return PR_SUCCESS;
477     }
478 }
479 
PR_Rename(const char * from,const char * to)480 PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to)
481 {
482 	PRInt32 rv;
483 
484 	rv = _PR_MD_RENAME(from, to);
485 	if (rv < 0) {
486 		return PR_FAILURE;
487 	} else
488 		return PR_SUCCESS;
489 }
490 
PR_Access(const char * name,PRAccessHow how)491 PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how)
492 {
493 PRInt32 rv;
494 
495 	rv = _PR_MD_ACCESS(name, how);
496 	if (rv < 0) {
497 		return PR_FAILURE;
498 	} else
499 		return PR_SUCCESS;
500 }
501 
502 /*
503 ** Import an existing OS file to NSPR
504 */
PR_ImportFile(PROsfd osfd)505 PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PROsfd osfd)
506 {
507     PRFileDesc *fd = NULL;
508 
509     if (!_pr_initialized) _PR_ImplicitInitialization();
510 
511     fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
512     if( !fd ) {
513         (void) _PR_MD_CLOSE_FILE(osfd);
514     } else {
515         _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
516     }
517 
518     return fd;
519 }
520 
521 /*
522 ** Import an existing OS pipe to NSPR
523 */
PR_ImportPipe(PROsfd osfd)524 PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PROsfd osfd)
525 {
526     PRFileDesc *fd = NULL;
527 
528     if (!_pr_initialized) _PR_ImplicitInitialization();
529 
530     fd = PR_AllocFileDesc(osfd, &_pr_pipeMethods);
531     if( !fd ) {
532         (void) _PR_MD_CLOSE_FILE(osfd);
533     } else {
534         _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
535 #ifdef WINNT
536         fd->secret->md.sync_file_io = PR_TRUE;
537 #endif
538     }
539 
540     return fd;
541 }
542 
543 #ifndef NO_NSPR_10_SUPPORT
544 /*
545 ** PR_Stat() for Win16 is defined in w16io.c
546 ** it is a hack to circumvent problems in Gromit and Java
547 ** See also: BugSplat: 98516.
548 */
549 #if !defined(WIN16)
550 /*
551  * This function is supposed to be for backward compatibility with
552  * nspr 1.0.  Therefore, it still uses the nspr 1.0 error-reporting
553  * mechanism -- returns a PRInt32, which is the error code when the call
554  * fails.
555  *
556  * If we need this function in nspr 2.0, it should be changed to
557  * return PRStatus, as follows:
558  *
559  * PR_IMPLEMENT(PRStatus) PR_Stat(const char *name, struct stat *buf)
560  * {
561  *     PRInt32 rv;
562  *
563  *     rv = _PR_MD_STAT(name, buf);
564  *     if (rv < 0)
565  *         return PR_FAILURE;
566  *     else
567  *         return PR_SUCCESS;
568  * }
569  *
570  * -- wtc, 2/14/97.
571  */
PR_Stat(const char * name,struct stat * buf)572 PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
573 {
574     PRInt32 rv;
575 
576     rv = _PR_MD_STAT(name, buf);
577 	return rv;
578 }
579 
580 #endif /* !defined(WIN16)  */
581 #endif /* ! NO_NSPR_10_SUPPORT */
582 
PR_LockFile(PRFileDesc * fd)583 PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
584 {
585     PRStatus status = PR_SUCCESS;
586 
587 #ifdef WINNT
588     if (!fd->secret->md.io_model_committed) {
589         PRInt32 rv;
590         rv = _md_Associate((HANDLE)fd->secret->md.osfd);
591         PR_ASSERT(0 != rv);
592         fd->secret->md.io_model_committed = PR_TRUE;
593     }
594 #endif
595 
596     PR_Lock(_pr_flock_lock);
597     while (fd->secret->lockCount == -1)
598         PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT);
599     if (fd->secret->lockCount == 0) {
600         fd->secret->lockCount = -1;
601         PR_Unlock(_pr_flock_lock);
602         status = _PR_MD_LOCKFILE(fd->secret->md.osfd);
603         PR_Lock(_pr_flock_lock);
604         fd->secret->lockCount = (status == PR_SUCCESS) ? 1 : 0;
605         PR_NotifyAllCondVar(_pr_flock_cv);
606     } else {
607         fd->secret->lockCount++;
608     }
609     PR_Unlock(_pr_flock_lock);
610 
611     return status;
612 }
613 
PR_TLockFile(PRFileDesc * fd)614 PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)
615 {
616     PRStatus status = PR_SUCCESS;
617 
618 #ifdef WINNT
619     if (!fd->secret->md.io_model_committed) {
620         PRInt32 rv;
621         rv = _md_Associate((HANDLE)fd->secret->md.osfd);
622         PR_ASSERT(0 != rv);
623         fd->secret->md.io_model_committed = PR_TRUE;
624     }
625 #endif
626 
627     PR_Lock(_pr_flock_lock);
628     if (fd->secret->lockCount == 0) {
629         status = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
630         PR_ASSERT(status == PR_SUCCESS || fd->secret->lockCount == 0);
631         if (status == PR_SUCCESS)
632             fd->secret->lockCount = 1;
633     } else {
634         fd->secret->lockCount++;
635     }
636     PR_Unlock(_pr_flock_lock);
637 
638     return status;
639 }
640 
PR_UnlockFile(PRFileDesc * fd)641 PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)
642 {
643     PRStatus rv = PR_SUCCESS;
644 
645     PR_Lock(_pr_flock_lock);
646     if (fd->secret->lockCount == 1) {
647         rv = _PR_MD_UNLOCKFILE(fd->secret->md.osfd);
648         if (rv == PR_SUCCESS)
649             fd->secret->lockCount = 0;
650     } else {
651         fd->secret->lockCount--;
652     }
653     PR_Unlock(_pr_flock_lock);
654 
655     return rv;
656 }
657 
PR_CreatePipe(PRFileDesc ** readPipe,PRFileDesc ** writePipe)658 PR_IMPLEMENT(PRStatus) PR_CreatePipe(
659     PRFileDesc **readPipe,
660     PRFileDesc **writePipe
661 )
662 {
663 #if defined(WIN32) && !defined(WINCE)
664     HANDLE readEnd, writeEnd;
665     SECURITY_ATTRIBUTES pipeAttributes;
666 
667     if (!_pr_initialized) _PR_ImplicitInitialization();
668 
669     ZeroMemory(&pipeAttributes, sizeof(pipeAttributes));
670     pipeAttributes.nLength = sizeof(pipeAttributes);
671     pipeAttributes.bInheritHandle = TRUE;
672     if (CreatePipe(&readEnd, &writeEnd, &pipeAttributes, 0) == 0) {
673         PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
674         return PR_FAILURE;
675     }
676     *readPipe = PR_AllocFileDesc((PROsfd)readEnd, &_pr_pipeMethods);
677     if (NULL == *readPipe) {
678         CloseHandle(readEnd);
679         CloseHandle(writeEnd);
680         return PR_FAILURE;
681     }
682     *writePipe = PR_AllocFileDesc((PROsfd)writeEnd, &_pr_pipeMethods);
683     if (NULL == *writePipe) {
684         PR_Close(*readPipe);
685         CloseHandle(writeEnd);
686         return PR_FAILURE;
687     }
688 #ifdef WINNT
689     (*readPipe)->secret->md.sync_file_io = PR_TRUE;
690     (*writePipe)->secret->md.sync_file_io = PR_TRUE;
691 #endif
692     (*readPipe)->secret->inheritable = _PR_TRI_TRUE;
693     (*writePipe)->secret->inheritable = _PR_TRI_TRUE;
694     return PR_SUCCESS;
695 #elif defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
696 #ifdef XP_OS2
697     HFILE pipefd[2];
698 #else
699     int pipefd[2];
700 #endif
701 
702     if (!_pr_initialized) _PR_ImplicitInitialization();
703 
704 #ifdef XP_OS2
705     if (DosCreatePipe(&pipefd[0], &pipefd[1], 4096) != 0) {
706 #else
707     if (pipe(pipefd) == -1) {
708 #endif
709         /* XXX map pipe error */
710         PR_SetError(PR_UNKNOWN_ERROR, errno);
711         return PR_FAILURE;
712     }
713     *readPipe = PR_AllocFileDesc(pipefd[0], &_pr_pipeMethods);
714     if (NULL == *readPipe) {
715         close(pipefd[0]);
716         close(pipefd[1]);
717         return PR_FAILURE;
718     }
719     *writePipe = PR_AllocFileDesc(pipefd[1], &_pr_pipeMethods);
720     if (NULL == *writePipe) {
721         PR_Close(*readPipe);
722         close(pipefd[1]);
723         return PR_FAILURE;
724     }
725 #ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
726     _PR_MD_MAKE_NONBLOCK(*readPipe);
727 #endif
728     _PR_MD_INIT_FD_INHERITABLE(*readPipe, PR_FALSE);
729 #ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
730     _PR_MD_MAKE_NONBLOCK(*writePipe);
731 #endif
732     _PR_MD_INIT_FD_INHERITABLE(*writePipe, PR_FALSE);
733     return PR_SUCCESS;
734 #else
735     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
736     return PR_FAILURE;
737 #endif
738 }
739 
740 #ifdef MOZ_UNICODE
741 /* ================ UTF16 Interfaces ================================ */
742 PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16(
743     const PRUnichar *name, PRIntn flags, PRIntn mode)
744 {
745     PROsfd osfd;
746     PRFileDesc *fd = 0;
747 #if !defined(_PR_HAVE_O_APPEND)
748     PRBool  appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
749 #endif
750 
751     if (!_pr_initialized) _PR_ImplicitInitialization();
752 
753     /* Map pr open flags and mode to os specific flags */
754     osfd = _PR_MD_OPEN_FILE_UTF16(name, flags, mode);
755     if (osfd != -1) {
756         fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
757         if (!fd) {
758             (void) _PR_MD_CLOSE_FILE(osfd);
759         } else {
760 #if !defined(_PR_HAVE_O_APPEND)
761             fd->secret->appendMode = appendMode;
762 #endif
763             _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
764         }
765     }
766     return fd;
767 }
768 
769 PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info)
770 {
771     PRInt32 rv;
772 
773     if (!_pr_initialized) _PR_ImplicitInitialization();
774     rv = _PR_MD_GETFILEINFO64_UTF16(fn, info);
775     if (rv < 0) {
776         return PR_FAILURE;
777     } else {
778         return PR_SUCCESS;
779     }
780 }
781 
782 /* ================ UTF16 Interfaces ================================ */
783 #endif /* MOZ_UNICODE */
784