s6_fdholder_setdump.c (2967B)
1 /* ISC license. */ 2 3 #include <sys/uio.h> 4 #include <stdint.h> 5 #include <string.h> 6 #include <errno.h> 7 8 #include <skalibs/uint32.h> 9 #include <skalibs/allreadwrite.h> 10 #include <skalibs/bytestr.h> 11 #include <skalibs/error.h> 12 #include <skalibs/tai.h> 13 #include <skalibs/unixmessage.h> 14 15 #include <s6/fdholder.h> 16 17 #include <skalibs/posixishard.h> 18 19 int s6_fdholder_setdump (s6_fdholder_t *a, s6_fdholder_fd_t const *list, unsigned int ntot, tain const *deadline, tain *stamp) 20 { 21 uint32_t trips ; 22 if (!ntot) return 1 ; 23 unsigned int i = 0 ; 24 for (; i < ntot ; i++) 25 { 26 size_t zpos = byte_chr(list[i].id, S6_FDHOLDER_ID_SIZE + 1, 0) ; 27 if (!zpos || zpos >= S6_FDHOLDER_ID_SIZE + 1) return (errno = EINVAL, 0) ; 28 } 29 { 30 char pack[5] = "!" ; 31 unixmessage m = { .s = pack, .len = 5, .fds = 0, .nfds = 0 } ; 32 uint32_pack_big(pack+1, ntot) ; 33 if (!unixmessage_put(&a->connection.out, &m)) return 0 ; 34 if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; 35 if (sanitize_read(unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) < 0) return 0 ; 36 if (!m.len || m.nfds) { unixmessage_drop(&m) ; return (errno = EPROTO, 0) ; } 37 if (m.s[0]) return (errno = (unsigned char)m.s[0], 0) ; 38 if (m.len != 5) return (errno = EPROTO, 0) ; 39 uint32_unpack_big(m.s + 1, &trips) ; 40 if (trips != 1 + (ntot-1) / UNIXMESSAGE_MAXFDS) return (errno = EPROTO, 0) ; 41 } 42 for (i = 0 ; i < trips ; i++, ntot -= UNIXMESSAGE_MAXFDS) 43 { 44 { 45 unsigned int n = ntot > UNIXMESSAGE_MAXFDS ? UNIXMESSAGE_MAXFDS : ntot ; 46 unsigned int j = 0 ; 47 struct iovec v[1 + (n<<1)] ; 48 int fds[n] ; 49 unixmessagev m = { .v = v, .vlen = 1 + (n<<1), .fds = fds, .nfds = n } ; 50 char pack[n * (TAIN_PACK+1)] ; 51 v[0].iov_base = "." ; v[0].iov_len = 1 ; 52 for (; j < n ; j++, list++, ntot--) 53 { 54 size_t len = strlen(list->id) ; 55 v[1 + (j<<1)].iov_base = pack + j * (TAIN_PACK+1) ; 56 v[1 + (j<<1)].iov_len = TAIN_PACK + 1 ; 57 tain_pack(pack + j * (TAIN_PACK+1), &list->limit) ; 58 pack[j * (TAIN_PACK+1) + TAIN_PACK] = (unsigned char)len ; 59 v[2 + (j<<1)].iov_base = (char *)list->id ; 60 v[2 + (j<<1)].iov_len = len + 1 ; 61 fds[j] = list->fd ; 62 } 63 if (!unixmessage_putv(&a->connection.out, &m)) return 0 ; 64 } 65 if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; 66 { 67 unixmessage m ; 68 if (sanitize_read(unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) < 0) return 0 ; 69 if (m.len != 1 || m.nfds) 70 { 71 unixmessage_drop(&m) ; 72 return (errno = EPROTO, 0) ; 73 } 74 if (!error_isagain((unsigned char)m.s[0]) && i < trips-1) 75 return errno = m.s[0] ? (unsigned char)m.s[0] : EPROTO, 0 ; 76 if (i == trips - 1 && m.s[0]) 77 return errno = error_isagain((unsigned char)m.s[0]) ? EPROTO : (unsigned char)m.s[0], 0 ; 78 } 79 } 80 return 1 ; 81 }