LCOV - code coverage report
Current view: top level - util/io - fd_io.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 158 301 52.5 %
Date: 2024-11-13 11:58:15 Functions: 6 7 85.7 %

          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             : 
      20             : int
      21             : fd_io_read( int     fd,
      22             :             void *  _dst,
      23             :             ulong   dst_min,
      24             :             ulong   dst_max,
      25      227763 :             ulong * _dst_sz ) {
      26             : 
      27      227763 :   if( FD_UNLIKELY( dst_max==0UL ) ) {
      28           6 :     *_dst_sz = 0UL;
      29           6 :     return 0;
      30           6 :   }
      31             : 
      32      227757 :   uchar * dst = (uchar *)_dst;
      33             : 
      34      227757 :   ulong dst_sz = 0UL;
      35      227757 :   do {
      36             : 
      37             :     /* Note: POSIX indicates read with sz larger than SSIZE_MAX (which
      38             :        is the same as LONG_MAX here) is IB.  While this is an
      39             :        impractically large value nowadays, we don't take chances. */
      40             : 
      41      227757 :     long  ssz = read( fd, dst+dst_sz, fd_ulong_min( dst_max-dst_sz, (ulong)LONG_MAX ) );
      42      227757 :     ulong rsz = (ulong)ssz;
      43             : 
      44      227757 :     if( FD_UNLIKELY( !((0L<ssz) & (rsz<=(dst_max-dst_sz))) ) ) {
      45             : 
      46             :       /* At this point, ssz is not in [1,dst_max-dst_sz] */
      47             : 
      48          30 :       if( FD_LIKELY( !ssz ) ) { /* hit EOF */
      49          24 :         *_dst_sz = dst_sz;
      50          24 :         return -1;
      51          24 :       }
      52             : 
      53             :       /* At this point, ssz is not in [0,dst_max-dst_sz].  Thus, ssz
      54             :          should be -1 and errno should be set.  If errno is set to
      55             :          EAGAIN, it appears that fd is configured as non-blocking and,
      56             :          because we have not yet read dst_min, we try again.  Because of
      57             :          glitches in the POSIX spec, read is also allowed to use
      58             :          EWOULDBLOCK for this and EWOULDBLOCK is not required to have
      59             :          the same value as EAGAIN (if EAGAIN==EWOULDBLOCK on the target,
      60             :          the compiler will almost certainly optimize out the unnecessary
      61             :          cmov). */
      62             : 
      63           6 :       int err = errno;
      64           6 :       if( err==EWOULDBLOCK ) err = EAGAIN; /* cmov / no-op */
      65           6 :       if( FD_UNLIKELY( (dst_sz<dst_min) & (err==EAGAIN) ) ) continue;
      66             : 
      67             :       /* At this point, ssz is not in [0,dst_max-dst_sz].  ssz should be
      68             :          -1 and errno set (and not EWOULDBLOCK).  If not, read does not
      69             :          seem to be following POSIX and we flag such as EPROTO (which
      70             :          should not be used as an errno case for read above and is at
      71             :          least suggestive of the issue) to make a strong guarantee to
      72             :          the caller. */
      73             : 
      74           6 :       if( !err ) err = EPROTO; /* cmov */
      75           6 :       *_dst_sz = 0UL;
      76           6 :       return err;
      77           6 :     }
      78             : 
      79             :     /* At this point, rsz is in [1,dst_max-dst_sz] */
      80             : 
      81      227727 :     dst_sz += rsz;
      82      227727 :   } while( dst_sz<dst_min );
      83             : 
      84      227727 :   *_dst_sz = dst_sz;
      85      227727 :   return 0;
      86      227757 : }
      87             : 
      88             : int
      89             : fd_io_write( int          fd,
      90             :              void const * _src,
      91             :              ulong        src_min,
      92             :              ulong        src_max,
      93      518976 :              ulong *      _src_sz ) {
      94             : 
      95      518976 :   if( FD_UNLIKELY( src_max==0UL ) ) {
      96           6 :     *_src_sz = 0UL;
      97           6 :     return 0;
      98           6 :   }
      99             : 
     100             :   /* Note: this is virtually identical to read.  See read for more
     101             :      details. */
     102             : 
     103      518970 :   uchar const * src = (uchar const *)_src;
     104             : 
     105      518970 :   ulong src_sz = 0UL;
     106      518970 :   do {
     107             : 
     108      518970 :     long  ssz = write( fd, src+src_sz, fd_ulong_min( src_max-src_sz, (ulong)LONG_MAX ) );
     109      518970 :     ulong wsz = (ulong)ssz;
     110             : 
     111      518970 :     if( FD_UNLIKELY( !((0L<ssz) & (wsz<=(src_max-src_sz))) ) ) {
     112             : 
     113             :       /* Note: The POSIX spec explicitly indicates _reads_ use ssz
     114             :          -1 and errno EAGAIN/EWOULDBLOCK for no-data-available-now and
     115             :          ssz 0 for end-of-file to explicitly disambiguate these cases.
     116             :          It also specifically indicates that _writes_ follow the same
     117             :          convention to keep read and write call return handling similar
     118             :          even though there is no POSIX concept of an end-of-file for
     119             :          writes.  At the same time, there seem to be no cases in the
     120             :          standard where a write with a positive size (as it is above)
     121             :          should return 0.  So, we skip "EOF" handling here.  If a zero
     122             :          ssz unexpectedly occurs, it will be likely be treated as an
     123             :          EPROTO below. */
     124             : 
     125             : #     if 0
     126             :       if( FD_UNLIKELY( !ssz ) ) {
     127             :         *_src_sz = src_sz;
     128             :         return -1;
     129             :       }
     130             : #     endif
     131             : 
     132           6 :       int err = errno;
     133           6 :       if( err==EWOULDBLOCK ) err = EAGAIN;
     134           6 :       if( FD_UNLIKELY( (src_sz<src_min) & (err==EAGAIN) ) ) continue;
     135             : 
     136           6 :       if( !err ) err = EPROTO;
     137           6 :       *_src_sz = 0UL;
     138           6 :       return err;
     139           6 :     }
     140             : 
     141      518964 :     src_sz += wsz;
     142      518964 :   } while( src_sz<src_min );
     143             : 
     144      518964 :   *_src_sz = src_sz;
     145      518964 :   return 0;
     146      518970 : }
     147             : 
     148             : int
     149             : fd_io_buffered_read( int     fd,
     150             :                      void *  _dst,
     151             :                      ulong   dst_sz,
     152             :                      void *  _rbuf,
     153             :                      ulong   rbuf_sz,
     154             :                      ulong * _rbuf_lo,
     155      823734 :                      ulong * _rbuf_ready ) {
     156             : 
     157      823734 :   if( FD_UNLIKELY( !dst_sz ) ) return 0; /* Nothing to do ... optimize for non-trivial read */
     158             : 
     159      823635 :   uchar * dst        = (uchar *)_dst;
     160      823635 :   uchar * rbuf       = (uchar *)_rbuf;
     161      823635 :   ulong   rbuf_lo    = *_rbuf_lo;
     162      823635 :   ulong   rbuf_ready = *_rbuf_ready;
     163             : 
     164      823635 :   ulong rsz;
     165             : 
     166      823635 :   if( FD_LIKELY( rbuf_ready ) ) { /* Optimize for lots of tiny reads */
     167             : 
     168             :     /* At this point we have at least one byte already buffered and one
     169             :        byte to write.  Copy as many bytes as possible from rbuf into
     170             :        dst. */
     171             : 
     172      815550 :     ulong cpy_sz = fd_ulong_min( dst_sz, rbuf_ready ); /* At least 1 and either dst_sz or rbuf_ready */
     173      815550 :     fd_memcpy( dst, rbuf + rbuf_lo, cpy_sz );
     174      815550 :     dst    += cpy_sz;
     175      815550 :     dst_sz -= cpy_sz;
     176             : 
     177             :     /* If this completed the read, we are done. */
     178             : 
     179      815550 :     if( FD_LIKELY( !dst_sz ) ) { /* Optimize for lots of tiny reads */
     180      737031 :       *_rbuf_lo    = rbuf_lo    + cpy_sz;
     181      737031 :       *_rbuf_ready = rbuf_ready - cpy_sz;
     182      737031 :       return 0;
     183      737031 :     }
     184             : 
     185             :     /* At this point we have more bytes to read, which implies cpy_sz
     186             :        was less than dst_sz, which implies cpy_sz was rbuf_ready, which
     187             :        implies rbuf is empty because it was drained above. */
     188      815550 :   }
     189             : 
     190             :   /* At this point, rbuf is empty and we have at least one byte to read. */
     191             : 
     192       86604 :   if( FD_UNLIKELY( dst_sz>=rbuf_sz ) ) { /* If we have a large amount of data to read ... (optimize for tiny reads) */
     193             : 
     194             : #   if 0 /* This implementation guarantees at most one fd read per call but will not block fd reads */
     195             : 
     196             :     /* Read it directly into dst */
     197             : 
     198             :     *_rbuf_lo    = 0UL;
     199             :     *_rbuf_ready = 0UL;
     200             :     return fd_io_read( fd, dst, dst_sz, dst_sz, &rsz );
     201             : 
     202             : #   else /* This implementation will block fd reads into multiples of rbuf_sz */
     203             : 
     204             :     /* Read the largest rbuf_sz multiple directly into dst. */
     205             : 
     206       11451 :     ulong bulk_sz = rbuf_sz*(dst_sz/rbuf_sz); /* TODO: require rbuf_sz to be a power of 2 for faster performance here? */
     207             : 
     208       11451 :     int err = fd_io_read( fd, dst, bulk_sz, bulk_sz, &rsz );
     209       11451 :     if( FD_UNLIKELY( err ) ) {
     210           9 :       *_rbuf_lo    = 0UL;
     211           9 :       *_rbuf_ready = 0UL;
     212           9 :       return err;
     213           9 :     }
     214             : 
     215       11442 :     dst    += bulk_sz;
     216       11442 :     dst_sz -= bulk_sz;
     217             : 
     218             :     /* If this completed the read, we are done. */
     219             : 
     220       11442 :     if( FD_LIKELY( !dst_sz ) ) { /* Optimize for tiny reads */
     221         240 :       *_rbuf_lo    = 0UL;
     222         240 :       *_rbuf_ready = 0UL;
     223         240 :       return 0;
     224         240 :     }
     225             : 
     226             :     /* At this point, we have dst_sz in [1,rbuf_sz) bytes to read */
     227             : 
     228       11442 : #   endif
     229             : 
     230       11442 :   }
     231             : 
     232             :   /* At this point, we have dst_sz in [1,rbuf_sz).  Fill up rbuf
     233             :      as much as we can and return the results from there. */
     234             : 
     235       86355 :   int err = fd_io_read( fd, rbuf, dst_sz, rbuf_sz, &rsz );
     236       86355 :   if( FD_UNLIKELY( err ) ) { /* failed (err>0,rsz==0) or EOF (err<0,rsz<dst_sz), either way, we can't handle the request */
     237           0 :     *_rbuf_lo    = 0UL;
     238           0 :     *_rbuf_ready = 0UL;
     239           0 :     return err;
     240           0 :   }
     241             : 
     242       86355 :   fd_memcpy( dst, rbuf, dst_sz );
     243       86355 :   *_rbuf_lo    = dst_sz;
     244       86355 :   *_rbuf_ready = rsz - dst_sz;
     245       86355 :   return 0;
     246       86355 : }
     247             : 
     248             : int
     249             : fd_io_buffered_skip( int     fd,
     250             :                      ulong   skip_sz,
     251             :                      void *  rbuf,
     252             :                      ulong   rbuf_sz,
     253             :                      ulong * _rbuf_lo,
     254        1197 :                      ulong * _rbuf_ready ) {
     255             : 
     256             :   /* For large skips, flush rbuf and lseek the fd for the remainder.
     257             :      TODO: Consider a variant where fd lseek is aligned to a rbuf_sz
     258             :      like the above (such might require this function to do some
     259             :      buffering of data if the skip_sz isn't an rbuf_sz multiple). */
     260             : 
     261        1197 :   ulong rbuf_ready = *_rbuf_ready;
     262             : 
     263        1197 :   if( FD_UNLIKELY( skip_sz>rbuf_ready ) ) { /* Optimize for tiny skips */
     264             : 
     265        1080 :     skip_sz -= rbuf_ready; /* At least 1 */
     266        1080 :     do {
     267             : 
     268             :       /* Note: lseek allows seeking past EOF (even on a RDONLY fd). */
     269             : 
     270        1080 :       ulong lseek_sz = fd_ulong_min( skip_sz, (ulong)LONG_MAX ); /* Workaround POSIX sign / unsigned glitches */
     271        1080 :       if( FD_UNLIKELY( lseek( fd, (long)lseek_sz, SEEK_CUR )==-1L ) ) {
     272             : 
     273           0 :         int err = errno;
     274             : 
     275           0 :         if( FD_UNLIKELY( err==ESPIPE ) ) {
     276             : 
     277             :           /* It appears the stream isn't seekable ... skip over via
     278             :              actual reads.  It is kinda gross that we do this every time
     279             :              we have to skip on an unseekable stream.  At the same time,
     280             :              such usages are likely so low bandwidth and so rare that
     281             :              the perf hit from just doing the spurious lseeks is
     282             :              probably in the noise and not worth the extra overhead /
     283             :              complexity to do more elaborate handling. */
     284             : 
     285           0 :           do {
     286           0 :             ulong read_sz = fd_ulong_min( rbuf_sz, skip_sz );
     287           0 :             ulong rsz;
     288           0 :             err = fd_io_read( fd, rbuf, read_sz, read_sz, &rsz );
     289           0 :             if( FD_UNLIKELY( !((!err) | (err==EAGAIN)) ) ) break;
     290           0 :             skip_sz -= rsz;
     291           0 :           } while( skip_sz );
     292             : 
     293           0 :           *_rbuf_lo    = 0UL;
     294           0 :           *_rbuf_ready = 0UL;
     295           0 :           return err;
     296             : 
     297           0 :         }
     298             : 
     299           0 :         if( !err ) err = EPROTO; /* cmov, paranoia for non-conform to provide strong guarantees to caller */
     300             : 
     301           0 :         *_rbuf_lo    = 0UL;
     302           0 :         *_rbuf_ready = 0UL;
     303           0 :         return err;
     304           0 :       }
     305             : 
     306        1080 :       skip_sz -= lseek_sz;
     307        1080 :     } while( FD_UNLIKELY( skip_sz ) );
     308             : 
     309        1080 :     *_rbuf_lo    = 0UL;
     310        1080 :     *_rbuf_ready = 0UL;
     311        1080 :     return 0;
     312        1080 :   }
     313             : 
     314             :   /* Skip is purely over buffered bytes */
     315             : 
     316         117 :   *_rbuf_lo    += skip_sz;
     317         117 :   *_rbuf_ready  = rbuf_ready - skip_sz;
     318         117 :   return 0;
     319        1197 : }
     320             : 
     321             : int
     322             : fd_io_buffered_write( int          fd,
     323             :                       void const * _src,
     324             :                       ulong        src_sz,
     325             :                       void *       _wbuf,
     326             :                       ulong        wbuf_sz,
     327      826659 :                       ulong *      _wbuf_used ) {
     328             : 
     329      826659 :   if( FD_UNLIKELY( !src_sz ) ) return 0; /* Nothing to do ... optimize for non-trivial writes */
     330             : 
     331      826635 :   uchar const * src  = (uchar const *)_src;
     332      826635 :   uchar *       wbuf = (uchar *)      _wbuf;
     333             : 
     334      826635 :   ulong wsz;
     335             : 
     336      826635 :   ulong wbuf_used = *_wbuf_used;
     337             : 
     338      826635 :   if( FD_LIKELY( wbuf_used ) ) { /* Optimize for lots of tiny writes */
     339             : 
     340             :     /* At this point, we have at least one byte already buffered and one
     341             :        byte to write.  Copy as many bytes as possible from src into
     342             :        wbuf. */
     343             : 
     344      738201 :     ulong cpy_sz = fd_ulong_min( wbuf_sz - wbuf_used, src_sz ); /* cpy_sz>=1, cpy_sz is either wbuf_free or src_sz */
     345             : 
     346      738201 :     if( FD_LIKELY( cpy_sz ) ) fd_memcpy( wbuf + wbuf_used, src, cpy_sz );
     347             : 
     348      738201 :     src       += cpy_sz;
     349      738201 :     src_sz    -= cpy_sz;
     350      738201 :     wbuf_used += cpy_sz;
     351             : 
     352             :     /* If this filled up the buffer, flush it */
     353             : 
     354      738201 :     if( FD_UNLIKELY( wbuf_used >= wbuf_sz ) ) { /* Optimize for lots of tiny writes */
     355       55962 :       int err = fd_io_write( fd, wbuf, wbuf_sz, wbuf_sz, &wsz );
     356       55962 :       if( FD_UNLIKELY( err ) ) {
     357           0 :         *_wbuf_used = 0UL;
     358           0 :         return err;
     359           0 :       }
     360       55962 :       wbuf_used = 0UL;
     361       55962 :     }
     362             : 
     363             :     /* If this completed the write, we are done. */
     364             : 
     365      738201 :     if( FD_LIKELY( !src_sz ) ) { /* Optimize for lots of tiny writes */
     366      682290 :       *_wbuf_used = wbuf_used;
     367      682290 :       return 0;
     368      682290 :     }
     369             : 
     370             :     /* At this point, we have more bytes to write, which implies cpy_sz
     371             :        was less than src_sz, which implies cpy_sz was wbuf_free, which
     372             :        implies wbuf is empty because it was flushed above. */
     373             : 
     374      738201 :   }
     375             : 
     376             :   /* At this point, wbuf is empty and we have at least one byte to
     377             :      write. */
     378             : 
     379      144345 :   if( FD_UNLIKELY( src_sz>=wbuf_sz ) ) { /* If we have a large amount of data to write ... (optimize for tiny writes) */
     380             : 
     381             : #   if 0 /* This implementation guarantees at most one fd write per call but will not block fd writes */
     382             : 
     383             :     /* Write it directly from src */
     384             : 
     385             :     *_wbuf_used = 0UL;
     386             :     return fd_io_write( fd, src, src_sz, src_sz, &wsz );
     387             : 
     388             : #   else /* This implementation will block fd writes into multiples of wbuf_sz */
     389             : 
     390             :     /* Write the largest wbuf_sz multiple directly into src. */
     391             : 
     392        9963 :     ulong bulk_sz = wbuf_sz*(src_sz/wbuf_sz); /* TODO: require wbuf_sz to be a power of 2 for faster performance here? */
     393             : 
     394        9963 :     int err = fd_io_write( fd, src, bulk_sz, bulk_sz, &wsz );
     395        9963 :     if( FD_UNLIKELY( err ) ) {
     396           0 :       *_wbuf_used = 0UL;
     397           0 :       return err;
     398           0 :     }
     399             : 
     400        9963 :     src    += bulk_sz;
     401        9963 :     src_sz -= bulk_sz;
     402             : 
     403             :     /* If this completed the write, we are done. */
     404             : 
     405        9963 :     if( FD_LIKELY( !src_sz ) ) { /* Optimize for tiny writes */
     406         120 :       *_wbuf_used = 0UL;
     407         120 :       return 0;
     408         120 :     }
     409             : 
     410             :     /* At this point, we have src_sz in [1,wbuf_sz) bytes to write. */
     411             : 
     412        9963 : #   endif
     413             : 
     414        9963 :   }
     415             : 
     416             :   /* At this point, we have src_sz in [1,wbuf_sz) and an empty
     417             :      buffer.  Buffer these bytes. */
     418             : 
     419      144225 :   fd_memcpy( wbuf, src, src_sz );
     420      144225 :   *_wbuf_used = src_sz;
     421      144225 :   return 0;
     422      144345 : }
     423             : 
     424             : char const *
     425         177 : fd_io_strerror( int err ) {
     426             : 
     427             :   /* This covers the standard POSIX-2008 errnos.  We handle the POSIX
     428             :      glitches around EWOULDBLOCK / EAGAIN and EOPNOTSUPP / ENOTSUP so
     429             :      this will build fine regardless of whether these map to the same
     430             :      or different error codes (they typically map to the same nowadays).
     431             :      We also throw in negative values for EOF as that is how the above
     432             :      handles such. */
     433             : 
     434         177 :   if( err<0 ) return "end-of-file";
     435             : 
     436         174 :   if( err==EWOULDBLOCK ) err = EAGAIN;  /* cmov / no-op */
     437         174 :   if( err==EOPNOTSUPP  ) err = ENOTSUP; /* cmov / no-op */
     438             : 
     439         174 :   switch( err ) {
     440           3 :   case 0              : return "success";
     441           0 :   case E2BIG          : return "E2BIG-argument list too long";
     442         147 :   case EACCES         : return "EACCES-permission denied";
     443           0 :   case EADDRINUSE     : return "EADDRINUSE-address already in use";
     444           0 :   case EADDRNOTAVAIL  : return "EADDRNOTAVAIL-cannot assign requested address";
     445           0 :   case EAFNOSUPPORT   : return "EAFNOSUPPORT-address family not supported by protocol";
     446           0 :   case EAGAIN         : return "EAGAIN-resource temporarily unavailable";
     447           0 :   case EALREADY       : return "EALREADY-operation already in progress";
     448           3 :   case EBADF          : return "EBADF-bad file descriptor";
     449           0 :   case EBADMSG        : return "EBADMSG-bad message";
     450           0 :   case EBUSY          : return "EBUSY-device or resource busy";
     451           0 :   case ECANCELED      : return "ECANCELED-operation canceled";
     452           0 :   case ECHILD         : return "ECHILD-no child processes";
     453           0 :   case ECONNABORTED   : return "ECONNABORTED-software caused connection abort";
     454           0 :   case ECONNREFUSED   : return "ECONNREFUSED-connection refused";
     455           0 :   case ECONNRESET     : return "ECONNRESET-connection reset by peer";
     456           0 :   case EDEADLK        : return "EDEADLK-resource deadlock avoided";
     457           0 :   case EDESTADDRREQ   : return "EDESTADDRREQ-destination address required";
     458           0 :   case EDOM           : return "EDOM-numerical argument out of domain";
     459           0 :   case EEXIST         : return "EEXIST-file exists";
     460           0 :   case EFAULT         : return "EFAULT-bad address";
     461           0 :   case EFBIG          : return "EFBIG-file too large";
     462           0 :   case EHOSTUNREACH   : return "EHOSTUNREACH-no route to host";
     463           0 :   case EIDRM          : return "EIDRM-identifier removed";
     464           0 :   case EILSEQ         : return "EILSEQ-invalid or incomplete multibyte or wide character";
     465           0 :   case EINPROGRESS    : return "EINPROGRESS-operation now in progress";
     466           0 :   case EINTR          : return "EINTR-interrupted system call";
     467           0 :   case EINVAL         : return "EINVAL-invalid argument";
     468           0 :   case EIO            : return "EIO-input/output error";
     469           0 :   case EISCONN        : return "EISCONN-transport endpoint is already connected";
     470           0 :   case EISDIR         : return "EISDIR-is a directory";
     471           0 :   case ELOOP          : return "ELOOP-too many levels of symbolic links";
     472           0 :   case EMFILE         : return "EMFILE-too many open files";
     473           0 :   case EMLINK         : return "EMLINK-too many links";
     474           0 :   case EMSGSIZE       : return "EMSGSIZE-message too long";
     475           0 :   case ENAMETOOLONG   : return "ENAMETOOLONG-file name too long";
     476           0 :   case ENETDOWN       : return "ENETDOWN-network is down";
     477           0 :   case ENETRESET      : return "ENETRESET-network dropped connection on reset";
     478           0 :   case ENETUNREACH    : return "ENETUNREACH-network is unreachable";
     479           0 :   case ENFILE         : return "ENFILE-too many open files in system";
     480           0 :   case ENOBUFS        : return "ENOBUFS-no buffer space available";
     481           0 :   case ENODEV         : return "ENODEV-no such device";
     482           0 :   case ENOENT         : return "ENOENT-no such file or directory";
     483           0 :   case ENOEXEC        : return "ENOEXEC-exec format error";
     484           0 :   case ENOLCK         : return "ENOLCK-no locks available";
     485          21 :   case ENOMEM         : return "ENOMEM-cannot allocate memory";
     486           0 :   case ENOMSG         : return "ENOMSG-no message of desired type";
     487           0 :   case ENOPROTOOPT    : return "ENOPROTOOPT-protocol not available";
     488           0 :   case ENOSPC         : return "ENOSPC-no space left on device";
     489           0 :   case ENOSYS         : return "ENOSYS-function not implemented";
     490           0 :   case ENOTCONN       : return "ENOTCONN-transport endpoint is not connected";
     491           0 :   case ENOTDIR        : return "ENOTDIR-not a directory";
     492           0 :   case ENOTEMPTY      : return "ENOTEMPTY-directory not empty";
     493           0 :   case ENOTRECOVERABLE: return "ENOTRECOVERABLE-state not recoverable";
     494           0 :   case ENOTSOCK       : return "ENOTSOCK-socket operation on non-socket";
     495           0 :   case ENOTSUP        : return "ENOTSUP-operation not supported";
     496           0 :   case ENOTTY         : return "ENOTTY-inappropriate ioctl for device";
     497           0 :   case ENXIO          : return "ENXIO-no such device or address";
     498           0 :   case EOVERFLOW      : return "EOVERFLOW-value too large for defined data type";
     499           0 :   case EOWNERDEAD     : return "EOWNERDEAD-owner died";
     500           0 :   case EPERM          : return "EPERM-operation not permitted";
     501           0 :   case EPIPE          : return "EPIPE-broken pipe";
     502           0 :   case EPROTONOSUPPORT: return "EPROTONOSUPPORT-protocol not supported";
     503           0 :   case EPROTO         : return "EPROTO-protocol error";
     504           0 :   case EPROTOTYPE     : return "EPROTOTYPE-protocol wrong type for socket";
     505           0 :   case ERANGE         : return "ERANGE-numerical result out of range";
     506           0 :   case EROFS          : return "EROFS-read-only file system";
     507           0 :   case ESPIPE         : return "ESPIPE-illegal seek";
     508           0 :   case ESRCH          : return "ESRCH-no such process";
     509           0 :   case ETIMEDOUT      : return "ETIMEDOUT-connection timed out";
     510           0 :   case ETXTBSY        : return "ETXTBSY-text file busy";
     511           0 :   case EXDEV          : return "EXDEV-invalid cross-device link";
     512           0 :   default: break;
     513         174 :   }
     514             : 
     515           0 :   return "unknown";
     516         174 : }
     517             : 
     518             : char const *
     519           0 : fd_io_strsignal( int sig ) {
     520           0 :   switch( sig ) {
     521           0 :   case 0              : return "success";
     522           0 :   case SIGHUP         : return "SIGHUP-Hangup";
     523           0 :   case SIGINT         : return "SIGINT-Interrupt";
     524           0 :   case SIGQUIT        : return "SIGQUIT-Quit";
     525           0 :   case SIGILL         : return "SIGILL-Illegal instruction";
     526           0 :   case SIGTRAP        : return "SIGTRAP-Trace/breakpoint trap";
     527           0 :   case SIGABRT        : return "SIGABRT-Aborted";
     528           0 :   case SIGBUS         : return "SIGBUS-Bus error";
     529           0 :   case SIGFPE         : return "SIGFPE-Arithmetic exception";
     530           0 :   case SIGKILL        : return "SIGKILL-Killed";
     531           0 :   case SIGUSR1        : return "SIGUSR1-User defined signal 1";
     532           0 :   case SIGSEGV        : return "SIGSEGV-Segmentation fault";
     533           0 :   case SIGUSR2        : return "SIGUSR2-User defined signal 2";
     534           0 :   case SIGPIPE        : return "SIGPIPE-Broken pipe";
     535           0 :   case SIGALRM        : return "SIGALRM-Alarm clock";
     536           0 :   case SIGTERM        : return "SIGTERM-Terminated";
     537           0 : #if defined(SIGSTKFLT)
     538           0 :   case SIGSTKFLT      : return "SIGSTKFLT-Stack fault";
     539             : #elif defined(SIGEMT)
     540             :   case SIGEMT         : return "SIGEMT-Emulator trap";
     541             : #endif
     542           0 :   case SIGCHLD        : return "SIGCHLD-Child process status";
     543           0 :   case SIGCONT        : return "SIGCONT-Continued";
     544           0 :   case SIGSTOP        : return "SIGSTOP-Stopped (signal)";
     545           0 :   case SIGTSTP        : return "SIGTSTP-Stopped";
     546           0 :   case SIGTTIN        : return "SIGTTIN-Stopped (tty input)";
     547           0 :   case SIGTTOU        : return "SIGTTOU-Stopped (tty output)";
     548           0 :   case SIGURG         : return "SIGURG-Urgent I/O condition";
     549           0 :   case SIGXCPU        : return "SIGXCPU-CPU time limit exceeded";
     550           0 :   case SIGXFSZ        : return "SIGXFSZ-File size limit exceeded";
     551           0 :   case SIGVTALRM      : return "SIGVTALRM-Virtual timer expired";
     552           0 :   case SIGPROF        : return "SIGPROF-Profiling timer expired";
     553           0 : #if defined(SIGWINCH)
     554           0 :   case SIGWINCH       : return "SIGWINCH-Window changed";
     555           0 : #endif
     556           0 : #if defined(SIGPOLL)
     557           0 :   case SIGPOLL        : return "SIGPOLL-I/O possible";
     558           0 : #endif
     559           0 : #if defined(SIGPWR)
     560           0 :   case SIGPWR         : return "SIGPWR-Power failure";
     561           0 : #endif
     562           0 :   case SIGSYS         : return "SIGSYS-Bad system call";
     563           0 :   default: break;
     564           0 :   }
     565             : 
     566           0 :   return "unknown";
     567           0 : }
     568             : 
     569             : #else
     570             : #error "Unknown FD_IO_STYLE"
     571             : #endif

Generated by: LCOV version 1.14