LCOV - code coverage report
Current view: top level - nsprpub/pr/src/io - priometh.c (source / functions) Hit Total Coverage
Test: output.info Lines: 15 152 9.9 %
Date: 2017-07-14 16:53:18 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : 
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #include "primpl.h"
       7             : 
       8             : #include <string.h>
       9             : 
      10             : /*****************************************************************************/
      11             : /************************** Invalid I/O method object ************************/
      12             : /*****************************************************************************/
      13             : PRIOMethods _pr_faulty_methods = {
      14             :     (PRDescType)0,
      15             :     (PRCloseFN)_PR_InvalidStatus,
      16             :     (PRReadFN)_PR_InvalidInt,
      17             :     (PRWriteFN)_PR_InvalidInt,
      18             :     (PRAvailableFN)_PR_InvalidInt,
      19             :     (PRAvailable64FN)_PR_InvalidInt64,
      20             :     (PRFsyncFN)_PR_InvalidStatus,
      21             :     (PRSeekFN)_PR_InvalidInt,
      22             :     (PRSeek64FN)_PR_InvalidInt64,
      23             :     (PRFileInfoFN)_PR_InvalidStatus,
      24             :     (PRFileInfo64FN)_PR_InvalidStatus,
      25             :     (PRWritevFN)_PR_InvalidInt,        
      26             :     (PRConnectFN)_PR_InvalidStatus,        
      27             :     (PRAcceptFN)_PR_InvalidDesc,        
      28             :     (PRBindFN)_PR_InvalidStatus,        
      29             :     (PRListenFN)_PR_InvalidStatus,        
      30             :     (PRShutdownFN)_PR_InvalidStatus,    
      31             :     (PRRecvFN)_PR_InvalidInt,        
      32             :     (PRSendFN)_PR_InvalidInt,        
      33             :     (PRRecvfromFN)_PR_InvalidInt,    
      34             :     (PRSendtoFN)_PR_InvalidInt,        
      35             :     (PRPollFN)_PR_InvalidInt16,
      36             :     (PRAcceptreadFN)_PR_InvalidInt,   
      37             :     (PRTransmitfileFN)_PR_InvalidInt, 
      38             :     (PRGetsocknameFN)_PR_InvalidStatus,    
      39             :     (PRGetpeernameFN)_PR_InvalidStatus,    
      40             :     (PRReservedFN)_PR_InvalidInt,    
      41             :     (PRReservedFN)_PR_InvalidInt,    
      42             :     (PRGetsocketoptionFN)_PR_InvalidStatus,
      43             :     (PRSetsocketoptionFN)_PR_InvalidStatus,
      44             :     (PRSendfileFN)_PR_InvalidInt, 
      45             :     (PRConnectcontinueFN)_PR_InvalidStatus,
      46             :     (PRReservedFN)_PR_InvalidInt,
      47             :     (PRReservedFN)_PR_InvalidInt,
      48             :     (PRReservedFN)_PR_InvalidInt,
      49             :     (PRReservedFN)_PR_InvalidInt
      50             : };
      51             : 
      52           0 : PRIntn _PR_InvalidInt(void)
      53             : {
      54           0 :     PR_NOT_REACHED("I/O method is invalid");
      55           0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
      56           0 :     return -1;
      57             : }  /* _PR_InvalidInt */
      58             : 
      59           0 : PRInt16 _PR_InvalidInt16(void)
      60             : {
      61           0 :     PR_NOT_REACHED("I/O method is invalid");
      62           0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
      63           0 :     return -1;
      64             : }  /* _PR_InvalidInt */
      65             : 
      66           0 : PRInt64 _PR_InvalidInt64(void)
      67             : {
      68             :     PRInt64 rv;
      69           0 :     LL_I2L(rv, -1);
      70           0 :     PR_NOT_REACHED("I/O method is invalid");
      71           0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
      72           0 :     return rv;
      73             : }  /* _PR_InvalidInt */
      74             : 
      75             : /*
      76             :  * An invalid method that returns PRStatus
      77             :  */
      78             : 
      79           0 : PRStatus _PR_InvalidStatus(void)
      80             : {
      81           0 :     PR_NOT_REACHED("I/O method is invalid");
      82           0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
      83           0 :     return PR_FAILURE;
      84             : }  /* _PR_InvalidDesc */
      85             : 
      86             : /*
      87             :  * An invalid method that returns a pointer
      88             :  */
      89             : 
      90           0 : PRFileDesc *_PR_InvalidDesc(void)
      91             : {
      92           0 :     PR_NOT_REACHED("I/O method is invalid");
      93           0 :     PR_SetError(PR_INVALID_METHOD_ERROR, 0);
      94           0 :     return NULL;
      95             : }  /* _PR_InvalidDesc */
      96             : 
      97             : PR_IMPLEMENT(PRDescType) PR_GetDescType(PRFileDesc *file)
      98             : {
      99           0 :     return file->methods->file_type;
     100             : }
     101             : 
     102             : PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd)
     103             : {
     104        1256 :     return (fd->methods->close)(fd);
     105             : }
     106             : 
     107             : PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
     108             : {
     109        1296 :         return((fd->methods->read)(fd,buf,amount));
     110             : }
     111             : 
     112             : PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
     113             : {
     114         159 :         return((fd->methods->write)(fd,buf,amount));
     115             : }
     116             : 
     117             : PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
     118             : {
     119           2 :         return((fd->methods->seek)(fd, offset, whence));
     120             : }
     121             : 
     122             : PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
     123             : {
     124          11 :         return((fd->methods->seek64)(fd, offset, whence));
     125             : }
     126             : 
     127             : PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd)
     128             : {
     129           3 :         return((fd->methods->available)(fd));
     130             : }
     131             : 
     132             : PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd)
     133             : {
     134         134 :         return((fd->methods->available64)(fd));
     135             : }
     136             : 
     137             : PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info)
     138             : {
     139           1 :         return((fd->methods->fileInfo)(fd, info));
     140             : }
     141             : 
     142             : PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
     143             : {
     144         941 :         return((fd->methods->fileInfo64)(fd, info));
     145             : }
     146             : 
     147             : PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd)
     148             : {
     149           6 :         return((fd->methods->fsync)(fd));
     150             : }
     151             : 
     152             : PR_IMPLEMENT(PRStatus) PR_Connect(
     153             :     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
     154             : {
     155           3 :         return((fd->methods->connect)(fd,addr,timeout));
     156             : }
     157             : 
     158             : PR_IMPLEMENT(PRStatus) PR_ConnectContinue(
     159             :     PRFileDesc *fd, PRInt16 out_flags)
     160             : {
     161           3 :         return((fd->methods->connectcontinue)(fd,out_flags));
     162             : }
     163             : 
     164             : PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr,
     165             : PRIntervalTime timeout)
     166             : {
     167           0 :         return((fd->methods->accept)(fd,addr,timeout));
     168             : }
     169             : 
     170             : PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr)
     171             : {
     172           0 :         return((fd->methods->bind)(fd,addr));
     173             : }
     174             : 
     175             : PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
     176             : {
     177           0 :         return((fd->methods->shutdown)(fd,how));
     178             : }
     179             : 
     180             : PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog)
     181             : {
     182           0 :         return((fd->methods->listen)(fd,backlog));
     183             : }
     184             : 
     185             : PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,
     186             : PRIntn flags, PRIntervalTime timeout)
     187             : {
     188           1 :         return((fd->methods->recv)(fd,buf,amount,flags,timeout));
     189             : }
     190             : 
     191             : PR_IMPLEMENT(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount,
     192             : PRIntn flags, PRIntervalTime timeout)
     193             : {
     194           0 :         return((fd->methods->send)(fd,buf,amount,flags,timeout));
     195             : }
     196             : 
     197             : PR_IMPLEMENT(PRInt32) PR_Writev(PRFileDesc *fd, const PRIOVec *iov,
     198             : PRInt32 iov_size, PRIntervalTime timeout)
     199             : {
     200           0 :     if (iov_size > PR_MAX_IOVECTOR_SIZE)
     201             :     {
     202           0 :         PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
     203           0 :         return -1;
     204             :     }
     205           0 :         return((fd->methods->writev)(fd,iov,iov_size,timeout));
     206             : }
     207             : 
     208             : PR_IMPLEMENT(PRInt32) PR_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
     209             : PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
     210             : {
     211           0 :         return((fd->methods->recvfrom)(fd,buf,amount,flags,addr,timeout));
     212             : }
     213             : 
     214             : PR_IMPLEMENT(PRInt32) PR_SendTo(
     215             :     PRFileDesc *fd, const void *buf, PRInt32 amount,
     216             :     PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
     217             : {
     218           0 :         return((fd->methods->sendto)(fd,buf,amount,flags,addr,timeout));
     219             : }
     220             : 
     221             : PR_IMPLEMENT(PRInt32) PR_TransmitFile(
     222             :     PRFileDesc *sd, PRFileDesc *fd, const void *hdr, PRInt32 hlen,
     223             :     PRTransmitFileFlags flags, PRIntervalTime timeout)
     224             : {
     225           0 :         return((sd->methods->transmitfile)(sd,fd,hdr,hlen,flags,timeout));
     226             : }
     227             : 
     228             : PR_IMPLEMENT(PRInt32) PR_AcceptRead(
     229             :     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
     230             :     void *buf, PRInt32 amount, PRIntervalTime timeout)
     231             : {
     232           0 :         return((sd->methods->acceptread)(sd, nd, raddr, buf, amount,timeout));
     233             : }
     234             : 
     235             : PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
     236             : {
     237           3 :         return((fd->methods->getsockname)(fd,addr));
     238             : }
     239             : 
     240             : PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
     241             : {
     242           0 :         return((fd->methods->getpeername)(fd,addr));
     243             : }
     244             : 
     245             : PR_IMPLEMENT(PRStatus) PR_GetSocketOption(
     246             :     PRFileDesc *fd, PRSocketOptionData *data)
     247             : {
     248           0 :         return((fd->methods->getsocketoption)(fd, data));
     249             : }
     250             : 
     251             : PR_IMPLEMENT(PRStatus) PR_SetSocketOption(
     252             :     PRFileDesc *fd, const PRSocketOptionData *data)
     253             : {
     254          11 :         return((fd->methods->setsocketoption)(fd, data));
     255             : }
     256             : 
     257             : PR_IMPLEMENT(PRInt32) PR_SendFile(
     258             :         PRFileDesc *sd, PRSendFileData *sfd,
     259             :         PRTransmitFileFlags flags, PRIntervalTime timeout)
     260             : {
     261           0 :         return((sd->methods->sendfile)(sd,sfd,flags,timeout));
     262             : }
     263             : 
     264           0 : PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead(
     265             :     PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
     266             :     void *buf, PRInt32 amount, PRIntervalTime timeout)
     267             : {
     268           0 :     PRInt32 rv = -1;
     269             :     PRNetAddr remote;
     270           0 :     PRFileDesc *accepted = NULL;
     271             : 
     272             :     /*
     273             :     ** The timeout does not apply to the accept portion of the
     274             :     ** operation - it waits indefinitely.
     275             :     */
     276           0 :     accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT);
     277           0 :     if (NULL == accepted) return rv;
     278             : 
     279           0 :     rv = PR_Recv(accepted, buf, amount, 0, timeout);
     280           0 :     if (rv >= 0)
     281             :     {
     282             :         /* copy the new info out where caller can see it */
     283             : #define AMASK ((PRPtrdiff)7)  /* mask for alignment of PRNetAddr */
     284           0 :         PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK;
     285           0 :         *raddr = (PRNetAddr*)(aligned & ~AMASK);
     286           0 :         memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote));
     287           0 :         *nd = accepted;
     288           0 :         return rv;
     289             :     }
     290             : 
     291           0 :     PR_Close(accepted);
     292           0 :     return rv;
     293             : }
     294             : 
     295             : /*
     296             :  * PR_EmulateSendFile
     297             :  *
     298             :  *    Send file sfd->fd across socket sd. If header/trailer are specified
     299             :  *    they are sent before and after the file, respectively.
     300             :  *
     301             :  *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
     302             :  *    
     303             :  *    return number of bytes sent or -1 on error
     304             :  *
     305             :  */
     306             : 
     307             : #if defined(XP_UNIX) || defined(WIN32)
     308             : 
     309             : /*
     310             :  * An implementation based on memory-mapped files
     311             :  */
     312             : 
     313             : #define SENDFILE_MMAP_CHUNK     (256 * 1024)
     314             : 
     315           0 : PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
     316             :     PRFileDesc *sd, PRSendFileData *sfd,
     317             :     PRTransmitFileFlags flags, PRIntervalTime timeout)
     318             : {
     319           0 :     PRInt32 rv, count = 0;
     320           0 :     PRInt32 len, file_bytes, index = 0;
     321             :     PRFileInfo info;
     322             :     PRIOVec iov[3];
     323           0 :     PRFileMap *mapHandle = NULL;
     324           0 :     void *addr = (void*)0; /* initialized to some arbitrary value. Keeps compiler warnings down. */
     325             :     PRUint32 file_mmap_offset, alignment;
     326             :     PRInt64 zero64;
     327             :     PROffset64 file_mmap_offset64;
     328             :     PRUint32 addr_offset, mmap_len;
     329             : 
     330             :     /* Get file size */
     331           0 :     if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) {
     332           0 :         count = -1;
     333           0 :         goto done;
     334             :     }
     335           0 :     if (sfd->file_nbytes &&
     336           0 :             (info.size < (sfd->file_offset + sfd->file_nbytes))) {
     337             :         /*
     338             :          * there are fewer bytes in file to send than specified
     339             :          */
     340           0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     341           0 :         count = -1;
     342           0 :         goto done;
     343             :     }
     344           0 :     if (sfd->file_nbytes)
     345           0 :         file_bytes = sfd->file_nbytes;
     346             :     else
     347           0 :         file_bytes = info.size - sfd->file_offset;
     348             : 
     349           0 :     alignment = PR_GetMemMapAlignment();
     350             : 
     351             :     /* number of initial bytes to skip in mmap'd segment */
     352           0 :     addr_offset = sfd->file_offset % alignment;
     353             : 
     354             :     /* find previous mmap alignment boundary */
     355           0 :     file_mmap_offset = sfd->file_offset - addr_offset;
     356             : 
     357             :     /*
     358             :      * If the file is large, mmap and send the file in chunks so as
     359             :      * to not consume too much virtual address space
     360             :      */
     361           0 :     mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK);
     362           0 :     len = mmap_len - addr_offset;
     363             : 
     364             :     /*
     365             :      * Map in (part of) file. Take care of zero-length files.
     366             :      */
     367           0 :     if (len) {
     368           0 :         LL_I2L(zero64, 0);
     369           0 :         mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY);
     370           0 :         if (!mapHandle) {
     371           0 :             count = -1;
     372           0 :             goto done;
     373             :         }
     374           0 :         LL_I2L(file_mmap_offset64, file_mmap_offset);
     375           0 :         addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len);
     376           0 :         if (!addr) {
     377           0 :             count = -1;
     378           0 :             goto done;
     379             :         }
     380             :     }
     381             :     /*
     382             :      * send headers first, followed by the file
     383             :      */
     384           0 :     if (sfd->hlen) {
     385           0 :         iov[index].iov_base = (char *) sfd->header;
     386           0 :         iov[index].iov_len = sfd->hlen;
     387           0 :         index++;
     388             :     }
     389           0 :     if (len) {
     390           0 :         iov[index].iov_base = (char*)addr + addr_offset;
     391           0 :         iov[index].iov_len = len;
     392           0 :         index++;
     393             :     }
     394           0 :     if ((file_bytes == len) && (sfd->tlen)) {
     395             :         /*
     396             :          * all file data is mapped in; send the trailer too
     397             :          */
     398           0 :         iov[index].iov_base = (char *) sfd->trailer;
     399           0 :         iov[index].iov_len = sfd->tlen;
     400           0 :         index++;
     401             :     }
     402           0 :     rv = PR_Writev(sd, iov, index, timeout);
     403           0 :     if (len)
     404           0 :         PR_MemUnmap(addr, mmap_len);
     405           0 :     if (rv < 0) {
     406           0 :         count = -1;
     407           0 :         goto done;
     408             :     }
     409             : 
     410           0 :     PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0));
     411             : 
     412           0 :     file_bytes -= len;
     413           0 :     count += rv;
     414           0 :     if (!file_bytes)    /* header, file and trailer are sent */
     415           0 :         goto done;
     416             : 
     417             :     /*
     418             :      * send remaining bytes of the file, if any
     419             :      */
     420           0 :     len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
     421           0 :     while (len > 0) {
     422             :         /*
     423             :          * Map in (part of) file
     424             :          */
     425           0 :         file_mmap_offset = sfd->file_offset + count - sfd->hlen;
     426           0 :         PR_ASSERT((file_mmap_offset % alignment) == 0);
     427             : 
     428           0 :         LL_I2L(file_mmap_offset64, file_mmap_offset);
     429           0 :         addr = PR_MemMap(mapHandle, file_mmap_offset64, len);
     430           0 :         if (!addr) {
     431           0 :             count = -1;
     432           0 :             goto done;
     433             :         }
     434           0 :         rv = PR_Send(sd, addr, len, 0, timeout);
     435           0 :         PR_MemUnmap(addr, len);
     436           0 :         if (rv < 0) {
     437           0 :             count = -1;
     438           0 :             goto done;
     439             :         }
     440             : 
     441           0 :         PR_ASSERT(rv == len);
     442           0 :         file_bytes -= rv;
     443           0 :         count += rv;
     444           0 :         len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
     445             :     }
     446           0 :     PR_ASSERT(0 == file_bytes);
     447           0 :     if (sfd->tlen) {
     448           0 :         rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
     449           0 :         if (rv >= 0) {
     450           0 :             PR_ASSERT(rv == sfd->tlen);
     451           0 :             count += rv;
     452             :         } else
     453           0 :             count = -1;
     454             :     }
     455             : done:
     456           0 :     if (mapHandle)
     457           0 :         PR_CloseFileMap(mapHandle);
     458           0 :     if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
     459           0 :         PR_Close(sd);
     460           0 :     return count;
     461             : }
     462             : 
     463             : #else
     464             : 
     465             : PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
     466             :     PRFileDesc *sd, PRSendFileData *sfd,
     467             :     PRTransmitFileFlags flags, PRIntervalTime timeout)
     468             : {
     469             :     PRInt32 rv, count = 0;
     470             :     PRInt32 rlen;
     471             :     const void * buffer;
     472             :     PRInt32 buflen;
     473             :     PRInt32 sendbytes, readbytes;
     474             :     char *buf;
     475             : 
     476             : #define _SENDFILE_BUFSIZE   (16 * 1024)
     477             : 
     478             :     buf = (char*)PR_MALLOC(_SENDFILE_BUFSIZE);
     479             :     if (buf == NULL) {
     480             :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     481             :         return -1;
     482             :     }
     483             : 
     484             :     /*
     485             :      * send header first
     486             :      */
     487             :     buflen = sfd->hlen;
     488             :     buffer = sfd->header;
     489             :     while (buflen) {
     490             :         rv = PR_Send(sd, buffer, buflen, 0, timeout);
     491             :         if (rv < 0) {
     492             :             /* PR_Send() has invoked PR_SetError(). */
     493             :             rv = -1;
     494             :             goto done;
     495             :         } else {
     496             :             count += rv;
     497             :             buffer = (const void*) ((const char*)buffer + rv);
     498             :             buflen -= rv;
     499             :         }
     500             :     }
     501             : 
     502             :     /*
     503             :      * send file next
     504             :      */
     505             :     if (PR_Seek(sfd->fd, sfd->file_offset, PR_SEEK_SET) < 0) {
     506             :         rv = -1;
     507             :         goto done;
     508             :     }
     509             :     sendbytes = sfd->file_nbytes;
     510             :     if (sendbytes == 0) {
     511             :         /* send entire file */
     512             :         while ((rlen = PR_Read(sfd->fd, buf, _SENDFILE_BUFSIZE)) > 0) {
     513             :             while (rlen) {
     514             :                 char *bufptr = buf;
     515             : 
     516             :                 rv =  PR_Send(sd, bufptr, rlen, 0, timeout);
     517             :                 if (rv < 0) {
     518             :                     /* PR_Send() has invoked PR_SetError(). */
     519             :                     rv = -1;
     520             :                     goto done;
     521             :                 } else {
     522             :                     count += rv;
     523             :                     bufptr = ((char*)bufptr + rv);
     524             :                     rlen -= rv;
     525             :                 }
     526             :             }
     527             :         }
     528             :         if (rlen < 0) {
     529             :             /* PR_Read() has invoked PR_SetError(). */
     530             :             rv = -1;
     531             :             goto done;
     532             :         }
     533             :     } else {
     534             :         readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);
     535             :         while (readbytes && ((rlen = PR_Read(sfd->fd, buf, readbytes)) > 0)) {
     536             :             while (rlen) {
     537             :                 char *bufptr = buf;
     538             : 
     539             :                 rv =  PR_Send(sd, bufptr, rlen, 0, timeout);
     540             :                 if (rv < 0) {
     541             :                     /* PR_Send() has invoked PR_SetError(). */
     542             :                     rv = -1;
     543             :                     goto done;
     544             :                 } else {
     545             :                     count += rv;
     546             :                     sendbytes -= rv;
     547             :                     bufptr = ((char*)bufptr + rv);
     548             :                     rlen -= rv;
     549             :                 }
     550             :             }
     551             :             readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);
     552             :         }
     553             :         if (rlen < 0) {
     554             :             /* PR_Read() has invoked PR_SetError(). */
     555             :             rv = -1;
     556             :             goto done;
     557             :         } else if (sendbytes != 0) {
     558             :             /*
     559             :              * there are fewer bytes in file to send than specified
     560             :              */
     561             :             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     562             :             rv = -1;
     563             :             goto done;
     564             :         }
     565             :     }
     566             : 
     567             :     /*
     568             :      * send trailer last
     569             :      */
     570             :     buflen = sfd->tlen;
     571             :     buffer = sfd->trailer;
     572             :     while (buflen) {
     573             :         rv =  PR_Send(sd, buffer, buflen, 0, timeout);
     574             :         if (rv < 0) {
     575             :             /* PR_Send() has invoked PR_SetError(). */
     576             :             rv = -1;
     577             :             goto done;
     578             :         } else {
     579             :             count += rv;
     580             :             buffer = (const void*) ((const char*)buffer + rv);
     581             :             buflen -= rv;
     582             :         }
     583             :     }
     584             :     rv = count;
     585             : 
     586             : done:
     587             :     if (buf)
     588             :         PR_DELETE(buf);
     589             :     if ((rv >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
     590             :         PR_Close(sd);
     591             :     return rv;
     592             : }
     593             : 
     594             : #endif
     595             : 
     596             : /* priometh.c */

Generated by: LCOV version 1.13