diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2015-01-19 16:11:24 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2015-01-19 16:11:24 +0000 |
commit | 701540827e27a4f07ac725db3ce361d3be0c106f (patch) | |
tree | 98c4b2fb8ba8f69ef791feebdcd61cd5bca34140 /src/libs6/s6_fdholder_getdump.c | |
parent | 83853a80eb18238796154164f9ea776b0c167ab7 (diff) | |
download | s6-701540827e27a4f07ac725db3ce361d3be0c106f.tar.xz |
- added the s6_fdholder library to libs6. (Nothing useful yet.)
- fixed execline invocation in s6-log with slashpackage
- integrated s6_svc_main.c's functionality into s6-svscanctl and deleted it
- integrated Olivier Brunel's suggestions for wstat report in supervise/status
- minor fixes to s6-supervise's status reports
- separated sigaction calls in ftrigw_notifyb, this spares a few syscalls in s6-supervise
- updated doc to reflect the changes
- version bumped to 2.1.0.0 because API breakage (./finish, s6-svstat)
Diffstat (limited to 'src/libs6/s6_fdholder_getdump.c')
-rw-r--r-- | src/libs6/s6_fdholder_getdump.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/libs6/s6_fdholder_getdump.c b/src/libs6/s6_fdholder_getdump.c new file mode 100644 index 0000000..3fce3a7 --- /dev/null +++ b/src/libs6/s6_fdholder_getdump.c @@ -0,0 +1,73 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/uint32.h> +#include <skalibs/error.h> +#include <skalibs/bytestr.h> +#include <skalibs/tai.h> +#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_getdump (s6_fdholder_t *a, genalloc *g, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_t m = { .s = "?", .len = 1, .fds = 0, .nfds = 0 } ; + uint32 ntot, n ; + unsigned int oldlen = genalloc_len(s6_fdholder_fd_t, g) ; + unsigned int i = 0 ; + int ok ; + if (!unixmessage_put(&a->connection.out, &m)) return 0 ; + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return 0 ; + if (!m.len || m.nfds) return (errno = EPROTO, 0) ; + if (m.s[0]) return (errno = m.s[0], 0) ; + if (m.len != 9) return (errno = EPROTO, 0) ; + uint32_unpack_big(m.s + 1, &n) ; + uint32_unpack_big(m.s + 5, &ntot) ; + if (!ntot) return 1 ; + if (n != 1 + (ntot-1) / UNIXMESSAGE_MAXFDS) return (errno = EPROTO, 0) ; + ok = genalloc_readyplus(s6_fdholder_fd_t, g, ntot) ; + + for (; i < n ; i++) + { + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) goto err ; + if (genalloc_len(s6_fdholder_fd_t, g) + m.nfds > ntot) goto droperr ; + if (ok) + { + s6_fdholder_fd_t *tab = genalloc_s(s6_fdholder_fd_t, g) + genalloc_len(s6_fdholder_fd_t, g) ; + unsigned int i = 0 ; + for (; i < m.nfds ; i++) + { + unsigned char thislen ; + if (m.len < TAIN_PACK + 3) goto droperr ; + tain_unpack(m.s, &tab[i].limit) ; + m.s += TAIN_PACK ; m.len -= TAIN_PACK + 1 ; + thislen = *m.s++ ; + if (thislen > m.len - 1 || thislen > S6_FDHOLDER_ID_SIZE || m.s[thislen]) goto droperr ; + byte_copy(tab[i].id, thislen, m.s) ; + byte_zero(tab[i].id + thislen, S6_FDHOLDER_ID_SIZE + 1 - thislen) ; + m.s += (unsigned int)thislen + 1 ; m.len -= (unsigned int)thislen + 1 ; + tab[i].fd = m.fds[i] ; + } + genalloc_setlen(s6_fdholder_fd_t, g, genalloc_len(s6_fdholder_fd_t, g) + m.nfds) ; + } + else unixmessage_drop(&m) ; + } + + if (!ok) return (errno = ENOMEM, 0) ; + return 1 ; + + droperr: + unixmessage_drop(&m) ; + errno = EPROTO ; + err: + { + int e = errno ; + i = genalloc_len(s6_fdholder_fd_t, g) ; + while (i-- > oldlen) fd_close(genalloc_s(s6_fdholder_fd_t, g)[i].fd) ; + genalloc_setlen(s6_fdholder_fd_t, g, oldlen) ; + errno = e ; + } + return 0 ; +} |