1 // Copyright (c) 1999-2018 David Muse
2 // See the COPYING file for more information
3
4 //#define DEBUG_PASSFD 1
5 //#define DEBUG_WRITE 1
6 //#define DEBUG_READ 1
7 //#define DEBUG_BUFFERING 1
8
9 #if defined(DEBUG_PASSFD) || defined(DEBUG_WRITE) || \
10 defined(DEBUG_READ) || defined(DEBUG_BUFFERING)
11 #ifdef _MSC_VER
12 #define debugPrintf(ARGS,...) if (this!=&stdoutput) { stdoutput.printf(ARGS,__VA_ARGS__); }
13 #else
14 #define debugPrintf(ARGS...) if (this!=&stdoutput) { stdoutput.printf(ARGS); }
15 #endif
16 #define debugSafePrint(string) if (this!=&stdoutput) { stdoutput.safePrint(string); }
17 #endif
18
19 #include <rudiments/filedescriptor.h>
20 #include <rudiments/listener.h>
21 #include <rudiments/charstring.h>
22 #include <rudiments/character.h>
23 #include <rudiments/bytestring.h>
24 #include <rudiments/stringbuffer.h>
25 #include <rudiments/security.h>
26 #if defined(DEBUG_PASSFD) || defined(DEBUG_WRITE) || \
27 defined(DEBUG_READ) || defined(RUDIMENTS_HAVE_DUPLICATEHANDLE)
28 #include <rudiments/process.h>
29 #endif
30 #include <rudiments/thread.h>
31 #include <rudiments/semaphoreset.h>
32 #include <rudiments/file.h>
33 #include <rudiments/permissions.h>
34 #include <rudiments/error.h>
35 #include <rudiments/stdio.h>
36
37 #include <rudiments/private/winsock.h>
38
39 #ifdef RUDIMENTS_HAVE_IO_H
40 #include <io.h>
41 #endif
42 #ifdef RUDIMENTS_HAVE_SYS_TIME_H
43 #include <sys/time.h>
44 #endif
45 #ifdef RUDIMENTS_HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #ifdef RUDIMENTS_HAVE_FCNTL_H
49 #include <fcntl.h>
50 #endif
51 #ifdef RUDIMENTS_HAVE_SYS_FCNTL_H
52 #include <sys/fcntl.h>
53 #endif
54 #ifdef RUDIMENTS_HAVE_SYS_IOCTL_H
55 #include <sys/ioctl.h>
56 #endif
57
58 #include <stdio.h>
59 #if defined(RUDIMENTS_HAVE_VASPRINTF) && defined(RUDIMENTS_HAVE_STDLIB_H)
60 #include <stdlib.h>
61 #endif
62
63 // NOTE: These next two headers must be included in this order or LITTLE_ENDIAN
64 // will be multiply-defined on linux libc4 systems. Other systems are
65 // unaffected.
66 #ifdef RUDIMENTS_HAVE_NETINET_TCP_H
67 // some libc5 systems need this extern "C" wrapper
68 extern "C" {
69 #include <netinet/tcp.h>
70 }
71 #endif
72 #ifdef RUDIMENTS_HAVE_NETINET_IN_H
73 #include <netinet/in.h>
74 #endif
75
76
77 #ifdef RUDIMENTS_HAVE_SYS_UIO_H
78 #include <sys/uio.h>
79 #endif
80 #ifdef RUDIMENTS_HAVE_LIMITS_H
81 #include <limits.h>
82 #endif
83 #ifdef RUDIMENTS_HAVE_ARPA_INET_H
84 #include <arpa/inet.h>
85 #endif
86 #ifdef RUDIMENTS_HAVE_BYTESWAP_H
87 #ifdef RUDIMENTS_HAVE_SAFE_BYTESWAP_H_AFTER_NETINET_IN_H
88 #include <byteswap.h>
89 #endif
90 #endif
91 #ifdef RUDIMENTS_HAVE_MACHINE_ENDIAN_H
92 #include <machine/endian.h>
93 #endif
94 #ifdef RUDIMENTS_HAVE_OSSWAPHOSTTOLITTLEINT64
95 #include <libkern/OSByteOrder.h>
96 #endif
97 #ifdef RUDIMENTS_HAVE_SYS_BYTEORDER_H
98 #include <sys/byteorder.h>
99 #endif
100 #ifdef RUDIMENTS_HAVE_OS_SUPPORT_BYTEORDER_H
101 #include <os/support/ByteOrder.h>
102 #endif
103
104 // apparently on windows, there are no byte-order macros of any kind
105 #ifdef _WIN32
106 #define __LITTLE_ENDIAN 1234
107 #define __BIG_ENDIAN 4321
108 #define __BYTE_ORDER __LITTLE_ENDIAN
109 #endif
110
111 // On solaris (and probably others), BYTE_ORDER is undefined (even with
112 // underscore prefixes. Either _BIG_ENDIAN or _LITTLE_ENDIAN is
113 // defined, but it's just "defined", not set to any value.
114 #if !defined(__BYTE_ORDER) && \
115 !defined(_BYTE_ORDER) && \
116 !defined(BYTE_ORDER) && \
117 (defined(_BIG_ENDIAN) || defined(_LITTLE_ENDIAN))
118
119 #define __LITTLE_ENDIAN 1234
120 #define __BIG_ENDIAN 4321
121
122 #ifdef _LITTLE_ENDIAN
123 #define __BYTE_ORDER __LITTLE_ENDIAN
124 #else
125 #define __BYTE_ORDER __BIG_ENDIAN
126 #endif
127 #endif
128
129 #ifndef __BYTE_ORDER
130 #if defined(BYTE_ORDER)
131 #define __BYTE_ORDER BYTE_ORDER
132 #elif defined (_BYTE_ORDER)
133 #define __BYTE_ORDER _BYTE_ORDER
134 #endif
135 #endif
136
137 #ifndef __BIG_ENDIAN
138 #if defined(BIG_ENDIAN)
139 #define __BIG_ENDIAN BIG_ENDIAN
140 #elif defined(_BIG_ENDIAN)
141 #define __BIG_ENDIAN _BIG_ENDIAN
142 #endif
143 #endif
144
145 #ifndef __LITTLE_ENDIAN
146 #if defined(LITTLE_ENDIAN)
147 #define __LITTLE_ENDIAN LITTLE_ENDIAN
148 #elif defined(_LITTLE_ENDIAN)
149 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
150 #endif
151 #endif
152
153 // for FD_SET (macro that uses memset) on solaris
154 #ifdef RUDIMENTS_HAVE_STRING_H
155 #include <string.h>
156 #endif
157
158 #ifdef RUDIMENTS_NEED_XNET_PROTOTYPES
159 extern ssize_t __xnet_recvmsg (int, struct msghdr *, int);
160 extern ssize_t __xnet_sendmsg (int, const struct msghdr *, int);
161 #endif
162
163 // some platforms (solaris <= 9) don't have these macros
164 #ifndef CMSG_LEN
165 #ifndef CMSG_ALIGN
166 #define CMSG_ALIGN(len) \
167 (((len) + sizeof(size_t)-1) & \
168 (size_t)~(sizeof(size_t)-1))
169 #endif
170 #define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+(len))
171 #endif
172
173 // SCO OpenServer < 5.0.7 has an error in the sys/socket.h header.
174 // Internally, libc supports accrights/accrightslen but the header defines
175 // the struct as having control/controllen components. This hack works
176 // around the problem.
177 // http://www.linuxmisc.com/9-unix-programmer/af8e2f1e03a2b913.htm
178 #ifdef RUDIMENTS_HAVE_BAD_SCO_MSGHDR
179 #undef RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN
180 #define RUDIMENTS_HAVE_MSGHDR_MSG_ACCRIGHTS 1
181 #define msg_accrights msg_control
182 #define msg_accrightslen msg_controllen
183 #endif
184
185 // if SSIZE_MAX is undefined...
186 #ifndef SSIZE_MAX
187 #if defined(_WIN32)
188 #define SSIZE_MAX LONG_MAX
189 #else
190 // a good safe value that should even work on 16-bit systems
191 #define SSIZE_MAX 16383
192 #endif
193 #endif
194
195 // most platforms FILE struct have a member for the file descriptor,
196 // try to find it...
197 // some platforms, like solaris 11.2 hide it altogether
198 #undef FD
199 #if defined(RUDIMENTS_HAVE_FILE_FILENO)
200 #define FD f->_fileno
201 #elif defined(RUDIMENTS_HAVE_FILE_FILE)
202 #ifdef __VMS
203 #define FD ((struct _iobuf *)f)->_file
204 #else
205 #define FD f->_file
206 #endif
207 #elif defined(RUDIMENTS_HAVE_FILE__FILE)
208 #define FD f->__file
209 #elif defined(RUDIMENTS_HAVE_FILE_FILEDES)
210 #define FD f->__filedes
211 #elif defined(RUDIMENTS_HAVE_FILE__FD)
212 #define FD f->_fd
213 #endif
214
215 #ifdef RUDIMENTS_HAVE_UNDEFINED_SENDMSG
216 extern "C" ssize_t sendmsg(int, const struct msghdr *,int);
217 #endif
218
219 #ifdef RUDIMENTS_HAVE_UNDEFINED_RECVMSG
220 extern "C" ssize_t recvmsg(int, struct msghdr *,int);
221 #endif
222
223 #ifdef RUDIMENTS_HAVE_UNDEFINED_GETPEERNAME
224 extern "C" int getpeername(int, struct sockaddr *,socklen_t *);
225 #endif
226
227 #ifdef RUDIMENTS_HAVE_UNDEFINED_GETSOCKOPT
228 extern "C" int getsockopt(int, int, int, void *, socklen_t *);
229 #endif
230
231 #ifdef RUDIMENTS_HAVE_UNDEFINED_SETSOCKOPT
232 extern "C" int setsockopt(int, int, int, const void *, socklen_t);
233 #endif
234
235 class filedescriptorprivate {
236 friend class filedescriptor;
237 private:
238 bool _retryinterruptedreads:1;
239 bool _retryinterruptedwrites:1;
240 bool _retryinterruptedwaits:1;
241 bool _retryinterruptedfcntl:1;
242 bool _retryinterruptedioctl:1;
243 bool _allowshortreads:1;
244 bool _allowshortwrites:1;
245 bool _translatebyteorder:1;
246
247 int32_t _fd;
248
249 securitycontext *_secctx;
250
251 const char *_type;
252
253 listener *_lstnr;
254
255 unsigned char *_writebuffer;
256 unsigned char *_writebufferend;
257 unsigned char *_writebufferptr;
258
259 unsigned char *_readbuffer;
260 unsigned char *_readbufferend;
261 unsigned char *_readbufferhead;
262 unsigned char *_readbuffertail;
263
264 thread *_thr;
265 semaphoreset *_thrsem;
266 bool _threxit;
267 bool _threrror;
268 bool _asyncwrite;
269 unsigned char *_asyncbuf;
270 uint32_t _asyncbufsize;
271 ssize_t _asynccount;
272 };
273
filedescriptor()274 filedescriptor::filedescriptor() {
275 pvt=new filedescriptorprivate;
276 filedescriptorInit();
277 }
278
filedescriptor(int32_t fd)279 filedescriptor::filedescriptor(int32_t fd) {
280 pvt=new filedescriptorprivate;
281 filedescriptorInit();
282 setFileDescriptor(fd);
283 }
284
filedescriptor(const filedescriptor & f)285 filedescriptor::filedescriptor(const filedescriptor &f) {
286 pvt=new filedescriptorprivate;
287 filedescriptorClone(f);
288 }
289
operator =(const filedescriptor & f)290 filedescriptor &filedescriptor::operator=(const filedescriptor &f) {
291 if (this!=&f) {
292 delete[] pvt->_writebuffer;
293 filedescriptorClone(f);
294 }
295 return *this;
296 }
297
filedescriptorInit()298 void filedescriptor::filedescriptorInit() {
299 setFileDescriptor(-1);
300 pvt->_retryinterruptedreads=false;
301 pvt->_retryinterruptedwrites=false;
302 pvt->_retryinterruptedwaits=true;
303 pvt->_retryinterruptedfcntl=true;
304 pvt->_retryinterruptedioctl=true;
305 pvt->_allowshortreads=false;
306 pvt->_allowshortwrites=false;
307 pvt->_translatebyteorder=false;
308 pvt->_secctx=NULL;
309 pvt->_type="filedescriptor";
310 pvt->_lstnr=NULL;
311 pvt->_writebuffer=NULL;
312 pvt->_writebufferend=NULL;
313 pvt->_writebufferptr=NULL;
314 pvt->_readbuffer=NULL;
315 pvt->_readbufferend=NULL;
316 pvt->_readbufferhead=NULL;
317 pvt->_readbuffertail=NULL;
318 pvt->_thr=NULL;
319 pvt->_thrsem=NULL;
320 pvt->_threxit=false;
321 pvt->_threrror=false;
322 pvt->_asyncwrite=false;
323 pvt->_asyncbuf=NULL;
324 pvt->_asyncbufsize=0;
325 pvt->_asynccount=0;
326 }
327
filedescriptorClone(const filedescriptor & f)328 void filedescriptor::filedescriptorClone(const filedescriptor &f) {
329 setFileDescriptor(f.pvt->_fd);
330 pvt->_translatebyteorder=f.pvt->_translatebyteorder;
331 pvt->_retryinterruptedreads=f.pvt->_retryinterruptedreads;
332 pvt->_retryinterruptedwrites=f.pvt->_retryinterruptedwrites;
333 pvt->_retryinterruptedwaits=f.pvt->_retryinterruptedwaits;
334 pvt->_retryinterruptedfcntl=f.pvt->_retryinterruptedfcntl;
335 pvt->_retryinterruptedioctl=f.pvt->_retryinterruptedioctl;
336 pvt->_allowshortreads=f.pvt->_allowshortreads;
337 pvt->_allowshortwrites=f.pvt->_allowshortwrites;
338 pvt->_secctx=f.pvt->_secctx;
339 if (f.pvt->_writebuffer) {
340 ssize_t writebuffersize=f.pvt->_writebufferend-
341 f.pvt->_writebuffer;
342 pvt->_writebuffer=new unsigned char[writebuffersize];
343 bytestring::copy(pvt->_writebuffer,
344 f.pvt->_writebuffer,
345 writebuffersize);
346 pvt->_writebufferend=pvt->_writebuffer+writebuffersize;
347 pvt->_writebufferptr=pvt->_writebuffer+
348 (f.pvt->_writebufferptr-f.pvt->_writebuffer);
349 } else {
350 pvt->_writebuffer=NULL;
351 pvt->_writebufferend=NULL;
352 pvt->_writebufferptr=NULL;
353 }
354 pvt->_lstnr=NULL;
355 }
356
~filedescriptor()357 filedescriptor::~filedescriptor() {
358
359 // see NOTE in ~threadmutex()
360
361 if (!pvt) {
362 return;
363 }
364
365 if (pvt->_thr) {
366
367 if (pvt->_thrsem) {
368 pvt->_thrsem->wait(1);
369 pvt->_threxit=true;
370 pvt->_thrsem->signal(0);
371 semaphoreset *tmpthrsem=pvt->_thrsem;
372 pvt->_thrsem=NULL;
373 delete tmpthrsem;
374 }
375
376 pvt->_thr->wait(NULL);
377 thread *tmpthr=pvt->_thr;
378 pvt->_thr=NULL;
379 delete tmpthr;
380
381 unsigned char *tmpasyncbuf=pvt->_asyncbuf;
382 pvt->_asyncbuf=NULL;
383 delete[] tmpasyncbuf;
384 }
385
386 unsigned char *tmpbuffer=pvt->_readbuffer;
387 pvt->_readbuffer=NULL;
388 delete[] tmpbuffer;
389
390 tmpbuffer=pvt->_writebuffer;
391 pvt->_writebuffer=NULL;
392 delete[] tmpbuffer;
393
394 listener *tmplstnr=pvt->_lstnr;
395 pvt->_lstnr=NULL;
396 delete tmplstnr;
397
398 close();
399
400 filedescriptorprivate *tmppvt=pvt;
401 pvt=NULL;
402 delete tmppvt;
403 }
404
setWriteBufferSize(ssize_t size) const405 bool filedescriptor::setWriteBufferSize(ssize_t size) const {
406
407 if (size>SSIZE_MAX) {
408 size=SSIZE_MAX;
409 }
410
411 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
412 debugPrintf("setting write buffer size to %d\n",size);
413 #endif
414
415 if (size<0) {
416 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
417 debugPrintf("invalid size: %d\n",size);
418 #endif
419 return false;
420 }
421
422 delete[] pvt->_writebuffer;
423 pvt->_writebuffer=(size)?new unsigned char[size]:NULL;
424 pvt->_writebufferend=pvt->_writebuffer+size;
425 pvt->_writebufferptr=pvt->_writebuffer;
426
427 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
428 debugPrintf("done setting write buffer size\n");
429 #endif
430 return true;
431 }
432
setReadBufferSize(ssize_t size) const433 bool filedescriptor::setReadBufferSize(ssize_t size) const {
434
435 if (size>SSIZE_MAX) {
436 size=SSIZE_MAX;
437 }
438
439 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
440 debugPrintf("setting read buffer size to %d\n",size);
441 #endif
442
443 if (size<0) {
444 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
445 debugPrintf("invalid size: %d\n",size);
446 #endif
447 return false;
448 }
449
450 delete[] pvt->_readbuffer;
451 pvt->_readbuffer=(size)?new unsigned char[size]:NULL;
452 pvt->_readbufferend=pvt->_readbuffer+size;
453 pvt->_readbufferhead=pvt->_readbuffer;
454 pvt->_readbuffertail=pvt->_readbuffer;
455
456 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
457 debugPrintf("done setting read buffer size\n");
458 #endif
459 return true;
460 }
461
getFileDescriptor() const462 int32_t filedescriptor::getFileDescriptor() const {
463 return pvt->_fd;
464 }
465
setFileDescriptor(int32_t filedesc)466 void filedescriptor::setFileDescriptor(int32_t filedesc) {
467 pvt->_fd=filedesc;
468 }
469
duplicate() const470 int32_t filedescriptor::duplicate() const {
471 int32_t result;
472 error::clearError();
473 do {
474 #if defined(RUDIMENTS_HAVE__DUP)
475 result=_dup(pvt->_fd);
476 #elif defined(RUDIMENTS_HAVE_DUP)
477 result=dup(pvt->_fd);
478 #else
479 #error no dup or anything like it
480 #endif
481 } while (result==-1 && error::getErrorNumber()==EINTR);
482 return result;
483 }
484
duplicate(int32_t newfd) const485 bool filedescriptor::duplicate(int32_t newfd) const {
486 int32_t result;
487 error::clearError();
488 do {
489 #if defined(RUDIMENTS_HAVE__DUP2)
490 result=_dup2(pvt->_fd,newfd);
491 #elif defined(RUDIMENTS_HAVE_DUP2)
492 result=dup2(pvt->_fd,newfd);
493 #else
494 #error no dup2 or anything like it
495 #endif
496 } while (result==-1 && error::getErrorNumber()==EINTR);
497 return (result==newfd);
498 }
499
setSecurityContext(securitycontext * ctx)500 void filedescriptor::setSecurityContext(securitycontext *ctx) {
501 pvt->_secctx=ctx;
502 }
503
getSecurityContext()504 securitycontext *filedescriptor::getSecurityContext() {
505 return pvt->_secctx;
506 }
507
supportsBlockingNonBlockingModes()508 bool filedescriptor::supportsBlockingNonBlockingModes() {
509 #if defined(RUDIMENTS_HAVE_FCNTL) && \
510 defined(F_SETFL) && defined (F_GETFL)
511 return true;
512 #else
513 return false;
514 #endif
515 }
516
useNonBlockingMode() const517 bool filedescriptor::useNonBlockingMode() const {
518 #if defined(RUDIMENTS_HAVE_FCNTL) && \
519 defined(F_SETFL) && defined (F_GETFL)
520 return (fCntl(F_SETFL,fCntl(F_GETFL,0)|O_NONBLOCK)!=-1);
521 #else
522 return false;
523 #endif
524 }
525
useBlockingMode() const526 bool filedescriptor::useBlockingMode() const {
527 #if defined(RUDIMENTS_HAVE_FCNTL) && \
528 defined(F_SETFL) && defined (F_GETFL)
529 return (fCntl(F_SETFL,fCntl(F_GETFL,0)&(~O_NONBLOCK))!=-1);
530 #else
531 return false;
532 #endif
533 }
534
isUsingNonBlockingMode() const535 bool filedescriptor::isUsingNonBlockingMode() const {
536 #if defined(RUDIMENTS_HAVE_FCNTL) && defined(F_GETFL)
537 return (fCntl(F_GETFL,0)&O_NONBLOCK);
538 #else
539 return false;
540 #endif
541 }
542
useAsyncWrite()543 void filedescriptor::useAsyncWrite() {
544 pvt->_asyncwrite=true;
545 }
546
dontUseAsyncWrite()547 void filedescriptor::dontUseAsyncWrite() {
548 pvt->_asyncwrite=false;
549 }
550
write(uint16_t number)551 ssize_t filedescriptor::write(uint16_t number) {
552 return write(number,-1,-1);
553 }
554
write(uint32_t number)555 ssize_t filedescriptor::write(uint32_t number) {
556 return write(number,-1,-1);
557 }
558
write(uint64_t number)559 ssize_t filedescriptor::write(uint64_t number) {
560 return write(number,-1,-1);
561 }
562
write(int16_t number)563 ssize_t filedescriptor::write(int16_t number) {
564 return write(number,-1,-1);
565 }
566
write(int32_t number)567 ssize_t filedescriptor::write(int32_t number) {
568 return write(number,-1,-1);
569 }
570
write(int64_t number)571 ssize_t filedescriptor::write(int64_t number) {
572 return write(number,-1,-1);
573 }
574
write(float number)575 ssize_t filedescriptor::write(float number) {
576 return write(number,-1,-1);
577 }
578
write(double number)579 ssize_t filedescriptor::write(double number) {
580 return write(number,-1,-1);
581 }
582
write(unsigned char character)583 ssize_t filedescriptor::write(unsigned char character) {
584 return write(character,-1,-1);
585 }
586
write(bool value)587 ssize_t filedescriptor::write(bool value) {
588 return write(value,-1,-1);
589 }
590
write(char character)591 ssize_t filedescriptor::write(char character) {
592 return write(character,-1,-1);
593 }
594
write(const unsigned char * string,size_t size)595 ssize_t filedescriptor::write(const unsigned char *string, size_t size) {
596 return write(string,size,-1,-1);
597 }
598
write(const char * string,size_t size)599 ssize_t filedescriptor::write(const char *string, size_t size) {
600 return write(string,size,-1,-1);
601 }
602
write(const unsigned char * string)603 ssize_t filedescriptor::write(const unsigned char *string) {
604 return write(string,charstring::length(string),-1,-1);
605 }
606
write(const char * string)607 ssize_t filedescriptor::write(const char *string) {
608 return write(string,charstring::length(string),-1,-1);
609 }
610
write(const void * buffer,size_t size)611 ssize_t filedescriptor::write(const void *buffer, size_t size) {
612 return write(buffer,size,-1,-1);
613 }
614
write(uint16_t number,int32_t sec,int32_t usec)615 ssize_t filedescriptor::write(uint16_t number, int32_t sec, int32_t usec) {
616 if (pvt->_translatebyteorder) {
617 number=hostToNet(number);
618 }
619 return bufferedWrite(&number,sizeof(uint16_t),sec,usec);
620 }
621
write(uint32_t number,int32_t sec,int32_t usec)622 ssize_t filedescriptor::write(uint32_t number, int32_t sec, int32_t usec) {
623 if (pvt->_translatebyteorder) {
624 number=hostToNet(number);
625 }
626 return bufferedWrite(&number,sizeof(uint32_t),sec,usec);
627 }
628
write(uint64_t number,int32_t sec,int32_t usec)629 ssize_t filedescriptor::write(uint64_t number, int32_t sec, int32_t usec) {
630 if (pvt->_translatebyteorder) {
631 number=hostToNet(number);
632 }
633 return bufferedWrite(&number,sizeof(uint64_t),sec,usec);
634 }
635
write(int16_t number,int32_t sec,int32_t usec)636 ssize_t filedescriptor::write(int16_t number, int32_t sec, int32_t usec) {
637 if (pvt->_translatebyteorder) {
638 number=hostToNet((uint16_t)number);
639 }
640 return bufferedWrite(&number,sizeof(int16_t),sec,usec);
641 }
642
write(int32_t number,int32_t sec,int32_t usec)643 ssize_t filedescriptor::write(int32_t number, int32_t sec, int32_t usec) {
644 if (pvt->_translatebyteorder) {
645 number=hostToNet((uint32_t)number);
646 }
647 return bufferedWrite(&number,sizeof(int32_t),sec,usec);
648 }
649
write(int64_t number,int32_t sec,int32_t usec)650 ssize_t filedescriptor::write(int64_t number, int32_t sec, int32_t usec) {
651 if (pvt->_translatebyteorder) {
652 number=hostToNet((uint64_t)number);
653 }
654 return bufferedWrite(&number,sizeof(int64_t),sec,usec);
655 }
656
write(float number,int32_t sec,int32_t usec)657 ssize_t filedescriptor::write(float number, int32_t sec,int32_t usec) {
658 return bufferedWrite(&number,sizeof(float),sec,usec);
659 }
660
write(double number,int32_t sec,int32_t usec)661 ssize_t filedescriptor::write(double number, int32_t sec, int32_t usec) {
662 return bufferedWrite(&number,sizeof(double),sec,usec);
663 }
664
write(unsigned char character,int32_t sec,int32_t usec)665 ssize_t filedescriptor::write(unsigned char character,
666 int32_t sec, int32_t usec) {
667 return bufferedWrite(&character,sizeof(unsigned char),sec,usec);
668 }
669
write(bool value,int32_t sec,int32_t usec)670 ssize_t filedescriptor::write(bool value, int32_t sec, int32_t usec) {
671 return bufferedWrite(&value,sizeof(bool),sec,usec);
672 }
673
write(char character,int32_t sec,int32_t usec)674 ssize_t filedescriptor::write(char character, int32_t sec, int32_t usec) {
675 return bufferedWrite(&character,sizeof(char),sec,usec);
676 }
677
write(const unsigned char * string,size_t size,int32_t sec,int32_t usec)678 ssize_t filedescriptor::write(const unsigned char *string, size_t size,
679 int32_t sec, int32_t usec) {
680 return bufferedWrite(string,size,sec,usec);
681 }
682
write(const char * string,size_t size,int32_t sec,int32_t usec)683 ssize_t filedescriptor::write(const char *string, size_t size,
684 int32_t sec, int32_t usec) {
685 return bufferedWrite(string,size,sec,usec);
686 }
687
write(const unsigned char * string,int32_t sec,int32_t usec)688 ssize_t filedescriptor::write(const unsigned char *string,
689 int32_t sec, int32_t usec) {
690 return bufferedWrite(string,charstring::length(string),sec,usec);
691 }
692
write(const char * string,int32_t sec,int32_t usec)693 ssize_t filedescriptor::write(const char *string,
694 int32_t sec, int32_t usec) {
695 return bufferedWrite(string,charstring::length(string),sec,usec);
696 }
697
write(const void * buffer,size_t size,int32_t sec,int32_t usec)698 ssize_t filedescriptor::write(const void *buffer, size_t size,
699 int32_t sec, int32_t usec) {
700 return bufferedWrite(buffer,size,sec,usec);
701 }
702
read(uint16_t * buffer)703 ssize_t filedescriptor::read(uint16_t *buffer) {
704 return read(buffer,-1,-1);
705 }
706
read(uint32_t * buffer)707 ssize_t filedescriptor::read(uint32_t *buffer) {
708 return read(buffer,-1,-1);
709 }
710
read(uint64_t * buffer)711 ssize_t filedescriptor::read(uint64_t *buffer) {
712 return read(buffer,-1,-1);
713 }
714
read(int16_t * buffer)715 ssize_t filedescriptor::read(int16_t *buffer) {
716 return read(buffer,-1,-1);
717 }
718
read(int32_t * buffer)719 ssize_t filedescriptor::read(int32_t *buffer) {
720 return read(buffer,-1,-1);
721 }
722
read(int64_t * buffer)723 ssize_t filedescriptor::read(int64_t *buffer) {
724 return read(buffer,-1,-1);
725 }
726
read(float * buffer)727 ssize_t filedescriptor::read(float *buffer) {
728 return read(buffer,-1,-1);
729 }
730
read(double * buffer)731 ssize_t filedescriptor::read(double *buffer) {
732 return read(buffer,-1,-1);
733 }
734
read(unsigned char * buffer)735 ssize_t filedescriptor::read(unsigned char *buffer) {
736 return read(buffer,-1,-1);
737 }
738
read(bool * buffer)739 ssize_t filedescriptor::read(bool *buffer) {
740 return read(buffer,-1,-1);
741 }
742
read(char * buffer)743 ssize_t filedescriptor::read(char *buffer) {
744 return read(buffer,-1,-1);
745 }
746
read(unsigned char * buffer,size_t size)747 ssize_t filedescriptor::read(unsigned char *buffer, size_t size) {
748 return read(buffer,size,-1,-1);
749 }
750
read(char * buffer,size_t size)751 ssize_t filedescriptor::read(char *buffer, size_t size) {
752 return read(buffer,size,-1,-1);
753 }
754
read(void * buffer,size_t size)755 ssize_t filedescriptor::read(void *buffer, size_t size) {
756 return read(buffer,size,-1,-1);
757 }
758
read(char ** buffer,const char * terminator)759 ssize_t filedescriptor::read(char **buffer, const char *terminator) {
760 return read(buffer,terminator,0,'\0',-1,-1);
761 }
762
read(char ** buffer,const char * terminator,size_t maxbytes)763 ssize_t filedescriptor::read(char **buffer,
764 const char *terminator, size_t maxbytes) {
765 return read(buffer,terminator,maxbytes,'\0',-1,-1);
766 }
767
read(char ** buffer,const char * terminator,int32_t sec,int32_t usec)768 ssize_t filedescriptor::read(char **buffer, const char *terminator,
769 int32_t sec, int32_t usec) {
770 return read(buffer,terminator,0,'\0',sec,usec);
771 }
772
read(uint16_t * buffer,int32_t sec,int32_t usec)773 ssize_t filedescriptor::read(uint16_t *buffer,
774 int32_t sec, int32_t usec) {
775 ssize_t retval=bufferedRead(buffer,sizeof(uint16_t),sec,usec);
776 if (pvt->_translatebyteorder) {
777 *buffer=netToHost(*buffer);
778 }
779 return retval;
780 }
781
read(uint32_t * buffer,int32_t sec,int32_t usec)782 ssize_t filedescriptor::read(uint32_t *buffer,
783 int32_t sec, int32_t usec) {
784 ssize_t retval=bufferedRead(buffer,sizeof(uint32_t),sec,usec);
785 if (pvt->_translatebyteorder) {
786 *buffer=netToHost(*buffer);
787 }
788 return retval;
789 }
790
read(uint64_t * buffer,int32_t sec,int32_t usec)791 ssize_t filedescriptor::read(uint64_t *buffer,
792 int32_t sec, int32_t usec) {
793 ssize_t retval=bufferedRead(buffer,sizeof(uint64_t),sec,usec);
794 if (pvt->_translatebyteorder) {
795 *buffer=netToHost(*buffer);
796 }
797 return retval;
798 }
799
read(int16_t * buffer,int32_t sec,int32_t usec)800 ssize_t filedescriptor::read(int16_t *buffer,
801 int32_t sec, int32_t usec) {
802 ssize_t retval=bufferedRead(buffer,sizeof(int16_t),sec,usec);
803 if (pvt->_translatebyteorder) {
804 *buffer=netToHost((uint16_t)*buffer);
805 }
806 return retval;
807 }
808
read(int32_t * buffer,int32_t sec,int32_t usec)809 ssize_t filedescriptor::read(int32_t *buffer,
810 int32_t sec, int32_t usec) {
811 ssize_t retval=bufferedRead(buffer,sizeof(int32_t),sec,usec);
812 if (pvt->_translatebyteorder) {
813 *buffer=netToHost((uint32_t)*buffer);
814 }
815 return retval;
816 }
817
read(int64_t * buffer,int32_t sec,int32_t usec)818 ssize_t filedescriptor::read(int64_t *buffer,
819 int32_t sec, int32_t usec) {
820 ssize_t retval=bufferedRead(buffer,sizeof(int64_t),sec,usec);
821 if (pvt->_translatebyteorder) {
822 *buffer=netToHost((uint64_t)*buffer);
823 }
824 return retval;
825 }
826
read(float * buffer,int32_t sec,int32_t usec)827 ssize_t filedescriptor::read(float *buffer,
828 int32_t sec, int32_t usec) {
829 return bufferedRead(buffer,sizeof(float),sec,usec);
830 }
831
read(double * buffer,int32_t sec,int32_t usec)832 ssize_t filedescriptor::read(double *buffer,
833 int32_t sec, int32_t usec) {
834 return bufferedRead(buffer,sizeof(double),sec,usec);
835 }
836
read(unsigned char * buffer,int32_t sec,int32_t usec)837 ssize_t filedescriptor::read(unsigned char *buffer,
838 int32_t sec, int32_t usec) {
839 return bufferedRead(buffer,sizeof(unsigned char),sec,usec);
840 }
841
read(bool * buffer,int32_t sec,int32_t usec)842 ssize_t filedescriptor::read(bool *buffer,
843 int32_t sec, int32_t usec) {
844 return bufferedRead(buffer,sizeof(bool),sec,usec);
845 }
846
read(char * buffer,int32_t sec,int32_t usec)847 ssize_t filedescriptor::read(char *buffer,
848 int32_t sec, int32_t usec) {
849 return bufferedRead(buffer,sizeof(char),sec,usec);
850 }
851
read(unsigned char * buffer,size_t size,int32_t sec,int32_t usec)852 ssize_t filedescriptor::read(unsigned char *buffer, size_t size,
853 int32_t sec, int32_t usec) {
854 return bufferedRead(buffer,size,sec,usec);
855 }
856
read(char * buffer,size_t size,int32_t sec,int32_t usec)857 ssize_t filedescriptor::read(char *buffer, size_t size,
858 int32_t sec, int32_t usec) {
859 return bufferedRead(buffer,size,sec,usec);
860 }
861
read(void * buffer,size_t size,int32_t sec,int32_t usec)862 ssize_t filedescriptor::read(void *buffer, size_t size,
863 int32_t sec, int32_t usec) {
864 return bufferedRead(buffer,size,sec,usec);
865 }
866
close()867 bool filedescriptor::close() {
868 if (pvt->_fd!=-1) {
869 int32_t result;
870 error::clearError();
871 do {
872 result=lowLevelClose();
873 } while (result==-1 && error::getErrorNumber()==EINTR);
874 if (result==-1) {
875 return false;
876 }
877 setFileDescriptor(-1);
878 }
879 return true;
880 }
881
lowLevelClose()882 int32_t filedescriptor::lowLevelClose() {
883 #if defined(RUDIMENTS_HAVE__CLOSE)
884 return _close(pvt->_fd);
885 #elif defined(RUDIMENTS_HAVE_CLOSE)
886 return ::close(pvt->_fd);
887 #else
888 #error no close or anything like it
889 #endif
890 }
891
retryInterruptedReads()892 void filedescriptor::retryInterruptedReads() {
893 pvt->_retryinterruptedreads=true;
894 }
895
dontRetryInterruptedReads()896 void filedescriptor::dontRetryInterruptedReads() {
897 pvt->_retryinterruptedreads=false;
898 }
899
getRetryInterruptedReads() const900 bool filedescriptor::getRetryInterruptedReads() const {
901 return pvt->_retryinterruptedreads;
902 }
903
retryInterruptedWrites()904 void filedescriptor::retryInterruptedWrites() {
905 pvt->_retryinterruptedwrites=true;
906 }
907
dontRetryInterruptedWrites()908 void filedescriptor::dontRetryInterruptedWrites() {
909 pvt->_retryinterruptedwrites=false;
910 }
911
getRetryInterruptedWrites() const912 bool filedescriptor::getRetryInterruptedWrites() const {
913 return pvt->_retryinterruptedwrites;
914 }
915
retryInterruptedWaits()916 void filedescriptor::retryInterruptedWaits() {
917 pvt->_retryinterruptedwaits=true;
918 }
919
dontRetryInterruptedWaits()920 void filedescriptor::dontRetryInterruptedWaits() {
921 pvt->_retryinterruptedwaits=false;
922 }
923
getRetryInterruptedWaits() const924 bool filedescriptor::getRetryInterruptedWaits() const {
925 return pvt->_retryinterruptedwaits;
926 }
927
retryInterruptedFcntl()928 void filedescriptor::retryInterruptedFcntl() {
929 pvt->_retryinterruptedfcntl=true;
930 }
931
dontRetryInterruptedFcntl()932 void filedescriptor::dontRetryInterruptedFcntl() {
933 pvt->_retryinterruptedfcntl=true;
934 }
935
getRetryInterruptedFcntl() const936 bool filedescriptor::getRetryInterruptedFcntl() const {
937 return pvt->_retryinterruptedfcntl;
938 }
939
retryInterruptedIoctl()940 void filedescriptor::retryInterruptedIoctl() {
941 pvt->_retryinterruptedioctl=true;
942 }
943
dontRetryInterruptedIoctl()944 void filedescriptor::dontRetryInterruptedIoctl() {
945 pvt->_retryinterruptedioctl=true;
946 }
947
getRetryInterruptedIoctl() const948 bool filedescriptor::getRetryInterruptedIoctl() const {
949 return pvt->_retryinterruptedioctl;
950 }
951
allowShortReads()952 void filedescriptor::allowShortReads() {
953 pvt->_allowshortreads=true;
954 }
955
dontAllowShortReads()956 void filedescriptor::dontAllowShortReads() {
957 pvt->_allowshortreads=false;
958 }
959
allowShortWrites()960 void filedescriptor::allowShortWrites() {
961 pvt->_allowshortwrites=true;
962 }
963
dontAllowShortWrites()964 void filedescriptor::dontAllowShortWrites() {
965 pvt->_allowshortwrites=false;
966 }
967
read(char ** buffer,const char * terminator,size_t maxbytes,int32_t sec,int32_t usec)968 ssize_t filedescriptor::read(char **buffer, const char *terminator,
969 size_t maxbytes, int32_t sec, int32_t usec) {
970 return read(buffer,terminator,maxbytes,'\0',sec,usec);
971 }
972
read(char ** buffer,const char * terminator,size_t maxbytes,char escapechar,int32_t sec,int32_t usec)973 ssize_t filedescriptor::read(char **buffer, const char *terminator,
974 size_t maxbytes, char escapechar,
975 int32_t sec, int32_t usec) {
976
977 // initialize the return buffer
978 if (buffer) {
979 *buffer=NULL;
980 }
981
982 // initialize a temp buffer
983 stringbuffer temp;
984
985 // initialize termination detector
986 int32_t termlen=charstring::length(terminator);
987 char *term=new char[termlen];
988 bytestring::zero(term,termlen);
989
990 // initialize some variables
991 ssize_t sizeread;
992 char charbuffer;
993 bool escaped=false;
994 bool copytobuffer;
995 bool copytoterm;
996 ssize_t retval=RESULT_SUCCESS;
997
998 // loop, getting 1 character at a time
999 for (;;) {
1000
1001 // read from the file descriptor
1002 sizeread=read(&charbuffer,sec,usec);
1003 if (sizeread<=0) {
1004 retval=sizeread;
1005 break;
1006 }
1007
1008 // handle escaping
1009 if (escaped) {
1010 copytobuffer=true;
1011 copytoterm=false;
1012 escaped=false;
1013 } else {
1014 escaped=((escapechar!='\0')?
1015 (charbuffer==escapechar):false);
1016 copytobuffer=!escaped;
1017 copytoterm=!escaped;
1018 }
1019
1020 // copy to return buffer
1021 if (copytobuffer && buffer) {
1022 temp.append(charbuffer);
1023 }
1024
1025 if (copytoterm) {
1026
1027 // update terminator detector
1028 for (int32_t i=0; i<termlen-1; i++) {
1029 term[i]=term[i+1];
1030 }
1031 term[termlen-1]=charbuffer;
1032
1033 // check for termination
1034 if (!charstring::compare(term,terminator,termlen)) {
1035 break;
1036 }
1037
1038 } else {
1039
1040 // clear terminator
1041 bytestring::zero(term,termlen);
1042 }
1043
1044 // max-bytes-read condition
1045 if (maxbytes && temp.getSize()>maxbytes) {
1046 retval=RESULT_MAX;
1047 break;
1048 }
1049 }
1050
1051 if (retval>=RESULT_SUCCESS) {
1052
1053 // get the size to return
1054 retval=temp.getSize();
1055
1056 // set the return buffer
1057 if (buffer) {
1058 *buffer=temp.detachString();
1059 }
1060 }
1061
1062 // clean up
1063 delete[] term;
1064
1065 return retval;
1066 }
1067
bufferedRead(void * buf,ssize_t count,int32_t sec,int32_t usec)1068 ssize_t filedescriptor::bufferedRead(void *buf, ssize_t count,
1069 int32_t sec, int32_t usec) {
1070
1071 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
1072 debugPrintf("bufferedRead of %d bytes\n",(int)count);
1073 #endif
1074
1075 if (!count) {
1076 return 0;
1077 }
1078
1079 if (!pvt->_readbuffer) {
1080 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
1081 debugPrintf("no read buffer...\n");
1082 #endif
1083 return safeRead(buf,count,sec,usec);
1084 }
1085
1086 unsigned char *data=(unsigned char *)buf;
1087 ssize_t bytesread=0;
1088 ssize_t bytesunread=count;
1089
1090 for (;;) {
1091
1092 // copy what we can from the buffer
1093 ssize_t bytesavailabletocopy=pvt->_readbuffertail-
1094 pvt->_readbufferhead;
1095 if (bytesavailabletocopy) {
1096
1097 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
1098 debugPrintf("%d bytes in read buffer\n",
1099 (int)bytesavailabletocopy);
1100 #endif
1101
1102 ssize_t bytestocopy=(bytesavailabletocopy<bytesunread)?
1103 bytesavailabletocopy:
1104 bytesunread;
1105
1106 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
1107 debugPrintf("copying %d bytes "
1108 "out of read buffer\n",
1109 (int)bytestocopy);
1110 #endif
1111
1112 bytestring::copy(data,pvt->_readbufferhead,bytestocopy);
1113 data=data+bytestocopy;
1114 bytesread=bytesread+bytestocopy;
1115 pvt->_readbufferhead=pvt->_readbufferhead+bytestocopy;
1116 bytesunread=bytesunread-bytestocopy;
1117
1118 // return if we've read enough
1119 if (bytesread==count) {
1120 #if defined(DEBUG_READ) && \
1121 defined(DEBUG_BUFFERING)
1122 debugPrintf("yay, we're done reading\n");
1123 #endif
1124 return bytesread;
1125 }
1126
1127 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
1128 debugPrintf("need to read %d more bytes\n",
1129 (int)bytesunread);
1130 #endif
1131 }
1132
1133 // if we've copied out everything in the buffer, read some more
1134 if (pvt->_readbufferhead==pvt->_readbuffertail) {
1135
1136 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
1137 debugPrintf("attempting to fill read buffer, ");
1138 debugPrintf("reading %d bytes...\n",
1139 (int)(pvt->_readbufferend-
1140 pvt->_readbuffer));
1141 #endif
1142
1143 bool saveasr=pvt->_allowshortreads;
1144 pvt->_allowshortreads=true;
1145 ssize_t result=safeRead(pvt->_readbuffer,
1146 pvt->_readbufferend-
1147 pvt->_readbuffer,
1148 sec,usec);
1149 pvt->_allowshortreads=saveasr;
1150
1151 if (!result) {
1152
1153 if (pvt->_allowshortreads) {
1154 #if defined(DEBUG_READ) && \
1155 defined(DEBUG_BUFFERING)
1156 debugPrintf("EOF\n");
1157 #endif
1158 return bytesread;
1159 }
1160
1161 #if defined(DEBUG_READ) && \
1162 defined(DEBUG_BUFFERING)
1163 debugPrintf("still need %d bytes, "
1164 "reading...\n",
1165 (int)bytesunread);
1166 #endif
1167 result=safeRead(pvt->_readbuffer,
1168 bytesunread,
1169 sec,usec);
1170
1171 if (result>-1 && result!=bytesunread) {
1172 #if defined(DEBUG_READ) && \
1173 defined(DEBUG_BUFFERING)
1174 debugPrintf("EOF\n");
1175 #endif
1176 return bytesread;
1177 }
1178 }
1179
1180 if (result<0) {
1181 #if defined(DEBUG_READ) && \
1182 defined(DEBUG_BUFFERING)
1183 debugPrintf("error reading...\n");
1184 #endif
1185 return result;
1186 }
1187
1188 pvt->_readbufferhead=pvt->_readbuffer;
1189 pvt->_readbuffertail=pvt->_readbuffer+result;
1190
1191 #if defined(DEBUG_READ) && defined(DEBUG_BUFFERING)
1192 debugPrintf("read %d bytes\n",(int)result);
1193 #endif
1194 }
1195 }
1196 }
1197
safeRead(void * buf,ssize_t count,int32_t sec,int32_t usec)1198 ssize_t filedescriptor::safeRead(void *buf, ssize_t count,
1199 int32_t sec, int32_t usec) {
1200
1201 if (!buf) {
1202 return 0;
1203 }
1204
1205 #ifdef DEBUG_READ
1206 debugPrintf("%d: safeRead(%d,(attempting %d bytes)",
1207 (int)process::getProcessId(),(int)pvt->_fd,(int)count);
1208 #endif
1209
1210 ssize_t totalread=0;
1211 ssize_t sizetoread;
1212 ssize_t actualread;
1213 ssize_t sizemax=(pvt->_secctx)?pvt->_secctx->getSizeMax():SSIZE_MAX;
1214 bool isusingnonblockingmode=isUsingNonBlockingMode();
1215 while (totalread<count) {
1216
1217 // limit size of individual reads
1218 sizetoread=count-totalread;
1219 if (sizetoread>sizemax) {
1220 sizetoread=sizemax;
1221 }
1222
1223 // wait if necessary
1224 if (sec>-1 && usec>-1) {
1225
1226 int32_t waitresult=waitForNonBlockingRead(sec,usec);
1227
1228 // return error or timeout
1229 if (waitresult<0) {
1230 #ifdef DEBUG_READ
1231 debugPrintf(")\n");
1232 #endif
1233 return waitresult;
1234 }
1235 }
1236
1237 // set a pointer to the position in the buffer that we need
1238 // to read data into
1239 void *ptr=(void *)((unsigned char *)buf+totalread);
1240
1241 // read...
1242 error::clearError();
1243 if (pvt->_secctx) {
1244
1245 #ifdef DEBUG_READ
1246 debugPrintf(" (SecurityContext) ");
1247 #endif
1248
1249 actualread=pvt->_secctx->read(ptr,sizetoread);
1250 } else {
1251 actualread=lowLevelRead(ptr,sizetoread);
1252 }
1253
1254 #ifdef DEBUG_READ
1255 for (int32_t i=0; i<actualread; i++) {
1256 debugSafePrint(((unsigned char *)ptr)[i]);
1257 }
1258 debugPrintf("(%ld bytes) ",(long)actualread);
1259 if (actualread==-1) {
1260 debugPrintf("%s ",error::getErrorString());
1261 }
1262 stdoutput.flush();
1263 #endif
1264
1265 // if we didn't read the number of bytes we expected to,
1266 // handle that...
1267 if (actualread!=sizetoread) {
1268 if (isusingnonblockingmode &&
1269 error::getErrorNumber()==EAGAIN) {
1270 #ifdef DEBUG_READ
1271 debugPrintf(" EAGAIN ");
1272 #endif
1273 // if we got an EAGAIN, and we're in
1274 // non-blocking mode, there was nothing
1275 // to read and we're done
1276 break;
1277 } else if (error::getErrorNumber()==EINTR) {
1278 #ifdef DEBUG_READ
1279 debugPrintf(" EINTR ");
1280 #endif
1281 // if we got an EINTR, then we may need to
1282 // retry the read
1283 if (pvt->_retryinterruptedreads) {
1284 continue;
1285 } else {
1286 totalread=totalread+actualread;
1287 break;
1288 }
1289 } else if (actualread==0 &&
1290 error::getErrorNumber()==0) {
1291 // eof condition
1292 #ifdef DEBUG_READ
1293 debugPrintf(" EOF ");
1294 #endif
1295 break;
1296 } else if (actualread==-1) {
1297 // error condition
1298 #ifdef DEBUG_READ
1299 debugPrintf(" ERROR )\n");
1300 #endif
1301 return RESULT_ERROR;
1302 }
1303 }
1304
1305 totalread=totalread+actualread;
1306
1307 // if we want to allow short reads, then break out here
1308 if (pvt->_allowshortreads) {
1309 #ifdef DEBUG_READ
1310 debugPrintf(" SHORTREAD ");
1311 #endif
1312 break;
1313 }
1314 }
1315
1316 #ifdef DEBUG_READ
1317 debugPrintf(",%d)\n",(int)totalread);
1318 #endif
1319 return totalread;
1320 }
1321
lowLevelRead(void * buf,ssize_t count)1322 ssize_t filedescriptor::lowLevelRead(void *buf, ssize_t count) {
1323 #if defined(RUDIMENTS_HAVE__READ)
1324 return _read(pvt->_fd,buf,count);
1325 #elif defined(RUDIMENTS_HAVE_READ)
1326 return ::read(pvt->_fd,buf,count);
1327 #else
1328 #error no read or anything like it
1329 #endif
1330 }
1331
bufferedWrite(const void * buf,ssize_t count,int32_t sec,int32_t usec)1332 ssize_t filedescriptor::bufferedWrite(const void *buf, ssize_t count,
1333 int32_t sec, int32_t usec) {
1334
1335 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
1336 debugPrintf("bufferedWrite of %d bytes\n",(int)count);
1337 #endif
1338
1339 if (!count) {
1340 return 0;
1341 }
1342
1343 if (!pvt->_writebuffer) {
1344 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
1345 debugPrintf("no write buffer...\n");
1346 #endif
1347 return safeWrite(buf,count,sec,usec);
1348 }
1349
1350 const unsigned char *data=(const unsigned char *)buf;
1351
1352 ssize_t initialwritebuffersize=pvt->_writebufferptr-pvt->_writebuffer;
1353 bool first=true;
1354
1355 ssize_t byteswritten=0;
1356 ssize_t bytesunwritten=count;
1357 while (byteswritten<count) {
1358
1359 ssize_t writebuffersize=pvt->_writebufferptr-
1360 pvt->_writebuffer;
1361 ssize_t writebufferspace=pvt->_writebufferend-
1362 pvt->_writebufferptr;
1363
1364 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
1365 debugPrintf(" writebuffersize=%d\n",
1366 (int)writebuffersize);
1367 debugPrintf(" writebufferspace=%d\n",
1368 (int)writebufferspace);
1369 debugPrintf(" byteswritten=%d\n",
1370 (int)byteswritten);
1371 debugPrintf(" bytesunwritten=%d\n",
1372 (int)bytesunwritten);
1373 #endif
1374
1375 if (bytesunwritten<=writebufferspace) {
1376
1377 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
1378 debugPrintf("buffering %d bytes\n",
1379 (int)bytesunwritten);
1380 #endif
1381
1382 bytestring::copy(pvt->_writebufferptr,
1383 data,bytesunwritten);
1384 pvt->_writebufferptr=pvt->_writebufferptr+
1385 bytesunwritten;
1386 byteswritten=byteswritten+bytesunwritten;
1387
1388 } else {
1389
1390 #if defined(DEBUG_WRITE) && defined(DEBUG_BUFFERING)
1391 debugPrintf("just buffering %d bytes\n",
1392 (int)writebufferspace);
1393 #endif
1394 #if defined(DEBUG_BUFFERING)
1395 debugPrintf("auto-flush write buffer: %d bytes\n",
1396 (int)(writebuffersize+writebufferspace));
1397 #endif
1398
1399 bytestring::copy(pvt->_writebufferptr,
1400 data,writebufferspace);
1401
1402 bool saveasw=pvt->_allowshortwrites;
1403 pvt->_allowshortwrites=true;
1404 ssize_t result=safeWrite(pvt->_writebuffer,
1405 writebuffersize+writebufferspace,
1406 sec,usec);
1407 pvt->_allowshortwrites=saveasw;
1408
1409 if (result!=writebuffersize+writebufferspace) {
1410 return result;
1411 }
1412
1413 pvt->_writebufferptr=pvt->_writebuffer;
1414 // The first time the buffer is written, the number of
1415 // bytes that were already in the buffer need to be
1416 // taken into account when calculating byteswritten,
1417 // bytesunwritten and data.
1418 ssize_t adjustment=(first)?initialwritebuffersize:0;
1419 if (first) {
1420 first=false;
1421 }
1422 byteswritten=byteswritten+result-adjustment;
1423 bytesunwritten=bytesunwritten-result+adjustment;
1424 data=data+result-adjustment;
1425 }
1426 }
1427
1428 return byteswritten;
1429 }
1430
flushWriteBuffer(int32_t sec,int32_t usec)1431 bool filedescriptor::flushWriteBuffer(int32_t sec, int32_t usec) {
1432 if (!pvt->_writebuffer) {
1433 return true;
1434 }
1435 ssize_t writebuffersize=pvt->_writebufferptr-pvt->_writebuffer;
1436 #if defined(DEBUG_BUFFERING)
1437 debugPrintf("flush write buffer: %d bytes\n",
1438 (int)writebuffersize);
1439 #endif
1440 bool retval=(safeWrite(pvt->_writebuffer,writebuffersize,
1441 sec,usec)==writebuffersize);
1442 pvt->_writebufferptr=pvt->_writebuffer;
1443 return retval;
1444 }
1445
safeWrite(const void * buf,ssize_t count,int32_t sec,int32_t usec)1446 ssize_t filedescriptor::safeWrite(const void *buf, ssize_t count,
1447 int32_t sec, int32_t usec) {
1448
1449 if (!buf) {
1450 return 0;
1451 }
1452
1453 #ifdef DEBUG_WRITE
1454 debugPrintf("%d: safeWrite(%d,",
1455 (int)process::getProcessId(),(int)pvt->_fd);
1456 #endif
1457
1458 int32_t olderrno=error::getErrorNumber();
1459
1460 ssize_t totalwrite=0;
1461 ssize_t sizetowrite;
1462 ssize_t actualwrite;
1463 ssize_t sizemax=(pvt->_secctx)?pvt->_secctx->getSizeMax():SSIZE_MAX;
1464 bool isusingnonblockingmode=isUsingNonBlockingMode();
1465 while (totalwrite<count) {
1466
1467 // limit size of individual writes
1468 sizetowrite=count-totalwrite;
1469 if (sizetowrite>sizemax) {
1470 sizetowrite=sizemax;
1471 }
1472
1473 // wait if necessary
1474 if (sec>-1 && usec>-1) {
1475
1476 int32_t waitresult=waitForNonBlockingWrite(sec,usec);
1477
1478 // return error or timeout
1479 if (waitresult<0) {
1480 #ifdef DEBUG_WRITE
1481 debugPrintf(")\n");
1482 #endif
1483 return waitresult;
1484 }
1485 }
1486
1487 // set a pointer to the position in the buffer that we need
1488 // to write data from
1489 const void *ptr=
1490 (const void *)((const unsigned char *)buf+totalwrite);
1491
1492 error::clearError();
1493 if (pvt->_secctx) {
1494
1495 #ifdef DEBUG_WRITE
1496 debugPrintf(" (SecurityContext) ");
1497 #endif
1498
1499 actualwrite=pvt->_secctx->write(ptr,sizetowrite);
1500 } else {
1501 actualwrite=midLevelWrite(ptr,sizetowrite);
1502 }
1503
1504 #ifdef DEBUG_WRITE
1505 for (int32_t i=0; i<actualwrite; i++) {
1506 debugSafePrint(((const unsigned char *)(ptr))[i]);
1507 }
1508 debugPrintf("(%ld bytes) ",(long)actualwrite);
1509 if (actualwrite==-1) {
1510 debugPrintf("%s ",error::getErrorString());
1511 }
1512 stdoutput.flush();
1513 #endif
1514
1515 // if we didn't read the number of bytes we expected to,
1516 // handle that...
1517 if (actualwrite!=sizetowrite) {
1518 if (isusingnonblockingmode &&
1519 error::getErrorNumber()==EAGAIN) {
1520 #ifdef DEBUG_READ
1521 debugPrintf(" EAGAIN ");
1522 #endif
1523 // if we got an EAGAIN, and we're in
1524 // non-blocking mode, then try again
1525 break;
1526 } else if (error::getErrorNumber()==EINTR) {
1527 #ifdef DEBUG_WRITE
1528 debugPrintf(" EINTR ");
1529 #endif
1530 // if we got an EINTR, then we may need to
1531 // retry the write
1532 if (pvt->_retryinterruptedwrites) {
1533 continue;
1534 } else {
1535 totalwrite=totalwrite+actualwrite;
1536 break;
1537 }
1538 } else if (actualwrite==0 &&
1539 error::getErrorNumber()==0) {
1540 // eof condition
1541 #ifdef DEBUG_WRITE
1542 debugPrintf(" EOF ");
1543 #endif
1544 break;
1545 } else if (actualwrite==-1) {
1546 // error condition
1547 #ifdef DEBUG_WRITE
1548 debugPrintf(" ERROR )\n");
1549 #endif
1550 return RESULT_ERROR;
1551 }
1552 }
1553
1554 totalwrite=totalwrite+actualwrite;
1555
1556 // if we want to allow short writes, then break out here
1557 if (pvt->_allowshortwrites) {
1558 #ifdef DEBUG_WRITE
1559 debugPrintf(" SHORTWRITE ");
1560 #endif
1561 break;
1562 }
1563 }
1564
1565 #ifdef DEBUG_WRITE
1566 debugPrintf(",%d)\n",(int)totalwrite);
1567 #endif
1568 error::setErrorNumber(olderrno);
1569 return totalwrite;
1570 }
1571
lowLevelWriteWorker(void * attr)1572 void filedescriptor::lowLevelWriteWorker(void *attr) {
1573
1574 // get the filedescriptor
1575 filedescriptor *fd=(filedescriptor *)attr;
1576
1577 for (;;) {
1578
1579 // signal that we're ready for work
1580 fd->pvt->_thrsem->signal(1);
1581
1582 // wait for work to do
1583 fd->pvt->_thrsem->wait(0);
1584
1585 // handle exit
1586 if (fd->pvt->_threxit) {
1587 return;
1588 }
1589
1590 // attempt to write all data
1591 // FIXME: what about allowshortwrites?
1592 ssize_t bytestowrite=fd->pvt->_asynccount;
1593 ssize_t byteswritten=0;
1594 do {
1595 error::clearError();
1596 ssize_t result=fd->lowLevelWrite(
1597 fd->pvt->_asyncbuf+byteswritten,
1598 bytestowrite);
1599 if (result==-1) {
1600 if (error::getErrorNumber()==EINTR &&
1601 fd->pvt->_retryinterruptedwrites) {
1602 continue;
1603 } else {
1604 break;
1605 }
1606 }
1607 bytestowrite-=result;
1608 byteswritten+=result;
1609 } while (byteswritten<fd->pvt->_asynccount);
1610
1611 // if we failed to write everything, then
1612 // declare than an error has occurred
1613 if (byteswritten!=fd->pvt->_asynccount) {
1614 fd->pvt->_threrror=true;
1615 }
1616 }
1617 }
1618
midLevelWrite(const void * buf,ssize_t count)1619 ssize_t filedescriptor::midLevelWrite(const void *buf, ssize_t count) {
1620
1621 if (pvt->_asyncwrite) {
1622
1623 if (!pvt->_thr) {
1624
1625 // create the worker thread semaphore
1626 pvt->_thrsem=new semaphoreset;
1627 int32_t vals[2]={0,0};
1628 if (!pvt->_thrsem->create(
1629 IPC_PRIVATE,
1630 permissions::evalPermString("rw-------"),
1631 2,vals)) {
1632 delete pvt->_thrsem;
1633 pvt->_thrsem=NULL;
1634 return RESULT_ERROR;
1635 }
1636
1637 // create the worker thread
1638 pvt->_thr=new thread;
1639 if (!pvt->_thr->spawn(
1640 (void *(*)(void *))lowLevelWriteWorker,
1641 (void *)this,false)) {
1642
1643 delete pvt->_thrsem;
1644 pvt->_thrsem=NULL;
1645 delete pvt->_thr;
1646 pvt->_thr=NULL;
1647 return RESULT_ERROR;
1648 }
1649 }
1650
1651 // wait for the worker thread to be ready
1652 pvt->_thrsem->wait(1);
1653
1654 // if a previous write failed, then return an error
1655 if (pvt->_threrror) {
1656 pvt->_threrror=false;
1657 // FIXME: RESULT_ASYNC_ERROR or something...
1658 return RESULT_ERROR;
1659 }
1660
1661 // copy the buffer
1662 if ((ssize_t)pvt->_asyncbufsize<count) {
1663 delete[] pvt->_asyncbuf;
1664 // pad to 1024-byte boundary to reduce the need to
1665 // re-allocate this buffer
1666 pvt->_asyncbufsize=count+((1024-(count%1024))%1024);
1667 pvt->_asyncbuf=new unsigned char[pvt->_asyncbufsize];
1668 }
1669 bytestring::copy(pvt->_asyncbuf,buf,count);
1670 pvt->_asynccount=count;
1671
1672 // signal the worker thread to do work
1673 pvt->_thrsem->signal(0);
1674
1675 // return success
1676 return count;
1677
1678 } else {
1679 return lowLevelWrite(buf,count);
1680 }
1681 }
1682
lowLevelWrite(const void * buf,ssize_t count)1683 ssize_t filedescriptor::lowLevelWrite(const void *buf, ssize_t count) {
1684 #if defined(RUDIMENTS_HAVE__WRITE)
1685 return _write(pvt->_fd,buf,count);
1686 #elif defined(RUDIMENTS_HAVE_WRITE)
1687 return ::write(pvt->_fd,buf,count);
1688 #else
1689 #error no write or anything like it
1690 #endif
1691 }
1692
waitForNonBlockingRead(int32_t sec,int32_t usec) const1693 int32_t filedescriptor::waitForNonBlockingRead(
1694 int32_t sec, int32_t usec) const {
1695 if (!pvt->_lstnr) {
1696 pvt->_lstnr=new listener();
1697 } else {
1698 pvt->_lstnr->removeAllFileDescriptors();
1699 }
1700 pvt->_lstnr->addReadFileDescriptor((filedescriptor *)this);
1701 return pvt->_lstnr->listen(sec,usec);
1702 }
1703
waitForNonBlockingWrite(int32_t sec,int32_t usec) const1704 int32_t filedescriptor::waitForNonBlockingWrite(
1705 int32_t sec, int32_t usec) const {
1706 if (!pvt->_lstnr) {
1707 pvt->_lstnr=new listener();
1708 } else {
1709 pvt->_lstnr->removeAllFileDescriptors();
1710 }
1711 pvt->_lstnr->addWriteFileDescriptor((filedescriptor *)this);
1712 return pvt->_lstnr->listen(sec,usec);
1713 }
1714
translateByteOrder()1715 void filedescriptor::translateByteOrder() {
1716 pvt->_translatebyteorder=true;
1717 }
1718
dontTranslateByteOrder()1719 void filedescriptor::dontTranslateByteOrder() {
1720 pvt->_translatebyteorder=false;
1721 }
1722
createPipe(filedescriptor * readfd,filedescriptor * writefd)1723 bool filedescriptor::createPipe(filedescriptor *readfd,
1724 filedescriptor *writefd) {
1725 int32_t result;
1726 int fd[2];
1727 error::clearError();
1728 do {
1729 #if defined(RUDIMENTS_HAVE_PIPE)
1730 result=pipe(fd);
1731 #elif defined(RUDIMENTS_HAVE__PIPE)
1732 result=_pipe(fd,1024,0);
1733 #else
1734 #error no pipe or anything like it
1735 #endif
1736 } while (result==-1 && error::getErrorNumber()==EINTR);
1737 if (!result) {
1738 if (readfd) {
1739 readfd->setFileDescriptor(fd[0]);
1740 }
1741 if (writefd) {
1742 writefd->setFileDescriptor(fd[1]);
1743 }
1744 }
1745 return !result;
1746 }
1747
hostToNet(uint16_t value)1748 uint16_t filedescriptor::hostToNet(uint16_t value) {
1749 return htons(value);
1750 }
1751
hostToNet(uint32_t value)1752 uint32_t filedescriptor::hostToNet(uint32_t value) {
1753 return htonl(value);
1754 }
1755
hostToNet(uint64_t value)1756 uint64_t filedescriptor::hostToNet(uint64_t value) {
1757 #if defined(RUDIMENTS_HAVE_HTONLL)
1758 return htonll(value);
1759 #elif __BYTE_ORDER == __BIG_ENDIAN
1760 return value;
1761 #elif defined(RUDIMENTS_HAVE_BSWAP_64)
1762 return bswap_64(value);
1763 #elif defined(RUDIMENTS_HAVE___BSWAP64)
1764 return __bswap64(value);
1765 #elif defined(RUDIMENTS_HAVE_BSWAP64)
1766 return bswap64(value);
1767 #elif defined(RUDIMENTS_HAVE_SWAP64)
1768 return swap64(value);
1769 #elif defined(RUDIMENTS_HAVE_SWAP_INT64)
1770 return __swap_int64(value);
1771 #elif defined(RUDIMENTS_HAVE_OSSWAPHOSTTOLITTLEINT64)
1772 return OSSwapHostToLittleInt64(value);
1773 #else
1774 #ifdef RUDIMENTS_HAVE_LONG_LONG
1775 return
1776 (((uint64_t)hostToNet(
1777 (uint32_t)(value&0x00000000FFFFFFFFLL)))<<32)|
1778 ((uint64_t)hostToNet(
1779 (uint32_t)((value&0xFFFFFFFF00000000LL)>>32)));
1780 #else
1781 return htonl(value);
1782 #endif
1783 #endif
1784 }
1785
netToHost(uint16_t value)1786 uint16_t filedescriptor::netToHost(uint16_t value) {
1787 return ntohs(value);
1788 }
1789
netToHost(uint32_t value)1790 uint32_t filedescriptor::netToHost(uint32_t value) {
1791 return ntohl(value);
1792 }
1793
netToHost(uint64_t value)1794 uint64_t filedescriptor::netToHost(uint64_t value) {
1795 #if defined(RUDIMENTS_HAVE_NTOHLL)
1796 return ntohll(value);
1797 #elif __BYTE_ORDER == __BIG_ENDIAN
1798 return value;
1799 #elif defined(RUDIMENTS_HAVE_BSWAP_64)
1800 return bswap_64(value);
1801 #elif defined(RUDIMENTS_HAVE___BSWAP64)
1802 return __bswap64(value);
1803 #elif defined(RUDIMENTS_HAVE_BSWAP64)
1804 return bswap64(value);
1805 #elif defined(RUDIMENTS_HAVE_SWAP64)
1806 return swap64(value);
1807 #elif defined(RUDIMENTS_HAVE_SWAP_INT64)
1808 return __swap_int64(value);
1809 #elif defined(RUDIMENTS_HAVE_OSSWAPLITTLETOHOSTINT64)
1810 return OSSwapLittleToHostInt64(value);
1811 #else
1812 #ifdef RUDIMENTS_HAVE_LONG_LONG
1813 return
1814 (((uint64_t)netToHost(
1815 (uint32_t)(value&0x00000000FFFFFFFFLL)))<<32)|
1816 ((uint64_t)netToHost(
1817 (uint32_t)((value&0xFFFFFFFF00000000LL)>>32)));
1818 #else
1819 return ntohl(value);
1820 #endif
1821 #endif
1822 }
1823
hostToLittleEndian(uint16_t value)1824 uint16_t filedescriptor::hostToLittleEndian(uint16_t value) {
1825 #if __BYTE_ORDER == __LITTLE_ENDIAN
1826 return value;
1827 #else
1828 return (((value&0x00FF)<<8)|((value&0xFF00)>>8));
1829 #endif
1830 }
1831
hostToLittleEndian(uint32_t value)1832 uint32_t filedescriptor::hostToLittleEndian(uint32_t value) {
1833 #if __BYTE_ORDER == __LITTLE_ENDIAN
1834 return value;
1835 #else
1836 return (((value&0x000000FF)<<24)|
1837 ((value&0x0000FF00)<<8)|
1838 ((value&0x00FF0000)>>8)|
1839 ((value&0xFF000000)>>24));
1840 #endif
1841 }
1842
hostToLittleEndian(uint64_t value)1843 uint64_t filedescriptor::hostToLittleEndian(uint64_t value) {
1844 #if __BYTE_ORDER == __LITTLE_ENDIAN
1845 return value;
1846 #else
1847 #ifdef RUDIMENTS_HAVE_LONG_LONG
1848 uint32_t low=(uint32_t)
1849 (value&0x00000000FFFFFFFFLL);
1850 uint32_t high=(uint32_t)
1851 ((value&0xFFFFFFFF00000000LL)>>32);
1852 low=(((low&0x000000FF)<<24)|
1853 ((low&0x0000FF00)<<8)|
1854 ((low&0x00FF0000)>>8)|
1855 ((low&0xFF000000)>>24));
1856 high=(((high&0x000000FF)<<24)|
1857 ((high&0x0000FF00)<<8)|
1858 ((high&0x00FF0000)>>8)|
1859 ((high&0xFF000000)>>24));
1860 return (((uint64_t)high)|(((uint64_t)low)<<32));
1861 #else
1862 return hostToLittleEndian((uint32_t)value);
1863 #endif
1864 #endif
1865 }
1866
littleEndianToHost(uint16_t value)1867 uint16_t filedescriptor::littleEndianToHost(uint16_t value) {
1868 #if __BYTE_ORDER == __LITTLE_ENDIAN
1869 return value;
1870 #else
1871 return (((value&0x00FF)<<8)|((value&0xFF00)>>8));
1872 #endif
1873 }
1874
littleEndianToHost(uint32_t value)1875 uint32_t filedescriptor::littleEndianToHost(uint32_t value) {
1876 #if __BYTE_ORDER == __LITTLE_ENDIAN
1877 return value;
1878 #else
1879 return (((value&0x000000FF)<<24)|
1880 ((value&0x0000FF00)<<8)|
1881 ((value&0x00FF0000)>>8)|
1882 ((value&0xFF000000)>>24));
1883 #endif
1884 }
1885
littleEndianToHost(uint64_t value)1886 uint64_t filedescriptor::littleEndianToHost(uint64_t value) {
1887 #if __BYTE_ORDER == __LITTLE_ENDIAN
1888 return value;
1889 #else
1890 #ifdef RUDIMENTS_HAVE_LONG_LONG
1891 uint32_t low=(uint32_t)
1892 (value&0x00000000FFFFFFFFLL);
1893 uint32_t high=(uint32_t)
1894 ((value&0xFFFFFFFF00000000LL)>>32);
1895 low=(((low&0x000000FF)<<24)|
1896 ((low&0x0000FF00)<<8)|
1897 ((low&0x00FF0000)>>8)|
1898 ((low&0xFF000000)>>24));
1899 high=(((high&0x000000FF)<<24)|
1900 ((high&0x0000FF00)<<8)|
1901 ((high&0x00FF0000)>>8)|
1902 ((high&0xFF000000)>>24));
1903 return (((uint64_t)high)|(((uint64_t)low)<<32));
1904 #else
1905 return littleEndianToHost((uint32_t)value);
1906 #endif
1907 #endif
1908 }
1909
fCntl(int32_t cmd,long arg) const1910 int32_t filedescriptor::fCntl(int32_t cmd, long arg) const {
1911 #ifdef RUDIMENTS_HAVE_FCNTL
1912 int32_t result;
1913 error::clearError();
1914 do {
1915 result=fcntl(pvt->_fd,cmd,arg);
1916 } while (pvt->_retryinterruptedfcntl && result==-1 &&
1917 error::getErrorNumber()==EINTR);
1918 return result;
1919 #else
1920 return -1;
1921 #endif
1922 }
1923
ioCtl(int32_t cmd,void * arg) const1924 int32_t filedescriptor::ioCtl(int32_t cmd, void *arg) const {
1925 #ifdef RUDIMENTS_HAVE_IOCTL
1926 int32_t result;
1927 error::clearError();
1928 do {
1929 result=ioctl(pvt->_fd,cmd,arg);
1930 } while (pvt->_retryinterruptedioctl && result==-1 &&
1931 error::getErrorNumber()==EINTR);
1932 return result;
1933 #else
1934 return -1;
1935 #endif
1936 }
1937
passFileDescriptor(int32_t fd)1938 bool filedescriptor::passFileDescriptor(int32_t fd) {
1939
1940 #if (defined(RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN) && \
1941 defined(RUDIMENTS_HAVE_CMSGHDR)) || \
1942 defined(RUDIMENTS_HAVE_MSGHDR_MSG_ACCRIGHTS)
1943
1944 // have to use sendmsg to pass a file descriptor.
1945 // sendmsg can only send a msghdr
1946 struct msghdr messageheader;
1947
1948 // these must be null for stream sockets
1949 messageheader.msg_name=NULL;
1950 messageheader.msg_namelen=0;
1951
1952 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_FLAGS
1953 // initialize flags to 0
1954 messageheader.msg_flags=0;
1955 #endif
1956
1957 // must send at least 1 iovector with 1 byte of real data
1958 struct iovec iovector[1];
1959 iovector[0].iov_base=(RUDIMENTS_IOV_BASE_TYPE)" ";
1960 iovector[0].iov_len=sizeof(char);
1961 messageheader.msg_iov=iovector;
1962 messageheader.msg_iovlen=1;
1963
1964 // use other parts of the msghdr structure to send the descriptor
1965 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN
1966
1967 // new-style: the descriptor is passed in the msg_control...
1968
1969 // On OS X 10.7, CMSG_LEN ultimately makes a functon call, so
1970 // this array must be dynamically allocated.
1971 unsigned char *control=new unsigned char[
1972 CMSG_LEN(sizeof(int32_t))];
1973 messageheader.msg_control=(caddr_t)control;
1974 messageheader.msg_controllen=CMSG_LEN(sizeof(int32_t));
1975
1976 struct cmsghdr *cmptr=CMSG_FIRSTHDR(&messageheader);
1977 cmptr->cmsg_level=SOL_SOCKET;
1978 cmptr->cmsg_type=SCM_RIGHTS;
1979 cmptr->cmsg_len=CMSG_LEN(sizeof(int32_t));
1980
1981 bytestring::copy((int32_t *)CMSG_DATA(cmptr),
1982 &fd,sizeof(int32_t));
1983 #else
1984 // old-style: the descriptor is passed in the accrights...
1985 messageheader.msg_accrights=(caddr_t)&fd;
1986 messageheader.msg_accrightslen=sizeof(int32_t);
1987 #endif
1988
1989 // finally, send the msghdr
1990 int32_t result;
1991 error::clearError();
1992 do {
1993 #if defined(RUDIMENTS_HAVE_SENDMSG) || \
1994 defined(RUDIMENTS_HAVE_UNDEFINED_SENDMSG)
1995 result=sendmsg(pvt->_fd,&messageheader,0);
1996 #else
1997 #error no sendmsg or anything like it
1998 #endif
1999 } while (result==-1 && error::getErrorNumber()==EINTR &&
2000 pvt->_retryinterruptedwrites);
2001
2002 // clean up
2003 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN
2004 delete[] control;
2005 #endif
2006
2007 return (result!=-1);
2008
2009 #elif defined(RUDIMENTS_HAVE_DUPLICATEHANDLE)
2010
2011 // get a handle to this process
2012 // Apparently we can't just use GetCurrentProcess() or
2013 // we'll just get the pseudo-handle for our process.
2014 HANDLE localprocesshandle=OpenProcess(PROCESS_DUP_HANDLE,FALSE,
2015 (DWORD)GetCurrentProcessId());
2016 if (!localprocesshandle) {
2017 return false;
2018 }
2019
2020 // tell the other process to go
2021 if (write(true)!=sizeof(bool)) {
2022 return false;
2023 }
2024
2025 // read the process id from the other side
2026 uint32_t otherpid;
2027 if (read(&otherpid)!=sizeof(uint32_t)) {
2028 return false;
2029 }
2030
2031 // get a handle to that process
2032 bool success=true;
2033 HANDLE otherprocesshandle=OpenProcess(PROCESS_DUP_HANDLE,
2034 FALSE,(DWORD)otherpid);
2035 if (!otherprocesshandle) {
2036 success=false;
2037 }
2038
2039 // get the handle from the fd
2040 HANDLE localhandle=INVALID_HANDLE_VALUE;
2041 if (success) {
2042 localhandle=(HANDLE)getHandleFromFileDescriptor(fd);
2043 success=(localhandle!=INVALID_HANDLE_VALUE);
2044 }
2045
2046 // duplicate the handle
2047 HANDLE otherhandle=INVALID_HANDLE_VALUE;
2048 if (success) {
2049 success=(DuplicateHandle(localprocesshandle,
2050 localhandle,
2051 otherprocesshandle,
2052 &otherhandle,
2053 0,TRUE,
2054 DUPLICATE_SAME_ACCESS)==TRUE);
2055 }
2056
2057 // send otherhandle to other process
2058 bool retval=(write((uint64_t)otherhandle)==sizeof(uint64_t));
2059
2060 // close the other process handle
2061 CloseHandle(otherprocesshandle);
2062
2063 // send done flag
2064 return retval;
2065 #else
2066 RUDIMENTS_SET_ENOSYS
2067 return false;
2068 #endif
2069 }
2070
receiveFileDescriptor(int32_t * fd)2071 bool filedescriptor::receiveFileDescriptor(int32_t *fd) {
2072
2073 #if (defined(RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN) && \
2074 defined(RUDIMENTS_HAVE_CMSGHDR)) || \
2075 defined(RUDIMENTS_HAVE_MSGHDR_MSG_ACCRIGHTS)
2076
2077 // have to use recvmsg to receive a file descriptor.
2078 // recvmsg can only send a msghdr
2079 struct msghdr messageheader;
2080
2081 // these must be null for stream sockets
2082 messageheader.msg_name=NULL;
2083 messageheader.msg_namelen=0;
2084
2085 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_FLAGS
2086 // initialize flags to 0
2087 messageheader.msg_flags=0;
2088 #endif
2089
2090 // the process that's going to handoff it's socket will also
2091 // send a single iovector with a single byte of data in it,
2092 // so we'll receive that too
2093 struct iovec iovector[1];
2094 char ptr;
2095 iovector[0].iov_base=(RUDIMENTS_IOV_BASE_TYPE)&ptr;
2096 iovector[0].iov_len=sizeof(char);
2097 messageheader.msg_iov=iovector;
2098 messageheader.msg_iovlen=1;
2099
2100 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN
2101 // new-style: the descriptor is passed in the msg_control...
2102
2103 // On OS X 10.7, CMSG_LEN ultimately makes a functon call, so
2104 // this array must be dynamically allocated.
2105 unsigned char *control=new unsigned char[
2106 CMSG_LEN(sizeof(int32_t))];
2107 messageheader.msg_control=(caddr_t)control;
2108 messageheader.msg_controllen=CMSG_LEN(sizeof(int32_t));
2109 #else
2110 // old-style: the descriptor is received in the accrights...
2111 int32_t newfd;
2112 messageheader.msg_accrights=(caddr_t)&newfd;
2113 messageheader.msg_accrightslen=sizeof(int32_t);
2114 #endif
2115
2116 // receive the msghdr
2117 int32_t result;
2118 error::clearError();
2119 do {
2120 // wait 120 seconds for data to come in
2121 // FIXME: this should be configurable
2122 bool oldwaits=pvt->_retryinterruptedwaits;
2123 pvt->_retryinterruptedwaits=pvt->_retryinterruptedreads;
2124 result=waitForNonBlockingRead(120,0);
2125 pvt->_retryinterruptedwaits=oldwaits;
2126 if (result==RESULT_TIMEOUT) {
2127 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN
2128 delete[] control;
2129 #endif
2130 return false;
2131 }
2132 if (result>-1) {
2133 #if defined(RUDIMENTS_HAVE_RECVMSG) || \
2134 defined(RUDIMENTS_HAVE_UNDEFINED_RECVMSG)
2135 result=recvmsg(pvt->_fd,&messageheader,0);
2136 #else
2137 #error no recvmsg or anything like it
2138 #endif
2139 }
2140 } while (result==-1 && error::getErrorNumber()==EINTR &&
2141 pvt->_retryinterruptedreads);
2142 if (result==-1) {
2143 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN
2144 delete[] control;
2145 #endif
2146 return false;
2147 }
2148
2149
2150 // if we got valid data, set the passed-in descriptor to the
2151 // descriptor we received and return success
2152 #ifdef RUDIMENTS_HAVE_MSGHDR_MSG_CONTROLLEN
2153
2154 struct cmsghdr *cmptr=CMSG_FIRSTHDR(&messageheader);
2155 if (cmptr && cmptr->cmsg_len==CMSG_LEN(sizeof(int32_t)) &&
2156 cmptr->cmsg_level==SOL_SOCKET &&
2157 cmptr->cmsg_type==SCM_RIGHTS) {
2158
2159 bytestring::copy(fd,(int32_t *)CMSG_DATA(cmptr),
2160 sizeof(int32_t));
2161
2162 delete[] control;
2163 return true;
2164 }
2165 #ifdef DEBUG_PASSFD
2166 else {
2167
2168 // if we got bad data, be specific about what was
2169 // wrong, this will help debug problems with different
2170 // platforms
2171 if (!cmptr) {
2172 debugPrintf("%d: ",
2173 (int)process::getProcessId());
2174 debugPrintf("null cmptr\n");
2175 } else {
2176 if (cmptr->cmsg_level!=SOL_SOCKET) {
2177 debugPrintf("%d: ",
2178 (int)process::getProcessId());
2179 debugPrintf("got cmsg_level=%ld",
2180 (long)(cmptr->cmsg_level));
2181 debugPrintf(" instead of %ld",
2182 (long)(SOL_SOCKET));
2183 debugPrintf("\n");
2184 }
2185 if (cmptr->cmsg_type!=SCM_RIGHTS) {
2186 debugPrintf("%d: ",
2187 (int)process::getProcessId());
2188 debugPrintf("got cmsg_type=%ld",
2189 (long)(cmptr->cmsg_type));
2190 debugPrintf(" instead of %ld",
2191 (long)(SCM_RIGHTS));
2192 debugPrintf("\n");
2193 }
2194 }
2195 }
2196 #endif
2197
2198 delete[] control;
2199 #else
2200 if (messageheader.msg_accrightslen==sizeof(int32_t)) {
2201 *fd=newfd;
2202 return true;
2203 }
2204 #endif
2205
2206 // if we're here then we must have received some bad data
2207 return false;
2208
2209 #elif defined(RUDIMENTS_HAVE_DUPLICATEHANDLE)
2210
2211 // wait for the other process to tell us to go
2212 bool go;
2213 if (read(&go)!=sizeof(bool)) {
2214 return false;
2215 }
2216
2217 // send our process id
2218 uint32_t pid=process::getProcessId();
2219 if (write(pid)!=sizeof(uint32_t)) {
2220 return false;
2221 }
2222
2223 // get the handle from the other process
2224 uint64_t handle;
2225 if (read(&handle)!=sizeof(uint64_t)) {
2226 return false;
2227 }
2228
2229 // get file descriptor from handle
2230 if ((HANDLE)handle!=INVALID_HANDLE_VALUE) {
2231 *fd=_open_osfhandle((long)handle,0);
2232 return true;
2233 }
2234 return false;
2235 #else
2236 RUDIMENTS_SET_ENOSYS
2237 return false;
2238 #endif
2239 }
2240
passSocket(int32_t sock)2241 bool filedescriptor::passSocket(int32_t sock) {
2242
2243 #if defined(RUDIMENTS_HAVE_WSADUPLICATESOCKET)
2244
2245 // tell the other process to go
2246 if (write(true)!=sizeof(bool)) {
2247 return false;
2248 }
2249
2250 // read the process id from the other side
2251 uint32_t otherpid;
2252 if (read(&otherpid)!=sizeof(uint32_t)) {
2253 return false;
2254 }
2255
2256 // duplicate the socket
2257 WSAPROTOCOL_INFO wpinfo;
2258 if (WSADuplicateSocket((SOCKET)sock,otherpid,&wpinfo)) {
2259 return false;
2260 }
2261
2262 // write the wsaprotocol_info to the other side
2263 if (write((void *)&wpinfo,sizeof(wpinfo))!=sizeof(wpinfo)) {
2264 return false;
2265 }
2266
2267 // get result from the other process
2268 bool result;
2269 if (read(&result)!=sizeof(bool)) {
2270 return false;
2271 }
2272 return result;
2273 #else
2274 return passFileDescriptor(sock);
2275 #endif
2276 }
2277
receiveSocket(int32_t * sock)2278 bool filedescriptor::receiveSocket(int32_t *sock) {
2279
2280 #if defined(RUDIMENTS_HAVE_WSADUPLICATESOCKET)
2281
2282 // wait for the other process to tell us to go
2283 bool go;
2284 if (read(&go)!=sizeof(bool)) {
2285 return false;
2286 }
2287
2288 // send our process id
2289 uint32_t pid=process::getProcessId();
2290 if (write(pid)!=sizeof(uint32_t)) {
2291 return false;
2292 }
2293
2294 // read a wsaprotocol_info from the other side
2295 WSAPROTOCOL_INFO wpinfo;
2296 if (read((void *)&wpinfo,sizeof(wpinfo))!=sizeof(wpinfo)) {
2297 return false;
2298 }
2299
2300 // create the socket
2301 *sock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,
2302 &wpinfo,0,WSA_FLAG_OVERLAPPED);
2303 bool result=(*sock!=INVALID_SOCKET);
2304
2305 // tell the other process how it went
2306 if (write(result)!=sizeof(bool)) {
2307 return false;
2308 }
2309 return result;
2310 #else
2311 return receiveFileDescriptor(sock);
2312 #endif
2313 }
2314
useNaglesAlgorithm()2315 bool filedescriptor::useNaglesAlgorithm() {
2316 return setNoDelay(0);
2317 }
2318
dontUseNaglesAlgorithm()2319 bool filedescriptor::dontUseNaglesAlgorithm() {
2320 return setNoDelay(1);
2321 }
2322
setNoDelay(int32_t onoff)2323 bool filedescriptor::setNoDelay(int32_t onoff) {
2324 #ifdef TCP_NODELAY
2325 int32_t value=onoff;
2326 return !setSockOpt(IPPROTO_TCP,TCP_NODELAY,
2327 (RUDIMENTS_SETSOCKOPT_OPTVAL_TYPE)&value,
2328 (socklen_t)sizeof(int));
2329 #else
2330 RUDIMENTS_SET_ENOSYS
2331 return false;
2332 #endif
2333 }
2334
getSocketWriteBufferSize(int32_t * size)2335 bool filedescriptor::getSocketWriteBufferSize(int32_t *size) {
2336 socklen_t intsize=sizeof(int);
2337 return getSockOpt(SOL_SOCKET,SO_SNDBUF,
2338 (RUDIMENTS_GETSOCKOPT_OPTVAL_TYPE)size,
2339 &intsize)!=-1;
2340 }
2341
setSocketWriteBufferSize(int32_t size)2342 bool filedescriptor::setSocketWriteBufferSize(int32_t size) {
2343 return !setSockOpt(SOL_SOCKET,SO_SNDBUF,
2344 (RUDIMENTS_SETSOCKOPT_OPTVAL_TYPE)&size,
2345 (socklen_t)sizeof(int));
2346 }
2347
getSocketReadBufferSize(int32_t * size)2348 bool filedescriptor::getSocketReadBufferSize(int32_t *size) {
2349 socklen_t intsize=sizeof(int);
2350 return getSockOpt(SOL_SOCKET,SO_RCVBUF,
2351 (RUDIMENTS_GETSOCKOPT_OPTVAL_TYPE)size,
2352 &intsize)!=-1;
2353 }
2354
setSocketReadBufferSize(int32_t size)2355 bool filedescriptor::setSocketReadBufferSize(int32_t size) {
2356 return setSockOpt(SOL_SOCKET,SO_RCVBUF,
2357 (RUDIMENTS_SETSOCKOPT_OPTVAL_TYPE)&size,
2358 (socklen_t)sizeof(int))!=-1;
2359 }
2360
disableIPv4()2361 bool filedescriptor::disableIPv4() {
2362 #ifdef IPV6_V6ONLY
2363 int32_t no=0;
2364 return setSockOpt(IPPROTO_IPV6,IPV6_V6ONLY,
2365 (void *)&no,
2366 (socklen_t)sizeof(int32_t))!=-1;
2367 #else
2368 RUDIMENTS_SET_ENOSYS
2369 return false;
2370 #endif
2371 }
2372
enableIPv4()2373 bool filedescriptor::enableIPv4() {
2374 #ifdef IPV6_V6ONLY
2375 int32_t yes=1;
2376 return setSockOpt(IPPROTO_IPV6,IPV6_V6ONLY,
2377 (void *)&yes,
2378 (socklen_t)sizeof(int32_t))!=-1;
2379 #else
2380 RUDIMENTS_SET_ENOSYS
2381 return false;
2382 #endif
2383 }
2384
getType() const2385 const char *filedescriptor::getType() const {
2386 return pvt->_type;
2387 }
2388
getPeerAddress() const2389 char *filedescriptor::getPeerAddress() const {
2390
2391 // initialize a socket address structure
2392 struct sockaddr_in clientsin;
2393 RUDIMENTS_SOCKLEN_OR_SIZE_T size=sizeof(clientsin);
2394 bytestring::zero(&clientsin,sizeof(clientsin));
2395
2396 // get the peer address
2397 int32_t result;
2398 error::clearError();
2399 do {
2400 #if defined(RUDIMENTS_HAVE_GETPEERNAME) || \
2401 defined(RUDIMENTS_HAVE_UNDEFINED_GETPEERNAME)
2402 result=getpeername(pvt->_fd,
2403 (struct sockaddr *)&clientsin,
2404 &size);
2405 #else
2406 #error no getpeername or anything like it
2407 #endif
2408 } while (result==-1 && error::getErrorNumber()==EINTR);
2409
2410 // if getpeername was successful and the peer was an inet socket,
2411 // convert the address to a string and return a copy of it,
2412 // otherwise return NULL
2413 if (result!=-1 && ((struct sockaddr *)&clientsin)->sa_family==AF_INET) {
2414 return charstring::duplicate(inet_ntoa(clientsin.sin_addr));
2415 }
2416 return NULL;
2417 }
2418
getSockOpt(int32_t level,int32_t optname,void * optval,socklen_t * optlen)2419 int32_t filedescriptor::getSockOpt(int32_t level, int32_t optname,
2420 void *optval, socklen_t *optlen) {
2421 int32_t result;
2422 RUDIMENTS_SOCKLEN_OR_SIZE_T tempoptlen;
2423 if (optlen) {
2424 tempoptlen=*optlen;
2425 }
2426 error::clearError();
2427 do {
2428 #if defined(RUDIMENTS_HAVE_GETSOCKOPT) || \
2429 defined(RUDIMENTS_HAVE_UNDEFINED_GETSOCKOPT)
2430 result=getsockopt(pvt->_fd,level,optname,
2431 (RUDIMENTS_GETSOCKOPT_OPTVAL_TYPE)optval,
2432 &tempoptlen);
2433 #else
2434 #error no getsockopt or anything like it
2435 #endif
2436 } while (result==-1 && error::getErrorNumber()==EINTR);
2437 if (optlen) {
2438 *optlen=tempoptlen;
2439 }
2440 return result;
2441 }
2442
setSockOpt(int32_t level,int32_t optname,const void * optval,socklen_t optlen)2443 int32_t filedescriptor::setSockOpt(int32_t level, int32_t optname,
2444 const void *optval, socklen_t optlen) {
2445 int32_t result;
2446 error::clearError();
2447 do {
2448 #if defined(RUDIMENTS_HAVE_SETSOCKOPT) || \
2449 defined(RUDIMENTS_HAVE_UNDEFINED_SETSOCKOPT)
2450 result=setsockopt(pvt->_fd,level,optname,
2451 (RUDIMENTS_SETSOCKOPT_OPTVAL_TYPE)optval,
2452 optlen);
2453 #else
2454 #error no setsockopt or anything like it
2455 #endif
2456 } while (result==-1 && error::getErrorNumber()==EINTR);
2457 return result;
2458 }
2459
type() const2460 const char *filedescriptor::type() const {
2461 return pvt->_type;
2462 }
2463
type(const char * tp)2464 void filedescriptor::type(const char *tp) {
2465 pvt->_type=tp;
2466 }
2467
fd() const2468 int32_t filedescriptor::fd() const {
2469 return pvt->_fd;
2470 }
2471
fd(int32_t filedes)2472 void filedescriptor::fd(int32_t filedes) {
2473 setFileDescriptor(filedes);
2474 }
2475
secctx()2476 securitycontext *filedescriptor::secctx() {
2477 return pvt->_secctx;
2478 }
2479
closeOnExec()2480 bool filedescriptor::closeOnExec() {
2481 #if defined(RUDIMENTS_HAVE_FD_CLOEXEC)
2482 return !fCntl(F_SETFD,fCntl(F_GETFD,FD_CLOEXEC)|FD_CLOEXEC);
2483 #elif defined(RUDIMENTS_HAVE_HANDLE_FLAG_INHERIT)
2484 return SetHandleInformation(
2485 (HANDLE)getHandleFromFileDescriptor(pvt->_fd),
2486 HANDLE_FLAG_INHERIT,0)!=0;
2487 #else
2488 #error no FD_CLOEXEC or anything like it
2489 #endif
2490 }
2491
dontCloseOnExec()2492 bool filedescriptor::dontCloseOnExec() {
2493 #if defined(RUDIMENTS_HAVE_FD_CLOEXEC)
2494 return !fCntl(F_SETFD,fCntl(F_GETFD,FD_CLOEXEC)&(~FD_CLOEXEC));
2495 #elif defined(RUDIMENTS_HAVE_HANDLE_FLAG_INHERIT)
2496 return SetHandleInformation(
2497 (HANDLE)getHandleFromFileDescriptor(pvt->_fd),
2498 HANDLE_FLAG_INHERIT,
2499 HANDLE_FLAG_INHERIT)!=0;
2500 #else
2501 #error no FD_CLOEXEC or anything like it
2502 #endif
2503 }
2504
getCloseOnExec()2505 bool filedescriptor::getCloseOnExec() {
2506 #if defined(RUDIMENTS_HAVE_FD_CLOEXEC)
2507 return fCntl(F_GETFD,FD_CLOEXEC);
2508 #elif defined(RUDIMENTS_HAVE_HANDLE_FLAG_INHERIT)
2509 DWORD inherit;
2510 if (GetHandleInformation(
2511 (HANDLE)getHandleFromFileDescriptor(pvt->_fd),
2512 &inherit)) {
2513 return (bool)(inherit&HANDLE_FLAG_INHERIT);
2514 }
2515 return false;
2516 #else
2517 #error no FD_CLOEXEC or anything like it
2518 #endif
2519 }
2520
printf(const char * format,...)2521 size_t filedescriptor::printf(const char *format, ...) {
2522 va_list argp;
2523 va_start(argp,format);
2524 size_t result=printf(format,&argp);
2525 va_end(argp);
2526 return result;
2527 }
2528
printf(const char * format,va_list * argp)2529 size_t filedescriptor::printf(const char *format, va_list *argp) {
2530
2531 ssize_t size=0;
2532
2533 // If we're not buffering writes...
2534 if (!pvt->_writebuffer) {
2535
2536 #ifdef RUDIMENTS_HAVE_VDPRINTF
2537
2538 // use vdprintf if it's available
2539 // (on some platforms (redhat 9), it tends to set
2540 // errno=ESPIPE, even on success, so save/restore
2541 // errno too)
2542 int32_t olderr=error::getErrorNumber();
2543 int result=vdprintf(pvt->_fd,format,*argp);
2544 if (result>-1) {
2545 error::setErrorNumber(olderr);
2546 }
2547 return result;
2548
2549 #else
2550
2551 // otherwise use vfprintf, if we can
2552 FILE *f=NULL;
2553 if (pvt->_fd==0) {
2554 f=stdin;
2555 } else if (pvt->_fd==1) {
2556 f=stdout;
2557 } else if (pvt->_fd==2) {
2558 f=stderr;
2559 }
2560
2561 // Use fdopen if it's available. Unfortunately we
2562 // can't (reliably) on Windows because it won't work
2563 // if the filedescriptor is a socket.
2564 #if defined(RUDIMENTS_HAVE_FDOPEN) && \
2565 defined(FD) && !defined(_WIN32)
2566 else {
2567 f=fdopen(pvt->_fd,"a");
2568
2569 // Some platforms (Unixware) don't like "a"
2570 // with some types of file descriptors, so if
2571 // "a" fails, then try "w".
2572 if (!f) {
2573 f=fdopen(pvt->_fd,"w");
2574 }
2575 }
2576 #endif
2577
2578 if (f) {
2579 size=vfprintf(f,format,*argp);
2580 fflush(f);
2581
2582 #if defined(RUDIMENTS_HAVE_FDOPEN) && \
2583 defined(FD) && !defined(_WIN32)
2584 if (f!=stdin && f!=stdout && f!=stderr) {
2585
2586 // We need to free f but we don't want
2587 // fclose() to close pvt->_fd. There's
2588 // no standard way of doing this though.
2589 //
2590 // Setting f's file descriptor member
2591 // to -1 is generally reliable, though
2592 // that's tricky too...
2593
2594 // The size and signedness of
2595 // FD varies a bit. This
2596 // is the only way to handle
2597 // all variations without the
2598 // compiler throwing errors.
2599 if (sizeof(FD)==1) {
2600 int8_t i8=-1;
2601 bytestring::copy(&(FD),&i8,1);
2602 } else if (sizeof(FD)==2) {
2603 int16_t i16=-1;
2604 bytestring::copy(&(FD),&i16,2);
2605 } else if (sizeof(FD)==4) {
2606 int32_t i32=-1;
2607 bytestring::copy(&(FD),&i32,4);
2608 } else if (sizeof(FD)==8) {
2609 int64_t i64=-1;
2610 bytestring::copy(&(FD),&i64,8);
2611 }
2612
2613 // ok, now close f
2614 fclose(f);
2615 }
2616 #endif
2617
2618 return size;
2619 }
2620 #endif
2621 }
2622
2623 // If we are buffering writes though, don't use the above because it
2624 // would bypass the buffer.
2625
2626 // write the formatted data to a buffer
2627 char *buffer=NULL;
2628 #ifdef RUDIMENTS_HAVE_VASPRINTF
2629 size=vasprintf(&buffer,format,*argp);
2630 #else
2631 size=charstring::printf(&buffer,format,argp);
2632 #endif
2633
2634 // write the buffer to the file descriptor
2635 write(buffer,size);
2636
2637 // clean up
2638 #ifdef RUDIMENTS_HAVE_VASPRINTF
2639 free(buffer);
2640 #else
2641 delete[] buffer;
2642 #endif
2643
2644 return size;
2645 }
2646
safePrint(char c)2647 void filedescriptor::safePrint(char c) {
2648 safePrint((unsigned char)c);
2649 }
2650
safePrint(const char * string,int32_t length)2651 void filedescriptor::safePrint(const char *string, int32_t length) {
2652 safePrint((const unsigned char *)string,length);
2653 }
2654
safePrint(const char * string)2655 void filedescriptor::safePrint(const char *string) {
2656 safePrint((const unsigned char *)string);
2657 }
2658
2659 static char hex[17]="0123456789ABCDEF";
2660
safePrint(unsigned char c)2661 void filedescriptor::safePrint(unsigned char c) {
2662 if (c=='\r') {
2663 printf("\\r");
2664 } else if (c=='\n') {
2665 printf("\\n");
2666 } else if (c==' ') {
2667 printf("\\t");
2668 } else if (c>=' ' && c<='~') {
2669 printf("%c",c);
2670 } else {
2671 unsigned int uintc=(unsigned char)c;
2672 printf("(0x%c%c|%d)",hex[((c>>4)&0x0F)],hex[(c&0x0F)],uintc);
2673 }
2674 }
2675
safePrint(const unsigned char * string,int32_t length)2676 void filedescriptor::safePrint(const unsigned char *string, int32_t length) {
2677 for (int32_t i=0; i<length; i++) {
2678 safePrint(*string);
2679 string++;
2680 }
2681 }
2682
safePrint(const unsigned char * string)2683 void filedescriptor::safePrint(const unsigned char *string) {
2684 safePrint(string,charstring::length((const char *)string));
2685 }
2686
printBits(unsigned char value)2687 void filedescriptor::printBits(unsigned char value) {
2688 printBits((const unsigned char *)&value,sizeof(value));
2689 }
2690
printBits(uint16_t value)2691 void filedescriptor::printBits(uint16_t value) {
2692 printBits((const unsigned char *)&value,sizeof(value));
2693 }
2694
printBits(uint32_t value)2695 void filedescriptor::printBits(uint32_t value) {
2696 printBits((const unsigned char *)&value,sizeof(value));
2697 }
2698
printBits(uint64_t value)2699 void filedescriptor::printBits(uint64_t value) {
2700 printBits((const unsigned char *)&value,sizeof(value));
2701 }
2702
printBits(char value)2703 void filedescriptor::printBits(char value) {
2704 printBits((const unsigned char *)&value,sizeof(value));
2705 }
2706
printBits(int16_t value)2707 void filedescriptor::printBits(int16_t value) {
2708 printBits((const unsigned char *)&value,sizeof(value));
2709 }
2710
printBits(int32_t value)2711 void filedescriptor::printBits(int32_t value) {
2712 printBits((const unsigned char *)&value,sizeof(value));
2713 }
2714
printBits(int64_t value)2715 void filedescriptor::printBits(int64_t value) {
2716 printBits((const unsigned char *)&value,sizeof(value));
2717 }
2718
printBits(const unsigned char * bits,uint64_t size)2719 void filedescriptor::printBits(const unsigned char *bits, uint64_t size) {
2720 for (uint64_t i=0; i<size; i++) {
2721 unsigned char byte=bits[i];
2722 for (int8_t j=7; j>=0; j--) {
2723 printf("%d",(byte>>j)&0x01);
2724 }
2725 }
2726 }
2727
2728 #if defined(_WIN32) && defined(RUDIMENTS_HAVE_LONG_LONG)
invalidParameterHandler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t preserved)2729 static void invalidParameterHandler(const wchar_t *expression,
2730 const wchar_t *function,
2731 const wchar_t *file,
2732 unsigned int line,
2733 uintptr_t preserved) {
2734 // don't do anything
2735 }
2736 #endif
2737
getHandleFromFileDescriptor(int32_t fd)2738 void *filedescriptor::getHandleFromFileDescriptor(int32_t fd) {
2739 #if defined(_WIN32)
2740 #if defined(RUDIMENTS_HAVE_LONG_LONG)
2741 if (fd<0) {
2742 return INVALID_HANDLE_VALUE;
2743 }
2744 _invalid_parameter_handler oldiph=
2745 _set_invalid_parameter_handler(invalidParameterHandler);
2746 intptr_t handle=_get_osfhandle(fd);
2747 _set_invalid_parameter_handler(oldiph);
2748 return (void *)handle;
2749 #else
2750 // this is dangerous, and can crash if fd is invalid,
2751 // but I'm not sure what else to do
2752 return (void *)_get_osfhandle(fd);
2753 #endif
2754 #else
2755 return NULL;
2756 #endif
2757 }
2758