Mercurial > trustbridge > nss-cmake-static
comparison nspr/pr/src/io/priometh.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 PRIntn _PR_InvalidInt(void) | |
53 { | |
54 PR_ASSERT(!"I/O method is invalid"); | |
55 PR_SetError(PR_INVALID_METHOD_ERROR, 0); | |
56 return -1; | |
57 } /* _PR_InvalidInt */ | |
58 | |
59 PRInt16 _PR_InvalidInt16(void) | |
60 { | |
61 PR_ASSERT(!"I/O method is invalid"); | |
62 PR_SetError(PR_INVALID_METHOD_ERROR, 0); | |
63 return -1; | |
64 } /* _PR_InvalidInt */ | |
65 | |
66 PRInt64 _PR_InvalidInt64(void) | |
67 { | |
68 PRInt64 rv; | |
69 LL_I2L(rv, -1); | |
70 PR_ASSERT(!"I/O method is invalid"); | |
71 PR_SetError(PR_INVALID_METHOD_ERROR, 0); | |
72 return rv; | |
73 } /* _PR_InvalidInt */ | |
74 | |
75 /* | |
76 * An invalid method that returns PRStatus | |
77 */ | |
78 | |
79 PRStatus _PR_InvalidStatus(void) | |
80 { | |
81 PR_ASSERT(!"I/O method is invalid"); | |
82 PR_SetError(PR_INVALID_METHOD_ERROR, 0); | |
83 return PR_FAILURE; | |
84 } /* _PR_InvalidDesc */ | |
85 | |
86 /* | |
87 * An invalid method that returns a pointer | |
88 */ | |
89 | |
90 PRFileDesc *_PR_InvalidDesc(void) | |
91 { | |
92 PR_ASSERT(!"I/O method is invalid"); | |
93 PR_SetError(PR_INVALID_METHOD_ERROR, 0); | |
94 return NULL; | |
95 } /* _PR_InvalidDesc */ | |
96 | |
97 PR_IMPLEMENT(PRDescType) PR_GetDescType(PRFileDesc *file) | |
98 { | |
99 return file->methods->file_type; | |
100 } | |
101 | |
102 PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd) | |
103 { | |
104 return (fd->methods->close)(fd); | |
105 } | |
106 | |
107 PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount) | |
108 { | |
109 return((fd->methods->read)(fd,buf,amount)); | |
110 } | |
111 | |
112 PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount) | |
113 { | |
114 return((fd->methods->write)(fd,buf,amount)); | |
115 } | |
116 | |
117 PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) | |
118 { | |
119 return((fd->methods->seek)(fd, offset, whence)); | |
120 } | |
121 | |
122 PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence) | |
123 { | |
124 return((fd->methods->seek64)(fd, offset, whence)); | |
125 } | |
126 | |
127 PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd) | |
128 { | |
129 return((fd->methods->available)(fd)); | |
130 } | |
131 | |
132 PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd) | |
133 { | |
134 return((fd->methods->available64)(fd)); | |
135 } | |
136 | |
137 PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info) | |
138 { | |
139 return((fd->methods->fileInfo)(fd, info)); | |
140 } | |
141 | |
142 PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info) | |
143 { | |
144 return((fd->methods->fileInfo64)(fd, info)); | |
145 } | |
146 | |
147 PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd) | |
148 { | |
149 return((fd->methods->fsync)(fd)); | |
150 } | |
151 | |
152 PR_IMPLEMENT(PRStatus) PR_Connect( | |
153 PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) | |
154 { | |
155 return((fd->methods->connect)(fd,addr,timeout)); | |
156 } | |
157 | |
158 PR_IMPLEMENT(PRStatus) PR_ConnectContinue( | |
159 PRFileDesc *fd, PRInt16 out_flags) | |
160 { | |
161 return((fd->methods->connectcontinue)(fd,out_flags)); | |
162 } | |
163 | |
164 PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr, | |
165 PRIntervalTime timeout) | |
166 { | |
167 return((fd->methods->accept)(fd,addr,timeout)); | |
168 } | |
169 | |
170 PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr) | |
171 { | |
172 return((fd->methods->bind)(fd,addr)); | |
173 } | |
174 | |
175 PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how) | |
176 { | |
177 return((fd->methods->shutdown)(fd,how)); | |
178 } | |
179 | |
180 PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog) | |
181 { | |
182 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 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 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 if (iov_size > PR_MAX_IOVECTOR_SIZE) | |
201 { | |
202 PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); | |
203 return -1; | |
204 } | |
205 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 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 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 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 return((sd->methods->acceptread)(sd, nd, raddr, buf, amount,timeout)); | |
233 } | |
234 | |
235 PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr) | |
236 { | |
237 return((fd->methods->getsockname)(fd,addr)); | |
238 } | |
239 | |
240 PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) | |
241 { | |
242 return((fd->methods->getpeername)(fd,addr)); | |
243 } | |
244 | |
245 PR_IMPLEMENT(PRStatus) PR_GetSocketOption( | |
246 PRFileDesc *fd, PRSocketOptionData *data) | |
247 { | |
248 return((fd->methods->getsocketoption)(fd, data)); | |
249 } | |
250 | |
251 PR_IMPLEMENT(PRStatus) PR_SetSocketOption( | |
252 PRFileDesc *fd, const PRSocketOptionData *data) | |
253 { | |
254 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 return((sd->methods->sendfile)(sd,sfd,flags,timeout)); | |
262 } | |
263 | |
264 PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead( | |
265 PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, | |
266 void *buf, PRInt32 amount, PRIntervalTime timeout) | |
267 { | |
268 PRInt32 rv = -1; | |
269 PRNetAddr remote; | |
270 PRFileDesc *accepted = NULL; | |
271 | |
272 /* | |
273 ** The timeout does not apply to the accept portion of the | |
274 ** operation - it waits indefinitely. | |
275 */ | |
276 accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT); | |
277 if (NULL == accepted) return rv; | |
278 | |
279 rv = PR_Recv(accepted, buf, amount, 0, timeout); | |
280 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 PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK; | |
285 *raddr = (PRNetAddr*)(aligned & ~AMASK); | |
286 memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote)); | |
287 *nd = accepted; | |
288 return rv; | |
289 } | |
290 | |
291 PR_Close(accepted); | |
292 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 PR_IMPLEMENT(PRInt32) PR_EmulateSendFile( | |
316 PRFileDesc *sd, PRSendFileData *sfd, | |
317 PRTransmitFileFlags flags, PRIntervalTime timeout) | |
318 { | |
319 PRInt32 rv, count = 0; | |
320 PRInt32 len, file_bytes, index = 0; | |
321 PRFileInfo info; | |
322 PRIOVec iov[3]; | |
323 PRFileMap *mapHandle = NULL; | |
324 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 if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) { | |
332 count = -1; | |
333 goto done; | |
334 } | |
335 if (sfd->file_nbytes && | |
336 (info.size < (sfd->file_offset + sfd->file_nbytes))) { | |
337 /* | |
338 * there are fewer bytes in file to send than specified | |
339 */ | |
340 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); | |
341 count = -1; | |
342 goto done; | |
343 } | |
344 if (sfd->file_nbytes) | |
345 file_bytes = sfd->file_nbytes; | |
346 else | |
347 file_bytes = info.size - sfd->file_offset; | |
348 | |
349 alignment = PR_GetMemMapAlignment(); | |
350 | |
351 /* number of initial bytes to skip in mmap'd segment */ | |
352 addr_offset = sfd->file_offset % alignment; | |
353 | |
354 /* find previous mmap alignment boundary */ | |
355 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 mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK); | |
362 len = mmap_len - addr_offset; | |
363 | |
364 /* | |
365 * Map in (part of) file. Take care of zero-length files. | |
366 */ | |
367 if (len) { | |
368 LL_I2L(zero64, 0); | |
369 mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY); | |
370 if (!mapHandle) { | |
371 count = -1; | |
372 goto done; | |
373 } | |
374 LL_I2L(file_mmap_offset64, file_mmap_offset); | |
375 addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len); | |
376 if (!addr) { | |
377 count = -1; | |
378 goto done; | |
379 } | |
380 } | |
381 /* | |
382 * send headers first, followed by the file | |
383 */ | |
384 if (sfd->hlen) { | |
385 iov[index].iov_base = (char *) sfd->header; | |
386 iov[index].iov_len = sfd->hlen; | |
387 index++; | |
388 } | |
389 if (len) { | |
390 iov[index].iov_base = (char*)addr + addr_offset; | |
391 iov[index].iov_len = len; | |
392 index++; | |
393 } | |
394 if ((file_bytes == len) && (sfd->tlen)) { | |
395 /* | |
396 * all file data is mapped in; send the trailer too | |
397 */ | |
398 iov[index].iov_base = (char *) sfd->trailer; | |
399 iov[index].iov_len = sfd->tlen; | |
400 index++; | |
401 } | |
402 rv = PR_Writev(sd, iov, index, timeout); | |
403 if (len) | |
404 PR_MemUnmap(addr, mmap_len); | |
405 if (rv < 0) { | |
406 count = -1; | |
407 goto done; | |
408 } | |
409 | |
410 PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0)); | |
411 | |
412 file_bytes -= len; | |
413 count += rv; | |
414 if (!file_bytes) /* header, file and trailer are sent */ | |
415 goto done; | |
416 | |
417 /* | |
418 * send remaining bytes of the file, if any | |
419 */ | |
420 len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK); | |
421 while (len > 0) { | |
422 /* | |
423 * Map in (part of) file | |
424 */ | |
425 file_mmap_offset = sfd->file_offset + count - sfd->hlen; | |
426 PR_ASSERT((file_mmap_offset % alignment) == 0); | |
427 | |
428 LL_I2L(file_mmap_offset64, file_mmap_offset); | |
429 addr = PR_MemMap(mapHandle, file_mmap_offset64, len); | |
430 if (!addr) { | |
431 count = -1; | |
432 goto done; | |
433 } | |
434 rv = PR_Send(sd, addr, len, 0, timeout); | |
435 PR_MemUnmap(addr, len); | |
436 if (rv < 0) { | |
437 count = -1; | |
438 goto done; | |
439 } | |
440 | |
441 PR_ASSERT(rv == len); | |
442 file_bytes -= rv; | |
443 count += rv; | |
444 len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK); | |
445 } | |
446 PR_ASSERT(0 == file_bytes); | |
447 if (sfd->tlen) { | |
448 rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout); | |
449 if (rv >= 0) { | |
450 PR_ASSERT(rv == sfd->tlen); | |
451 count += rv; | |
452 } else | |
453 count = -1; | |
454 } | |
455 done: | |
456 if (mapHandle) | |
457 PR_CloseFileMap(mapHandle); | |
458 if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET)) | |
459 PR_Close(sd); | |
460 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 */ |