s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

s6_dtally_read.c (1318B)


      1 /* ISC license. */
      2 
      3 #include <sys/stat.h>
      4 #include <string.h>
      5 #include <unistd.h>
      6 #include <errno.h>
      7 
      8 #include <skalibs/allreadwrite.h>
      9 #include <skalibs/tai.h>
     10 #include <skalibs/djbunix.h>
     11 #include <s6/supervise.h>
     12 
     13 static int truncit (char const *s)
     14 {
     15   int fd = open_trunc(s) ;
     16   if (fd < 0) return -1 ;
     17   fd_close(fd) ;
     18   return 0 ;
     19 }
     20 
     21 ssize_t s6_dtally_read (char const *sv, s6_dtally_t *tab, size_t max)
     22 {
     23   int e = errno ;
     24   size_t len = strlen(sv) ;
     25   size_t n ;
     26   int fd ;
     27   struct stat st ;
     28   char fn[len + sizeof(S6_DTALLY_FILENAME) + 1] ;
     29   memcpy(fn, sv, len) ;
     30   memcpy(fn + len, "/" S6_DTALLY_FILENAME, sizeof(S6_DTALLY_FILENAME) + 1) ;
     31   fd = open_read(fn) ;
     32   if (fd < 0) return errno == ENOENT ? truncit(fn) : -1 ;
     33   if (fstat(fd, &st) < 0) goto err ;
     34   if (st.st_size % S6_DTALLY_PACK)
     35   {
     36     fd_close(fd) ;
     37     return truncit(fn) ;
     38   }
     39   n = st.st_size / S6_DTALLY_PACK ;
     40   if (n > max) n = max ;
     41   {
     42     char tmp[n ? S6_DTALLY_PACK * n : 1] ;
     43     if (lseek(fd, -(off_t)(n * S6_DTALLY_PACK), SEEK_END) < 0) goto err ;
     44     errno = EPIPE ;
     45     if (allread(fd, tmp, n * S6_DTALLY_PACK) < n * S6_DTALLY_PACK) goto err ;
     46     fd_close(fd) ;
     47     for (size_t i = 0 ; i < n ; i++) s6_dtally_unpack(tmp + i * S6_DTALLY_PACK, tab + i) ;
     48   }
     49   errno = e ;
     50   return n ;
     51 
     52  err:
     53   fd_close(fd) ;
     54   return -1 ;
     55 }