LCOV - code coverage report
Current view: directory - nsprpub/pr/src/io - priometh.c (source / functions) Found Hit Coverage
Test: app.info Lines: 181 38 21.0 %
Date: 2012-06-02 Functions: 36 19 52.8 %

       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          371086 : PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd)
     135                 : {
     136          371086 :     return (fd->methods->close)(fd);
     137                 : }
     138                 : 
     139          422216 : PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
     140                 : {
     141          422216 :         return((fd->methods->read)(fd,buf,amount));
     142                 : }
     143                 : 
     144          530827 : PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
     145                 : {
     146          530827 :         return((fd->methods->write)(fd,buf,amount));
     147                 : }
     148                 : 
     149            3068 : PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
     150                 : {
     151            3068 :         return((fd->methods->seek)(fd, offset, whence));
     152                 : }
     153                 : 
     154           10233 : PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
     155                 : {
     156           10233 :         return((fd->methods->seek64)(fd, offset, whence));
     157                 : }
     158                 : 
     159             995 : PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd)
     160                 : {
     161             995 :         return((fd->methods->available)(fd));
     162                 : }
     163                 : 
     164           17984 : PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd)
     165                 : {
     166           17984 :         return((fd->methods->available64)(fd));
     167                 : }
     168                 : 
     169           13740 : PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info)
     170                 : {
     171           13740 :         return((fd->methods->fileInfo)(fd, info));
     172                 : }
     173                 : 
     174          317573 : PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
     175                 : {
     176          317573 :         return((fd->methods->fileInfo64)(fd, info));
     177                 : }
     178                 : 
     179            1839 : PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd)
     180                 : {
     181            1839 :         return((fd->methods->fsync)(fd));
     182                 : }
     183                 : 
     184            3006 : PR_IMPLEMENT(PRStatus) PR_Connect(
     185                 :     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
     186                 : {
     187            3006 :         return((fd->methods->connect)(fd,addr,timeout));
     188                 : }
     189                 : 
     190            3006 : PR_IMPLEMENT(PRStatus) PR_ConnectContinue(
     191                 :     PRFileDesc *fd, PRInt16 out_flags)
     192                 : {
     193            3006 :         return((fd->methods->connectcontinue)(fd,out_flags));
     194                 : }
     195                 : 
     196            2870 : PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr,
     197                 : PRIntervalTime timeout)
     198                 : {
     199            2870 :         return((fd->methods->accept)(fd,addr,timeout));
     200                 : }
     201                 : 
     202             421 : PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr)
     203                 : {
     204             421 :         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             420 : PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog)
     213                 : {
     214             420 :         return((fd->methods->listen)(fd,backlog));
     215                 : }
     216                 : 
     217              10 : PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,
     218                 : PRIntn flags, PRIntervalTime timeout)
     219                 : {
     220              10 :         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            3350 : PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
     268                 : {
     269            3350 :         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              16 : PR_IMPLEMENT(PRStatus) PR_GetSocketOption(
     278                 :     PRFileDesc *fd, PRSocketOptionData *data)
     279                 : {
     280              16 :         return((fd->methods->getsocketoption)(fd, data));
     281                 : }
     282                 : 
     283            9724 : PR_IMPLEMENT(PRStatus) PR_SetSocketOption(
     284                 :     PRFileDesc *fd, const PRSocketOptionData *data)
     285                 : {
     286            9724 :         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