unixmessage_put.c (1926B)
1 /* ISC license. */ 2 3 #include <string.h> 4 #include <errno.h> 5 6 #include <skalibs/bitarray.h> 7 #include <skalibs/disize.h> 8 #include <skalibs/stralloc.h> 9 #include <skalibs/genalloc.h> 10 #include <skalibs/siovec.h> 11 #include <skalibs/unixmessage.h> 12 #include <skalibs/posixishard.h> 13 14 static inline int copyfds (char *s, int const *fds, unsigned int n, unsigned char const *bits, unixmessage_sender_closecb_func_ref closecb, void *closecbdata) 15 { 16 unsigned int i = 0 ; 17 for (; i < n ; i++) 18 { 19 int fd = fds[i] ; 20 if (fd < 0) return (errno = EINVAL, -1) ; 21 if (bitarray_peek(bits, i)) fd = - fd - 1 ; 22 memcpy(s, (char const *)&fd, sizeof(int)) ; 23 s += sizeof(int) ; 24 } 25 return 1 ; 26 } 27 28 static int reserve_and_copy (unixmessage_sender *b, size_t len, int const *fds, unsigned int nfds, unsigned char const *bits) 29 { 30 disize cur = { .left = b->data.len, .right = genalloc_len(int, &b->fds) } ; 31 if (len > UNIXMESSAGE_MAXSIZE || nfds > UNIXMESSAGE_MAXFDS) 32 return (errno = EPROTO, 0) ; 33 if (!genalloc_readyplus(disize, &b->offsets, 1) 34 || !genalloc_readyplus(int, &b->fds, nfds) 35 || !stralloc_readyplus(&b->data, len)) 36 return 0 ; 37 if (!copyfds(b->fds.s + b->fds.len, fds, nfds, bits, b->closecb, b->closecbdata)) return 0 ; 38 genalloc_setlen(int, &b->fds, cur.right + nfds) ; 39 return genalloc_append(disize, &b->offsets, &cur) ; 40 } 41 42 int unixmessage_put_and_close (unixmessage_sender *b, unixmessage const *m, unsigned char const *bits) 43 { 44 if (!reserve_and_copy(b, m->len, m->fds, m->nfds, bits)) return 0 ; 45 memmove(b->data.s + b->data.len, m->s, m->len) ; 46 b->data.len += m->len ; 47 return 1 ; 48 } 49 50 int unixmessage_putv_and_close (unixmessage_sender *b, unixmessagev const *m, unsigned char const *bits) 51 { 52 size_t len = siovec_len(m->v, m->vlen) ; 53 if (!reserve_and_copy(b, len, m->fds, m->nfds, bits)) return 0 ; 54 b->data.len += siovec_gather(m->v, m->vlen, b->data.s + b->data.len, len) ; 55 return 1 ; 56 }