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 }