LCOV - app.info - nsprpub/pr/src/io/priometh.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/io - priometh.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 181 | 0 | 0.0 %
| Date: | 2012-04-07 | Functions: | 36 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 :
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is the Netscape Portable Runtime (NSPR).
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Netscape Communications Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 1998-2000
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 : #include "primpl.h"
          39                 :
          40                 : #include <string.h>
          41                 :
          42                 : /*****************************************************************************/
          43                 : /************************** Invalid I/O method object ************************/
          44                 : /*****************************************************************************/
          45                 : PRIOMethods _pr_faulty_methods = {
          46                 :     (PRDescType)0,
          47                 :     (PRCloseFN)_PR_InvalidStatus,
          48                 :     (PRReadFN)_PR_InvalidInt,
          49                 :     (PRWriteFN)_PR_InvalidInt,
          50                 :     (PRAvailableFN)_PR_InvalidInt,
          51                 :     (PRAvailable64FN)_PR_InvalidInt64,
          52                 :     (PRFsyncFN)_PR_InvalidStatus,
          53                 :     (PRSeekFN)_PR_InvalidInt,
          54                 :     (PRSeek64FN)_PR_InvalidInt64,
          55                 :     (PRFileInfoFN)_PR_InvalidStatus,
          56                 :     (PRFileInfo64FN)_PR_InvalidStatus,
          57                 :     (PRWritevFN)_PR_InvalidInt,
          58                 :     (PRConnectFN)_PR_InvalidStatus,
          59                 :     (PRAcceptFN)_PR_InvalidDesc,
          60                 :     (PRBindFN)_PR_InvalidStatus,
          61                 :     (PRListenFN)_PR_InvalidStatus,
          62                 :     (PRShutdownFN)_PR_InvalidStatus,
          63                 :     (PRRecvFN)_PR_InvalidInt,
          64                 :     (PRSendFN)_PR_InvalidInt,
          65                 :     (PRRecvfromFN)_PR_InvalidInt,
          66                 :     (PRSendtoFN)_PR_InvalidInt,
          67                 :     (PRPollFN)_PR_InvalidInt16,
          68                 :     (PRAcceptreadFN)_PR_InvalidInt,
          69                 :     (PRTransmitfileFN)_PR_InvalidInt,
          70                 :     (PRGetsocknameFN)_PR_InvalidStatus,
          71                 :     (PRGetpeernameFN)_PR_InvalidStatus,
          72                 :     (PRReservedFN)_PR_InvalidInt,
          73                 :     (PRReservedFN)_PR_InvalidInt,
          74                 :     (PRGetsocketoptionFN)_PR_InvalidStatus,
          75                 :     (PRSetsocketoptionFN)_PR_InvalidStatus,
          76                 :     (PRSendfileFN)_PR_InvalidInt,
          77                 :     (PRConnectcontinueFN)_PR_InvalidStatus,
          78                 :     (PRReservedFN)_PR_InvalidInt,
          79                 :     (PRReservedFN)_PR_InvalidInt,
          80                 :     (PRReservedFN)_PR_InvalidInt,
          81                 :     (PRReservedFN)_PR_InvalidInt
          82                 : };
          83                 :
          84               0 : PRIntn _PR_InvalidInt(void)
          85                 : {
          86               0 :     PR_ASSERT(!"I/O method is invalid");
          87               0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
          88               0 :     return -1;
          89                 : }  /* _PR_InvalidInt */
          90                 :
          91               0 : PRInt16 _PR_InvalidInt16(void)
          92                 : {
          93               0 :     PR_ASSERT(!"I/O method is invalid");
          94               0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
          95               0 :     return -1;
          96                 : }  /* _PR_InvalidInt */
          97                 :
          98               0 : PRInt64 _PR_InvalidInt64(void)
          99                 : {
         100                 :     PRInt64 rv;
         101               0 :     LL_I2L(rv, -1);
         102               0 :     PR_ASSERT(!"I/O method is invalid");
         103               0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
         104               0 :     return rv;
         105                 : }  /* _PR_InvalidInt */
         106                 :
         107                 : /*
         108                 :  * An invalid method that returns PRStatus
         109                 :  */
         110                 :
         111               0 : PRStatus _PR_InvalidStatus(void)
         112                 : {
         113               0 :     PR_ASSERT(!"I/O method is invalid");
         114               0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
         115               0 :     return PR_FAILURE;
         116                 : }  /* _PR_InvalidDesc */
         117                 :
         118                 : /*
         119                 :  * An invalid method that returns a pointer
         120                 :  */
         121                 :
         122               0 : PRFileDesc *_PR_InvalidDesc(void)
         123                 : {
         124               0 :     PR_ASSERT(!"I/O method is invalid");
         125               0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
         126               0 :     return NULL;
         127                 : }  /* _PR_InvalidDesc */
         128                 :
         129               0 : PR_IMPLEMENT(PRDescType) PR_GetDescType(PRFileDesc *file)
         130                 : {
         131               0 :     return file->methods->file_type;
         132                 : }
         133                 :
         134               0 : PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd)
         135                 : {
         136               0 :     return (fd->methods->close)(fd);
         137                 : }
         138                 :
         139               0 : PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
         140                 : {
         141               0 :         return((fd->methods->read)(fd,buf,amount));
         142                 : }
         143                 :
         144               0 : PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
         145                 : {
         146               0 :         return((fd->methods->write)(fd,buf,amount));
         147                 : }
         148                 :
         149               0 : PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
         150                 : {
         151               0 :         return((fd->methods->seek)(fd, offset, whence));
         152                 : }
         153                 :
         154               0 : PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
         155                 : {
         156               0 :         return((fd->methods->seek64)(fd, offset, whence));
         157                 : }
         158                 :
         159               0 : PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd)
         160                 : {
         161               0 :         return((fd->methods->available)(fd));
         162                 : }
         163                 :
         164               0 : PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd)
         165                 : {
         166               0 :         return((fd->methods->available64)(fd));
         167                 : }
         168                 :
         169               0 : PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info)
         170                 : {
         171               0 :         return((fd->methods->fileInfo)(fd, info));
         172                 : }
         173                 :
         174               0 : PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
         175                 : {
         176               0 :         return((fd->methods->fileInfo64)(fd, info));
         177                 : }
         178                 :
         179               0 : PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd)
         180                 : {
         181               0 :         return((fd->methods->fsync)(fd));
         182                 : }
         183                 :
         184               0 : PR_IMPLEMENT(PRStatus) PR_Connect(
         185                 :     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
         186                 : {
         187               0 :         return((fd->methods->connect)(fd,addr,timeout));
         188                 : }
         189                 :
         190               0 : PR_IMPLEMENT(PRStatus) PR_ConnectContinue(
         191                 :     PRFileDesc *fd, PRInt16 out_flags)
         192                 : {
         193               0 :         return((fd->methods->connectcontinue)(fd,out_flags));
         194                 : }
         195                 :
         196               0 : PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr,
         197                 : PRIntervalTime timeout)
         198                 : {
         199               0 :         return((fd->methods->accept)(fd,addr,timeout));
         200                 : }
         201                 :
         202               0 : PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr)
         203                 : {
         204               0 :         return((fd->methods->bind)(fd,addr));
         205                 : }
         206                 :
         207               0 : PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
         208                 : {
         209               0 :         return((fd->methods->shutdown)(fd,how));
         210                 : }
         211                 :
         212               0 : PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog)
         213                 : {
         214               0 :         return((fd->methods->listen)(fd,backlog));
         215                 : }
         216                 :
         217               0 : PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,
         218                 : PRIntn flags, PRIntervalTime timeout)
         219                 : {
         220               0 :         return((fd->methods->recv)(fd,buf,amount,flags,timeout));
         221                 : }
         222                 :
         223               0 : PR_IMPLEMENT(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount,
         224                 : PRIntn flags, PRIntervalTime timeout)
         225                 : {
         226               0 :         return((fd->methods->send)(fd,buf,amount,flags,timeout));
         227                 : }
         228                 :
         229               0 : PR_IMPLEMENT(PRInt32) PR_Writev(PRFileDesc *fd, const PRIOVec *iov,
         230                 : PRInt32 iov_size, PRIntervalTime timeout)
         231                 : {
         232               0 :     if (iov_size > PR_MAX_IOVECTOR_SIZE)
         233                 :     {
         234               0 :         PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
         235               0 :         return -1;
         236                 :     }
         237               0 :         return((fd->methods->writev)(fd,iov,iov_size,timeout));
         238                 : }
         239                 :
         240               0 : PR_IMPLEMENT(PRInt32) PR_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
         241                 : PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
         242                 : {
         243               0 :         return((fd->methods->recvfrom)(fd,buf,amount,flags,addr,timeout));
         244                 : }
         245                 :
         246               0 : PR_IMPLEMENT(PRInt32) PR_SendTo(
         247                 :     PRFileDesc *fd, const void *buf, PRInt32 amount,
         248                 :     PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
         249                 : {
         250               0 :         return((fd->methods->sendto)(fd,buf,amount,flags,addr,timeout));
         251                 : }
         252                 :
         253               0 : PR_IMPLEMENT(PRInt32) PR_TransmitFile(
         254                 :     PRFileDesc *sd, PRFileDesc *fd, const void *hdr, PRInt32 hlen,
         255                 :     PRTransmitFileFlags flags, PRIntervalTime timeout)
         256                 : {
         257               0 :         return((sd->methods->transmitfile)(sd,fd,hdr,hlen,flags,timeout));
         258                 : }
         259                 :
         260               0 : PR_IMPLEMENT(PRInt32) PR_AcceptRead(
         261                 :     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
         262                 :     void *buf, PRInt32 amount, PRIntervalTime timeout)
         263                 : {
         264               0 :         return((sd->methods->acceptread)(sd, nd, raddr, buf, amount,timeout));
         265                 : }
         266                 :
         267               0 : PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
         268                 : {
         269               0 :         return((fd->methods->getsockname)(fd,addr));
         270                 : }
         271                 :
         272               0 : PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
         273                 : {
         274               0 :         return((fd->methods->getpeername)(fd,addr));
         275                 : }
         276                 :
         277               0 : PR_IMPLEMENT(PRStatus) PR_GetSocketOption(
         278                 :     PRFileDesc *fd, PRSocketOptionData *data)
         279                 : {
         280               0 :         return((fd->methods->getsocketoption)(fd, data));
         281                 : }
         282                 :
         283               0 : PR_IMPLEMENT(PRStatus) PR_SetSocketOption(
         284                 :     PRFileDesc *fd, const PRSocketOptionData *data)
         285                 : {
         286               0 :         return((fd->methods->setsocketoption)(fd, data));
         287                 : }
         288                 :
         289               0 : PR_IMPLEMENT(PRInt32) PR_SendFile(
         290                 :         PRFileDesc *sd, PRSendFileData *sfd,
         291                 :         PRTransmitFileFlags flags, PRIntervalTime timeout)
         292                 : {
         293               0 :         return((sd->methods->sendfile)(sd,sfd,flags,timeout));
         294                 : }
         295                 :
         296               0 : PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead(
         297                 :     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
         298                 :     void *buf, PRInt32 amount, PRIntervalTime timeout)
         299                 : {
         300               0 :     PRInt32 rv = -1;
         301                 :     PRNetAddr remote;
         302               0 :     PRFileDesc *accepted = NULL;
         303                 :
         304                 :     /*
         305                 :     ** The timeout does not apply to the accept portion of the
         306                 :     ** operation - it waits indefinitely.
         307                 :     */
         308               0 :     accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT);
         309               0 :     if (NULL == accepted) return rv;
         310                 :
         311               0 :     rv = PR_Recv(accepted, buf, amount, 0, timeout);
         312               0 :     if (rv >= 0)
         313                 :     {
         314                 :         /* copy the new info out where caller can see it */
         315                 : #define AMASK ((PRPtrdiff)7)  /* mask for alignment of PRNetAddr */
         316               0 :         PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK;
         317               0 :         *raddr = (PRNetAddr*)(aligned & ~AMASK);
         318               0 :         memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote));
         319               0 :         *nd = accepted;
         320               0 :         return rv;
         321                 :     }
         322                 :
         323               0 :     PR_Close(accepted);
         324               0 :     return rv;
         325                 : }
         326                 :
         327                 : /*
         328                 :  * PR_EmulateSendFile
         329                 :  *
         330                 :  *    Send file sfd->fd across socket sd. If header/trailer are specified
         331                 :  *    they are sent before and after the file, respectively.
         332                 :  *
         333                 :  *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
         334                 :  *
         335                 :  *    return number of bytes sent or -1 on error
         336                 :  *
         337                 :  */
         338                 :
         339                 : #if defined(XP_UNIX) || defined(WIN32)
         340                 :
         341                 : /*
         342                 :  * An implementation based on memory-mapped files
         343                 :  */
         344                 :
         345                 : #define SENDFILE_MMAP_CHUNK     (256 * 1024)
         346                 :
         347               0 : PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
         348                 :     PRFileDesc *sd, PRSendFileData *sfd,
         349                 :     PRTransmitFileFlags flags, PRIntervalTime timeout)
         350                 : {
         351               0 :     PRInt32 rv, count = 0;
         352               0 :     PRInt32 len, file_bytes, index = 0;
         353                 :     PRFileInfo info;
         354                 :     PRIOVec iov[3];
         355               0 :     PRFileMap *mapHandle = NULL;
         356               0 :     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               0 :     if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) {
         364               0 :         count = -1;
         365               0 :         goto done;
         366                 :     }
         367               0 :     if (sfd->file_nbytes &&
         368               0 :             (info.size < (sfd->file_offset + sfd->file_nbytes))) {
         369                 :         /*
         370                 :          * there are fewer bytes in file to send than specified
         371                 :          */
         372               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
         373               0 :         count = -1;
         374               0 :         goto done;
         375                 :     }
         376               0 :     if (sfd->file_nbytes)
         377               0 :         file_bytes = sfd->file_nbytes;
         378                 :     else
         379               0 :         file_bytes = info.size - sfd->file_offset;
         380                 :
         381               0 :     alignment = PR_GetMemMapAlignment();
         382                 :
         383                 :     /* number of initial bytes to skip in mmap'd segment */
         384               0 :     addr_offset = sfd->file_offset % alignment;
         385                 :
         386                 :     /* find previous mmap alignment boundary */
         387               0 :     file_mmap_offset = sfd->file_offset - addr_offset;
         388                 :
         389                 :     /*
         390                 :      * If the file is large, mmap and send the file in chunks so as
         391                 :      * to not consume too much virtual address space
         392                 :      */
         393               0 :     mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK);
         394               0 :     len = mmap_len - addr_offset;
         395                 :
         396                 :     /*
         397                 :      * Map in (part of) file. Take care of zero-length files.
         398                 :      */
         399               0 :     if (len) {
         400               0 :         LL_I2L(zero64, 0);
         401               0 :         mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY);
         402               0 :         if (!mapHandle) {
         403               0 :             count = -1;
         404               0 :             goto done;
         405                 :         }
         406               0 :         LL_I2L(file_mmap_offset64, file_mmap_offset);
         407               0 :         addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len);
         408               0 :         if (!addr) {
         409               0 :             count = -1;
         410               0 :             goto done;
         411                 :         }
         412                 :     }
         413                 :     /*
         414                 :      * send headers first, followed by the file
         415                 :      */
         416               0 :     if (sfd->hlen) {
         417               0 :         iov[index].iov_base = (char *) sfd->header;
         418               0 :         iov[index].iov_len = sfd->hlen;
         419               0 :         index++;
         420                 :     }
         421               0 :     if (len) {
         422               0 :         iov[index].iov_base = (char*)addr + addr_offset;
         423               0 :         iov[index].iov_len = len;
         424               0 :         index++;
         425                 :     }
         426               0 :     if ((file_bytes == len) && (sfd->tlen)) {
         427                 :         /*
         428                 :          * all file data is mapped in; send the trailer too
         429                 :          */
         430               0 :         iov[index].iov_base = (char *) sfd->trailer;
         431               0 :         iov[index].iov_len = sfd->tlen;
         432               0 :         index++;
         433                 :     }
         434               0 :     rv = PR_Writev(sd, iov, index, timeout);
         435               0 :     if (len)
         436               0 :         PR_MemUnmap(addr, mmap_len);
         437               0 :     if (rv < 0) {
         438               0 :         count = -1;
         439               0 :         goto done;
         440                 :     }
         441                 :
         442               0 :     PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0));
         443                 :
         444               0 :     file_bytes -= len;
         445               0 :     count += rv;
         446               0 :     if (!file_bytes)    /* header, file and trailer are sent */
         447               0 :         goto done;
         448                 :
         449                 :     /*
         450                 :      * send remaining bytes of the file, if any
         451                 :      */
         452               0 :     len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
         453               0 :     while (len > 0) {
         454                 :         /*
         455                 :          * Map in (part of) file
         456                 :          */
         457               0 :         file_mmap_offset = sfd->file_offset + count - sfd->hlen;
         458               0 :         PR_ASSERT((file_mmap_offset % alignment) == 0);
         459                 :
         460               0 :         LL_I2L(file_mmap_offset64, file_mmap_offset);
         461               0 :         addr = PR_MemMap(mapHandle, file_mmap_offset64, len);
         462               0 :         if (!addr) {
         463               0 :             count = -1;
         464               0 :             goto done;
         465                 :         }
         466               0 :         rv = PR_Send(sd, addr, len, 0, timeout);
         467               0 :         PR_MemUnmap(addr, len);
         468               0 :         if (rv < 0) {
         469               0 :             count = -1;
         470               0 :             goto done;
         471                 :         }
         472                 :
         473               0 :         PR_ASSERT(rv == len);
         474               0 :         file_bytes -= rv;
         475               0 :         count += rv;
         476               0 :         len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
         477                 :     }
         478               0 :     PR_ASSERT(0 == file_bytes);
         479               0 :     if (sfd->tlen) {
         480               0 :         rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
         481               0 :         if (rv >= 0) {
         482               0 :             PR_ASSERT(rv == sfd->tlen);
         483               0 :             count += rv;
         484                 :         } else
         485               0 :             count = -1;
         486                 :     }
         487                 : done:
         488               0 :     if (mapHandle)
         489               0 :         PR_CloseFileMap(mapHandle);
         490               0 :     if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
         491               0 :         PR_Close(sd);
         492               0 :     return count;
         493                 : }
         494                 :
         495                 : #else
         496                 :
         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 first
         518                 :      */
         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 next
         536                 :      */
         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 specified
         592                 :              */
         593                 :             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
         594                 :             rv = -1;
         595                 :             goto done;
         596                 :         }
         597                 :     }
         598                 :
         599                 :     /*
         600                 :      * send trailer last
         601                 :      */
         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                 : #endif
         627                 :
         628                 : /* priometh.c */

Generated by: LCOV version 1.7