s6

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

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 }