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/. */
12 # if defined(AIX) || defined(QNX)
13 /* To pick up sysconf */
16 /* To pick up getrlimit, setrlimit */
17 # include <sys/time.h>
18 # include <sys/resource.h>
22 extern PRLock
* _pr_flock_lock
;
23 extern PRCondVar
* _pr_flock_cv
;
25 static PRInt32 PR_CALLBACK
FileRead(PRFileDesc
* fd
, void* buf
, PRInt32 amount
) {
27 PRThread
* me
= _PR_MD_CURRENT_THREAD();
29 if (_PR_PENDING_INTERRUPT(me
)) {
30 me
->flags
&= ~_PR_INTERRUPT
;
31 PR_SetError(PR_PENDING_INTERRUPT_ERROR
, 0);
34 if (_PR_IO_PENDING(me
)) {
35 PR_SetError(PR_IO_PENDING_ERROR
, 0);
42 rv
= _PR_MD_READ(fd
, buf
, amount
);
46 PR_LOG(_pr_io_lm
, PR_LOG_MAX
, ("read -> %d", rv
));
50 static PRInt32 PR_CALLBACK
FileWrite(PRFileDesc
* fd
, const void* buf
,
54 PRThread
* me
= _PR_MD_CURRENT_THREAD();
56 if (_PR_PENDING_INTERRUPT(me
)) {
57 me
->flags
&= ~_PR_INTERRUPT
;
58 PR_SetError(PR_PENDING_INTERRUPT_ERROR
, 0);
61 if (_PR_IO_PENDING(me
)) {
62 PR_SetError(PR_IO_PENDING_ERROR
, 0);
70 #if !defined(_PR_HAVE_O_APPEND) /* Bugzilla: 4090, 276330 */
71 if (fd
->secret
->appendMode
) {
72 if (PR_Seek64(fd
, 0, PR_SEEK_END
) == -1) {
75 } /* if (fd->secret->appendMode...) */
76 #endif /* _PR_HAVE_O_APPEND */
78 temp
= _PR_MD_WRITE(fd
, buf
, amount
);
84 if (fd
->secret
->nonblocking
) {
87 buf
= (const void*)((const char*)buf
+ temp
);
90 PR_LOG(_pr_io_lm
, PR_LOG_MAX
, ("write -> %d", count
));
94 static PROffset32 PR_CALLBACK
FileSeek(PRFileDesc
* fd
, PROffset32 offset
,
95 PRSeekWhence whence
) {
98 result
= _PR_MD_LSEEK(fd
, offset
, whence
);
102 static PROffset64 PR_CALLBACK
FileSeek64(PRFileDesc
* fd
, PROffset64 offset
,
103 PRSeekWhence whence
) {
106 result
= _PR_MD_LSEEK64(fd
, offset
, whence
);
110 static PRInt32 PR_CALLBACK
FileAvailable(PRFileDesc
* fd
) {
111 PRInt32 result
, cur
, end
;
113 cur
= _PR_MD_LSEEK(fd
, 0, PR_SEEK_CUR
);
116 end
= _PR_MD_LSEEK(fd
, 0, PR_SEEK_END
);
119 if ((cur
< 0) || (end
< 0)) {
124 _PR_MD_LSEEK(fd
, cur
, PR_SEEK_SET
);
129 static PRInt64 PR_CALLBACK
FileAvailable64(PRFileDesc
* fd
) {
130 PRInt64 result
, cur
, end
;
133 LL_I2L(minus_one
, -1);
134 cur
= _PR_MD_LSEEK64(fd
, LL_ZERO
, PR_SEEK_CUR
);
136 if (LL_GE_ZERO(cur
)) {
137 end
= _PR_MD_LSEEK64(fd
, LL_ZERO
, PR_SEEK_END
);
140 if (!LL_GE_ZERO(cur
) || !LL_GE_ZERO(end
)) {
144 LL_SUB(result
, end
, cur
);
145 (void)_PR_MD_LSEEK64(fd
, cur
, PR_SEEK_SET
);
150 static PRInt32 PR_CALLBACK
PipeAvailable(PRFileDesc
* fd
) {
152 rv
= _PR_MD_PIPEAVAILABLE(fd
);
156 static PRInt64 PR_CALLBACK
PipeAvailable64(PRFileDesc
* fd
) {
158 LL_I2L(rv
, _PR_MD_PIPEAVAILABLE(fd
));
162 static PRStatus PR_CALLBACK
PipeSync(PRFileDesc
* fd
) { return PR_SUCCESS
; }
164 static PRStatus PR_CALLBACK
FileGetInfo(PRFileDesc
* fd
, PRFileInfo
* info
) {
167 rv
= _PR_MD_GETOPENFILEINFO(fd
, info
);
175 static PRStatus PR_CALLBACK
FileGetInfo64(PRFileDesc
* fd
, PRFileInfo64
* info
) {
176 /* $$$$ NOT YET IMPLEMENTED */
179 rv
= _PR_MD_GETOPENFILEINFO64(fd
, info
);
187 static PRStatus PR_CALLBACK
FileSync(PRFileDesc
* fd
) {
189 result
= _PR_MD_FSYNC(fd
);
196 static PRStatus PR_CALLBACK
FileClose(PRFileDesc
* fd
) {
197 if (!fd
|| !fd
->secret
||
198 (fd
->secret
->state
!= _PR_FILEDESC_OPEN
&&
199 fd
->secret
->state
!= _PR_FILEDESC_CLOSED
)) {
200 PR_SetError(PR_BAD_DESCRIPTOR_ERROR
, 0);
204 if (fd
->secret
->state
== _PR_FILEDESC_OPEN
) {
205 if (_PR_MD_CLOSE_FILE(fd
->secret
->md
.osfd
) < 0) {
208 fd
->secret
->state
= _PR_FILEDESC_CLOSED
;
214 static PRInt16 PR_CALLBACK
FilePoll(PRFileDesc
* fd
, PRInt16 in_flags
,
215 PRInt16
* out_flags
) {
220 static PRIOMethods _pr_fileMethods
= {PR_DESC_FILE
,
231 (PRWritevFN
)_PR_InvalidInt
,
232 (PRConnectFN
)_PR_InvalidStatus
,
233 (PRAcceptFN
)_PR_InvalidDesc
,
234 (PRBindFN
)_PR_InvalidStatus
,
235 (PRListenFN
)_PR_InvalidStatus
,
236 (PRShutdownFN
)_PR_InvalidStatus
,
237 (PRRecvFN
)_PR_InvalidInt
,
238 (PRSendFN
)_PR_InvalidInt
,
239 (PRRecvfromFN
)_PR_InvalidInt
,
240 (PRSendtoFN
)_PR_InvalidInt
,
242 (PRAcceptreadFN
)_PR_InvalidInt
,
243 (PRTransmitfileFN
)_PR_InvalidInt
,
244 (PRGetsocknameFN
)_PR_InvalidStatus
,
245 (PRGetpeernameFN
)_PR_InvalidStatus
,
246 (PRReservedFN
)_PR_InvalidInt
,
247 (PRReservedFN
)_PR_InvalidInt
,
248 (PRGetsocketoptionFN
)_PR_InvalidStatus
,
249 (PRSetsocketoptionFN
)_PR_InvalidStatus
,
250 (PRSendfileFN
)_PR_InvalidInt
,
251 (PRConnectcontinueFN
)_PR_InvalidStatus
,
252 (PRReservedFN
)_PR_InvalidInt
,
253 (PRReservedFN
)_PR_InvalidInt
,
254 (PRReservedFN
)_PR_InvalidInt
,
255 (PRReservedFN
)_PR_InvalidInt
};
257 PR_IMPLEMENT(const PRIOMethods
*) PR_GetFileMethods(void) {
258 return &_pr_fileMethods
;
261 static PRIOMethods _pr_pipeMethods
= {PR_DESC_PIPE
,
268 (PRSeekFN
)_PR_InvalidInt
,
269 (PRSeek64FN
)_PR_InvalidInt64
,
270 (PRFileInfoFN
)_PR_InvalidStatus
,
271 (PRFileInfo64FN
)_PR_InvalidStatus
,
272 (PRWritevFN
)_PR_InvalidInt
,
273 (PRConnectFN
)_PR_InvalidStatus
,
274 (PRAcceptFN
)_PR_InvalidDesc
,
275 (PRBindFN
)_PR_InvalidStatus
,
276 (PRListenFN
)_PR_InvalidStatus
,
277 (PRShutdownFN
)_PR_InvalidStatus
,
278 (PRRecvFN
)_PR_InvalidInt
,
279 (PRSendFN
)_PR_InvalidInt
,
280 (PRRecvfromFN
)_PR_InvalidInt
,
281 (PRSendtoFN
)_PR_InvalidInt
,
283 (PRAcceptreadFN
)_PR_InvalidInt
,
284 (PRTransmitfileFN
)_PR_InvalidInt
,
285 (PRGetsocknameFN
)_PR_InvalidStatus
,
286 (PRGetpeernameFN
)_PR_InvalidStatus
,
287 (PRReservedFN
)_PR_InvalidInt
,
288 (PRReservedFN
)_PR_InvalidInt
,
289 (PRGetsocketoptionFN
)_PR_InvalidStatus
,
290 (PRSetsocketoptionFN
)_PR_InvalidStatus
,
291 (PRSendfileFN
)_PR_InvalidInt
,
292 (PRConnectcontinueFN
)_PR_InvalidStatus
,
293 (PRReservedFN
)_PR_InvalidInt
,
294 (PRReservedFN
)_PR_InvalidInt
,
295 (PRReservedFN
)_PR_InvalidInt
,
296 (PRReservedFN
)_PR_InvalidInt
};
298 PR_IMPLEMENT(const PRIOMethods
*) PR_GetPipeMethods(void) {
299 return &_pr_pipeMethods
;
302 PR_IMPLEMENT(PRFileDesc
*) PR_Open(const char* name
, PRIntn flags
, PRIntn mode
) {
305 #if !defined(_PR_HAVE_O_APPEND)
306 PRBool appendMode
= (PR_APPEND
& flags
) ? PR_TRUE
: PR_FALSE
;
309 if (!_pr_initialized
) {
310 _PR_ImplicitInitialization();
313 /* Map pr open flags and mode to os specific flags */
315 osfd
= _PR_MD_OPEN(name
, flags
, mode
);
317 fd
= PR_AllocFileDesc(osfd
, &_pr_fileMethods
);
319 (void)_PR_MD_CLOSE_FILE(osfd
);
321 #if !defined(_PR_HAVE_O_APPEND)
322 fd
->secret
->appendMode
= appendMode
;
324 _PR_MD_INIT_FD_INHERITABLE(fd
, PR_FALSE
);
330 PR_IMPLEMENT(PRFileDesc
*)
331 PR_OpenFile(const char* name
, PRIntn flags
, PRIntn mode
) {
334 #if !defined(_PR_HAVE_O_APPEND)
335 PRBool appendMode
= (PR_APPEND
& flags
) ? PR_TRUE
: PR_FALSE
;
338 if (!_pr_initialized
) {
339 _PR_ImplicitInitialization();
342 /* Map pr open flags and mode to os specific flags */
344 osfd
= _PR_MD_OPEN_FILE(name
, flags
, mode
);
346 fd
= PR_AllocFileDesc(osfd
, &_pr_fileMethods
);
348 (void)_PR_MD_CLOSE_FILE(osfd
);
350 #if !defined(_PR_HAVE_O_APPEND)
351 fd
->secret
->appendMode
= appendMode
;
353 _PR_MD_INIT_FD_INHERITABLE(fd
, PR_FALSE
);
359 PR_IMPLEMENT(PRInt32
) PR_GetSysfdTableMax(void) {
360 #if defined(XP_UNIX) && !defined(AIX) && !defined(QNX)
363 if (getrlimit(RLIMIT_NOFILE
, &rlim
) < 0) {
364 /* XXX need to call PR_SetError() */
368 return rlim
.rlim_max
;
369 #elif defined(AIX) || defined(QNX)
370 return sysconf(_SC_OPEN_MAX
);
373 * There is a systemwide limit of 65536 user handles.
381 PR_IMPLEMENT(PRInt32
) PR_SetSysfdTableSize(int table_size
) {
382 #if defined(XP_UNIX) && !defined(AIX) && !defined(QNX)
384 PRInt32 tableMax
= PR_GetSysfdTableMax();
390 if (tableMax
> FD_SETSIZE
) {
391 tableMax
= FD_SETSIZE
;
394 rlim
.rlim_max
= tableMax
;
396 /* Grow as much as we can; even if too big */
397 if (rlim
.rlim_max
< table_size
) {
398 rlim
.rlim_cur
= rlim
.rlim_max
;
400 rlim
.rlim_cur
= table_size
;
403 if (setrlimit(RLIMIT_NOFILE
, &rlim
) < 0) {
404 /* XXX need to call PR_SetError() */
408 return rlim
.rlim_cur
;
409 #elif defined(AIX) || defined(QNX) || defined(WIN32)
410 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
417 PR_IMPLEMENT(PRStatus
) PR_Delete(const char* name
) {
420 rv
= _PR_MD_DELETE(name
);
428 PR_IMPLEMENT(PRStatus
) PR_GetFileInfo(const char* fn
, PRFileInfo
* info
) {
431 rv
= _PR_MD_GETFILEINFO(fn
, info
);
439 PR_IMPLEMENT(PRStatus
) PR_GetFileInfo64(const char* fn
, PRFileInfo64
* info
) {
442 if (!_pr_initialized
) {
443 _PR_ImplicitInitialization();
445 rv
= _PR_MD_GETFILEINFO64(fn
, info
);
453 PR_IMPLEMENT(PRStatus
) PR_Rename(const char* from
, const char* to
) {
456 rv
= _PR_MD_RENAME(from
, to
);
464 PR_IMPLEMENT(PRStatus
) PR_Access(const char* name
, PRAccessHow how
) {
467 rv
= _PR_MD_ACCESS(name
, how
);
476 ** Import an existing OS file to NSPR
478 PR_IMPLEMENT(PRFileDesc
*) PR_ImportFile(PROsfd osfd
) {
479 PRFileDesc
* fd
= NULL
;
481 if (!_pr_initialized
) {
482 _PR_ImplicitInitialization();
485 fd
= PR_AllocFileDesc(osfd
, &_pr_fileMethods
);
487 (void)_PR_MD_CLOSE_FILE(osfd
);
489 _PR_MD_INIT_FD_INHERITABLE(fd
, PR_TRUE
);
496 ** Import an existing OS pipe to NSPR
498 PR_IMPLEMENT(PRFileDesc
*) PR_ImportPipe(PROsfd osfd
) {
499 PRFileDesc
* fd
= NULL
;
501 if (!_pr_initialized
) {
502 _PR_ImplicitInitialization();
505 fd
= PR_AllocFileDesc(osfd
, &_pr_pipeMethods
);
507 (void)_PR_MD_CLOSE_FILE(osfd
);
509 _PR_MD_INIT_FD_INHERITABLE(fd
, PR_TRUE
);
511 fd
->secret
->md
.sync_file_io
= PR_TRUE
;
518 #ifndef NO_NSPR_10_SUPPORT
521 * This function is supposed to be for backward compatibility with
522 * nspr 1.0. Therefore, it still uses the nspr 1.0 error-reporting
523 * mechanism -- returns a PRInt32, which is the error code when the call
526 * If we need this function in nspr 2.0, it should be changed to
527 * return PRStatus, as follows:
529 * PR_IMPLEMENT(PRStatus) PR_Stat(const char *name, struct stat *buf)
533 * rv = _PR_MD_STAT(name, buf);
542 PR_IMPLEMENT(PRInt32
) PR_Stat(const char* name
, struct stat
* buf
) {
545 rv
= _PR_MD_STAT(name
, buf
);
549 #endif /* ! NO_NSPR_10_SUPPORT */
551 PR_IMPLEMENT(PRStatus
) PR_LockFile(PRFileDesc
* fd
) {
552 PRStatus status
= PR_SUCCESS
;
555 if (!fd
->secret
->md
.io_model_committed
) {
557 rv
= _md_Associate((HANDLE
)fd
->secret
->md
.osfd
);
559 fd
->secret
->md
.io_model_committed
= PR_TRUE
;
563 PR_Lock(_pr_flock_lock
);
564 while (fd
->secret
->lockCount
== -1) {
565 PR_WaitCondVar(_pr_flock_cv
, PR_INTERVAL_NO_TIMEOUT
);
567 if (fd
->secret
->lockCount
== 0) {
568 fd
->secret
->lockCount
= -1;
569 PR_Unlock(_pr_flock_lock
);
570 status
= _PR_MD_LOCKFILE(fd
->secret
->md
.osfd
);
571 PR_Lock(_pr_flock_lock
);
572 fd
->secret
->lockCount
= (status
== PR_SUCCESS
) ? 1 : 0;
573 PR_NotifyAllCondVar(_pr_flock_cv
);
575 fd
->secret
->lockCount
++;
577 PR_Unlock(_pr_flock_lock
);
582 PR_IMPLEMENT(PRStatus
) PR_TLockFile(PRFileDesc
* fd
) {
583 PRStatus status
= PR_SUCCESS
;
586 if (!fd
->secret
->md
.io_model_committed
) {
588 rv
= _md_Associate((HANDLE
)fd
->secret
->md
.osfd
);
590 fd
->secret
->md
.io_model_committed
= PR_TRUE
;
594 PR_Lock(_pr_flock_lock
);
595 if (fd
->secret
->lockCount
== 0) {
596 status
= _PR_MD_TLOCKFILE(fd
->secret
->md
.osfd
);
597 PR_ASSERT(status
== PR_SUCCESS
|| fd
->secret
->lockCount
== 0);
598 if (status
== PR_SUCCESS
) {
599 fd
->secret
->lockCount
= 1;
602 fd
->secret
->lockCount
++;
604 PR_Unlock(_pr_flock_lock
);
609 PR_IMPLEMENT(PRStatus
) PR_UnlockFile(PRFileDesc
* fd
) {
610 PRStatus rv
= PR_SUCCESS
;
612 PR_Lock(_pr_flock_lock
);
613 if (fd
->secret
->lockCount
== 1) {
614 rv
= _PR_MD_UNLOCKFILE(fd
->secret
->md
.osfd
);
615 if (rv
== PR_SUCCESS
) {
616 fd
->secret
->lockCount
= 0;
619 fd
->secret
->lockCount
--;
621 PR_Unlock(_pr_flock_lock
);
626 PR_IMPLEMENT(PRStatus
)
627 PR_CreatePipe(PRFileDesc
** readPipe
, PRFileDesc
** writePipe
) {
628 #if defined(WIN32) && !defined(WINCE)
629 HANDLE readEnd
, writeEnd
;
630 SECURITY_ATTRIBUTES pipeAttributes
;
632 if (!_pr_initialized
) {
633 _PR_ImplicitInitialization();
636 ZeroMemory(&pipeAttributes
, sizeof(pipeAttributes
));
637 pipeAttributes
.nLength
= sizeof(pipeAttributes
);
638 pipeAttributes
.bInheritHandle
= TRUE
;
639 if (CreatePipe(&readEnd
, &writeEnd
, &pipeAttributes
, 0) == 0) {
640 PR_SetError(PR_UNKNOWN_ERROR
, GetLastError());
643 *readPipe
= PR_AllocFileDesc((PROsfd
)readEnd
, &_pr_pipeMethods
);
644 if (NULL
== *readPipe
) {
645 CloseHandle(readEnd
);
646 CloseHandle(writeEnd
);
649 *writePipe
= PR_AllocFileDesc((PROsfd
)writeEnd
, &_pr_pipeMethods
);
650 if (NULL
== *writePipe
) {
652 CloseHandle(writeEnd
);
656 (*readPipe
)->secret
->md
.sync_file_io
= PR_TRUE
;
657 (*writePipe
)->secret
->md
.sync_file_io
= PR_TRUE
;
659 (*readPipe
)->secret
->inheritable
= _PR_TRI_TRUE
;
660 (*writePipe
)->secret
->inheritable
= _PR_TRI_TRUE
;
662 #elif defined(XP_UNIX)
665 if (!_pr_initialized
) {
666 _PR_ImplicitInitialization();
669 if (pipe(pipefd
) == -1) {
670 /* XXX map pipe error */
671 PR_SetError(PR_UNKNOWN_ERROR
, errno
);
674 *readPipe
= PR_AllocFileDesc(pipefd
[0], &_pr_pipeMethods
);
675 if (NULL
== *readPipe
) {
680 *writePipe
= PR_AllocFileDesc(pipefd
[1], &_pr_pipeMethods
);
681 if (NULL
== *writePipe
) {
686 _PR_MD_MAKE_NONBLOCK(*readPipe
);
687 _PR_MD_INIT_FD_INHERITABLE(*readPipe
, PR_FALSE
);
688 _PR_MD_MAKE_NONBLOCK(*writePipe
);
689 _PR_MD_INIT_FD_INHERITABLE(*writePipe
, PR_FALSE
);
692 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
698 /* ================ UTF16 Interfaces ================================ */
699 PR_IMPLEMENT(PRFileDesc
*)
700 PR_OpenFileUTF16(const PRUnichar
* name
, PRIntn flags
, PRIntn mode
) {
703 # if !defined(_PR_HAVE_O_APPEND)
704 PRBool appendMode
= (PR_APPEND
& flags
) ? PR_TRUE
: PR_FALSE
;
707 if (!_pr_initialized
) {
708 _PR_ImplicitInitialization();
711 /* Map pr open flags and mode to os specific flags */
712 osfd
= _PR_MD_OPEN_FILE_UTF16(name
, flags
, mode
);
714 fd
= PR_AllocFileDesc(osfd
, &_pr_fileMethods
);
716 (void)_PR_MD_CLOSE_FILE(osfd
);
718 # if !defined(_PR_HAVE_O_APPEND)
719 fd
->secret
->appendMode
= appendMode
;
721 _PR_MD_INIT_FD_INHERITABLE(fd
, PR_FALSE
);
727 PR_IMPLEMENT(PRStatus
)
728 PR_GetFileInfo64UTF16(const PRUnichar
* fn
, PRFileInfo64
* info
) {
731 if (!_pr_initialized
) {
732 _PR_ImplicitInitialization();
734 rv
= _PR_MD_GETFILEINFO64_UTF16(fn
, info
);
742 /* ================ UTF16 Interfaces ================================ */
743 #endif /* MOZ_UNICODE */