Changeset 101870 in vbox
- Timestamp:
- Nov 6, 2023 2:08:07 PM (15 months ago)
- Location:
- trunk/src/libs/xpcom18a4
- Files:
-
- 1 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/Makefile.kmk
r101869 r101870 62 62 NSPRPUB-HEADERS \ 63 63 NSPRPUB-MD-HEADERS \ 64 NSPRPUB-OBS-HEADERS \65 64 NSPRPUB-PRIV-HEADERS \ 66 65 STRING-HEADERS \ … … 218 217 nsprpub/pr/include/md/_solaris32.cfg \ 219 218 nsprpub/pr/include/md/_solaris64.cfg 220 NSPRPUB-OBS-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/nsprpub/obsolete/221 NSPRPUB-OBS-HEADERS_IFFLAGS = -m 644222 NSPRPUB-OBS-HEADERS_SOURCES = \223 nsprpub/pr/include/obsolete/probslet.h224 219 225 220 NSPRPUB-PRIV-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/nsprpub/private/ -
trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixos.h
r101810 r101870 356 356 extern PRInt32 _MD_accept_read(PRInt32 sock, PRInt32 *newSock, 357 357 PRNetAddr **raddr, void *buf, PRInt32 amount); 358 extern PRInt32 _PR_UnixSendFile(PRFileDesc *sd, PRSendFileData *sfd,359 PRTransmitFileFlags flags, PRIntervalTime timeout);360 361 extern PRStatus _MD_LockFile(PRInt32 osfd);362 extern PRStatus _MD_TLockFile(PRInt32 osfd);363 extern PRStatus _MD_UnlockFile(PRInt32 osfd);364 358 365 359 #define _MD_OPEN_DIR(dir, name) _MD_open_dir(dir, name) … … 383 377 #define _MD_RMDIR(name) _MD_rmdir(name) 384 378 #define _MD_ACCEPT_READ(sock, newSock, raddr, buf, amount) _MD_accept_read(sock, newSock, raddr, buf, amount) 385 386 #define _MD_LOCKFILE _MD_LockFile387 #define _MD_TLOCKFILE _MD_TLockFile388 #define _MD_UNLOCKFILE _MD_UnlockFile389 390 379 391 380 extern PRInt32 _MD_socket(int af, int type, int flags); -
trunk/src/libs/xpcom18a4/nsprpub/pr/include/prio.h
r101869 r101870 112 112 #define PR_SendTo VBoxNsprPR_SendTo 113 113 #define PR_TransmitFile VBoxNsprPR_TransmitFile 114 #define PR_SendFile VBoxNsprPR_SendFile115 114 #define PR_GetSockName VBoxNsprPR_GetSockName 116 115 #define PR_GetPeerName VBoxNsprPR_GetPeerName … … 136 135 typedef struct PRPollDesc PRPollDesc; 137 136 typedef struct PRFilePrivate PRFilePrivate; 138 typedef struct PRSendFileData PRSendFileData;139 137 140 138 /* … … 422 420 PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, 423 421 void *buf, PRInt32 amount, PRIntervalTime t); 424 typedef PRInt32 (PR_CALLBACK *PRTransmitfileFN)(425 PRFileDesc *sd, PRFileDesc *fd, const void *headers,426 PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime t);427 422 typedef PRStatus (PR_CALLBACK *PRGetsocknameFN)(PRFileDesc *fd, PRNetAddr *addr); 428 423 typedef PRStatus (PR_CALLBACK *PRGetpeernameFN)(PRFileDesc *fd, PRNetAddr *addr); … … 431 426 typedef PRStatus (PR_CALLBACK *PRSetsocketoptionFN)( 432 427 PRFileDesc *fd, const PRSocketOptionData *data); 433 typedef PRInt32 (PR_CALLBACK *PRSendfileFN)(434 PRFileDesc *networkSocket, PRSendFileData *sendData,435 PRTransmitFileFlags flags, PRIntervalTime timeout);436 428 typedef PRStatus (PR_CALLBACK *PRConnectcontinueFN)( 437 429 PRFileDesc *fd, PRInt16 out_flags); … … 462 454 PRPollFN poll; /* Test the fd to see if it is ready */ 463 455 PRAcceptreadFN acceptread; /* Accept and read on a new (net) fd */ 464 PRTransmitfileFN transmitfile; /* Transmit at entire file */465 456 PRGetsocknameFN getsockname; /* Get (net) address associated with fd */ 466 457 PRGetpeernameFN getpeername; /* Get peer's (net) address */ … … 471 462 PRSetsocketoptionFN setsocketoption; 472 463 /* Set value of specified option */ 473 PRSendfileFN sendfile; /* Send a (partial) file with header/trailer*/474 464 PRConnectcontinueFN connectcontinue; 475 465 /* Continue a nonblocking connect */ … … 1530 1520 PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, 1531 1521 const PRNetAddr *addr, PRIntervalTime timeout); 1532 1533 /*1534 *************************************************************************1535 ** FUNCTION: PR_TransmitFile1536 ** DESCRIPTION:1537 ** Transmitfile sends a complete file (sourceFile) across a socket1538 ** (networkSocket). If headers is non-NULL, the headers will be sent across1539 ** the socket prior to sending the file.1540 **1541 ** Optionally, the PR_TRANSMITFILE_CLOSE_SOCKET flag may be passed to1542 ** transmitfile. This flag specifies that transmitfile should close the1543 ** socket after sending the data.1544 **1545 ** INPUTS:1546 ** PRFileDesc *networkSocket1547 ** The socket to send data over1548 ** PRFileDesc *sourceFile1549 ** The file to send1550 ** const void *headers1551 ** A pointer to headers to be sent before sending data1552 ** PRInt32 hlen1553 ** length of header buffers in bytes.1554 ** PRTransmitFileFlags flags1555 ** If the flags indicate that the connection should be closed,1556 ** it will be done immediately after transferring the file, unless1557 ** the operation is unsuccessful.1558 .* PRIntervalTime timeout1559 * Time limit for completion of the transmit operation.1560 **1561 ** RETURNS:1562 ** Returns the number of bytes written or -1 if the operation failed.1563 ** If an error occurs while sending the file, the PR_TRANSMITFILE_CLOSE_1564 ** SOCKET flag is ignored. The reason for the failure is obtained1565 ** by calling PR_GetError().1566 **************************************************************************1567 */1568 1569 NSPR_API(PRInt32) PR_TransmitFile(1570 PRFileDesc *networkSocket, PRFileDesc *sourceFile,1571 const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,1572 PRIntervalTime timeout);1573 1574 /*1575 *************************************************************************1576 ** FUNCTION: PR_SendFile1577 ** DESCRIPTION:1578 ** PR_SendFile sends data from a file (sendData->fd) across a socket1579 ** (networkSocket). If specified, a header and/or trailer buffer are sent1580 ** before and after the file, respectively. The file offset, number of bytes1581 ** of file data to send, the header and trailer buffers are specified in the1582 ** sendData argument.1583 **1584 ** Optionally, if the PR_TRANSMITFILE_CLOSE_SOCKET flag is passed, the1585 ** socket is closed after successfully sending the data.1586 **1587 ** INPUTS:1588 ** PRFileDesc *networkSocket1589 ** The socket to send data over1590 ** PRSendFileData *sendData1591 ** Contains the FD, file offset and length, header and trailer1592 ** buffer specifications.1593 ** PRTransmitFileFlags flags1594 ** If the flags indicate that the connection should be closed,1595 ** it will be done immediately after transferring the file, unless1596 ** the operation is unsuccessful.1597 .* PRIntervalTime timeout1598 * Time limit for completion of the send operation.1599 **1600 ** RETURNS:1601 ** Returns the number of bytes written or -1 if the operation failed.1602 ** If an error occurs while sending the file, the PR_TRANSMITFILE_CLOSE_1603 ** SOCKET flag is ignored. The reason for the failure is obtained1604 ** by calling PR_GetError().1605 **************************************************************************1606 */1607 1608 struct PRSendFileData {1609 PRFileDesc *fd; /* file to send */1610 PRUint32 file_offset; /* file offset */1611 PRSize file_nbytes; /* number of bytes of file data to send */1612 /* if 0, send data from file_offset to */1613 /* end-of-file. */1614 const void *header; /* header buffer */1615 PRInt32 hlen; /* header len */1616 const void *trailer; /* trailer buffer */1617 PRInt32 tlen; /* trailer len */1618 };1619 1620 1621 NSPR_API(PRInt32) PR_SendFile(1622 PRFileDesc *networkSocket, PRSendFileData *sendData,1623 PRTransmitFileFlags flags, PRIntervalTime timeout);1624 1522 1625 1523 /* -
trunk/src/libs/xpcom18a4/nsprpub/pr/include/private/pprio.h
r101869 r101870 159 159 NSPR_API(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto); 160 160 161 /* FUNCTION: PR_LockFile162 ** DESCRIPTION:163 ** Lock a file for exclusive access.164 ** RETURNS:165 ** PR_SUCCESS when the lock is held166 ** PR_FAILURE otherwise167 */168 NSPR_API(PRStatus) PR_LockFile(PRFileDesc *fd);169 170 /* FUNCTION: PR_TLockFile171 ** DESCRIPTION:172 ** Test and Lock a file for exclusive access. Do not block if the173 ** file cannot be locked immediately.174 ** RETURNS:175 ** PR_SUCCESS when the lock is held176 ** PR_FAILURE otherwise177 */178 NSPR_API(PRStatus) PR_TLockFile(PRFileDesc *fd);179 180 /* FUNCTION: PR_UnlockFile181 ** DESCRIPTION:182 ** Unlock a file which has been previously locked successfully by this183 ** process.184 ** RETURNS:185 ** PR_SUCCESS when the lock is released186 ** PR_FAILURE otherwise187 */188 NSPR_API(PRStatus) PR_UnlockFile(PRFileDesc *fd);189 190 161 /* 191 162 ** Emulate acceptread by accept and recv. … … 194 165 PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout); 195 166 196 /*197 ** Emulate sendfile by reading from the file and writing to the socket.198 ** The file is memory-mapped if memory-mapped files are supported.199 */200 NSPR_API(PRInt32) PR_EmulateSendFile(201 PRFileDesc *networkSocket, PRSendFileData *sendData,202 PRTransmitFileFlags flags, PRIntervalTime timeout);203 204 167 PR_END_EXTERN_C 205 168 -
trunk/src/libs/xpcom18a4/nsprpub/pr/include/private/primpl.h
r101869 r101870 55 55 56 56 #include "md/prosdep.h" 57 #include "obsolete/probslet.h"58 57 59 58 #ifdef _PR_HAVE_POSIX_SEMAPHORES -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/io/priometh.c
r1 r101870 67 67 (PRPollFN)_PR_InvalidInt16, 68 68 (PRAcceptreadFN)_PR_InvalidInt, 69 (PRTransmitfileFN)_PR_InvalidInt,70 69 (PRGetsocknameFN)_PR_InvalidStatus, 71 70 (PRGetpeernameFN)_PR_InvalidStatus, … … 74 73 (PRGetsocketoptionFN)_PR_InvalidStatus, 75 74 (PRSetsocketoptionFN)_PR_InvalidStatus, 76 (PRSendfileFN)_PR_InvalidInt,77 75 (PRConnectcontinueFN)_PR_InvalidStatus, 78 76 (PRReservedFN)_PR_InvalidInt, … … 251 249 } 252 250 253 PR_IMPLEMENT(PRInt32) PR_TransmitFile(254 PRFileDesc *sd, PRFileDesc *fd, const void *hdr, PRInt32 hlen,255 PRTransmitFileFlags flags, PRIntervalTime timeout)256 {257 return((sd->methods->transmitfile)(sd,fd,hdr,hlen,flags,timeout));258 }259 260 251 PR_IMPLEMENT(PRInt32) PR_AcceptRead( 261 252 PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, … … 285 276 { 286 277 return((fd->methods->setsocketoption)(fd, data)); 287 }288 289 PR_IMPLEMENT(PRInt32) PR_SendFile(290 PRFileDesc *sd, PRSendFileData *sfd,291 PRTransmitFileFlags flags, PRIntervalTime timeout)292 {293 return((sd->methods->sendfile)(sd,sfd,flags,timeout));294 278 } 295 279 … … 325 309 } 326 310 327 /*328 * PR_EmulateSendFile329 *330 * Send file sfd->fd across socket sd. If header/trailer are specified331 * they are sent before and after the file, respectively.332 *333 * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file334 *335 * return number of bytes sent or -1 on error336 *337 */338 339 #if defined(XP_UNIX) || defined(WIN32)340 341 /*342 * An implementation based on memory-mapped files343 */344 345 #define SENDFILE_MMAP_CHUNK (256 * 1024)346 347 PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(348 PRFileDesc *sd, PRSendFileData *sfd,349 PRTransmitFileFlags flags, PRIntervalTime timeout)350 {351 PRInt32 rv, count = 0;352 PRInt32 len, file_bytes, index = 0;353 PRFileInfo info;354 PRIOVec iov[3];355 PRFileMap *mapHandle = NULL;356 void *addr = (void*)0; /* initialized to some arbitrary value. Keeps compiler warnings down. */357 PRUint32 file_mmap_offset, alignment;358 PRInt64 zero64;359 PROffset64 file_mmap_offset64;360 PRUint32 addr_offset, mmap_len;361 362 /* Get file size */363 if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) {364 count = -1;365 goto done;366 }367 if (sfd->file_nbytes &&368 (info.size < (sfd->file_offset + sfd->file_nbytes))) {369 /*370 * there are fewer bytes in file to send than specified371 */372 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);373 count = -1;374 goto done;375 }376 if (sfd->file_nbytes)377 file_bytes = sfd->file_nbytes;378 else379 file_bytes = info.size - sfd->file_offset;380 381 alignment = PR_GetMemMapAlignment();382 383 /* number of initial bytes to skip in mmap'd segment */384 addr_offset = sfd->file_offset % alignment;385 386 /* find previous mmap alignment boundary */387 file_mmap_offset = sfd->file_offset - addr_offset;388 389 /*390 * If the file is large, mmap and send the file in chunks so as391 * to not consume too much virtual address space392 */393 mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK);394 len = mmap_len - addr_offset;395 396 /*397 * Map in (part of) file. Take care of zero-length files.398 */399 if (len) {400 LL_I2L(zero64, 0);401 mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY);402 if (!mapHandle) {403 count = -1;404 goto done;405 }406 LL_I2L(file_mmap_offset64, file_mmap_offset);407 addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len);408 if (!addr) {409 count = -1;410 goto done;411 }412 }413 /*414 * send headers first, followed by the file415 */416 if (sfd->hlen) {417 iov[index].iov_base = (char *) sfd->header;418 iov[index].iov_len = sfd->hlen;419 index++;420 }421 if (len) {422 iov[index].iov_base = (char*)addr + addr_offset;423 iov[index].iov_len = len;424 index++;425 }426 if ((file_bytes == len) && (sfd->tlen)) {427 /*428 * all file data is mapped in; send the trailer too429 */430 iov[index].iov_base = (char *) sfd->trailer;431 iov[index].iov_len = sfd->tlen;432 index++;433 }434 rv = PR_Writev(sd, iov, index, timeout);435 if (len)436 PR_MemUnmap(addr, mmap_len);437 if (rv < 0) {438 count = -1;439 goto done;440 }441 442 PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0));443 444 file_bytes -= len;445 count += rv;446 if (!file_bytes) /* header, file and trailer are sent */447 goto done;448 449 /*450 * send remaining bytes of the file, if any451 */452 len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);453 while (len > 0) {454 /*455 * Map in (part of) file456 */457 file_mmap_offset = sfd->file_offset + count - sfd->hlen;458 PR_ASSERT((file_mmap_offset % alignment) == 0);459 460 LL_I2L(file_mmap_offset64, file_mmap_offset);461 addr = PR_MemMap(mapHandle, file_mmap_offset64, len);462 if (!addr) {463 count = -1;464 goto done;465 }466 rv = PR_Send(sd, addr, len, 0, timeout);467 PR_MemUnmap(addr, len);468 if (rv < 0) {469 count = -1;470 goto done;471 }472 473 PR_ASSERT(rv == len);474 file_bytes -= rv;475 count += rv;476 len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);477 }478 PR_ASSERT(0 == file_bytes);479 if (sfd->tlen) {480 rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);481 if (rv >= 0) {482 PR_ASSERT(rv == sfd->tlen);483 count += rv;484 } else485 count = -1;486 }487 done:488 if (mapHandle)489 PR_CloseFileMap(mapHandle);490 if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))491 PR_Close(sd);492 return count;493 }494 495 #else496 497 PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(498 PRFileDesc *sd, PRSendFileData *sfd,499 PRTransmitFileFlags flags, PRIntervalTime timeout)500 {501 PRInt32 rv, count = 0;502 PRInt32 rlen;503 const void * buffer;504 PRInt32 buflen;505 PRInt32 sendbytes, readbytes;506 char *buf;507 508 #define _SENDFILE_BUFSIZE (16 * 1024)509 510 buf = (char*)PR_MALLOC(_SENDFILE_BUFSIZE);511 if (buf == NULL) {512 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);513 return -1;514 }515 516 /*517 * send header first518 */519 buflen = sfd->hlen;520 buffer = sfd->header;521 while (buflen) {522 rv = PR_Send(sd, buffer, buflen, 0, timeout);523 if (rv < 0) {524 /* PR_Send() has invoked PR_SetError(). */525 rv = -1;526 goto done;527 } else {528 count += rv;529 buffer = (const void*) ((const char*)buffer + rv);530 buflen -= rv;531 }532 }533 534 /*535 * send file next536 */537 if (PR_Seek(sfd->fd, sfd->file_offset, PR_SEEK_SET) < 0) {538 rv = -1;539 goto done;540 }541 sendbytes = sfd->file_nbytes;542 if (sendbytes == 0) {543 /* send entire file */544 while ((rlen = PR_Read(sfd->fd, buf, _SENDFILE_BUFSIZE)) > 0) {545 while (rlen) {546 char *bufptr = buf;547 548 rv = PR_Send(sd, bufptr, rlen, 0, timeout);549 if (rv < 0) {550 /* PR_Send() has invoked PR_SetError(). */551 rv = -1;552 goto done;553 } else {554 count += rv;555 bufptr = ((char*)bufptr + rv);556 rlen -= rv;557 }558 }559 }560 if (rlen < 0) {561 /* PR_Read() has invoked PR_SetError(). */562 rv = -1;563 goto done;564 }565 } else {566 readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);567 while (readbytes && ((rlen = PR_Read(sfd->fd, buf, readbytes)) > 0)) {568 while (rlen) {569 char *bufptr = buf;570 571 rv = PR_Send(sd, bufptr, rlen, 0, timeout);572 if (rv < 0) {573 /* PR_Send() has invoked PR_SetError(). */574 rv = -1;575 goto done;576 } else {577 count += rv;578 sendbytes -= rv;579 bufptr = ((char*)bufptr + rv);580 rlen -= rv;581 }582 }583 readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);584 }585 if (rlen < 0) {586 /* PR_Read() has invoked PR_SetError(). */587 rv = -1;588 goto done;589 } else if (sendbytes != 0) {590 /*591 * there are fewer bytes in file to send than specified592 */593 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);594 rv = -1;595 goto done;596 }597 }598 599 /*600 * send trailer last601 */602 buflen = sfd->tlen;603 buffer = sfd->trailer;604 while (buflen) {605 rv = PR_Send(sd, buffer, buflen, 0, timeout);606 if (rv < 0) {607 /* PR_Send() has invoked PR_SetError(). */608 rv = -1;609 goto done;610 } else {611 count += rv;612 buffer = (const void*) ((const char*)buffer + rv);613 buflen -= rv;614 }615 }616 rv = count;617 618 done:619 if (buf)620 PR_DELETE(buf);621 if ((rv >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))622 PR_Close(sd);623 return rv;624 }625 626 #endif627 628 311 /* priometh.c */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/io/prlayer.c
r65848 r101870 367 367 } 368 368 369 static PRInt32 PR_CALLBACK pl_DefTransmitfile (370 PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen,371 PRTransmitFileFlags flags, PRIntervalTime t)372 {373 PR_ASSERT(sd != NULL);374 PR_ASSERT(sd->lower != NULL);375 376 return sd->lower->methods->transmitfile(377 sd->lower, fd, headers, hlen, flags, t);378 }379 380 369 static PRStatus PR_CALLBACK pl_DefGetsockname (PRFileDesc *fd, PRNetAddr *addr) 381 370 { … … 410 399 411 400 return (fd->lower->methods->setsocketoption)(fd->lower, data); 412 }413 414 static PRInt32 PR_CALLBACK pl_DefSendfile (415 PRFileDesc *sd, PRSendFileData *sfd,416 PRTransmitFileFlags flags, PRIntervalTime timeout)417 {418 PR_ASSERT(sd != NULL);419 PR_ASSERT(sd->lower != NULL);420 421 return sd->lower->methods->sendfile(422 sd->lower, sfd, flags, timeout);423 401 } 424 402 … … 448 426 pl_DefPoll, 449 427 pl_DefAcceptread, 450 pl_DefTransmitfile,451 428 pl_DefGetsockname, 452 429 pl_DefGetpeername, … … 455 432 pl_DefGetsocketoption, 456 433 pl_DefSetsocketoption, 457 pl_DefSendfile,458 434 pl_DefConnectcontinue, 459 435 (PRReservedFN)_PR_InvalidInt, -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/io/prpolevt.c
r101792 r101870 107 107 _pr_PolEvtPoll, 108 108 (PRAcceptreadFN)_PR_InvalidInt, 109 (PRTransmitfileFN)_PR_InvalidInt,110 109 (PRGetsocknameFN)_PR_InvalidStatus, 111 110 (PRGetpeernameFN)_PR_InvalidStatus, … … 114 113 (PRGetsocketoptionFN)_PR_InvalidStatus, 115 114 (PRSetsocketoptionFN)_PR_InvalidStatus, 116 (PRSendfileFN)_PR_InvalidInt,117 115 (PRConnectcontinueFN)_PR_InvalidStatus, 118 116 (PRReservedFN)_PR_InvalidInt, -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptio.c
r101813 r101870 55 55 #include <sys/utsname.h> /* for uname */ 56 56 #endif 57 #if defined(SOLARIS) || defined(UNIXWARE)57 #if defined(SOLARIS) 58 58 #include <sys/filio.h> /* to pick up FIONREAD */ 59 59 #endif … … 61 61 #include <poll.h> 62 62 #endif 63 #ifdef AIX64 /* To pick up sysconf() */65 #include <unistd.h>66 #include <dlfcn.h> /* for dlopen */67 #else68 63 /* To pick up getrlimit() etc. */ 69 64 #include <sys/time.h> 70 65 #include <sys/resource.h> 71 #endif72 73 #ifdef SOLARIS74 /*75 * Define HAVE_SENDFILEV if the system has the sendfilev() system call.76 * Code built this way won't run on a system without sendfilev().77 * We can define HAVE_SENDFILEV by default when the minimum release78 * of Solaris that NSPR supports has sendfilev().79 */80 #ifdef HAVE_SENDFILEV81 82 #include <sys/sendfile.h>83 84 #define SOLARIS_SENDFILEV(a, b, c, d) sendfilev((a), (b), (c), (d))85 86 #else87 88 #include <dlfcn.h> /* for dlopen */89 90 /*91 * Match the definitions in <sys/sendfile.h>.92 */93 typedef struct sendfilevec {94 int sfv_fd; /* input fd */95 uint_t sfv_flag; /* flags */96 off_t sfv_off; /* offset to start reading from */97 size_t sfv_len; /* amount of data */98 } sendfilevec_t;99 100 #define SFV_FD_SELF (-2)101 102 /*103 * extern ssize_t sendfilev(int, const struct sendfilevec *, int, size_t *);104 */105 static ssize_t (*pt_solaris_sendfilev_fptr)() = NULL;106 107 #define SOLARIS_SENDFILEV(a, b, c, d) \108 (*pt_solaris_sendfilev_fptr)((a), (b), (c), (d))109 110 #endif /* HAVE_SENDFILEV */111 #endif /* SOLARIS */112 113 /*114 * The send_file() system call is available in AIX 4.3.2 or later.115 * If this file is compiled on an older AIX system, it attempts to116 * look up the send_file symbol at run time to determine whether117 * we can use the faster PR_SendFile/PR_TransmitFile implementation based on118 * send_file(). On AIX 4.3.2 or later, we can safely skip this119 * runtime function dispatching and just use the send_file based120 * implementation.121 */122 #ifdef AIX123 #ifdef SF_CLOSE124 #define HAVE_SEND_FILE125 #endif126 127 #ifdef HAVE_SEND_FILE128 129 #define AIX_SEND_FILE(a, b, c) send_file(a, b, c)130 131 #else /* HAVE_SEND_FILE */132 133 /*134 * The following definitions match those in <sys/socket.h>135 * on AIX 4.3.2.136 */137 138 /*139 * Structure for the send_file() system call140 */141 struct sf_parms {142 /* --------- header parms ---------- */143 void *header_data; /* Input/Output. Points to header buf */144 uint_t header_length; /* Input/Output. Length of the header */145 /* --------- file parms ------------ */146 int file_descriptor; /* Input. File descriptor of the file */147 unsigned long long file_size; /* Output. Size of the file */148 unsigned long long file_offset; /* Input/Output. Starting offset */149 long long file_bytes; /* Input/Output. no. of bytes to send */150 /* --------- trailer parms --------- */151 void *trailer_data; /* Input/Output. Points to trailer buf */152 uint_t trailer_length; /* Input/Output. Length of the trailer */153 /* --------- return info ----------- */154 unsigned long long bytes_sent; /* Output. no. of bytes sent */155 };156 157 /*158 * Flags for the send_file() system call159 */160 #define SF_CLOSE 0x00000001 /* close the socket after completion */161 #define SF_REUSE 0x00000002 /* reuse socket. not supported */162 #define SF_DONT_CACHE 0x00000004 /* don't apply network buffer cache */163 #define SF_SYNC_CACHE 0x00000008 /* sync/update network buffer cache */164 165 /*166 * prototype: size_t send_file(int *, struct sf_parms *, uint_t);167 */168 static ssize_t (*pt_aix_sendfile_fptr)() = NULL;169 170 #define AIX_SEND_FILE(a, b, c) (*pt_aix_sendfile_fptr)(a, b, c)171 172 #endif /* HAVE_SEND_FILE */173 #endif /* AIX */174 175 #ifdef LINUX176 #include <sys/sendfile.h>177 #endif178 66 179 67 #include "primpl.h" … … 325 213 union { PRIntn flags; } arg4; /* #4 - read/write flags */ 326 214 union { PRNetAddr *addr; } arg5; /* #5 - send/recv address */ 327 328 #ifdef SOLARIS329 /*330 * For sendfilev()331 */332 int nbytes_to_send; /* size of header and file */333 #endif /* SOLARIS */334 335 #ifdef LINUX336 /*337 * For sendfile()338 */339 int in_fd; /* descriptor of file to send */340 off_t offset;341 size_t count;342 #endif /* LINUX */343 215 344 216 PRIntervalTime timeout; /* client (relative) timeout */ … … 777 649 } /* pt_recvfrom_cont */ 778 650 779 #ifdef SOLARIS780 static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents)781 {782 struct sendfilevec *vec = (struct sendfilevec *) op->arg2.buffer;783 size_t xferred;784 ssize_t count;785 786 count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred);787 op->syserrno = errno;788 PR_ASSERT((count == -1) || (count == xferred));789 790 if (count == -1) {791 if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN792 && op->syserrno != EINTR) {793 op->result.code = -1;794 return PR_TRUE;795 }796 count = xferred;797 }798 PR_ASSERT(count <= op->nbytes_to_send);799 800 op->result.code += count;801 if (count < op->nbytes_to_send) {802 op->nbytes_to_send -= count;803 804 while (count >= vec->sfv_len) {805 count -= vec->sfv_len;806 vec++;807 op->arg3.amount--;808 }809 PR_ASSERT(op->arg3.amount > 0);810 811 vec->sfv_off += count;812 vec->sfv_len -= count;813 PR_ASSERT(vec->sfv_len > 0);814 op->arg2.buffer = vec;815 816 return PR_FALSE;817 }818 819 return PR_TRUE;820 }821 #endif /* SOLARIS */822 823 #ifdef LINUX824 static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents)825 {826 ssize_t rv;827 off_t oldoffset;828 829 oldoffset = op->offset;830 rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count);831 op->syserrno = errno;832 833 if (rv == -1) {834 if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {835 op->result.code = -1;836 return PR_TRUE;837 }838 rv = 0;839 }840 PR_ASSERT(rv == op->offset - oldoffset);841 op->result.code += rv;842 if (rv < op->count) {843 op->count -= rv;844 return PR_FALSE;845 }846 return PR_TRUE;847 }848 #endif /* LINUX */849 850 651 void _PR_InitIO(void) 851 652 { … … 1672 1473 } /* pt_SocketWrite */ 1673 1474 1674 #ifdef SOLARIS1675 1676 /*1677 * pt_SolarisSendFile1678 *1679 * Send file sfd->fd across socket sd. If specified, header and trailer1680 * buffers are sent before and after the file, respectively.1681 *1682 * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file1683 *1684 * return number of bytes sent or -1 on error1685 *1686 * This implementation takes advantage of the sendfilev() system1687 * call available in Solaris 8.1688 */1689 1690 static PRInt32 pt_SolarisSendFile(PRFileDesc *sd, PRSendFileData *sfd,1691 PRTransmitFileFlags flags, PRIntervalTime timeout)1692 {1693 struct stat statbuf;1694 size_t nbytes_to_send, file_nbytes_to_send;1695 struct sendfilevec sfv_struct[3];1696 int sfvcnt = 0;1697 size_t xferred;1698 PRInt32 count;1699 int syserrno;1700 1701 if (sfd->file_nbytes == 0) {1702 /* Get file size */1703 if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {1704 _PR_MD_MAP_FSTAT_ERROR(errno);1705 return -1;1706 }1707 file_nbytes_to_send = statbuf.st_size - sfd->file_offset;1708 } else {1709 file_nbytes_to_send = sfd->file_nbytes;1710 }1711 1712 nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send;1713 1714 if (sfd->hlen != 0) {1715 sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF;1716 sfv_struct[sfvcnt].sfv_flag = 0;1717 sfv_struct[sfvcnt].sfv_off = (off_t) sfd->header;1718 sfv_struct[sfvcnt].sfv_len = sfd->hlen;1719 sfvcnt++;1720 }1721 1722 if (file_nbytes_to_send != 0) {1723 sfv_struct[sfvcnt].sfv_fd = sfd->fd->secret->md.osfd;1724 sfv_struct[sfvcnt].sfv_flag = 0;1725 sfv_struct[sfvcnt].sfv_off = sfd->file_offset;1726 sfv_struct[sfvcnt].sfv_len = file_nbytes_to_send;1727 sfvcnt++;1728 }1729 1730 if (sfd->tlen != 0) {1731 sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF;1732 sfv_struct[sfvcnt].sfv_flag = 0;1733 sfv_struct[sfvcnt].sfv_off = (off_t) sfd->trailer;1734 sfv_struct[sfvcnt].sfv_len = sfd->tlen;1735 sfvcnt++;1736 }1737 1738 if (0 == sfvcnt) {1739 count = 0;1740 goto done;1741 }1742 1743 /*1744 * Strictly speaking, we may have sent some bytes when the1745 * sendfilev() is interrupted and we should retry it from an1746 * updated offset. We are not doing that here.1747 */1748 count = SOLARIS_SENDFILEV(sd->secret->md.osfd, sfv_struct,1749 sfvcnt, &xferred);1750 1751 PR_ASSERT((count == -1) || (count == xferred));1752 1753 if (count == -1) {1754 syserrno = errno;1755 if (syserrno == EINTR1756 || syserrno == EAGAIN || syserrno == EWOULDBLOCK) {1757 count = xferred;1758 }1759 }1760 1761 if (count != -1 && count < nbytes_to_send) {1762 pt_Continuation op;1763 struct sendfilevec *vec = sfv_struct;1764 PRInt32 rem = count;1765 1766 while (rem >= vec->sfv_len) {1767 rem -= vec->sfv_len;1768 vec++;1769 sfvcnt--;1770 }1771 PR_ASSERT(sfvcnt > 0);1772 1773 vec->sfv_off += rem;1774 vec->sfv_len -= rem;1775 PR_ASSERT(vec->sfv_len > 0);1776 1777 op.arg1.osfd = sd->secret->md.osfd;1778 op.arg2.buffer = vec;1779 op.arg3.amount = sfvcnt;1780 op.arg4.flags = 0;1781 op.nbytes_to_send = nbytes_to_send - count;1782 op.result.code = count;1783 op.timeout = timeout;1784 op.function = pt_solaris_sendfile_cont;1785 op.event = POLLOUT | POLLPRI;1786 count = pt_Continue(&op);1787 syserrno = op.syserrno;1788 }1789 1790 done:1791 if (count == -1) {1792 pt_MapError(_MD_solaris_map_sendfile_error, syserrno);1793 return -1;1794 }1795 if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {1796 PR_Close(sd);1797 }1798 PR_ASSERT(count == nbytes_to_send);1799 return count;1800 }1801 1802 #ifndef HAVE_SENDFILEV1803 static pthread_once_t pt_solaris_sendfilev_once_block = PTHREAD_ONCE_INIT;1804 1805 static void pt_solaris_sendfilev_init_routine(void)1806 {1807 void *handle;1808 PRBool close_it = PR_FALSE;1809 1810 /*1811 * We do not want to unload libsendfile.so. This handle is leaked1812 * intentionally.1813 */1814 handle = dlopen("libsendfile.so", RTLD_LAZY | RTLD_GLOBAL);1815 PR_LOG(_pr_io_lm, PR_LOG_DEBUG,1816 ("dlopen(libsendfile.so) returns %p", handle));1817 1818 if (NULL == handle) {1819 /*1820 * The dlopen(0, mode) call is to allow for the possibility that1821 * sendfilev() may become part of a standard system library in a1822 * future Solaris release.1823 */1824 handle = dlopen(0, RTLD_LAZY | RTLD_GLOBAL);1825 PR_LOG(_pr_io_lm, PR_LOG_DEBUG,1826 ("dlopen(0) returns %p", handle));1827 close_it = PR_TRUE;1828 }1829 pt_solaris_sendfilev_fptr = (ssize_t (*)()) dlsym(handle, "sendfilev");1830 PR_LOG(_pr_io_lm, PR_LOG_DEBUG,1831 ("dlsym(sendfilev) returns %p", pt_solaris_sendfilev_fptr));1832 1833 if (close_it) {1834 dlclose(handle);1835 }1836 }1837 1838 /*1839 * pt_SolarisDispatchSendFile1840 */1841 static PRInt32 pt_SolarisDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd,1842 PRTransmitFileFlags flags, PRIntervalTime timeout)1843 {1844 int rv;1845 1846 rv = pthread_once(&pt_solaris_sendfilev_once_block,1847 pt_solaris_sendfilev_init_routine);1848 PR_ASSERT(0 == rv);1849 if (pt_solaris_sendfilev_fptr) {1850 return pt_SolarisSendFile(sd, sfd, flags, timeout);1851 } else {1852 return PR_EmulateSendFile(sd, sfd, flags, timeout);1853 }1854 }1855 #endif /* !HAVE_SENDFILEV */1856 1857 #endif /* SOLARIS */1858 1859 #ifdef LINUX1860 /*1861 * pt_LinuxSendFile1862 *1863 * Send file sfd->fd across socket sd. If specified, header and trailer1864 * buffers are sent before and after the file, respectively.1865 *1866 * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file1867 *1868 * return number of bytes sent or -1 on error1869 *1870 * This implementation takes advantage of the sendfile() system1871 * call available in Linux kernel 2.2 or higher.1872 */1873 1874 static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd,1875 PRTransmitFileFlags flags, PRIntervalTime timeout)1876 {1877 struct stat statbuf;1878 size_t file_nbytes_to_send;1879 PRInt32 count = 0;1880 ssize_t rv;1881 int syserrno;1882 off_t offset;1883 PRBool tcp_cork_enabled = PR_FALSE;1884 int tcp_cork;1885 1886 if (sfd->file_nbytes == 0) {1887 /* Get file size */1888 if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {1889 _PR_MD_MAP_FSTAT_ERROR(errno);1890 return -1;1891 }1892 file_nbytes_to_send = statbuf.st_size - sfd->file_offset;1893 } else {1894 file_nbytes_to_send = sfd->file_nbytes;1895 }1896 1897 if ((sfd->hlen != 0 || sfd->tlen != 0)1898 && sd->secret->md.tcp_nodelay == 0) {1899 tcp_cork = 1;1900 if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,1901 &tcp_cork, sizeof tcp_cork) == 0) {1902 tcp_cork_enabled = PR_TRUE;1903 } else {1904 syserrno = errno;1905 if (syserrno != EINVAL) {1906 _PR_MD_MAP_SETSOCKOPT_ERROR(syserrno);1907 return -1;1908 }1909 /*1910 * The most likely reason for the EINVAL error is that1911 * TCP_NODELAY is set (with a function other than1912 * PR_SetSocketOption). This is not fatal, so we keep1913 * on going.1914 */1915 PR_LOG(_pr_io_lm, PR_LOG_WARNING,1916 ("pt_LinuxSendFile: "1917 "setsockopt(TCP_CORK) failed with EINVAL\n"));1918 }1919 }1920 1921 if (sfd->hlen != 0) {1922 count = PR_Send(sd, sfd->header, sfd->hlen, 0, timeout);1923 if (count == -1) {1924 goto failed;1925 }1926 }1927 1928 if (file_nbytes_to_send != 0) {1929 offset = sfd->file_offset;1930 do {1931 rv = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd,1932 &offset, file_nbytes_to_send);1933 } while (rv == -1 && (syserrno = errno) == EINTR);1934 if (rv == -1) {1935 if (syserrno != EAGAIN && syserrno != EWOULDBLOCK) {1936 _MD_linux_map_sendfile_error(syserrno);1937 count = -1;1938 goto failed;1939 }1940 rv = 0;1941 }1942 PR_ASSERT(rv == offset - sfd->file_offset);1943 count += rv;1944 1945 if (rv < file_nbytes_to_send) {1946 pt_Continuation op;1947 1948 op.arg1.osfd = sd->secret->md.osfd;1949 op.in_fd = sfd->fd->secret->md.osfd;1950 op.offset = offset;1951 op.count = file_nbytes_to_send - rv;1952 op.result.code = count;1953 op.timeout = timeout;1954 op.function = pt_linux_sendfile_cont;1955 op.event = POLLOUT | POLLPRI;1956 count = pt_Continue(&op);1957 syserrno = op.syserrno;1958 if (count == -1) {1959 pt_MapError(_MD_linux_map_sendfile_error, syserrno);1960 goto failed;1961 }1962 }1963 }1964 1965 if (sfd->tlen != 0) {1966 rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);1967 if (rv == -1) {1968 count = -1;1969 goto failed;1970 }1971 count += rv;1972 }1973 1974 failed:1975 if (tcp_cork_enabled) {1976 tcp_cork = 0;1977 if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,1978 &tcp_cork, sizeof tcp_cork) == -1 && count != -1) {1979 _PR_MD_MAP_SETSOCKOPT_ERROR(errno);1980 count = -1;1981 }1982 }1983 if (count != -1) {1984 if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {1985 PR_Close(sd);1986 }1987 PR_ASSERT(count == sfd->hlen + sfd->tlen + file_nbytes_to_send);1988 }1989 return count;1990 }1991 #endif /* LINUX */1992 1993 static PRInt32 pt_SendFile(1994 PRFileDesc *sd, PRSendFileData *sfd,1995 PRTransmitFileFlags flags, PRIntervalTime timeout)1996 {1997 if (pt_TestAbort()) return -1;1998 /* The socket must be in blocking mode. */1999 if (sd->secret->nonblocking)2000 {2001 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);2002 return -1;2003 }2004 #if defined(SOLARIS)2005 #ifdef HAVE_SENDFILEV2006 return(pt_SolarisSendFile(sd, sfd, flags, timeout));2007 #else2008 return(pt_SolarisDispatchSendFile(sd, sfd, flags, timeout));2009 #endif /* HAVE_SENDFILEV */2010 #elif defined(LINUX)2011 return(pt_LinuxSendFile(sd, sfd, flags, timeout));2012 #else2013 return(PR_EmulateSendFile(sd, sfd, flags, timeout));2014 #endif2015 }2016 2017 static PRInt32 pt_TransmitFile(2018 PRFileDesc *sd, PRFileDesc *fd, const void *headers,2019 PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)2020 {2021 PRSendFileData sfd;2022 2023 sfd.fd = fd;2024 sfd.file_offset = 0;2025 sfd.file_nbytes = 0;2026 sfd.header = headers;2027 sfd.hlen = hlen;2028 sfd.trailer = NULL;2029 sfd.tlen = 0;2030 2031 return(pt_SendFile(sd, &sfd, flags, timeout));2032 } /* pt_TransmitFile */2033 2034 1475 static PRInt32 pt_AcceptRead( 2035 1476 PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, … … 2268 1709 (char*)&value, sizeof(PRIntn)); 2269 1710 #ifdef LINUX 2270 /* for pt_Linux SendFile*/1711 /* for pt_Linux1 */ 2271 1712 if (name == TCP_NODELAY && rv == 0) { 2272 1713 fd->secret->md.tcp_nodelay = value; … … 2367 1808 pt_Poll, 2368 1809 (PRAcceptreadFN)_PR_InvalidInt, 2369 (PRTransmitfileFN)_PR_InvalidInt,2370 1810 (PRGetsocknameFN)_PR_InvalidStatus, 2371 1811 (PRGetpeernameFN)_PR_InvalidStatus, … … 2374 1814 (PRGetsocketoptionFN)_PR_InvalidStatus, 2375 1815 (PRSetsocketoptionFN)_PR_InvalidStatus, 2376 (PRSendfileFN)_PR_InvalidInt,2377 1816 (PRConnectcontinueFN)_PR_InvalidStatus, 2378 1817 (PRReservedFN)_PR_InvalidInt, … … 2406 1845 pt_Poll, 2407 1846 (PRAcceptreadFN)_PR_InvalidInt, 2408 (PRTransmitfileFN)_PR_InvalidInt,2409 1847 (PRGetsocknameFN)_PR_InvalidStatus, 2410 1848 (PRGetpeernameFN)_PR_InvalidStatus, … … 2413 1851 (PRGetsocketoptionFN)_PR_InvalidStatus, 2414 1852 (PRSetsocketoptionFN)_PR_InvalidStatus, 2415 (PRSendfileFN)_PR_InvalidInt,2416 1853 (PRConnectcontinueFN)_PR_InvalidStatus, 2417 1854 (PRReservedFN)_PR_InvalidInt, … … 2445 1882 pt_Poll, 2446 1883 pt_AcceptRead, 2447 pt_TransmitFile,2448 1884 pt_GetSockName, 2449 1885 pt_GetPeerName, … … 2452 1888 pt_GetSocketOption, 2453 1889 pt_SetSocketOption, 2454 pt_SendFile,2455 1890 pt_ConnectContinue, 2456 1891 (PRReservedFN)_PR_InvalidInt, … … 2484 1919 pt_Poll, 2485 1920 (PRAcceptreadFN)_PR_InvalidInt, 2486 (PRTransmitfileFN)_PR_InvalidInt,2487 1921 (PRGetsocknameFN)_PR_InvalidStatus, 2488 1922 (PRGetpeernameFN)_PR_InvalidStatus, … … 2491 1925 (PRGetsocketoptionFN)_PR_InvalidStatus, 2492 1926 (PRSetsocketoptionFN)_PR_InvalidStatus, 2493 (PRSendfileFN)_PR_InvalidInt,2494 1927 (PRConnectcontinueFN)_PR_InvalidStatus, 2495 1928 (PRReservedFN)_PR_InvalidInt, … … 3350 2783 } /* PR_ChangeFileDescNativeHandle*/ 3351 2784 3352 PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)3353 {3354 PRStatus status = PR_SUCCESS;3355 3356 if (pt_TestAbort()) return PR_FAILURE;3357 3358 PR_Lock(_pr_flock_lock);3359 while (-1 == fd->secret->lockCount)3360 PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT);3361 if (0 == fd->secret->lockCount)3362 {3363 fd->secret->lockCount = -1;3364 PR_Unlock(_pr_flock_lock);3365 status = _PR_MD_LOCKFILE(fd->secret->md.osfd);3366 PR_Lock(_pr_flock_lock);3367 fd->secret->lockCount = (PR_SUCCESS == status) ? 1 : 0;3368 PR_NotifyAllCondVar(_pr_flock_cv);3369 }3370 else3371 {3372 fd->secret->lockCount += 1;3373 }3374 PR_Unlock(_pr_flock_lock);3375 3376 return status;3377 } /* PR_LockFile */3378 3379 PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)3380 {3381 PRStatus status = PR_SUCCESS;3382 3383 if (pt_TestAbort()) return PR_FAILURE;3384 3385 PR_Lock(_pr_flock_lock);3386 if (0 == fd->secret->lockCount)3387 {3388 status = _PR_MD_TLOCKFILE(fd->secret->md.osfd);3389 if (PR_SUCCESS == status) fd->secret->lockCount = 1;3390 }3391 else fd->secret->lockCount += 1;3392 PR_Unlock(_pr_flock_lock);3393 3394 return status;3395 } /* PR_TLockFile */3396 3397 PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)3398 {3399 PRStatus status = PR_SUCCESS;3400 3401 if (pt_TestAbort()) return PR_FAILURE;3402 3403 PR_Lock(_pr_flock_lock);3404 if (fd->secret->lockCount == 1)3405 {3406 status = _PR_MD_UNLOCKFILE(fd->secret->md.osfd);3407 if (PR_SUCCESS == status) fd->secret->lockCount = 0;3408 }3409 else fd->secret->lockCount -= 1;3410 PR_Unlock(_pr_flock_lock);3411 3412 return status;3413 }3414 3415 /*3416 * The next two entry points should not be in the API, but they are3417 * defined here for historical (or hysterical) reasons.3418 */3419 3420 #ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP3421 static PRInt32 PR_GetSysfdTableMax(void)3422 #else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */3423 PRInt32 PR_GetSysfdTableMax(void)3424 #endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */3425 {3426 #if defined(XP_UNIX) && !defined(AIX) && !defined(VMS)3427 struct rlimit rlim;3428 3429 if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0)3430 return -1;3431 3432 return rlim.rlim_max;3433 #elif defined(AIX) || defined(VMS)3434 return sysconf(_SC_OPEN_MAX);3435 #endif3436 }3437 3438 #ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP3439 static PRInt32 PR_SetSysfdTableSize(PRIntn table_size)3440 #else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */3441 PRInt32 PR_SetSysfdTableSize(PRIntn table_size)3442 #endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */3443 {3444 #if defined(XP_UNIX) && !defined(AIX) && !defined(VMS)3445 struct rlimit rlim;3446 PRInt32 tableMax = PR_GetSysfdTableMax();3447 3448 if (tableMax < 0) return -1;3449 rlim.rlim_max = tableMax;3450 3451 /* Grow as much as we can; even if too big */3452 if ( rlim.rlim_max < table_size )3453 rlim.rlim_cur = rlim.rlim_max;3454 else3455 rlim.rlim_cur = table_size;3456 3457 if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0)3458 return -1;3459 3460 return rlim.rlim_cur;3461 #elif defined(AIX) || defined(VMS)3462 return -1;3463 #endif3464 }3465 3466 /*3467 * PR_Stat is supported for backward compatibility; some existing Java3468 * code uses it. New code should use PR_GetFileInfo.3469 */3470 3471 #ifndef NO_NSPR_10_SUPPORT3472 PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)3473 {3474 static PRBool unwarned = PR_TRUE;3475 if (unwarned) unwarned = _PR_Obsolete("PR_Stat", "PR_GetFileInfo");3476 3477 if (pt_TestAbort()) return -1;3478 3479 if (-1 == stat(name, buf)) {3480 pt_MapError(_PR_MD_MAP_STAT_ERROR, errno);3481 return -1;3482 } else {3483 return 0;3484 }3485 }3486 #endif /* ! NO_NSPR_10_SUPPORT */3487 3488 3489 PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set)3490 {3491 static PRBool unwarned = PR_TRUE;3492 if (unwarned) unwarned = _PR_Obsolete("PR_FD_ZERO (PR_Select)", "PR_Poll");3493 memset(set, 0, sizeof(PR_fd_set));3494 }3495 3496 PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set)3497 {3498 static PRBool unwarned = PR_TRUE;3499 if (unwarned) unwarned = _PR_Obsolete("PR_FD_SET (PR_Select)", "PR_Poll");3500 PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC );3501 3502 set->harray[set->hsize++] = fh;3503 }3504 3505 PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set)3506 {3507 PRUint32 index, index2;3508 static PRBool unwarned = PR_TRUE;3509 if (unwarned) unwarned = _PR_Obsolete("PR_FD_CLR (PR_Select)", "PR_Poll");3510 3511 for (index = 0; index<set->hsize; index++)3512 if (set->harray[index] == fh) {3513 for (index2=index; index2 < (set->hsize-1); index2++) {3514 set->harray[index2] = set->harray[index2+1];3515 }3516 set->hsize--;3517 break;3518 }3519 }3520 3521 PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set)3522 {3523 PRUint32 index;3524 static PRBool unwarned = PR_TRUE;3525 if (unwarned) unwarned = _PR_Obsolete("PR_FD_ISSET (PR_Select)", "PR_Poll");3526 for (index = 0; index<set->hsize; index++)3527 if (set->harray[index] == fh) {3528 return 1;3529 }3530 return 0;3531 }3532 3533 PR_IMPLEMENT(void) PR_FD_NSET(PRInt32 fd, PR_fd_set *set)3534 {3535 static PRBool unwarned = PR_TRUE;3536 if (unwarned) unwarned = _PR_Obsolete("PR_FD_NSET (PR_Select)", "PR_Poll");3537 PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC );3538 3539 set->narray[set->nsize++] = fd;3540 }3541 3542 PR_IMPLEMENT(void) PR_FD_NCLR(PRInt32 fd, PR_fd_set *set)3543 {3544 PRUint32 index, index2;3545 static PRBool unwarned = PR_TRUE;3546 if (unwarned) unwarned = _PR_Obsolete("PR_FD_NCLR (PR_Select)", "PR_Poll");3547 3548 for (index = 0; index<set->nsize; index++)3549 if (set->narray[index] == fd) {3550 for (index2=index; index2 < (set->nsize-1); index2++) {3551 set->narray[index2] = set->narray[index2+1];3552 }3553 set->nsize--;3554 break;3555 }3556 }3557 3558 PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PRInt32 fd, PR_fd_set *set)3559 {3560 PRUint32 index;3561 static PRBool unwarned = PR_TRUE;3562 if (unwarned) unwarned = _PR_Obsolete("PR_FD_NISSET (PR_Select)", "PR_Poll");3563 for (index = 0; index<set->nsize; index++)3564 if (set->narray[index] == fd) {3565 return 1;3566 }3567 return 0;3568 }3569 3570 #include <sys/types.h>3571 #include <sys/time.h>3572 #if !defined(SUNOS4) && !defined(HPUX) && !defined(LINUX)3573 #include <sys/select.h>3574 #endif3575 3576 static PRInt323577 _PR_getset(PR_fd_set *pr_set, fd_set *set)3578 {3579 PRUint32 index;3580 PRInt32 max = 0;3581 3582 if (!pr_set)3583 return 0;3584 3585 FD_ZERO(set);3586 3587 /* First set the pr file handle osfds */3588 for (index=0; index<pr_set->hsize; index++) {3589 FD_SET(pr_set->harray[index]->secret->md.osfd, set);3590 if (pr_set->harray[index]->secret->md.osfd > max)3591 max = pr_set->harray[index]->secret->md.osfd;3592 }3593 /* Second set the native osfds */3594 for (index=0; index<pr_set->nsize; index++) {3595 FD_SET(pr_set->narray[index], set);3596 if (pr_set->narray[index] > max)3597 max = pr_set->narray[index];3598 }3599 return max;3600 }3601 3602 static void3603 _PR_setset(PR_fd_set *pr_set, fd_set *set)3604 {3605 PRUint32 index, last_used;3606 3607 if (!pr_set)3608 return;3609 3610 for (last_used=0, index=0; index<pr_set->hsize; index++) {3611 if ( FD_ISSET(pr_set->harray[index]->secret->md.osfd, set) ) {3612 pr_set->harray[last_used++] = pr_set->harray[index];3613 }3614 }3615 pr_set->hsize = last_used;3616 3617 for (last_used=0, index=0; index<pr_set->nsize; index++) {3618 if ( FD_ISSET(pr_set->narray[index], set) ) {3619 pr_set->narray[last_used++] = pr_set->narray[index];3620 }3621 }3622 pr_set->nsize = last_used;3623 }3624 3625 PR_IMPLEMENT(PRInt32) PR_Select(3626 PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr,3627 PR_fd_set *pr_ex, PRIntervalTime timeout)3628 {3629 fd_set rd, wr, ex;3630 struct timeval tv, *tvp;3631 PRInt32 max, max_fd;3632 PRInt32 rv;3633 /*3634 * For restarting select() if it is interrupted by a Unix signal.3635 * We use these variables to figure out how much time has elapsed3636 * and how much of the timeout still remains.3637 */3638 PRIntervalTime start, elapsed, remaining;3639 3640 static PRBool unwarned = PR_TRUE;3641 if (unwarned) unwarned = _PR_Obsolete( "PR_Select", "PR_Poll");3642 3643 FD_ZERO(&rd);3644 FD_ZERO(&wr);3645 FD_ZERO(&ex);3646 3647 max_fd = _PR_getset(pr_rd, &rd);3648 max_fd = (max = _PR_getset(pr_wr, &wr))>max_fd?max:max_fd;3649 max_fd = (max = _PR_getset(pr_ex, &ex))>max_fd?max:max_fd;3650 3651 if (timeout == PR_INTERVAL_NO_TIMEOUT) {3652 tvp = NULL;3653 } else {3654 tv.tv_sec = (PRInt32)PR_IntervalToSeconds(timeout);3655 tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds(3656 timeout - PR_SecondsToInterval(tv.tv_sec));3657 tvp = &tv;3658 start = PR_IntervalNow();3659 }3660 3661 retry:3662 rv = select(max_fd + 1, (_PRSelectFdSetArg_t) &rd,3663 (_PRSelectFdSetArg_t) &wr, (_PRSelectFdSetArg_t) &ex, tvp);3664 3665 if (rv == -1 && errno == EINTR) {3666 if (timeout == PR_INTERVAL_NO_TIMEOUT) {3667 goto retry;3668 } else {3669 elapsed = (PRIntervalTime) (PR_IntervalNow() - start);3670 if (elapsed > timeout) {3671 rv = 0; /* timed out */3672 } else {3673 remaining = timeout - elapsed;3674 tv.tv_sec = (PRInt32)PR_IntervalToSeconds(remaining);3675 tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds(3676 remaining - PR_SecondsToInterval(tv.tv_sec));3677 goto retry;3678 }3679 }3680 }3681 3682 if (rv > 0) {3683 _PR_setset(pr_rd, &rd);3684 _PR_setset(pr_wr, &wr);3685 _PR_setset(pr_ex, &ex);3686 } else if (rv == -1) {3687 pt_MapError(_PR_MD_MAP_SELECT_ERROR, errno);3688 }3689 return rv;3690 }3691 3692 2785 /* ptio.c */
Note:
See TracChangeset
for help on using the changeset viewer.