s6_fdholder_getdump.c (2553B)
1 /* ISC license. */ 2 3 #include <string.h> 4 #include <stdint.h> 5 #include <errno.h> 6 7 #include <skalibs/uint32.h> 8 #include <skalibs/allreadwrite.h> 9 #include <skalibs/tai.h> 10 #include <skalibs/genalloc.h> 11 #include <skalibs/djbunix.h> 12 #include <skalibs/unixmessage.h> 13 14 #include <s6/fdholder.h> 15 16 #include <skalibs/posixishard.h> 17 18 int s6_fdholder_getdump (s6_fdholder_t *a, genalloc *g, tain const *deadline, tain *stamp) 19 { 20 unixmessage m = { .s = "?", .len = 1, .fds = 0, .nfds = 0 } ; 21 uint32_t ntot, n ; 22 size_t oldlen = genalloc_len(s6_fdholder_fd_t, g) ; 23 unsigned int i = 0 ; 24 int ok ; 25 if (!unixmessage_put(&a->connection.out, &m)) return 0 ; 26 if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; 27 if (sanitize_read(unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) < 0) return 0 ; 28 if (!m.len || m.nfds) return (errno = EPROTO, 0) ; 29 if (m.s[0]) return (errno = (unsigned char)m.s[0], 0) ; 30 if (m.len != 9) return (errno = EPROTO, 0) ; 31 uint32_unpack_big(m.s + 1, &n) ; 32 uint32_unpack_big(m.s + 5, &ntot) ; 33 if (!ntot) return 1 ; 34 if (n != 1 + (ntot-1) / UNIXMESSAGE_MAXFDS) return (errno = EPROTO, 0) ; 35 ok = genalloc_readyplus(s6_fdholder_fd_t, g, ntot) ; 36 37 for (; i < n ; i++) 38 { 39 if (sanitize_read(unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) < 0) goto err ; 40 if (genalloc_len(s6_fdholder_fd_t, g) + m.nfds > ntot) goto droperr ; 41 if (ok) 42 { 43 s6_fdholder_fd_t *tab = genalloc_s(s6_fdholder_fd_t, g) + genalloc_len(s6_fdholder_fd_t, g) ; 44 unsigned int j = 0 ; 45 for (; j < m.nfds ; j++) 46 { 47 unsigned char thislen ; 48 if (m.len < TAIN_PACK + 3) goto droperr ; 49 tain_unpack(m.s, &tab[j].limit) ; 50 m.s += TAIN_PACK ; m.len -= TAIN_PACK + 1 ; 51 thislen = *m.s++ ; 52 if (thislen > m.len - 1 || m.s[thislen]) goto droperr ; 53 memcpy(tab[j].id, m.s, thislen) ; 54 memset(tab[j].id + thislen, 0, S6_FDHOLDER_ID_SIZE + 1 - thislen) ; 55 m.s += (size_t)thislen + 1 ; m.len -= (size_t)thislen + 1 ; 56 tab[j].fd = m.fds[j] ; 57 } 58 genalloc_setlen(s6_fdholder_fd_t, g, genalloc_len(s6_fdholder_fd_t, g) + m.nfds) ; 59 } 60 else unixmessage_drop(&m) ; 61 } 62 63 if (!ok) return (errno = ENOMEM, 0) ; 64 return 1 ; 65 66 droperr: 67 unixmessage_drop(&m) ; 68 errno = EPROTO ; 69 err: 70 { 71 size_t j = genalloc_len(s6_fdholder_fd_t, g) ; 72 while (j-- > oldlen) fd_close(genalloc_s(s6_fdholder_fd_t, g)[j].fd) ; 73 genalloc_setlen(s6_fdholder_fd_t, g, oldlen) ; 74 } 75 return 0 ; 76 }