Line data Source code
1 : #include "fd_io.h"
2 :
3 : /* TODO: try to eliminate use of FD_LOG_STYLE in log if possible in
4 : favor of FD_IO_STYLE here. */
5 :
6 : #ifndef FD_IO_STYLE
7 : #if FD_HAS_HOSTED
8 : #define FD_IO_STYLE 0
9 : #else
10 : #error "Define FD_IO_STYLE for this platform"
11 : #endif
12 : #endif
13 :
14 : #if FD_IO_STYLE==0 /* POSIX style */
15 :
16 : #include <errno.h>
17 : #include <signal.h>
18 : #include <unistd.h>
19 : #include <sys/stat.h>
20 : #include <sys/mman.h>
21 :
22 : int
23 : fd_io_read( int fd,
24 : void * _dst,
25 : ulong dst_min,
26 : ulong dst_max,
27 544785 : ulong * _dst_sz ) {
28 :
29 544785 : if( FD_UNLIKELY( dst_max==0UL ) ) {
30 12 : *_dst_sz = 0UL;
31 12 : return 0;
32 12 : }
33 :
34 544773 : uchar * dst = (uchar *)_dst;
35 :
36 544773 : ulong dst_sz = 0UL;
37 544773 : do {
38 :
39 : /* Note: POSIX indicates read with sz larger than SSIZE_MAX (which
40 : is the same as LONG_MAX here) is IB. While this is an
41 : impractically large value nowadays, we don't take chances. */
42 :
43 544773 : long ssz = read( fd, dst+dst_sz, fd_ulong_min( dst_max-dst_sz, (ulong)LONG_MAX ) );
44 544773 : ulong rsz = (ulong)ssz;
45 :
46 544773 : if( FD_UNLIKELY( !((0L<ssz) & (rsz<=(dst_max-dst_sz))) ) ) {
47 :
48 : /* At this point, ssz is not in [1,dst_max-dst_sz] */
49 :
50 30 : if( FD_LIKELY( !ssz ) ) { /* hit EOF */
51 24 : *_dst_sz = dst_sz;
52 24 : return -1;
53 24 : }
54 :
55 : /* At this point, ssz is not in [0,dst_max-dst_sz]. Thus, ssz
56 : should be -1 and errno should be set. If errno is set to
57 : EAGAIN, it appears that fd is configured as non-blocking and,
58 : because we have not yet read dst_min, we try again. Because of
59 : glitches in the POSIX spec, read is also allowed to use
60 : EWOULDBLOCK for this and EWOULDBLOCK is not required to have
61 : the same value as EAGAIN (if EAGAIN==EWOULDBLOCK on the target,
62 : the compiler will almost certainly optimize out the unnecessary
63 : cmov). */
64 :
65 6 : int err = errno;
66 6 : if( err==EWOULDBLOCK ) err = EAGAIN; /* cmov / no-op */
67 6 : if( FD_UNLIKELY( (dst_sz<dst_min) & (err==EAGAIN) ) ) continue;
68 :
69 : /* At this point, ssz is not in [0,dst_max-dst_sz]. ssz should be
70 : -1 and errno set (and not EWOULDBLOCK). If not, read does not
71 : seem to be following POSIX and we flag such as EPROTO (which
72 : should not be used as an errno case for read above and is at
73 : least suggestive of the issue) to make a strong guarantee to
74 : the caller. */
75 :
76 6 : if( !err ) err = EPROTO; /* cmov */
77 6 : *_dst_sz = 0UL;
78 6 : return err;
79 6 : }
80 :
81 : /* At this point, rsz is in [1,dst_max-dst_sz] */
82 :
83 544743 : dst_sz += rsz;
84 544743 : } while( dst_sz<dst_min );
85 :
86 544743 : *_dst_sz = dst_sz;
87 544743 : return 0;
88 544773 : }
89 :
90 : int
91 : fd_io_write( int fd,
92 : void const * _src,
93 : ulong src_min,
94 : ulong src_max,
95 862609 : ulong * _src_sz ) {
96 :
97 862609 : if( FD_UNLIKELY( src_max==0UL ) ) {
98 12 : *_src_sz = 0UL;
99 12 : return 0;
100 12 : }
101 :
102 : /* Note: this is virtually identical to read. See read for more
103 : details. */
104 :
105 862597 : uchar const * src = (uchar const *)_src;
106 :
107 862597 : ulong src_sz = 0UL;
108 862597 : do {
109 :
110 862597 : long ssz = write( fd, src+src_sz, fd_ulong_min( src_max-src_sz, (ulong)LONG_MAX ) );
111 862597 : ulong wsz = (ulong)ssz;
112 :
113 862597 : if( FD_UNLIKELY( !((0L<ssz) & (wsz<=(src_max-src_sz))) ) ) {
114 :
115 : /* Note: The POSIX spec explicitly indicates _reads_ use ssz
116 : -1 and errno EAGAIN/EWOULDBLOCK for no-data-available-now and
117 : ssz 0 for end-of-file to explicitly disambiguate these cases.
118 : It also specifically indicates that _writes_ follow the same
119 : convention to keep read and write call return handling similar
120 : even though there is no POSIX concept of an end-of-file for
121 : writes. At the same time, there seem to be no cases in the
122 : standard where a write with a positive size (as it is above)
123 : should return 0. So, we skip "EOF" handling here. If a zero
124 : ssz unexpectedly occurs, it will be likely be treated as an
125 : EPROTO below. */
126 :
127 : # if 0
128 : if( FD_UNLIKELY( !ssz ) ) {
129 : *_src_sz = src_sz;
130 : return -1;
131 : }
132 : # endif
133 :
134 6 : int err = errno;
135 6 : if( err==EWOULDBLOCK ) err = EAGAIN;
136 6 : if( FD_UNLIKELY( (src_sz<src_min) & (err==EAGAIN) ) ) continue;
137 :
138 6 : if( !err ) err = EPROTO;
139 6 : *_src_sz = 0UL;
140 6 : return err;
141 6 : }
142 :
143 862591 : src_sz += wsz;
144 862591 : } while( src_sz<src_min );
145 :
146 862591 : *_src_sz = src_sz;
147 862591 : return 0;
148 862597 : }
149 :
150 : int
151 : fd_io_sz( int fd,
152 3051951 : ulong * _sz ) {
153 3051951 : struct stat stat[1];
154 :
155 3051951 : int ret = fstat( fd, stat );
156 3051951 : off_t sz = stat->st_size;
157 3051951 : if( FD_UNLIKELY( !((ret==0) & (((off_t)0)<=sz) & (((ulong)sz)<=((ulong)LONG_MAX))) ) ) {
158 9 : int err = errno;
159 9 : if( !err ) err = EPROTO;
160 9 : *_sz = 0UL;
161 9 : return err;
162 9 : }
163 :
164 3051942 : *_sz = (ulong)sz;
165 3051942 : return 0;
166 3051951 : }
167 :
168 : int
169 : fd_io_truncate( int fd,
170 12294 : ulong sz ) {
171 12294 : if( FD_UNLIKELY( (sz>(ulong)LONG_MAX) | (sz!=(ulong)(off_t)sz) ) ) return EINVAL;
172 12291 : if( FD_UNLIKELY( ftruncate( fd, (off_t)sz ) ) ) {
173 3 : int err = errno;
174 3 : if( !err ) err = EPROTO;
175 3 : return err;
176 3 : }
177 12288 : return 0;
178 12291 : }
179 :
180 : int
181 : fd_io_seek( int fd,
182 : long rel_off,
183 : int type,
184 3099774 : ulong * _idx ) {
185 3099774 : static int const whence[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
186 :
187 3099774 : if( FD_UNLIKELY( !((0<=type) & (type<=3) & (rel_off==(long)(off_t)rel_off)) ) ) {
188 3 : *_idx = 0UL;
189 3 : return EINVAL;
190 3 : }
191 :
192 3099771 : off_t idx = lseek( fd, (off_t)rel_off, whence[ type ] );
193 :
194 3099771 : if( FD_UNLIKELY( !((((off_t)0)<=idx) & (((ulong)idx)<=((ulong)LONG_MAX))) ) ) {
195 6 : int err = errno;
196 6 : if( !err ) err = EPROTO;
197 6 : *_idx = 0UL;
198 6 : return err;
199 6 : }
200 :
201 3099765 : *_idx = (ulong)idx;
202 3099765 : return 0;
203 3099771 : }
204 :
205 : int
206 : fd_io_buffered_read( int fd,
207 : void * _dst,
208 : ulong dst_sz,
209 : void * _rbuf,
210 : ulong rbuf_sz,
211 : ulong * _rbuf_lo,
212 802908 : ulong * _rbuf_ready ) {
213 :
214 802908 : if( FD_UNLIKELY( !dst_sz ) ) return 0; /* Nothing to do ... optimize for non-trivial read */
215 :
216 802812 : uchar * dst = (uchar *)_dst;
217 802812 : uchar * rbuf = (uchar *)_rbuf;
218 802812 : ulong rbuf_lo = *_rbuf_lo;
219 802812 : ulong rbuf_ready = *_rbuf_ready;
220 :
221 802812 : ulong rsz;
222 :
223 802812 : if( FD_LIKELY( rbuf_ready ) ) { /* Optimize for lots of tiny reads */
224 :
225 : /* At this point we have at least one byte already buffered and one
226 : byte to write. Copy as many bytes as possible from rbuf into
227 : dst. */
228 :
229 791880 : ulong cpy_sz = fd_ulong_min( dst_sz, rbuf_ready ); /* At least 1 and either dst_sz or rbuf_ready */
230 791880 : fd_memcpy( dst, rbuf + rbuf_lo, cpy_sz );
231 791880 : dst += cpy_sz;
232 791880 : dst_sz -= cpy_sz;
233 :
234 : /* If this completed the read, we are done. */
235 :
236 791880 : if( FD_LIKELY( !dst_sz ) ) { /* Optimize for lots of tiny reads */
237 710607 : *_rbuf_lo = rbuf_lo + cpy_sz;
238 710607 : *_rbuf_ready = rbuf_ready - cpy_sz;
239 710607 : return 0;
240 710607 : }
241 :
242 : /* At this point we have more bytes to read, which implies cpy_sz
243 : was less than dst_sz, which implies cpy_sz was rbuf_ready, which
244 : implies rbuf is empty because it was drained above. */
245 791880 : }
246 :
247 : /* At this point, rbuf is empty and we have at least one byte to read. */
248 :
249 92205 : if( FD_UNLIKELY( dst_sz>=rbuf_sz ) ) { /* If we have a large amount of data to read ... (optimize for tiny reads) */
250 :
251 : # if 0 /* This implementation guarantees at most one fd read per call but will not block fd reads */
252 :
253 : /* Read it directly into dst */
254 :
255 : *_rbuf_lo = 0UL;
256 : *_rbuf_ready = 0UL;
257 : return fd_io_read( fd, dst, dst_sz, dst_sz, &rsz );
258 :
259 : # else /* This implementation will block fd reads into multiples of rbuf_sz */
260 :
261 : /* Read the largest rbuf_sz multiple directly into dst. */
262 :
263 15561 : ulong bulk_sz = rbuf_sz*(dst_sz/rbuf_sz); /* TODO: require rbuf_sz to be a power of 2 for faster performance here? */
264 :
265 15561 : int err = fd_io_read( fd, dst, bulk_sz, bulk_sz, &rsz );
266 15561 : if( FD_UNLIKELY( err ) ) {
267 9 : *_rbuf_lo = 0UL;
268 9 : *_rbuf_ready = 0UL;
269 9 : return err;
270 9 : }
271 :
272 15552 : dst += bulk_sz;
273 15552 : dst_sz -= bulk_sz;
274 :
275 : /* If this completed the read, we are done. */
276 :
277 15552 : if( FD_LIKELY( !dst_sz ) ) { /* Optimize for tiny reads */
278 225 : *_rbuf_lo = 0UL;
279 225 : *_rbuf_ready = 0UL;
280 225 : return 0;
281 225 : }
282 :
283 : /* At this point, we have dst_sz in [1,rbuf_sz) bytes to read */
284 :
285 15552 : # endif
286 :
287 15552 : }
288 :
289 : /* At this point, we have dst_sz in [1,rbuf_sz). Fill up rbuf
290 : as much as we can and return the results from there. */
291 :
292 91971 : int err = fd_io_read( fd, rbuf, dst_sz, rbuf_sz, &rsz );
293 91971 : if( FD_UNLIKELY( err ) ) { /* failed (err>0,rsz==0) or EOF (err<0,rsz<dst_sz), either way, we can't handle the request */
294 0 : *_rbuf_lo = 0UL;
295 0 : *_rbuf_ready = 0UL;
296 0 : return err;
297 0 : }
298 :
299 91971 : fd_memcpy( dst, rbuf, dst_sz );
300 91971 : *_rbuf_lo = dst_sz;
301 91971 : *_rbuf_ready = rsz - dst_sz;
302 91971 : return 0;
303 91971 : }
304 :
305 : int
306 : fd_io_buffered_skip( int fd,
307 : ulong skip_sz,
308 : void * rbuf,
309 : ulong rbuf_sz,
310 : ulong * _rbuf_lo,
311 1242 : ulong * _rbuf_ready ) {
312 :
313 : /* For large skips, flush rbuf and lseek the fd for the remainder.
314 : TODO: Consider a variant where fd lseek is aligned to a rbuf_sz
315 : like the above (such might require this function to do some
316 : buffering of data if the skip_sz isn't an rbuf_sz multiple). */
317 :
318 1242 : ulong rbuf_ready = *_rbuf_ready;
319 :
320 1242 : if( FD_UNLIKELY( skip_sz>rbuf_ready ) ) { /* Optimize for tiny skips */
321 :
322 1152 : skip_sz -= rbuf_ready; /* At least 1 */
323 1152 : do {
324 :
325 : /* Note: lseek allows seeking past EOF (even on a RDONLY fd). */
326 :
327 1152 : ulong lseek_sz = fd_ulong_min( skip_sz, (ulong)LONG_MAX ); /* Workaround POSIX sign / unsigned glitches */
328 1152 : if( FD_UNLIKELY( lseek( fd, (long)lseek_sz, SEEK_CUR )==-1L ) ) {
329 :
330 0 : int err = errno;
331 :
332 0 : if( FD_UNLIKELY( err==ESPIPE ) ) {
333 :
334 : /* It appears the stream isn't seekable ... skip over via
335 : actual reads. It is kinda gross that we do this every time
336 : we have to skip on an unseekable stream. At the same time,
337 : such usages are likely so low bandwidth and so rare that
338 : the perf hit from just doing the spurious lseeks is
339 : probably in the noise and not worth the extra overhead /
340 : complexity to do more elaborate handling. */
341 :
342 0 : do {
343 0 : ulong read_sz = fd_ulong_min( rbuf_sz, skip_sz );
344 0 : ulong rsz;
345 0 : err = fd_io_read( fd, rbuf, read_sz, read_sz, &rsz );
346 0 : if( FD_UNLIKELY( !((!err) | (err==EAGAIN)) ) ) break;
347 0 : skip_sz -= rsz;
348 0 : } while( skip_sz );
349 :
350 0 : *_rbuf_lo = 0UL;
351 0 : *_rbuf_ready = 0UL;
352 0 : return err;
353 :
354 0 : }
355 :
356 0 : if( !err ) err = EPROTO; /* cmov, paranoia for non-conform to provide strong guarantees to caller */
357 :
358 0 : *_rbuf_lo = 0UL;
359 0 : *_rbuf_ready = 0UL;
360 0 : return err;
361 0 : }
362 :
363 1152 : skip_sz -= lseek_sz;
364 1152 : } while( FD_UNLIKELY( skip_sz ) );
365 :
366 1152 : *_rbuf_lo = 0UL;
367 1152 : *_rbuf_ready = 0UL;
368 1152 : return 0;
369 1152 : }
370 :
371 : /* Skip is purely over buffered bytes */
372 :
373 90 : *_rbuf_lo += skip_sz;
374 90 : *_rbuf_ready = rbuf_ready - skip_sz;
375 90 : return 0;
376 1242 : }
377 :
378 : int
379 : fd_io_buffered_write( int fd,
380 : void const * _src,
381 : ulong src_sz,
382 : void * _wbuf,
383 : ulong wbuf_sz,
384 796953 : ulong * _wbuf_used ) {
385 :
386 796953 : if( FD_UNLIKELY( !src_sz ) ) return 0; /* Nothing to do ... optimize for non-trivial writes */
387 :
388 796926 : uchar const * src = (uchar const *)_src;
389 796926 : uchar * wbuf = (uchar *) _wbuf;
390 :
391 796926 : ulong wsz;
392 :
393 796926 : ulong wbuf_used = *_wbuf_used;
394 :
395 796926 : if( FD_LIKELY( wbuf_used ) ) { /* Optimize for lots of tiny writes */
396 :
397 : /* At this point, we have at least one byte already buffered and one
398 : byte to write. Copy as many bytes as possible from src into
399 : wbuf. */
400 :
401 705141 : ulong cpy_sz = fd_ulong_min( wbuf_sz - wbuf_used, src_sz ); /* cpy_sz>=1, cpy_sz is either wbuf_free or src_sz */
402 :
403 705141 : if( FD_LIKELY( cpy_sz ) ) fd_memcpy( wbuf + wbuf_used, src, cpy_sz );
404 :
405 705141 : src += cpy_sz;
406 705141 : src_sz -= cpy_sz;
407 705141 : wbuf_used += cpy_sz;
408 :
409 : /* If this filled up the buffer, flush it */
410 :
411 705141 : if( FD_UNLIKELY( wbuf_used >= wbuf_sz ) ) { /* Optimize for lots of tiny writes */
412 57858 : int err = fd_io_write( fd, wbuf, wbuf_sz, wbuf_sz, &wsz );
413 57858 : if( FD_UNLIKELY( err ) ) {
414 0 : *_wbuf_used = 0UL;
415 0 : return err;
416 0 : }
417 57858 : wbuf_used = 0UL;
418 57858 : }
419 :
420 : /* If this completed the write, we are done. */
421 :
422 705141 : if( FD_LIKELY( !src_sz ) ) { /* Optimize for lots of tiny writes */
423 647313 : *_wbuf_used = wbuf_used;
424 647313 : return 0;
425 647313 : }
426 :
427 : /* At this point, we have more bytes to write, which implies cpy_sz
428 : was less than src_sz, which implies cpy_sz was wbuf_free, which
429 : implies wbuf is empty because it was flushed above. */
430 :
431 705141 : }
432 :
433 : /* At this point, wbuf is empty and we have at least one byte to
434 : write. */
435 :
436 149613 : if( FD_UNLIKELY( src_sz>=wbuf_sz ) ) { /* If we have a large amount of data to write ... (optimize for tiny writes) */
437 :
438 : # if 0 /* This implementation guarantees at most one fd write per call but will not block fd writes */
439 :
440 : /* Write it directly from src */
441 :
442 : *_wbuf_used = 0UL;
443 : return fd_io_write( fd, src, src_sz, src_sz, &wsz );
444 :
445 : # else /* This implementation will block fd writes into multiples of wbuf_sz */
446 :
447 : /* Write the largest wbuf_sz multiple directly into src. */
448 :
449 14043 : ulong bulk_sz = wbuf_sz*(src_sz/wbuf_sz); /* TODO: require wbuf_sz to be a power of 2 for faster performance here? */
450 :
451 14043 : int err = fd_io_write( fd, src, bulk_sz, bulk_sz, &wsz );
452 14043 : if( FD_UNLIKELY( err ) ) {
453 0 : *_wbuf_used = 0UL;
454 0 : return err;
455 0 : }
456 :
457 14043 : src += bulk_sz;
458 14043 : src_sz -= bulk_sz;
459 :
460 : /* If this completed the write, we are done. */
461 :
462 14043 : if( FD_LIKELY( !src_sz ) ) { /* Optimize for tiny writes */
463 93 : *_wbuf_used = 0UL;
464 93 : return 0;
465 93 : }
466 :
467 : /* At this point, we have src_sz in [1,wbuf_sz) bytes to write. */
468 :
469 14043 : # endif
470 :
471 14043 : }
472 :
473 : /* At this point, we have src_sz in [1,wbuf_sz) and an empty
474 : buffer. Buffer these bytes. */
475 :
476 149520 : fd_memcpy( wbuf, src, src_sz );
477 149520 : *_wbuf_used = src_sz;
478 149520 : return 0;
479 149613 : }
480 :
481 : int
482 : fd_io_mmio_init( int fd,
483 : int mode,
484 : void * _mmio,
485 12357 : ulong * _mmio_sz ) {
486 :
487 : /* Check input args */
488 :
489 12357 : if( FD_UNLIKELY( (mode!=FD_IO_MMIO_MODE_READ_ONLY) & (mode!=FD_IO_MMIO_MODE_READ_WRITE) ) ) {
490 3 : *(void **)_mmio = NULL;
491 3 : *_mmio_sz = 0UL;
492 3 : return EINVAL;
493 3 : }
494 :
495 12354 : int rw = (mode==FD_IO_MMIO_MODE_READ_WRITE);
496 :
497 : /* Determine the file size. If this is a zero length file, just give
498 : the caller a mapping to nothing. */
499 :
500 12354 : ulong mmio_sz;
501 12354 : int err = fd_io_sz( fd, &mmio_sz );
502 12354 : if( FD_UNLIKELY( (!!err) | (!mmio_sz) ) ) {
503 15 : *(void **)_mmio = NULL;
504 15 : *_mmio_sz = 0UL;
505 15 : return err;
506 15 : }
507 :
508 : /* mmap the file into the caller's address space. Note: memory mapped
509 : I/O TLB and NUMA optimization options in Linux / POSIX are
510 : extremely limited. (No support or limited support or buggy support
511 : or conflicting standards or different handling across different
512 : OS/kernels/file systems or ... for requesting huge page backing,
513 : gigantic page backing, NUMA affinities, etc. Page sizes other
514 : than normal and/or NUMA multicore systems were just not a thing
515 : when VM APIs and implementations ossified.) We currently don't
516 : even try here for portability and simplicity.
517 :
518 : FIXME: consider widening to expose features like MAP_POPULATE
519 : and/or MAP_FIXED. Also consider widening to allow callers to
520 : specify their TLB and NUMA needs in hopes that, in a glorious
521 : future, virtual memory APIs and subsystems will come around to the
522 : fact that, as virtual memory is really a distributed file system
523 : under the hood these days where TLB and NUMA optimizations are
524 : critical, TLB and NUMA optimizations are equally critical for file
525 : system files mapped into virtual memory ... this would allow
526 : callers would get the benefits for free once support is available
527 : Probably would need to move these APIs to shmem. */
528 :
529 12339 : void * mmio = mmap( NULL, mmio_sz, rw ? (PROT_READ|PROT_WRITE) : PROT_READ, MAP_SHARED, fd, (off_t)0 );
530 12339 : if( FD_UNLIKELY( (mmio==MAP_FAILED) | (!mmio) ) ) {
531 0 : int err = errno;
532 0 : if( !err ) err = EPROTO; /* cmov */
533 0 : *(void **)_mmio = NULL;
534 0 : *_mmio_sz = 0UL;
535 0 : return err;
536 0 : }
537 :
538 : /* At this point, we've mapped the file */
539 :
540 12339 : *(void **)_mmio = mmio;
541 12339 : *_mmio_sz = mmio_sz;
542 12339 : return 0;
543 12339 : }
544 :
545 : void
546 : fd_io_mmio_fini( void const * mmio,
547 12357 : ulong mmio_sz ) {
548 :
549 : /* Check input args and handle zero length files */
550 :
551 12357 : if( FD_UNLIKELY( (!mmio) | (!mmio_sz) ) ) return;
552 :
553 : /* Handle non-zero length files */
554 :
555 12339 : munmap( (void *)mmio, mmio_sz ); /* note: fd_log not available here so we don't error trap as it makes no difference */
556 12339 : }
557 :
558 : char const *
559 213 : fd_io_strerror( int err ) {
560 :
561 : /* This covers the standard POSIX-2008 errnos. We handle the POSIX
562 : glitches around EWOULDBLOCK / EAGAIN and EOPNOTSUPP / ENOTSUP so
563 : this will build fine regardless of whether these map to the same
564 : or different error codes (they typically map to the same nowadays).
565 : We also throw in negative values for EOF as that is how the above
566 : handles such. */
567 :
568 213 : if( err<0 ) return "end-of-file";
569 :
570 210 : if( err==EWOULDBLOCK ) err = EAGAIN; /* cmov / no-op */
571 210 : if( err==EOPNOTSUPP ) err = ENOTSUP; /* cmov / no-op */
572 :
573 210 : switch( err ) {
574 3 : case 0 : return "success";
575 0 : case E2BIG : return "E2BIG-argument list too long";
576 147 : case EACCES : return "EACCES-permission denied";
577 0 : case EADDRINUSE : return "EADDRINUSE-address already in use";
578 0 : case EADDRNOTAVAIL : return "EADDRNOTAVAIL-cannot assign requested address";
579 0 : case EAFNOSUPPORT : return "EAFNOSUPPORT-address family not supported by protocol";
580 0 : case EAGAIN : return "EAGAIN-resource temporarily unavailable";
581 0 : case EALREADY : return "EALREADY-operation already in progress";
582 3 : case EBADF : return "EBADF-bad file descriptor";
583 0 : case EBADMSG : return "EBADMSG-bad message";
584 0 : case EBUSY : return "EBUSY-device or resource busy";
585 0 : case ECANCELED : return "ECANCELED-operation canceled";
586 0 : case ECHILD : return "ECHILD-no child processes";
587 0 : case ECONNABORTED : return "ECONNABORTED-software caused connection abort";
588 0 : case ECONNREFUSED : return "ECONNREFUSED-connection refused";
589 0 : case ECONNRESET : return "ECONNRESET-connection reset by peer";
590 0 : case EDEADLK : return "EDEADLK-resource deadlock avoided";
591 0 : case EDESTADDRREQ : return "EDESTADDRREQ-destination address required";
592 0 : case EDOM : return "EDOM-numerical argument out of domain";
593 15 : case EEXIST : return "EEXIST-file exists";
594 0 : case EFAULT : return "EFAULT-bad address";
595 0 : case EFBIG : return "EFBIG-file too large";
596 0 : case EHOSTUNREACH : return "EHOSTUNREACH-no route to host";
597 0 : case EIDRM : return "EIDRM-identifier removed";
598 0 : case EILSEQ : return "EILSEQ-invalid or incomplete multibyte or wide character";
599 0 : case EINPROGRESS : return "EINPROGRESS-operation now in progress";
600 0 : case EINTR : return "EINTR-interrupted system call";
601 3 : case EINVAL : return "EINVAL-invalid argument";
602 0 : case EIO : return "EIO-input/output error";
603 0 : case EISCONN : return "EISCONN-transport endpoint is already connected";
604 0 : case EISDIR : return "EISDIR-is a directory";
605 0 : case ELOOP : return "ELOOP-too many levels of symbolic links";
606 0 : case EMFILE : return "EMFILE-too many open files";
607 0 : case EMLINK : return "EMLINK-too many links";
608 0 : case EMSGSIZE : return "EMSGSIZE-message too long";
609 0 : case ENAMETOOLONG : return "ENAMETOOLONG-file name too long";
610 0 : case ENETDOWN : return "ENETDOWN-network is down";
611 0 : case ENETRESET : return "ENETRESET-network dropped connection on reset";
612 0 : case ENETUNREACH : return "ENETUNREACH-network is unreachable";
613 0 : case ENFILE : return "ENFILE-too many open files in system";
614 0 : case ENOBUFS : return "ENOBUFS-no buffer space available";
615 0 : case ENODEV : return "ENODEV-no such device";
616 3 : case ENOENT : return "ENOENT-no such file or directory";
617 0 : case ENOEXEC : return "ENOEXEC-exec format error";
618 0 : case ENOLCK : return "ENOLCK-no locks available";
619 36 : case ENOMEM : return "ENOMEM-cannot allocate memory";
620 0 : case ENOMSG : return "ENOMSG-no message of desired type";
621 0 : case ENOPROTOOPT : return "ENOPROTOOPT-protocol not available";
622 0 : case ENOSPC : return "ENOSPC-no space left on device";
623 0 : case ENOSYS : return "ENOSYS-function not implemented";
624 0 : case ENOTCONN : return "ENOTCONN-transport endpoint is not connected";
625 0 : case ENOTDIR : return "ENOTDIR-not a directory";
626 0 : case ENOTEMPTY : return "ENOTEMPTY-directory not empty";
627 0 : case ENOTRECOVERABLE: return "ENOTRECOVERABLE-state not recoverable";
628 0 : case ENOTSOCK : return "ENOTSOCK-socket operation on non-socket";
629 0 : case ENOTSUP : return "ENOTSUP-operation not supported";
630 0 : case ENOTTY : return "ENOTTY-inappropriate ioctl for device";
631 0 : case ENXIO : return "ENXIO-no such device or address";
632 0 : case EOVERFLOW : return "EOVERFLOW-value too large for defined data type";
633 0 : case EOWNERDEAD : return "EOWNERDEAD-owner died";
634 0 : case EPERM : return "EPERM-operation not permitted";
635 0 : case EPIPE : return "EPIPE-broken pipe";
636 0 : case EPROTONOSUPPORT: return "EPROTONOSUPPORT-protocol not supported";
637 0 : case EPROTO : return "EPROTO-protocol error";
638 0 : case EPROTOTYPE : return "EPROTOTYPE-protocol wrong type for socket";
639 0 : case ERANGE : return "ERANGE-numerical result out of range";
640 0 : case EROFS : return "EROFS-read-only file system";
641 0 : case ESPIPE : return "ESPIPE-illegal seek";
642 0 : case ESRCH : return "ESRCH-no such process";
643 0 : case ETIMEDOUT : return "ETIMEDOUT-connection timed out";
644 0 : case ETXTBSY : return "ETXTBSY-text file busy";
645 0 : case EXDEV : return "EXDEV-invalid cross-device link";
646 0 : default: break;
647 210 : }
648 :
649 0 : return "unknown";
650 210 : }
651 :
652 : char const *
653 0 : fd_io_strsignal( int sig ) {
654 0 : switch( sig ) {
655 0 : case 0 : return "success";
656 0 : case SIGHUP : return "SIGHUP-Hangup";
657 0 : case SIGINT : return "SIGINT-Interrupt";
658 0 : case SIGQUIT : return "SIGQUIT-Quit";
659 0 : case SIGILL : return "SIGILL-Illegal instruction";
660 0 : case SIGTRAP : return "SIGTRAP-Trace/breakpoint trap";
661 0 : case SIGABRT : return "SIGABRT-Aborted";
662 0 : case SIGBUS : return "SIGBUS-Bus error";
663 0 : case SIGFPE : return "SIGFPE-Arithmetic exception";
664 0 : case SIGKILL : return "SIGKILL-Killed";
665 0 : case SIGUSR1 : return "SIGUSR1-User defined signal 1";
666 0 : case SIGSEGV : return "SIGSEGV-Segmentation fault";
667 0 : case SIGUSR2 : return "SIGUSR2-User defined signal 2";
668 0 : case SIGPIPE : return "SIGPIPE-Broken pipe";
669 0 : case SIGALRM : return "SIGALRM-Alarm clock";
670 0 : case SIGTERM : return "SIGTERM-Terminated";
671 0 : #if defined(SIGSTKFLT)
672 0 : case SIGSTKFLT : return "SIGSTKFLT-Stack fault";
673 : #elif defined(SIGEMT)
674 : case SIGEMT : return "SIGEMT-Emulator trap";
675 : #endif
676 0 : case SIGCHLD : return "SIGCHLD-Child process status";
677 0 : case SIGCONT : return "SIGCONT-Continued";
678 0 : case SIGSTOP : return "SIGSTOP-Stopped (signal)";
679 0 : case SIGTSTP : return "SIGTSTP-Stopped";
680 0 : case SIGTTIN : return "SIGTTIN-Stopped (tty input)";
681 0 : case SIGTTOU : return "SIGTTOU-Stopped (tty output)";
682 0 : case SIGURG : return "SIGURG-Urgent I/O condition";
683 0 : case SIGXCPU : return "SIGXCPU-CPU time limit exceeded";
684 0 : case SIGXFSZ : return "SIGXFSZ-File size limit exceeded";
685 0 : case SIGVTALRM : return "SIGVTALRM-Virtual timer expired";
686 0 : case SIGPROF : return "SIGPROF-Profiling timer expired";
687 0 : #if defined(SIGWINCH)
688 0 : case SIGWINCH : return "SIGWINCH-Window changed";
689 0 : #endif
690 0 : #if defined(SIGPOLL)
691 0 : case SIGPOLL : return "SIGPOLL-I/O possible";
692 0 : #endif
693 0 : #if defined(SIGPWR)
694 0 : case SIGPWR : return "SIGPWR-Power failure";
695 0 : #endif
696 0 : case SIGSYS : return "SIGSYS-Bad system call";
697 0 : default: break;
698 0 : }
699 :
700 0 : return "unknown";
701 0 : }
702 :
703 : #else
704 : #error "Unknown FD_IO_STYLE"
705 : #endif
|