Index: mozilla/nsprpub/pr/src/io/priometh.c |
=================================================================== |
--- mozilla/nsprpub/pr/src/io/priometh.c (revision 191424) |
+++ mozilla/nsprpub/pr/src/io/priometh.c (working copy) |
@@ -1,596 +0,0 @@ |
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
- |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-#include "primpl.h" |
- |
-#include <string.h> |
- |
-/*****************************************************************************/ |
-/************************** Invalid I/O method object ************************/ |
-/*****************************************************************************/ |
-PRIOMethods _pr_faulty_methods = { |
- (PRDescType)0, |
- (PRCloseFN)_PR_InvalidStatus, |
- (PRReadFN)_PR_InvalidInt, |
- (PRWriteFN)_PR_InvalidInt, |
- (PRAvailableFN)_PR_InvalidInt, |
- (PRAvailable64FN)_PR_InvalidInt64, |
- (PRFsyncFN)_PR_InvalidStatus, |
- (PRSeekFN)_PR_InvalidInt, |
- (PRSeek64FN)_PR_InvalidInt64, |
- (PRFileInfoFN)_PR_InvalidStatus, |
- (PRFileInfo64FN)_PR_InvalidStatus, |
- (PRWritevFN)_PR_InvalidInt, |
- (PRConnectFN)_PR_InvalidStatus, |
- (PRAcceptFN)_PR_InvalidDesc, |
- (PRBindFN)_PR_InvalidStatus, |
- (PRListenFN)_PR_InvalidStatus, |
- (PRShutdownFN)_PR_InvalidStatus, |
- (PRRecvFN)_PR_InvalidInt, |
- (PRSendFN)_PR_InvalidInt, |
- (PRRecvfromFN)_PR_InvalidInt, |
- (PRSendtoFN)_PR_InvalidInt, |
- (PRPollFN)_PR_InvalidInt16, |
- (PRAcceptreadFN)_PR_InvalidInt, |
- (PRTransmitfileFN)_PR_InvalidInt, |
- (PRGetsocknameFN)_PR_InvalidStatus, |
- (PRGetpeernameFN)_PR_InvalidStatus, |
- (PRReservedFN)_PR_InvalidInt, |
- (PRReservedFN)_PR_InvalidInt, |
- (PRGetsocketoptionFN)_PR_InvalidStatus, |
- (PRSetsocketoptionFN)_PR_InvalidStatus, |
- (PRSendfileFN)_PR_InvalidInt, |
- (PRConnectcontinueFN)_PR_InvalidStatus, |
- (PRReservedFN)_PR_InvalidInt, |
- (PRReservedFN)_PR_InvalidInt, |
- (PRReservedFN)_PR_InvalidInt, |
- (PRReservedFN)_PR_InvalidInt |
-}; |
- |
-PRIntn _PR_InvalidInt(void) |
-{ |
- PR_ASSERT(!"I/O method is invalid"); |
- PR_SetError(PR_INVALID_METHOD_ERROR, 0); |
- return -1; |
-} /* _PR_InvalidInt */ |
- |
-PRInt16 _PR_InvalidInt16(void) |
-{ |
- PR_ASSERT(!"I/O method is invalid"); |
- PR_SetError(PR_INVALID_METHOD_ERROR, 0); |
- return -1; |
-} /* _PR_InvalidInt */ |
- |
-PRInt64 _PR_InvalidInt64(void) |
-{ |
- PRInt64 rv; |
- LL_I2L(rv, -1); |
- PR_ASSERT(!"I/O method is invalid"); |
- PR_SetError(PR_INVALID_METHOD_ERROR, 0); |
- return rv; |
-} /* _PR_InvalidInt */ |
- |
-/* |
- * An invalid method that returns PRStatus |
- */ |
- |
-PRStatus _PR_InvalidStatus(void) |
-{ |
- PR_ASSERT(!"I/O method is invalid"); |
- PR_SetError(PR_INVALID_METHOD_ERROR, 0); |
- return PR_FAILURE; |
-} /* _PR_InvalidDesc */ |
- |
-/* |
- * An invalid method that returns a pointer |
- */ |
- |
-PRFileDesc *_PR_InvalidDesc(void) |
-{ |
- PR_ASSERT(!"I/O method is invalid"); |
- PR_SetError(PR_INVALID_METHOD_ERROR, 0); |
- return NULL; |
-} /* _PR_InvalidDesc */ |
- |
-PR_IMPLEMENT(PRDescType) PR_GetDescType(PRFileDesc *file) |
-{ |
- return file->methods->file_type; |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd) |
-{ |
- return (fd->methods->close)(fd); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount) |
-{ |
- return((fd->methods->read)(fd,buf,amount)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount) |
-{ |
- return((fd->methods->write)(fd,buf,amount)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) |
-{ |
- return((fd->methods->seek)(fd, offset, whence)); |
-} |
- |
-PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence) |
-{ |
- return((fd->methods->seek64)(fd, offset, whence)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd) |
-{ |
- return((fd->methods->available)(fd)); |
-} |
- |
-PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd) |
-{ |
- return((fd->methods->available64)(fd)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info) |
-{ |
- return((fd->methods->fileInfo)(fd, info)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info) |
-{ |
- return((fd->methods->fileInfo64)(fd, info)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd) |
-{ |
- return((fd->methods->fsync)(fd)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_Connect( |
- PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) |
-{ |
- return((fd->methods->connect)(fd,addr,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_ConnectContinue( |
- PRFileDesc *fd, PRInt16 out_flags) |
-{ |
- return((fd->methods->connectcontinue)(fd,out_flags)); |
-} |
- |
-PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr, |
-PRIntervalTime timeout) |
-{ |
- return((fd->methods->accept)(fd,addr,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr) |
-{ |
- return((fd->methods->bind)(fd,addr)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how) |
-{ |
- return((fd->methods->shutdown)(fd,how)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog) |
-{ |
- return((fd->methods->listen)(fd,backlog)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount, |
-PRIntn flags, PRIntervalTime timeout) |
-{ |
- return((fd->methods->recv)(fd,buf,amount,flags,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount, |
-PRIntn flags, PRIntervalTime timeout) |
-{ |
- return((fd->methods->send)(fd,buf,amount,flags,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_Writev(PRFileDesc *fd, const PRIOVec *iov, |
-PRInt32 iov_size, PRIntervalTime timeout) |
-{ |
- if (iov_size > PR_MAX_IOVECTOR_SIZE) |
- { |
- PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); |
- return -1; |
- } |
- return((fd->methods->writev)(fd,iov,iov_size,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, |
-PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) |
-{ |
- return((fd->methods->recvfrom)(fd,buf,amount,flags,addr,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_SendTo( |
- PRFileDesc *fd, const void *buf, PRInt32 amount, |
- PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) |
-{ |
- return((fd->methods->sendto)(fd,buf,amount,flags,addr,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_TransmitFile( |
- PRFileDesc *sd, PRFileDesc *fd, const void *hdr, PRInt32 hlen, |
- PRTransmitFileFlags flags, PRIntervalTime timeout) |
-{ |
- return((sd->methods->transmitfile)(sd,fd,hdr,hlen,flags,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_AcceptRead( |
- PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, |
- void *buf, PRInt32 amount, PRIntervalTime timeout) |
-{ |
- return((sd->methods->acceptread)(sd, nd, raddr, buf, amount,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr) |
-{ |
- return((fd->methods->getsockname)(fd,addr)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) |
-{ |
- return((fd->methods->getpeername)(fd,addr)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_GetSocketOption( |
- PRFileDesc *fd, PRSocketOptionData *data) |
-{ |
- return((fd->methods->getsocketoption)(fd, data)); |
-} |
- |
-PR_IMPLEMENT(PRStatus) PR_SetSocketOption( |
- PRFileDesc *fd, const PRSocketOptionData *data) |
-{ |
- return((fd->methods->setsocketoption)(fd, data)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_SendFile( |
- PRFileDesc *sd, PRSendFileData *sfd, |
- PRTransmitFileFlags flags, PRIntervalTime timeout) |
-{ |
- return((sd->methods->sendfile)(sd,sfd,flags,timeout)); |
-} |
- |
-PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead( |
- PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, |
- void *buf, PRInt32 amount, PRIntervalTime timeout) |
-{ |
- PRInt32 rv = -1; |
- PRNetAddr remote; |
- PRFileDesc *accepted = NULL; |
- |
- /* |
- ** The timeout does not apply to the accept portion of the |
- ** operation - it waits indefinitely. |
- */ |
- accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT); |
- if (NULL == accepted) return rv; |
- |
- rv = PR_Recv(accepted, buf, amount, 0, timeout); |
- if (rv >= 0) |
- { |
- /* copy the new info out where caller can see it */ |
-#define AMASK ((PRPtrdiff)7) /* mask for alignment of PRNetAddr */ |
- PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK; |
- *raddr = (PRNetAddr*)(aligned & ~AMASK); |
- memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote)); |
- *nd = accepted; |
- return rv; |
- } |
- |
- PR_Close(accepted); |
- return rv; |
-} |
- |
-/* |
- * PR_EmulateSendFile |
- * |
- * Send file sfd->fd across socket sd. If header/trailer are specified |
- * they are sent before and after the file, respectively. |
- * |
- * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file |
- * |
- * return number of bytes sent or -1 on error |
- * |
- */ |
- |
-#if defined(XP_UNIX) || defined(WIN32) |
- |
-/* |
- * An implementation based on memory-mapped files |
- */ |
- |
-#define SENDFILE_MMAP_CHUNK (256 * 1024) |
- |
-PR_IMPLEMENT(PRInt32) PR_EmulateSendFile( |
- PRFileDesc *sd, PRSendFileData *sfd, |
- PRTransmitFileFlags flags, PRIntervalTime timeout) |
-{ |
- PRInt32 rv, count = 0; |
- PRInt32 len, file_bytes, index = 0; |
- PRFileInfo info; |
- PRIOVec iov[3]; |
- PRFileMap *mapHandle = NULL; |
- void *addr = (void*)0; /* initialized to some arbitrary value. Keeps compiler warnings down. */ |
- PRUint32 file_mmap_offset, alignment; |
- PRInt64 zero64; |
- PROffset64 file_mmap_offset64; |
- PRUint32 addr_offset, mmap_len; |
- |
- /* Get file size */ |
- if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) { |
- count = -1; |
- goto done; |
- } |
- if (sfd->file_nbytes && |
- (info.size < (sfd->file_offset + sfd->file_nbytes))) { |
- /* |
- * there are fewer bytes in file to send than specified |
- */ |
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
- count = -1; |
- goto done; |
- } |
- if (sfd->file_nbytes) |
- file_bytes = sfd->file_nbytes; |
- else |
- file_bytes = info.size - sfd->file_offset; |
- |
- alignment = PR_GetMemMapAlignment(); |
- |
- /* number of initial bytes to skip in mmap'd segment */ |
- addr_offset = sfd->file_offset % alignment; |
- |
- /* find previous mmap alignment boundary */ |
- file_mmap_offset = sfd->file_offset - addr_offset; |
- |
- /* |
- * If the file is large, mmap and send the file in chunks so as |
- * to not consume too much virtual address space |
- */ |
- mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK); |
- len = mmap_len - addr_offset; |
- |
- /* |
- * Map in (part of) file. Take care of zero-length files. |
- */ |
- if (len) { |
- LL_I2L(zero64, 0); |
- mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY); |
- if (!mapHandle) { |
- count = -1; |
- goto done; |
- } |
- LL_I2L(file_mmap_offset64, file_mmap_offset); |
- addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len); |
- if (!addr) { |
- count = -1; |
- goto done; |
- } |
- } |
- /* |
- * send headers first, followed by the file |
- */ |
- if (sfd->hlen) { |
- iov[index].iov_base = (char *) sfd->header; |
- iov[index].iov_len = sfd->hlen; |
- index++; |
- } |
- if (len) { |
- iov[index].iov_base = (char*)addr + addr_offset; |
- iov[index].iov_len = len; |
- index++; |
- } |
- if ((file_bytes == len) && (sfd->tlen)) { |
- /* |
- * all file data is mapped in; send the trailer too |
- */ |
- iov[index].iov_base = (char *) sfd->trailer; |
- iov[index].iov_len = sfd->tlen; |
- index++; |
- } |
- rv = PR_Writev(sd, iov, index, timeout); |
- if (len) |
- PR_MemUnmap(addr, mmap_len); |
- if (rv < 0) { |
- count = -1; |
- goto done; |
- } |
- |
- PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0)); |
- |
- file_bytes -= len; |
- count += rv; |
- if (!file_bytes) /* header, file and trailer are sent */ |
- goto done; |
- |
- /* |
- * send remaining bytes of the file, if any |
- */ |
- len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK); |
- while (len > 0) { |
- /* |
- * Map in (part of) file |
- */ |
- file_mmap_offset = sfd->file_offset + count - sfd->hlen; |
- PR_ASSERT((file_mmap_offset % alignment) == 0); |
- |
- LL_I2L(file_mmap_offset64, file_mmap_offset); |
- addr = PR_MemMap(mapHandle, file_mmap_offset64, len); |
- if (!addr) { |
- count = -1; |
- goto done; |
- } |
- rv = PR_Send(sd, addr, len, 0, timeout); |
- PR_MemUnmap(addr, len); |
- if (rv < 0) { |
- count = -1; |
- goto done; |
- } |
- |
- PR_ASSERT(rv == len); |
- file_bytes -= rv; |
- count += rv; |
- len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK); |
- } |
- PR_ASSERT(0 == file_bytes); |
- if (sfd->tlen) { |
- rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout); |
- if (rv >= 0) { |
- PR_ASSERT(rv == sfd->tlen); |
- count += rv; |
- } else |
- count = -1; |
- } |
-done: |
- if (mapHandle) |
- PR_CloseFileMap(mapHandle); |
- if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET)) |
- PR_Close(sd); |
- return count; |
-} |
- |
-#else |
- |
-PR_IMPLEMENT(PRInt32) PR_EmulateSendFile( |
- PRFileDesc *sd, PRSendFileData *sfd, |
- PRTransmitFileFlags flags, PRIntervalTime timeout) |
-{ |
- PRInt32 rv, count = 0; |
- PRInt32 rlen; |
- const void * buffer; |
- PRInt32 buflen; |
- PRInt32 sendbytes, readbytes; |
- char *buf; |
- |
-#define _SENDFILE_BUFSIZE (16 * 1024) |
- |
- buf = (char*)PR_MALLOC(_SENDFILE_BUFSIZE); |
- if (buf == NULL) { |
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
- return -1; |
- } |
- |
- /* |
- * send header first |
- */ |
- buflen = sfd->hlen; |
- buffer = sfd->header; |
- while (buflen) { |
- rv = PR_Send(sd, buffer, buflen, 0, timeout); |
- if (rv < 0) { |
- /* PR_Send() has invoked PR_SetError(). */ |
- rv = -1; |
- goto done; |
- } else { |
- count += rv; |
- buffer = (const void*) ((const char*)buffer + rv); |
- buflen -= rv; |
- } |
- } |
- |
- /* |
- * send file next |
- */ |
- if (PR_Seek(sfd->fd, sfd->file_offset, PR_SEEK_SET) < 0) { |
- rv = -1; |
- goto done; |
- } |
- sendbytes = sfd->file_nbytes; |
- if (sendbytes == 0) { |
- /* send entire file */ |
- while ((rlen = PR_Read(sfd->fd, buf, _SENDFILE_BUFSIZE)) > 0) { |
- while (rlen) { |
- char *bufptr = buf; |
- |
- rv = PR_Send(sd, bufptr, rlen, 0, timeout); |
- if (rv < 0) { |
- /* PR_Send() has invoked PR_SetError(). */ |
- rv = -1; |
- goto done; |
- } else { |
- count += rv; |
- bufptr = ((char*)bufptr + rv); |
- rlen -= rv; |
- } |
- } |
- } |
- if (rlen < 0) { |
- /* PR_Read() has invoked PR_SetError(). */ |
- rv = -1; |
- goto done; |
- } |
- } else { |
- readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE); |
- while (readbytes && ((rlen = PR_Read(sfd->fd, buf, readbytes)) > 0)) { |
- while (rlen) { |
- char *bufptr = buf; |
- |
- rv = PR_Send(sd, bufptr, rlen, 0, timeout); |
- if (rv < 0) { |
- /* PR_Send() has invoked PR_SetError(). */ |
- rv = -1; |
- goto done; |
- } else { |
- count += rv; |
- sendbytes -= rv; |
- bufptr = ((char*)bufptr + rv); |
- rlen -= rv; |
- } |
- } |
- readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE); |
- } |
- if (rlen < 0) { |
- /* PR_Read() has invoked PR_SetError(). */ |
- rv = -1; |
- goto done; |
- } else if (sendbytes != 0) { |
- /* |
- * there are fewer bytes in file to send than specified |
- */ |
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
- rv = -1; |
- goto done; |
- } |
- } |
- |
- /* |
- * send trailer last |
- */ |
- buflen = sfd->tlen; |
- buffer = sfd->trailer; |
- while (buflen) { |
- rv = PR_Send(sd, buffer, buflen, 0, timeout); |
- if (rv < 0) { |
- /* PR_Send() has invoked PR_SetError(). */ |
- rv = -1; |
- goto done; |
- } else { |
- count += rv; |
- buffer = (const void*) ((const char*)buffer + rv); |
- buflen -= rv; |
- } |
- } |
- rv = count; |
- |
-done: |
- if (buf) |
- PR_DELETE(buf); |
- if ((rv >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET)) |
- PR_Close(sd); |
- return rv; |
-} |
- |
-#endif |
- |
-/* priometh.c */ |