diff options
Diffstat (limited to 'src/libunixonacid')
78 files changed, 1783 insertions, 0 deletions
diff --git a/src/libunixonacid/bufalloc_timed_flush.c b/src/libunixonacid/bufalloc_timed_flush.c new file mode 100644 index 0000000..df0eb79 --- /dev/null +++ b/src/libunixonacid/bufalloc_timed_flush.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/bufalloc.h> +#include <skalibs/functypes.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +static int bufalloc_isnonempty (bufalloc *ba) +{ + return !!bufalloc_len(ba) ; +} + +int bufalloc_timed_flush (bufalloc *ba, tain_t const *deadline, tain_t *stamp) +{ + return timed_flush(ba, (initfunc_t_ref)&bufalloc_getfd, (initfunc_t_ref)&bufalloc_isnonempty, (initfunc_t_ref)&bufalloc_flush, deadline, stamp) ; +} diff --git a/src/libunixonacid/buffer_timed_fill.c b/src/libunixonacid/buffer_timed_fill.c new file mode 100644 index 0000000..c6f580f --- /dev/null +++ b/src/libunixonacid/buffer_timed_fill.c @@ -0,0 +1,17 @@ +/* ISC license. */ + +#include <skalibs/allreadwrite.h> +#include <skalibs/buffer.h> +#include <skalibs/functypes.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +static int get (buffer *b) +{ + return sanitize_read(buffer_fill(b)) ; +} + +int buffer_timed_fill (buffer *b, tain_t const *deadline, tain_t *stamp) +{ + return timed_get(b, (initfunc_t_ref)&buffer_getfd, (initfunc_t_ref)&get, deadline, stamp) ; +} diff --git a/src/libunixonacid/buffer_timed_flush.c b/src/libunixonacid/buffer_timed_flush.c new file mode 100644 index 0000000..63a2587 --- /dev/null +++ b/src/libunixonacid/buffer_timed_flush.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/buffer.h> +#include <skalibs/functypes.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +static int buffer_isnonempty (buffer *b) +{ + return !buffer_isempty(b) ; +} + +int timed_buffer_flush (buffer *b, tain_t const *deadline, tain_t *stamp) +{ + return timed_flush(b, (initfunc_t_ref)&buffer_getfd, (initfunc_t_ref)&buffer_isnonempty, (initfunc_t_ref)&buffer_flush, deadline, stamp) ; +} diff --git a/src/libunixonacid/buffer_timed_get.c b/src/libunixonacid/buffer_timed_get.c new file mode 100644 index 0000000..2f3b751 --- /dev/null +++ b/src/libunixonacid/buffer_timed_get.c @@ -0,0 +1,30 @@ +/* ISC license. */ + +#include <skalibs/buffer.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +struct blah_s +{ + buffer *b ; + char *s ; + unsigned int len ; + unsigned int w ; +} ; + +static int getfd (struct blah_s *blah) +{ + return buffer_fd(blah->b) ; +} + +static int get (struct blah_s *blah) +{ + return buffer_getall(blah->b, blah->s, blah->len, &blah->w) ; +} + +unsigned int buffer_timed_get (buffer *b, char *s, unsigned int len, tain_t const *deadline, tain_t *stamp) +{ + struct blah_s blah = { .b = b, .s = s, .len = len, .w = 0 } ; + timed_get(&blah, (initfunc_t_ref)&getfd, (initfunc_t_ref)&get, deadline, stamp) ; + return blah.w ; +} diff --git a/src/libunixonacid/dd_cancel.c b/src/libunixonacid/dd_cancel.c new file mode 100644 index 0000000..22adf4e --- /dev/null +++ b/src/libunixonacid/dd_cancel.c @@ -0,0 +1,17 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +void dd_cancel (dirdescriptor_t_ref dd) +{ + dirdescriptor_t zero = DIRDESCRIPTOR_ZERO ; + register int e = errno ; + fd_close(dd->fd) ; + rm_rf_in_tmp(&dd->new, 0) ; + stralloc_free(&dd->new) ; + *dd = zero ; + errno = e ; +} diff --git a/src/libunixonacid/dd_close.c b/src/libunixonacid/dd_close.c new file mode 100644 index 0000000..74961a1 --- /dev/null +++ b/src/libunixonacid/dd_close.c @@ -0,0 +1,9 @@ +/* ISC license. */ + +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int dd_close (dirdescriptor_t_ref dd) +{ + return (fd_close(dd->fd) >= 0) ; +} diff --git a/src/libunixonacid/dd_commit.c b/src/libunixonacid/dd_commit.c new file mode 100644 index 0000000..b55addb --- /dev/null +++ b/src/libunixonacid/dd_commit.c @@ -0,0 +1,68 @@ +/* ISC license. */ + +#include <unistd.h> +#include <errno.h> +#include <stdio.h> /* for rename() */ +#include <skalibs/bytestr.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/random.h> +#include <skalibs/unix-transactional.h> + +static char const *mybasename (char const *s, unsigned int len) +{ + register unsigned int i = len ; + while (i--) if (s[i] == '/') return s + i + 1 ; + return s ; +} + +int dd_commit (dirdescriptor_t_ref dd) +{ + dirdescriptor_t zero = DIRDESCRIPTOR_ZERO ; + unsigned int len = str_len(dd->lnkfn) ; + unsigned int oldbase = dd->new.len ; + unsigned int newlnkbase ; + char const *lnkbn = mybasename(dd->lnkfn, len) ; + if (!sadirname(&dd->new, dd->lnkfn, len)) return 0 ; + if (!stralloc_catb(&dd->new, "/", 1)) goto fail ; + if (sareadlink(&dd->new, dd->lnkfn) < 0) + { + unsigned int lnkbnbase = dd->new.len ; + if (errno != EINVAL) goto fail ; + if (!stralloc_cats(&dd->new, lnkbn)) goto fail ; + if (random_sauniquename(&dd->new, 8) < 0) goto fail ; + if (!stralloc_0(&dd->new)) goto fail ; + if (rename(dd->lnkfn, dd->new.s + oldbase) < 0) goto fail ; + /* /!\ race condition right here: there's no lnkfn in the fs */ + if (symlink(dd->new.s + lnkbnbase, dd->lnkfn) < 0) /* now that's VERY BAD if it fails */ + { + register int e = errno ; + rename(dd->new.s + oldbase, dd->lnkfn) ; /* attempt to revert to initial situation */ + errno = e ; + goto fail ; /* and hope for the best */ + } + } + if (!stralloc_0(&dd->new)) goto fail ; + newlnkbase = dd->new.len ; + if (!stralloc_catb(&dd->new, dd->lnkfn, len)) goto fail ; + if (random_sauniquename(&dd->new, 8) < 0) goto fail ; + if (!stralloc_0(&dd->new)) goto fail ; + if (symlink(dd->new.s, dd->new.s + newlnkbase) < 0) goto fail ; + if (rename(dd->new.s + newlnkbase, dd->lnkfn) < 0) + { + register int e = errno ; + unlink(dd->new.s + newlnkbase) ; + errno = e ; + goto fail ; + } + fd_close(dd->fd) ; + dd->new.len = newlnkbase ; + rm_rf_in_tmp(&dd->new, oldbase) ; + stralloc_free(&dd->new) ; + *dd = zero ; + return 1 ; + + fail: + dd->new.len = oldbase ; + return 0 ; +} diff --git a/src/libunixonacid/dd_commit_devino.c b/src/libunixonacid/dd_commit_devino.c new file mode 100644 index 0000000..481db19 --- /dev/null +++ b/src/libunixonacid/dd_commit_devino.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <skalibs/uint64.h> +#include <skalibs/unix-transactional.h> + +int dd_commit_devino (dirdescriptor_t_ref dd, uint64 *dev, uint64 *ino) +{ + struct stat st ; + if (fstat(dd->fd, &st) < 0) return 0 ; + if (!dd_commit(dd)) return 0 ; + *dev = (uint64)st.st_dev ; + *ino = (uint64)st.st_ino ; + return 1 ; +} diff --git a/src/libunixonacid/dd_open_read.c b/src/libunixonacid/dd_open_read.c new file mode 100644 index 0000000..1996297 --- /dev/null +++ b/src/libunixonacid/dd_open_read.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int dd_open_read (dirdescriptor_t_ref dd, char const *path) +{ + dirdescriptor_t d = DIRDESCRIPTOR_ZERO ; + d.fd = open_read(path) ; + if (d.fd < 0) return 0 ; + d.lnkfn = path ; + *dd = d ; + return 1 ; +} diff --git a/src/libunixonacid/dd_open_write.c b/src/libunixonacid/dd_open_write.c new file mode 100644 index 0000000..efee60f --- /dev/null +++ b/src/libunixonacid/dd_open_write.c @@ -0,0 +1,34 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/random.h> +#include <skalibs/unix-transactional.h> + +int dd_open_write (dirdescriptor_t_ref dd, char const *lnkfn, unsigned int mode) +{ + dirdescriptor_t d = DIRDESCRIPTOR_ZERO ; + d.lnkfn = lnkfn ; + if (!stralloc_cats(&d.new, lnkfn)) return 0 ; + if (random_sauniquename(&d.new, 8) < 0) goto fail ; + if (!stralloc_0(&d.new)) goto fail ; + if (mkdir(d.new.s, mode) < 0) goto fail ; + d.fd = open_read(d.new.s) ; + if (d.fd < 0) + { + register int e = errno ; + rmdir(d.new.s) ; + errno = e ; + goto fail ; + } + *dd = d ; + return 1 ; + + fail: + stralloc_free(&d.new) ; + return 0 ; +} diff --git a/src/libunixonacid/kolbak_call.c b/src/libunixonacid/kolbak_call.c new file mode 100644 index 0000000..b7b97c0 --- /dev/null +++ b/src/libunixonacid/kolbak_call.c @@ -0,0 +1,13 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/unixmessage.h> +#include <skalibs/kolbak.h> + +int kolbak_call (unixmessage_t const *m, kolbak_queue_t *q) +{ + if (q->head == q->tail) return (errno = EILSEQ, 0) ; + if (!(*q->x[q->head].f)(m, q->x[q->head].data)) return 0 ; + q->head = (q->head + 1) % q->n ; + return 1 ; +} diff --git a/src/libunixonacid/kolbak_enqueue.c b/src/libunixonacid/kolbak_enqueue.c new file mode 100644 index 0000000..80fce01 --- /dev/null +++ b/src/libunixonacid/kolbak_enqueue.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/kolbak.h> +#include <skalibs/unixmessage.h> + +int kolbak_enqueue (kolbak_queue_t *q, unixmessage_handler_func_t *f, void *data) +{ + register unsigned int newtail = (q->tail + 1) % q->n ; + if (newtail == q->head) return (errno = ENOBUFS, 0) ; + q->x[q->tail].f = f ; + q->x[q->tail].data = data ; + q->tail = newtail ; + return 1 ; +} diff --git a/src/libunixonacid/kolbak_queue_init.c b/src/libunixonacid/kolbak_queue_init.c new file mode 100644 index 0000000..6d91232 --- /dev/null +++ b/src/libunixonacid/kolbak_queue_init.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/kolbak.h> + +int kolbak_queue_init (kolbak_queue_t *q, kolbak_closure_t *s, unsigned int len) +{ + if (len < 2) return (errno = EINVAL, 0) ; + q->x = s ; + q->n = len ; + q->head = 0 ; + q->tail = 0 ; + return 1 ; +} diff --git a/src/libunixonacid/kolbak_unenqueue.c b/src/libunixonacid/kolbak_unenqueue.c new file mode 100644 index 0000000..894beea --- /dev/null +++ b/src/libunixonacid/kolbak_unenqueue.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/kolbak.h> + +int kolbak_unenqueue (kolbak_queue_t *q) +{ + if (q->head == q->tail) return (errno = EINVAL, 0) ; + q->tail = (q->tail + q->n - 1) % q->n ; + return 1 ; +} diff --git a/src/libunixonacid/mkdir_unique.c b/src/libunixonacid/mkdir_unique.c new file mode 100644 index 0000000..523ecef --- /dev/null +++ b/src/libunixonacid/mkdir_unique.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include <sys/stat.h> +#include <skalibs/stralloc.h> +#include <skalibs/random.h> +#include <skalibs/unix-transactional.h> + +int mkdir_unique (stralloc *sa, char const *fn, unsigned int mode) +{ + unsigned int base = sa->len ; + int wasnull = !sa->s ; + if (!stralloc_cats(sa, fn)) return 0 ; + if (!stralloc_cats(sa, "/mkdir_unique")) goto fail ; + if (random_sauniquename(sa, 8) < 0) goto fail ; + if (!stralloc_0(sa)) goto fail ; + if (mkdir(sa->s + base, mode) < 0) goto fail ; + sa->len-- ; + return 1 ; + + fail: + if (wasnull) stralloc_free(sa) ; + else sa->len = base ; + return 0 ; +} diff --git a/src/libunixonacid/netstring_timed_get.c b/src/libunixonacid/netstring_timed_get.c new file mode 100644 index 0000000..04ace6c --- /dev/null +++ b/src/libunixonacid/netstring_timed_get.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/netstring.h> +#include <skalibs/tai.h> +#include <skalibs/iopause.h> +#include <skalibs/unix-timed.h> + +int netstring_timed_get (buffer *b, stralloc *sa, tain_t const *deadline, tain_t *stamp) +{ + iopause_fd x = { .fd = buffer_fd(b), .events = IOPAUSE_READ } ; + unsigned int w = 0 ; + for (;;) + { + register int r = netstring_get(b, sa, &w) ; + if (r > 0) return r ; + if (r < 0) return 0 ; + r = iopause_stamp(&x, 1, deadline, stamp) ; + if (r < 0) return 0 ; + else if (!r) return (errno = ETIMEDOUT, 0) ; + } +} diff --git a/src/libunixonacid/open2_at.c b/src/libunixonacid/open2_at.c new file mode 100644 index 0000000..4deb837 --- /dev/null +++ b/src/libunixonacid/open2_at.c @@ -0,0 +1,60 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> + +#ifdef SKALIBS_HASOPENAT + +#ifndef _ATFILE_SOURCE +#define _ATFILE_SOURCE +#endif + +#include <skalibs/nonposix.h> +#include <fcntl.h> +#include <skalibs/unix-transactional.h> + +int open2_at (int dirfd, char const *file, int flags) +{ + return openat(dirfd, file, flags) ; +} + +#else + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int open2_at (int dirfd, char const *file, int flags) +{ + int fd ; + int fdhere = open_read(".") ; + if (fdhere < 0) return -1 ; + if (fd_chdir(dirfd) < 0) + { + register int e = errno ; + fd_close(fdhere) ; + errno = e ; + return -1 ; + } + fd = open2(file, flags) ; + if (fd < 0) + { + register int e = errno ; + fd_chdir(fdhere) ; + fd_close(fdhere) ; + errno = e ; + return -1 ; + } + if (fd_chdir(fdhere) < 0) + { + register int e = errno ; + fd_close(fdhere) ; + errno = e ; + return -1 ; + } + return fd ; +} + +#endif diff --git a/src/libunixonacid/open3_at.c b/src/libunixonacid/open3_at.c new file mode 100644 index 0000000..d9c7222 --- /dev/null +++ b/src/libunixonacid/open3_at.c @@ -0,0 +1,60 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> + +#ifdef SKALIBS_HASOPENAT + +#ifndef _ATFILE_SOURCE +#define _ATFILE_SOURCE +#endif + +#include <skalibs/nonposix.h> +#include <fcntl.h> +#include <skalibs/unix-transactional.h> + +int open3_at (int dirfd, char const *file, int flags, unsigned int mode) +{ + return openat(dirfd, file, flags, mode) ; +} + +#else + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int open3_at (int dirfd, char const *file, int flags, unsigned int mode) +{ + int fd ; + int fdhere = open_read(".") ; + if (fdhere < 0) return -1 ; + if (fd_chdir(dirfd) < 0) + { + register int e = errno ; + fd_close(fdhere) ; + errno = e ; + return -1 ; + } + fd = open3(file, flags, mode) ; + if (fd < 0) + { + register int e = errno ; + fd_chdir(fdhere) ; + fd_close(fdhere) ; + errno = e ; + return -1 ; + } + if (fd_chdir(fdhere) < 0) + { + register int e = errno ; + fd_close(fdhere) ; + errno = e ; + return -1 ; + } + return fd ; +} + +#endif diff --git a/src/libunixonacid/open_appendat.c b/src/libunixonacid/open_appendat.c new file mode 100644 index 0000000..debfe8a --- /dev/null +++ b/src/libunixonacid/open_appendat.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <skalibs/unix-transactional.h> + +int open_appendat (int fd, char const *name) +{ + return open3_at(fd, name, O_WRONLY | O_NONBLOCK | O_APPEND | O_CREAT, 0666) ; +} diff --git a/src/libunixonacid/open_appendatb.c b/src/libunixonacid/open_appendatb.c new file mode 100644 index 0000000..5a75120 --- /dev/null +++ b/src/libunixonacid/open_appendatb.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int open_appendatb (int dirfd, char const *name) +{ + int fd = open_appendat(dirfd, name) ; + if (fd < 0) return -1 ; + if (ndelay_off(fd) < 0) return -1 ; + return fd ; +} diff --git a/src/libunixonacid/open_readat.c b/src/libunixonacid/open_readat.c new file mode 100644 index 0000000..7764ffc --- /dev/null +++ b/src/libunixonacid/open_readat.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <fcntl.h> +#include <skalibs/unix-transactional.h> + +int open_readat (int fd, char const *name) +{ + return open2_at(fd, name, O_RDONLY | O_NONBLOCK) ; +} diff --git a/src/libunixonacid/open_readatb.c b/src/libunixonacid/open_readatb.c new file mode 100644 index 0000000..6e4cd0f --- /dev/null +++ b/src/libunixonacid/open_readatb.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int open_readatb (int dirfd, char const *name) +{ + int fd = open_readat(dirfd, name) ; + if (fd < 0) return -1 ; + if (ndelay_off(fd) < 0) return -1 ; + return fd ; +} diff --git a/src/libunixonacid/open_truncat.c b/src/libunixonacid/open_truncat.c new file mode 100644 index 0000000..2a868d2 --- /dev/null +++ b/src/libunixonacid/open_truncat.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <fcntl.h> +#include <skalibs/unix-transactional.h> + +int open_truncat (int fd, char const *name) +{ + return open3_at(fd, name, O_WRONLY | O_NONBLOCK | O_TRUNC | O_CREAT, 0666) ; +} diff --git a/src/libunixonacid/open_truncatb.c b/src/libunixonacid/open_truncatb.c new file mode 100644 index 0000000..fc4d685 --- /dev/null +++ b/src/libunixonacid/open_truncatb.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int open_truncatb (int dirfd, char const *name) +{ + int fd = open_truncat(dirfd, name) ; + if (fd < 0) return -1 ; + if (ndelay_off(fd) < 0) return -1 ; + return fd ; +} diff --git a/src/libunixonacid/open_writeat.c b/src/libunixonacid/open_writeat.c new file mode 100644 index 0000000..6b1a173 --- /dev/null +++ b/src/libunixonacid/open_writeat.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <fcntl.h> +#include <skalibs/unix-transactional.h> + +int open_writeat (int fd, char const *name) +{ + return open2_at(fd, name, O_WRONLY | O_NONBLOCK) ; +} diff --git a/src/libunixonacid/open_writeatb.c b/src/libunixonacid/open_writeatb.c new file mode 100644 index 0000000..fd75365 --- /dev/null +++ b/src/libunixonacid/open_writeatb.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int open_writeatb (int dirfd, char const *name) +{ + int fd = open_writeat(dirfd, name) ; + if (fd < 0) return -1 ; + if (ndelay_off(fd) < 0) return -1 ; + return fd ; +} diff --git a/src/libunixonacid/opengetlnclose.c b/src/libunixonacid/opengetlnclose.c new file mode 100644 index 0000000..ca1959e --- /dev/null +++ b/src/libunixonacid/opengetlnclose.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> +#include <skalibs/unix-transactional.h> + +int opengetlnclose (char const *fn, stralloc *sa, int sep) +{ + char buf[BUFFER_INSIZE] ; + buffer b ; + register int r ; + register int e ; + int fd = open_readb(fn) ; + if (fd < 0) return -1 ; + buffer_init(&b, &buffer_read, fd, buf, BUFFER_INSIZE) ; + r = skagetln(&b, sa, sep) ; + e = errno ; + fd_close(fd) ; + errno = e ; + return r ; +} diff --git a/src/libunixonacid/opengetlnclose_at.c b/src/libunixonacid/opengetlnclose_at.c new file mode 100644 index 0000000..be2ffaf --- /dev/null +++ b/src/libunixonacid/opengetlnclose_at.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> +#include <skalibs/unix-transactional.h> + +int opengetlnclose_at (int dirfd, char const *fn, stralloc *sa, int sep) +{ + char buf[BUFFER_INSIZE] ; + buffer b ; + register int r ; + register int e ; + int fd = open_readatb(dirfd, fn) ; + if (fd < 0) return -1 ; + buffer_init(&b, &buffer_read, fd, buf, BUFFER_INSIZE) ; + r = skagetln(&b, sa, sep) ; + e = errno ; + fd_close(fd) ; + errno = e ; + return r ; +} diff --git a/src/libunixonacid/openreadnclose_at.c b/src/libunixonacid/openreadnclose_at.c new file mode 100644 index 0000000..4e8209d --- /dev/null +++ b/src/libunixonacid/openreadnclose_at.c @@ -0,0 +1,19 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +unsigned int openreadnclose_at (int dirfd, char const *file, char *s, unsigned int n) +{ + register unsigned int r ; + register int e ; + int fd = open_readatb(dirfd, file) ; + if (fd < 0) return 0 ; + r = allread(fd, s, n) ; + e = errno ; + fd_close(fd) ; + errno = e ; + return r ; +} diff --git a/src/libunixonacid/openslurpclose_at.c b/src/libunixonacid/openslurpclose_at.c new file mode 100644 index 0000000..cf2f8ee --- /dev/null +++ b/src/libunixonacid/openslurpclose_at.c @@ -0,0 +1,21 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +int openslurpclose_at (int dirfd, char const *fn, stralloc *sa) +{ + int fd = open_readatb(dirfd, fn) ; + if (fd < 0) return 0 ; + if (!slurp(sa, fd)) + { + register int e = errno ; + fd_close(fd) ; + errno = e ; + return 0 ; + } + fd_close(fd) ; + return 1 ; +} diff --git a/src/libunixonacid/openwritenclose.c b/src/libunixonacid/openwritenclose.c new file mode 100644 index 0000000..09149e2 --- /dev/null +++ b/src/libunixonacid/openwritenclose.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +/* MT-unsafe */ + +#include <skalibs/skamisc.h> +#include <skalibs/unix-transactional.h> + +int openwritenclose (char const *fn, char const *s, unsigned int len) +{ + return openwritenclose_tmp(fn, s, len, &satmp) ; +} diff --git a/src/libunixonacid/openwritenclose_at.c b/src/libunixonacid/openwritenclose_at.c new file mode 100644 index 0000000..fe92a5e --- /dev/null +++ b/src/libunixonacid/openwritenclose_at.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include <unistd.h> +#include <errno.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/djbunix.h> +#include <skalibs/unix-transactional.h> + +unsigned int openwritenclose_at (int dirfd, char const *file, char const *s, unsigned int n) +{ + register unsigned int r ; + int fd = open_truncatb(dirfd, file) ; + if (fd < 0) return 0 ; + r = allwrite(fd, s, n) ; + if ((r < n) || (fsync(fd) < 0)) + { + register int e = errno ; + fd_close(fd) ; + errno = e ; + return r ; + } + fd_close(fd) ; + return r ; +} diff --git a/src/libunixonacid/openwritenclose_devino.c b/src/libunixonacid/openwritenclose_devino.c new file mode 100644 index 0000000..5edc646 --- /dev/null +++ b/src/libunixonacid/openwritenclose_devino.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +/* MT-unsafe */ + +#include <skalibs/uint64.h> +#include <skalibs/skamisc.h> +#include <skalibs/unix-transactional.h> + +int openwritenclose_devino (char const *fn, char const *s, unsigned int len, uint64 *dev, uint64 *ino) +{ + return openwritenclose_devino_tmp(fn, s, len, dev, ino, &satmp) ; +} diff --git a/src/libunixonacid/openwritenclose_devino_tmp.c b/src/libunixonacid/openwritenclose_devino_tmp.c new file mode 100644 index 0000000..343da65 --- /dev/null +++ b/src/libunixonacid/openwritenclose_devino_tmp.c @@ -0,0 +1,35 @@ +/* ISC license. */ + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> /* for rename() */ +#include <skalibs/uint64.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/random.h> +#include <skalibs/unix-transactional.h> + +int openwritenclose_devino_tmp (char const *fn, char const *s, unsigned int len, uint64 *dev, uint64 *ino, stralloc *tmp) +{ + uint64 tmpdev, tmpino ; + unsigned int base = tmp->len ; + if (!stralloc_cats(tmp, fn)) return 0 ; + if (random_sauniquename(tmp, 8) < 0) goto fail ; + if (!stralloc_0(tmp)) goto fail ; + if (!openwritenclose_unsafe_devino_sync(tmp->s + base, s, len, &tmpdev, &tmpino)) goto fail ; + if (rename(tmp->s + base, fn) < 0) + { + register int e = errno ; + unlink(tmp->s + base) ; + errno = e ; + goto fail ; + } + tmp->len = base ; + *dev = tmpdev ; + *ino = tmpino ; + return 1 ; + + fail: + tmp->len = base ; + return 0 ; +} diff --git a/src/libunixonacid/openwritenclose_tmp.c b/src/libunixonacid/openwritenclose_tmp.c new file mode 100644 index 0000000..1ada80b --- /dev/null +++ b/src/libunixonacid/openwritenclose_tmp.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <skalibs/uint64.h> +#include <skalibs/stralloc.h> +#include <skalibs/unix-transactional.h> + +int openwritenclose_tmp (char const *fn, char const *s, unsigned int len, stralloc *tmp) +{ + uint64 dev, ino ; + return openwritenclose_devino_tmp(fn, s, len, &dev, &ino, tmp) ; +} diff --git a/src/libunixonacid/skaclient-internal.h b/src/libunixonacid/skaclient-internal.h new file mode 100644 index 0000000..f0a9bfe --- /dev/null +++ b/src/libunixonacid/skaclient-internal.h @@ -0,0 +1,15 @@ +/* ISC license. */ + +#ifndef SKACLIENT_INTERNAL_H +#define SKACLIENT_INTERNAL_H + +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +extern int skaclient_init (skaclient_t *, int, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, unsigned int) ; +extern int skaclient_start_async_th (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *, unsigned int) ; +extern int skaclient_startf_async_th (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *const *, char const *const *, uint32, char const *, unsigned int) ; +extern int skaclient_start_cb (unixmessage_t const *, skaclient_cbdata_t *) ; + +#endif diff --git a/src/libunixonacid/skaclient_default_cb.c b/src/libunixonacid/skaclient_default_cb.c new file mode 100644 index 0000000..10934e5 --- /dev/null +++ b/src/libunixonacid/skaclient_default_cb.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/error.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +int skaclient_default_cb (unixmessage_t const *m, void *p) +{ + unsigned char *err = p ; + if (m->len != 1 || m->nfds) return (errno = EPROTO, 0) ; + *err = m->s[0] ; + return 1 ; +} diff --git a/src/libunixonacid/skaclient_end.c b/src/libunixonacid/skaclient_end.c new file mode 100644 index 0000000..23dafab --- /dev/null +++ b/src/libunixonacid/skaclient_end.c @@ -0,0 +1,21 @@ +/* ISC license. */ + +#include <skalibs/djbunix.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +void skaclient_end (skaclient_t *a) +{ + fd_close(a->syncout.fd) ; + fd_close(a->asyncout.fd) ; + unixmessage_sender_free(&a->syncout) ; + unixmessage_sender_free(&a->asyncout) ; + unixmessage_receiver_free(&a->syncin) ; + unixmessage_receiver_free(&a->asyncin) ; + if (a->pid && a->options & SKACLIENT_OPTION_WAITPID) + { + int wstat ; + waitpid_nointr(a->pid, &wstat, 0) ; + } + *a = skaclient_zero ; +} diff --git a/src/libunixonacid/skaclient_init.c b/src/libunixonacid/skaclient_init.c new file mode 100644 index 0000000..89ed59c --- /dev/null +++ b/src/libunixonacid/skaclient_init.c @@ -0,0 +1,32 @@ +/* ISC license. */ + +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> +#include "skaclient-internal.h" + +int skaclient_init ( + skaclient_t *a, + int fd, + char *bufss, + unsigned int bufsn, + char *auxbufss, + unsigned int auxbufsn, + char *bufas, + unsigned int bufan, + char *auxbufas, + unsigned int auxbufan, + kolbak_closure_t *q, + unsigned int qlen, + char const *before, + unsigned int beforelen) +{ + unixmessage_t msg = { .s = (char *)before, .len = beforelen, .fds = 0, .nfds = 0 } ; + if (!unixmessage_receiver_init(&a->syncin, fd, bufss, bufsn, auxbufss, auxbufsn) + || !unixmessage_receiver_init(&a->asyncin, -1, bufas, bufan, auxbufas, auxbufan) + || !kolbak_queue_init(&a->kq, q, qlen)) return 0 ; + unixmessage_sender_init(&a->syncout, fd) ; + unixmessage_sender_init(&a->asyncout, -1) ; + if (!unixmessage_put(&a->syncout, &msg)) return 0 ; + return 1 ; +} diff --git a/src/libunixonacid/skaclient_put.c b/src/libunixonacid/skaclient_put.c new file mode 100644 index 0000000..5e3dc92 --- /dev/null +++ b/src/libunixonacid/skaclient_put.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +int skaclient_put (skaclient_t *a, char const *s, unsigned int len, unixmessage_handler_func_t *cb, void *result) +{ + unixmessage_t m = { .s = (char *)s, .len = len, .fds = 0, .nfds = 0 } ; + return skaclient_putmsg(a, &m, cb, result) ; +} diff --git a/src/libunixonacid/skaclient_putmsg.c b/src/libunixonacid/skaclient_putmsg.c new file mode 100644 index 0000000..9dcb37d --- /dev/null +++ b/src/libunixonacid/skaclient_putmsg.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +int skaclient_putmsg_and_close (skaclient_t *a, unixmessage_t const *m, unsigned char const *bits, unixmessage_handler_func_t *cb, void *result) +{ + if (!kolbak_enqueue(&a->kq, cb, result)) return 0 ; + if (!unixmessage_put_and_close(&a->syncout, m, bits)) + { + kolbak_unenqueue(&a->kq) ; + return 0 ; + } + return 1 ; +} diff --git a/src/libunixonacid/skaclient_putmsgv.c b/src/libunixonacid/skaclient_putmsgv.c new file mode 100644 index 0000000..e53935a --- /dev/null +++ b/src/libunixonacid/skaclient_putmsgv.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +int skaclient_putmsgv_and_close (skaclient_t *a, unixmessage_v_t const *m, unsigned char const *bits, unixmessage_handler_func_t *cb, void *result) +{ + if (!kolbak_enqueue(&a->kq, cb, result)) return 0 ; + if (!unixmessage_putv_and_close(&a->syncout, m, bits)) + { + kolbak_unenqueue(&a->kq) ; + return 0 ; + } + return 1 ; +} diff --git a/src/libunixonacid/skaclient_putv.c b/src/libunixonacid/skaclient_putv.c new file mode 100644 index 0000000..c41b092 --- /dev/null +++ b/src/libunixonacid/skaclient_putv.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <skalibs/siovec.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +int skaclient_putv (skaclient_t *a, siovec_t const *v, unsigned int vlen, unixmessage_handler_func_t *cb, void *result) +{ + unixmessage_v_t m = { .v = (siovec_t *)v, .vlen = vlen, .fds = 0, .nfds = 0 } ; + return skaclient_putmsgv(a, &m, cb, result) ; +} diff --git a/src/libunixonacid/skaclient_send.c b/src/libunixonacid/skaclient_send.c new file mode 100644 index 0000000..8bd31ab --- /dev/null +++ b/src/libunixonacid/skaclient_send.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <skalibs/skaclient.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> + +int skaclient_send (skaclient_t *a, char const *s, unsigned int len, unixmessage_handler_func_t *cb, void *result, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_t m = { .s = (char *)s, .len = len, .fds = 0, .nfds = 0 } ; + return skaclient_sendmsg(a, &m, cb, result, deadline, stamp) ; +} diff --git a/src/libunixonacid/skaclient_sendmsg.c b/src/libunixonacid/skaclient_sendmsg.c new file mode 100644 index 0000000..3f88ec7 --- /dev/null +++ b/src/libunixonacid/skaclient_sendmsg.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/skaclient.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> + +int skaclient_sendmsg_and_close (skaclient_t *a, unixmessage_t const *m, unsigned char const *bits, unixmessage_handler_func_t *cb, void *result, tain_t const *deadline, tain_t *stamp) +{ + register int r ; + if (!skaclient_putmsg_and_close(a, m, bits, cb, result)) return 0 ; + if (!skaclient_timed_flush(a, deadline, stamp)) return 0 ; + r = skaclient_timed_supdate(a, deadline, stamp) ; + return r < 0 ? 0 : !r ? (errno = EPIPE, 0) : 1 ; +} diff --git a/src/libunixonacid/skaclient_sendmsgv.c b/src/libunixonacid/skaclient_sendmsgv.c new file mode 100644 index 0000000..ac4bcdb --- /dev/null +++ b/src/libunixonacid/skaclient_sendmsgv.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/skaclient.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> + +int skaclient_sendmsgv_and_close (skaclient_t *a, unixmessage_v_t const *m, unsigned char const *bits, unixmessage_handler_func_t *cb, void *result, tain_t const *deadline, tain_t *stamp) +{ + register int r ; + if (!skaclient_putmsgv_and_close(a, m, bits, cb, result)) return 0 ; + if (!skaclient_timed_flush(a, deadline, stamp)) return 0 ; + r = skaclient_timed_supdate(a, deadline, stamp) ; + return r < 0 ? 0 : !r ? (errno = EPIPE, 0) : 1 ; +} diff --git a/src/libunixonacid/skaclient_sendv.c b/src/libunixonacid/skaclient_sendv.c new file mode 100644 index 0000000..a140768 --- /dev/null +++ b/src/libunixonacid/skaclient_sendv.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include <skalibs/siovec.h> +#include <skalibs/skaclient.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> + +int skaclient_sendv (skaclient_t *a, siovec_t const *v, unsigned int vlen, unixmessage_handler_func_t *cb, void *result, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_v_t m = { .v = (siovec_t *)v, .vlen = vlen, .fds = 0, .nfds = 0 } ; + return skaclient_sendmsgv(a, &m, cb, result, deadline, stamp) ; +} diff --git a/src/libunixonacid/skaclient_server_ack.c b/src/libunixonacid/skaclient_server_ack.c new file mode 100644 index 0000000..31ee9fe --- /dev/null +++ b/src/libunixonacid/skaclient_server_ack.c @@ -0,0 +1,30 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/djbunix.h> +#include <skalibs/error.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> +#include <skalibs/webipc.h> + +int skaclient_server_ack (unixmessage_t const *clientmsg, unixmessage_sender_t *out, unixmessage_sender_t *asyncout, char const *before, unsigned int beforelen, char const *after, unsigned int afterlen) +{ + int fd[2] ; + unixmessage_t m = { .s = (char *)after, .len = afterlen, .fds = fd, .nfds = 1 } ; + static unsigned char const bits = 0xff ; + if (clientmsg->nfds + || clientmsg->len != beforelen + || byte_diff(clientmsg->s, beforelen, before)) return (errno = EPROTO, 0) ; + if (ipc_pair_nbcoe(fd) < 0) return 0 ; + unixmessage_sender_init(asyncout, fd[1]) ; + if (!unixmessage_put_and_close(out, &m, &bits)) + { + int e = errno ; + fd_close(fd[1]) ; + fd_close(fd[0]) ; + errno = e ; + return 0 ; + } + return 1 ; +} diff --git a/src/libunixonacid/skaclient_server_bidi_ack.c b/src/libunixonacid/skaclient_server_bidi_ack.c new file mode 100644 index 0000000..eede82c --- /dev/null +++ b/src/libunixonacid/skaclient_server_bidi_ack.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> + +int skaclient_server_bidi_ack (unixmessage_t const *clientmsg, unixmessage_sender_t *out, unixmessage_sender_t *asyncout, unixmessage_receiver_t *asyncin, char *mainbuf, unsigned int mainlen, char *auxbuf, unsigned int auxlen, char const *before, unsigned int beforelen, char const *after, unsigned int afterlen) +{ + if (!unixmessage_receiver_init(asyncin, -1, mainbuf, mainlen, auxbuf, auxlen)) return 0 ; + if (!skaclient_server_ack(clientmsg, out, asyncout, before, beforelen, after, afterlen)) return 0 ; + asyncin->mainb.fd = unixmessage_sender_fd(asyncout) ; + return 1 ; +} diff --git a/src/libunixonacid/skaclient_server_init.c b/src/libunixonacid/skaclient_server_init.c new file mode 100644 index 0000000..bd7c143 --- /dev/null +++ b/src/libunixonacid/skaclient_server_init.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include <skalibs/skaclient.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> + +int skaclient_server_init (unixmessage_receiver_t *in, char *mainbuf, unsigned int mainlen, char *auxbuf, unsigned int auxlen, unixmessage_sender_t *out, unixmessage_sender_t *asyncout, char const *before, unsigned int beforelen, char const *after, unsigned int afterlen, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_t m ; + if (!unixmessage_receiver_init(in, 0, mainbuf, mainlen, auxbuf, auxlen)) return 0 ; + unixmessage_sender_init(out, 1) ; + if (unixmessage_timed_receive(in, &m, deadline, stamp) < 0) return 0 ; + if (!skaclient_server_ack(&m, out, asyncout, before, beforelen, after, afterlen)) return 0 ; + return unixmessage_sender_timed_flush(out, deadline, stamp) ; +} diff --git a/src/libunixonacid/skaclient_start.c b/src/libunixonacid/skaclient_start.c new file mode 100644 index 0000000..b17750b --- /dev/null +++ b/src/libunixonacid/skaclient_start.c @@ -0,0 +1,43 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/tai.h> +#include "skaclient-internal.h" + +int skaclient_start ( + skaclient_t *a, + char *bufss, + unsigned int bufsn, + char *auxbufss, + unsigned int auxbufsn, + char *bufas, + unsigned int bufan, + char *auxbufas, + unsigned int auxbufan, + kolbak_closure_t *q, + unsigned int qlen, + char const *path, + char const *before, + unsigned int beforelen, + char const *after, + unsigned int afterlen, + tain_t const *deadline, + tain_t *stamp) +{ + skaclient_cbdata_t blah ; + unixmessage_t m ; + register int r ; + if (!skaclient_start_async(a, bufss, bufsn, auxbufss, auxbufsn, bufas, bufan, auxbufas, auxbufan, q, qlen, path, before, beforelen, after, afterlen, &blah)) return 0 ; + r = unixmessage_timed_receive(&a->syncin, &m, deadline, stamp) ; + if (r < 1) + { + int e = errno ; + if (!r) e = EPIPE ; + skaclient_end(a) ; + errno = e ; + return 0 ; + } + return kolbak_call(&m, &a->kq) ; +} diff --git a/src/libunixonacid/skaclient_start_async.c b/src/libunixonacid/skaclient_start_async.c new file mode 100644 index 0000000..4dbbf1c --- /dev/null +++ b/src/libunixonacid/skaclient_start_async.c @@ -0,0 +1,52 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/error.h> +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> +#include <skalibs/webipc.h> +#include "skaclient-internal.h" + +int skaclient_start_async ( + skaclient_t *a, + char *bufss, + unsigned int bufsn, + char *auxbufss, + unsigned int auxbufsn, + char *bufas, + unsigned int bufan, + char *auxbufas, + unsigned int auxbufan, + kolbak_closure_t *q, + unsigned int qlen, + char const *path, + char const *before, + unsigned int beforelen, + char const *after, + unsigned int afterlen, + skaclient_cbdata_t *blah) +{ + int fd = ipc_stream_nbcoe() ; + if (fd < 0) return 0 ; + if ((!ipc_connect(fd, path) && !error_isalready(errno)) + || !skaclient_init(a, fd, bufss, bufsn, auxbufss, auxbufsn, bufas, bufan, auxbufas, auxbufan, q, qlen, before, beforelen)) + { + register int e = errno ; + fd_close(fd) ; + errno = e ; + return 0 ; + } + a->pid = 0 ; + a->options = 0 ; + if (!kolbak_enqueue(&a->kq, (unixmessage_handler_func_t_ref)&skaclient_start_cb, blah)) + { + skaclient_end(a) ; + return 0 ; + } + blah->asyncin = &a->asyncin ; + blah->asyncout = &a->asyncout ; + blah->after = after ; + blah->afterlen = afterlen ; + return 1 ; +} diff --git a/src/libunixonacid/skaclient_start_cb.c b/src/libunixonacid/skaclient_start_cb.c new file mode 100644 index 0000000..6e641e2 --- /dev/null +++ b/src/libunixonacid/skaclient_start_cb.c @@ -0,0 +1,18 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/error.h> +#include <skalibs/skaclient.h> +#include <skalibs/unixmessage.h> +#include "skaclient-internal.h" + +int skaclient_start_cb (unixmessage_t const *m, skaclient_cbdata_t *blah) +{ + if (m->len != blah->afterlen + || byte_diff(m->s, m->len, blah->after) + || m->nfds != 1) return (errno = EPROTO, 0) ; + blah->asyncin->mainb.fd = m->fds[0] ; + blah->asyncout->fd = m->fds[0] ; + return 1 ; +} diff --git a/src/libunixonacid/skaclient_startf.c b/src/libunixonacid/skaclient_startf.c new file mode 100644 index 0000000..aa36323 --- /dev/null +++ b/src/libunixonacid/skaclient_startf.c @@ -0,0 +1,46 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/tai.h> +#include "skaclient-internal.h" + +int skaclient_startf ( + skaclient_t *a, + char *bufss, + unsigned int bufsn, + char *auxbufss, + unsigned int auxbufsn, + char *bufas, + unsigned int bufan, + char *auxbufas, + unsigned int auxbufan, + kolbak_closure_t *q, + unsigned int qlen, + char const *prog, + char const *const *argv, + char const *const *envp, + uint32 options, + char const *before, + unsigned int beforelen, + char const *after, + unsigned int afterlen, + tain_t const *deadline, + tain_t *stamp) +{ + skaclient_cbdata_t blah ; + unixmessage_t m ; + register int r ; + if (!skaclient_startf_async(a, bufss, bufsn, auxbufss, auxbufsn, bufas, bufan, auxbufas, auxbufan, q, qlen, prog, argv, envp, options, before, beforelen, after, afterlen, &blah)) return 0 ; + r = unixmessage_timed_receive(&a->syncin, &m, deadline, stamp) ; + if (r < 1) + { + int e = errno ; + if (!r) e = EPIPE ; + skaclient_end(a) ; + errno = e ; + return 0 ; + } + return kolbak_call(&m, &a->kq) ; +} diff --git a/src/libunixonacid/skaclient_startf_async.c b/src/libunixonacid/skaclient_startf_async.c new file mode 100644 index 0000000..4077c1e --- /dev/null +++ b/src/libunixonacid/skaclient_startf_async.c @@ -0,0 +1,61 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <errno.h> +#include <signal.h> +#include <skalibs/djbunix.h> +#include <skalibs/kolbak.h> +#include <skalibs/skaclient.h> +#include <skalibs/uint32.h> +#include "skaclient-internal.h" + +int skaclient_startf_async ( + skaclient_t *a, + char *bufss, + unsigned int bufsn, + char *auxbufss, + unsigned int auxbufsn, + char *bufas, + unsigned int bufan, + char *auxbufas, + unsigned int auxbufan, + kolbak_closure_t *q, + unsigned int qlen, + char const *prog, + char const *const *argv, + char const *const *envp, + uint32 options, + char const *before, + unsigned int beforelen, + char const *after, + unsigned int afterlen, + skaclient_cbdata_t *blah) +{ + int fd ; + pid_t pid = child_spawn(prog, argv, envp, &fd, 1) ; + if (!pid) return 0 ; + if (!skaclient_init(a, fd, bufss, bufsn, auxbufss, auxbufsn, bufas, bufan, auxbufas, auxbufan, q, qlen, before, beforelen)) + { + register int e = errno ; + fd_close(fd) ; + if (options & SKACLIENT_OPTION_WAITPID) + { + int wstat ; + waitpid_nointr(a->pid, &wstat, 0) ; + } + errno = e ; + return 0 ; + } + a->pid = pid ; + a->options = options ; + if (!kolbak_enqueue(&a->kq, (unixmessage_handler_func_t_ref)&skaclient_start_cb, blah)) + { + skaclient_end(a) ; + return 0 ; + } + blah->asyncin = &a->asyncin ; + blah->asyncout = &a->asyncout ; + blah->after = after ; + blah->afterlen = afterlen ; + return 1 ; +} diff --git a/src/libunixonacid/skaclient_zero.c b/src/libunixonacid/skaclient_zero.c new file mode 100644 index 0000000..4bb85b5 --- /dev/null +++ b/src/libunixonacid/skaclient_zero.c @@ -0,0 +1,5 @@ +/* ISC license. */ + +#include <skalibs/skaclient.h> + +skaclient_t const skaclient_zero = SKACLIENT_ZERO ; diff --git a/src/libunixonacid/timed_flush.c b/src/libunixonacid/timed_flush.c new file mode 100644 index 0000000..2d60256 --- /dev/null +++ b/src/libunixonacid/timed_flush.c @@ -0,0 +1,26 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/error.h> +#include <skalibs/bufalloc.h> +#include <skalibs/functypes.h> +#include <skalibs/iopause.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +int timed_flush (void *b, initfunc_t_ref getfd, initfunc_t_ref isnonempty, initfunc_t_ref flush, tain_t const *deadline, tain_t *stamp) +{ + iopause_fd x = { .fd = (*getfd)(b), .events = IOPAUSE_WRITE, .revents = 0 } ; + while ((*isnonempty)(b)) + { + register int r = iopause_stamp(&x, 1, deadline, stamp) ; + if (r < 0) return 0 ; + else if (!r) return (errno = ETIMEDOUT, 0) ; + else if (x.revents & IOPAUSE_WRITE) + { + if (!((*flush)(b)) && !error_isagain(errno)) return 0 ; + } + else if (x.revents & IOPAUSE_EXCEPT) return (*flush)(b) ; + } + return 1 ; +} diff --git a/src/libunixonacid/timed_get.c b/src/libunixonacid/timed_get.c new file mode 100644 index 0000000..0a02382 --- /dev/null +++ b/src/libunixonacid/timed_get.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/functypes.h> +#include <skalibs/tai.h> +#include <skalibs/iopause.h> +#include <skalibs/unix-timed.h> + +int timed_get (void *b, initfunc_t *getfd, initfunc_t *get, tain_t const *deadline, tain_t *stamp) +{ + iopause_fd x = { .fd = (*getfd)(b), .events = IOPAUSE_READ, .revents = 0 } ; + register int r = (*get)(b) ; + while (!r) + { + r = iopause_stamp(&x, 1, deadline, stamp) ; + if (!r) return (errno = ETIMEDOUT, -1) ; + else if (r > 0 && x.revents & (IOPAUSE_READ | IOPAUSE_EXCEPT)) + r = (*get)(b) ; + } + return unsanitize_read(r) ; +} diff --git a/src/libunixonacid/timed_getln.c b/src/libunixonacid/timed_getln.c new file mode 100644 index 0000000..0c442de --- /dev/null +++ b/src/libunixonacid/timed_getln.c @@ -0,0 +1,32 @@ +/* ISC license. */ + +#include <skalibs/allreadwrite.h> +#include <skalibs/buffer.h> +#include <skalibs/functypes.h> +#include <skalibs/skamisc.h> +#include <skalibs/stralloc.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +struct blah_s +{ + buffer *b ; + stralloc *sa ; + char sep ; +} ; + +static int getfd (struct blah_s *blah) +{ + return buffer_fd(blah->b) ; +} + +static int get (struct blah_s *blah) +{ + return sanitize_read(skagetln(blah->b, blah->sa, blah->sep)) ; +} + +int timed_getln (buffer *b, stralloc *sa, char sep, tain_t const *deadline, tain_t *stamp) +{ + struct blah_s blah = { .b = b, .sa = sa, .sep = sep } ; + return timed_get(&blah, (initfunc_t_ref)&getfd, (initfunc_t_ref)&get, deadline, stamp) ; +} diff --git a/src/libunixonacid/timed_getlnmax.c b/src/libunixonacid/timed_getlnmax.c new file mode 100644 index 0000000..8953606 --- /dev/null +++ b/src/libunixonacid/timed_getlnmax.c @@ -0,0 +1,33 @@ +/* ISC license. */ + +#include <skalibs/allreadwrite.h> +#include <skalibs/buffer.h> +#include <skalibs/functypes.h> +#include <skalibs/skamisc.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> + +struct blah_s +{ + buffer *b ; + char *d ; + unsigned int max ; + unsigned int w ; + char sep ; +} ; + +static int getfd (struct blah_s *blah) +{ + return buffer_fd(blah->b) ; +} + +static int get (struct blah_s *blah) +{ + return sanitize_read(getlnmax(blah->b, blah->d, blah->max, &blah->w, blah->sep)) ; +} + +int timed_getlnmax (buffer *b, char *d, unsigned int max, unsigned int *w, char sep, tain_t const *deadline, tain_t *stamp) +{ + struct blah_s blah = { .b = b, .d = d, .max = max, .w = 0, .sep = sep } ; + return timed_get(&blah, (initfunc_t_ref)&getfd, (initfunc_t_ref)&get, deadline, stamp) ; +} diff --git a/src/libunixonacid/unixmessage_bits_closeall.c b/src/libunixonacid/unixmessage_bits_closeall.c new file mode 100644 index 0000000..a963809 --- /dev/null +++ b/src/libunixonacid/unixmessage_bits_closeall.c @@ -0,0 +1,7 @@ +/* ISC license. */ + +#include <skalibs/bitarray.h> +#include <skalibs/unixmessage.h> + +static unsigned char _unixmessage_bits_closeall[bitarray_div8(UNIXMESSAGE_MAXFDS)] = "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" ; +unsigned char const *const unixmessage_bits_closeall = _unixmessage_bits_closeall ; diff --git a/src/libunixonacid/unixmessage_bits_closenone.c b/src/libunixonacid/unixmessage_bits_closenone.c new file mode 100644 index 0000000..79412a5 --- /dev/null +++ b/src/libunixonacid/unixmessage_bits_closenone.c @@ -0,0 +1,7 @@ +/* ISC license. */ + +#include <skalibs/bitarray.h> +#include <skalibs/unixmessage.h> + +static unsigned char _unixmessage_bits_closenone[bitarray_div8(UNIXMESSAGE_MAXFDS)] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ; +unsigned char const *const unixmessage_bits_closenone = _unixmessage_bits_closenone ; diff --git a/src/libunixonacid/unixmessage_handle.c b/src/libunixonacid/unixmessage_handle.c new file mode 100644 index 0000000..ad5789c --- /dev/null +++ b/src/libunixonacid/unixmessage_handle.c @@ -0,0 +1,19 @@ +/* ISC license. */ + +#include <skalibs/unixmessage.h> + +int unixmessage_handle (unixmessage_receiver_t *b, unixmessage_handler_func_t *f, void *p) +{ + unsigned int n = UNIXMESSAGE_MAXREADS ; + int count = 0 ; + while (n--) + { + unixmessage_t m ; + register int r = unixmessage_receive(b, &m) ; + if (r < 0) return -1 ; + if (!r) break ; + if (!(*f)(&m, p)) return -2 ; + count++ ; + } + return count ; +} diff --git a/src/libunixonacid/unixmessage_put.c b/src/libunixonacid/unixmessage_put.c new file mode 100644 index 0000000..f6db23b --- /dev/null +++ b/src/libunixonacid/unixmessage_put.c @@ -0,0 +1,83 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> +#ifdef SKALIBS_HASANCILAUTOCLOSE +#include <unistd.h> +#endif +#include <errno.h> +#include <skalibs/bitarray.h> +#include <skalibs/bytestr.h> +#include <skalibs/diuint.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/siovec.h> +#include <skalibs/unixmessage.h> + +static inline int copyfds (char *s, int const *fds, unsigned int n, unsigned char const *bits) +{ + register unsigned int i = 0 ; + for (; i < n ; i++) + { + int fd = fds[i] ; + if (fd < 0) return (errno = EINVAL, -1) ; + if (bitarray_peek(bits, i)) fd = - fd - 1 ; +#ifdef SKALIBS_HASANCILAUTOCLOSE + else + { + fd = dup(fd) ; + if (fd < 0) + { + int e = errno ; + while (i--) + { + s -= sizeof(int) ; + byte_copy((char *)fd, sizeof(int), s) ; + if (fd >= 0) fd_close(fd) ; + } + errno = e ; + return 0 ; + } + } +#else +#endif + byte_copy(s, sizeof(int), (char const *)&fd) ; + s += sizeof(int) ; + } + return 1 ; +} + +static int reserve_and_copy (unixmessage_sender_t *b, unsigned int len, int const *fds, unsigned int nfds, unsigned char const *bits) +{ + diuint cur = { .left = b->data.len, .right = b->fds.len } ; + if (!genalloc_readyplus(diuint, &b->offsets, 1) + || !genalloc_readyplus(int, &b->fds, nfds) + || !stralloc_readyplus(&b->data, len)) + return 0 ; + if (!copyfds(b->fds.s + b->fds.len, fds, nfds, bits)) return 0 ; + b->fds.len += nfds * sizeof(int) ; + byte_copy(b->offsets.s + b->offsets.len, sizeof(diuint), (char const *)&cur) ; + b->offsets.len += sizeof(diuint) ; + return 1 ; +} + +int unixmessage_put_and_close (unixmessage_sender_t *b, unixmessage_t const *m, unsigned char const *bits) +{ + if (!reserve_and_copy(b, m->len, m->fds, m->nfds, bits)) return 0 ; + byte_copy(b->data.s + b->data.len, m->len, m->s) ; + b->data.len += m->len ; + return 1 ; +} + +int unixmessage_putv_and_close (unixmessage_sender_t *b, unixmessage_v_t const *m, unsigned char const *bits) +{ + unsigned int len = 0 ; + register unsigned int i = 0 ; + for (; i < m->vlen ; i++) len += m->v[i].len ; + if (!reserve_and_copy(b, len, m->fds, m->nfds, bits)) return 0 ; + for (i = 0 ; i < m->vlen ; i++) + { + byte_copy(b->data.s + b->data.len, m->v[i].len, m->v[i].s) ; + b->data.len += m->v[i].len ; + } + return 1 ; +} diff --git a/src/libunixonacid/unixmessage_read.c b/src/libunixonacid/unixmessage_read.c new file mode 100644 index 0000000..5a23b84 --- /dev/null +++ b/src/libunixonacid/unixmessage_read.c @@ -0,0 +1,60 @@ +/* ISC license. */ + +#define _XPG4_2 +#include <skalibs/sysdeps.h> +#include <skalibs/nonposix.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <skalibs/buffer.h> +#include <skalibs/cbuffer.h> +#include <skalibs/djbunix.h> +#include <skalibs/error.h> +#include <skalibs/siovec.h> +#include <skalibs/unixmessage.h> + +int unixmessage_read (int fd, siovec_t const *v, unsigned int n, void *aux) +{ + int r ; + char ancilbuf[CMSG_SPACE(UNIXMESSAGE_MAXFDS * sizeof(int))] ; + struct iovec iov[n] ; + struct msghdr msghdr = + { + .msg_name = 0, + .msg_namelen = 0, + .msg_iov = iov, + .msg_iovlen = n, + .msg_flags = 0, + .msg_control = ancilbuf, + .msg_controllen = sizeof(ancilbuf) + } ; + iovec_from_siovec(iov, v, n) ; +#ifdef SKALIBS_HASCMSGCLOEXEC + r = recvmsg(fd, &msghdr, MSG_WAITALL | MSG_CMSG_CLOEXEC) ; +#else + r = recvmsg(fd, &msghdr, MSG_WAITALL) ; +#endif + if (r > 0) + { + struct cmsghdr *c = CMSG_FIRSTHDR(&msghdr) ; + if (c) + { + cbuffer_t *auxb = aux ; + unsigned int len ; + if (c->cmsg_level != SOL_SOCKET + || c->cmsg_type != SCM_RIGHTS) return (errno = EPROTO, -1-r) ; + len = (unsigned int)(c->cmsg_len - (CMSG_DATA(c) - (unsigned char *)c)) ; +#ifndef SKALIBS_HASCMSGCLOEXEC + { + register unsigned int i = 0 ; + for (; i < len/sizeof(int) ; i++) + if (coe(((int *)CMSG_DATA(c))[i]) < 0) return -1-r ; + } +#endif + if (msghdr.msg_flags | MSG_CTRUNC) return (errno = EPROTO, -1-r) ; + if (cbuffer_put(auxb, (char *)CMSG_DATA(c), len) < len) + return (errno = ENOBUFS, -1-r) ; + } + } + return r ; +} diff --git a/src/libunixonacid/unixmessage_receive.c b/src/libunixonacid/unixmessage_receive.c new file mode 100644 index 0000000..dc75263 --- /dev/null +++ b/src/libunixonacid/unixmessage_receive.c @@ -0,0 +1,44 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/buffer.h> +#include <skalibs/cbuffer.h> +#include <skalibs/error.h> +#include <skalibs/stralloc.h> +#include <skalibs/uint.h> +#include <skalibs/unixmessage.h> + +int unixmessage_receive (unixmessage_receiver_t *b, unixmessage_t *m) +{ + if (b->data.len == b->mainlen) + { + char pack[sizeof(unsigned int) << 1] ; + if (buffer_len(&b->mainb) < sizeof(unsigned int) << 1) + { + register int r = sanitize_read(buffer_fill(&b->mainb)) ; + if (r <= 0) return r ; + if (r < sizeof(unsigned int) << 1) return (errno = EWOULDBLOCK, 0) ; + } + buffer_getnofill(&b->mainb, pack, sizeof(unsigned int) << 1) ; + uint_unpack_big(pack, &b->mainlen) ; + uint_unpack_big(pack + sizeof(unsigned int), &b->auxlen) ; + if (b->auxlen > UNIXMESSAGE_MAXFDS) return (errno = EPROTO, -1) ; + b->auxlen *= sizeof(int) ; + if (!stralloc_ready(&b->data, b->mainlen)) return -1 ; + b->data.len = 0 ; + b->auxw = cbuffer_get(&b->auxb, (char *)b->fds, b->auxlen) ; + } + { + register int r = buffer_getall(&b->mainb, b->data.s, b->mainlen, &b->data.len) ; + if (r <= 0) return r ; + } + if (b->auxw < b->auxlen) + b->auxw += cbuffer_get(&b->auxb, (char *)b->fds, b->auxlen - b->auxw) ; + if (b->auxw < b->auxlen) return (errno = EPROTO, -1) ; + m->s = b->data.s ; + m->len = b->data.len ; + m->fds = b->fds ; + m->nfds = b->auxlen / sizeof(int) ; + return 1 ; +} diff --git a/src/libunixonacid/unixmessage_receiver_free.c b/src/libunixonacid/unixmessage_receiver_free.c new file mode 100644 index 0000000..c23cc77 --- /dev/null +++ b/src/libunixonacid/unixmessage_receiver_free.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <skalibs/stralloc.h> +#include <skalibs/unixmessage.h> + +void unixmessage_receiver_free (unixmessage_receiver_t *b) +{ + stralloc_free(&b->data) ; + b->mainb.fd = -1 ; + b->mainlen = b->auxlen = b->auxw = 0 ; +} diff --git a/src/libunixonacid/unixmessage_receiver_init.c b/src/libunixonacid/unixmessage_receiver_init.c new file mode 100644 index 0000000..982547c --- /dev/null +++ b/src/libunixonacid/unixmessage_receiver_init.c @@ -0,0 +1,17 @@ +/* ISC license. */ + +#include <errno.h> +#include <skalibs/buffer.h> +#include <skalibs/cbuffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/unixmessage.h> + +int unixmessage_receiver_init (unixmessage_receiver_t *b, int fd, char *mainbuf, unsigned int mainlen, char *auxbuf, unsigned int auxlen) +{ + if (mainlen < 9 || auxlen < UNIXMESSAGE_MAXFDS * sizeof(int) + 1) return (errno = EINVAL, 0) ; + if (!cbuffer_init(&b->auxb, auxbuf, auxlen)) return 0 ; + if (!buffer_init_aux(&b->mainb, &unixmessage_read, fd, mainbuf, mainlen, &b->auxb)) return 0 ; + b->mainlen = b->auxlen = b->auxw = 0 ; + b->data = stralloc_zero ; + return 1 ; +} diff --git a/src/libunixonacid/unixmessage_sender_flush.c b/src/libunixonacid/unixmessage_sender_flush.c new file mode 100644 index 0000000..ab8d460 --- /dev/null +++ b/src/libunixonacid/unixmessage_sender_flush.c @@ -0,0 +1,82 @@ +/* ISC license. */ + +#define _XPG4_2 +#include <skalibs/sysdeps.h> +#include <skalibs/nonposix.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <unistd.h> +#include <skalibs/uint.h> +#include <skalibs/diuint.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/unixmessage.h> + + /* MacOS X tries hard to be POSIX-compliant... and fails. */ +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +int unixmessage_sender_flush (unixmessage_sender_t *b) +{ + diuint last = { .left = b->data.len, .right = genalloc_len(int, &b->fds) } ; + diuint *offsets = genalloc_s(diuint, &b->offsets) ; + unsigned int n = genalloc_len(diuint, &b->offsets) ; + unsigned int oldhead = b->head ; + for (; b->head < n ; b->head++) + { + diuint *next = b->head+1 < n ? offsets + b->head+1 : &last ; + unsigned int len = next->left - offsets[b->head].left ; + unsigned int nfds = next->right - offsets[b->head].right ; + char pack[sizeof(unsigned int) << 1] ; + struct iovec v[2] = + { + { .iov_base = pack, .iov_len = sizeof(unsigned int) << 1 }, + { .iov_base = b->data.s + offsets[b->head].left, .iov_len = len } + } ; + char ancilbuf[CMSG_SPACE(nfds * sizeof(int))] ; + struct msghdr hdr = + { + .msg_name = 0, + .msg_namelen = 0, + .msg_iov = v, + .msg_iovlen = 2, + .msg_control = nfds ? ancilbuf : 0, + .msg_controllen = nfds ? sizeof(ancilbuf) : 0 + } ; + uint_pack_big(pack, len) ; + uint_pack_big(pack + sizeof(unsigned int), nfds) ; + if (nfds) + { + struct cmsghdr *cp = CMSG_FIRSTHDR(&hdr) ; + register unsigned int i = 0 ; + cp->cmsg_level = SOL_SOCKET ; + cp->cmsg_type = SCM_RIGHTS ; + cp->cmsg_len = CMSG_LEN(nfds * sizeof(int)) ; + for (; i < nfds ; i++) + { + register int fd = genalloc_s(int, &b->fds)[offsets[b->head].right + i] ; + ((int *)CMSG_DATA(cp))[i] = fd < 0 ? -(fd+1) : fd ; + } + } + if (sendmsg(b->fd, &hdr, MSG_NOSIGNAL) < len + (sizeof(unsigned int) << 1)) + return -(int)(b->head-oldhead)-1 ; +#ifndef SKALIBS_HASANCILAUTOCLOSE + if (nfds) + { + register unsigned int i = 0 ; + for (; i < nfds ; i++) + { + register int fd = genalloc_s(int, &b->fds)[offsets[b->head].right + i] ; + if (fd < 0) fd_close(-(fd+1)) ; + } + } +#endif + } + b->data.len = 0 ; + genalloc_setlen(int, &b->fds, 0) ; + genalloc_setlen(diuint, &b->offsets, 0) ; + b->head = 0 ; + return (int)(n - oldhead) ; +} diff --git a/src/libunixonacid/unixmessage_sender_free.c b/src/libunixonacid/unixmessage_sender_free.c new file mode 100644 index 0000000..797220c --- /dev/null +++ b/src/libunixonacid/unixmessage_sender_free.c @@ -0,0 +1,29 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> +#include <skalibs/diuint.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/unixmessage.h> + +void unixmessage_sender_free (unixmessage_sender_t *b) +{ +#ifdef SKALIBS_HASANCILAUTOCLOSE + { + diuint *offsets = genalloc_s(unsigned int, &b->offsets) ; + unsigned int n = genalloc_len(unsigned int, &b->offsets) ; + int *fds = genalloc_s(int, &b->fds) ; + unsigned int nfds = genalloc_len(int, &b->fds) ; + for (; b->head < n ; b->head++) + { + register unsigned int last = b->head+1 < n ? offsets[b->head+1].right : nfds ; + register unsigned int i = offsets[b->head].right ; + for (; i < last ; i++) if (fds[i] >= 0) fd_close(fds[i]) ; + } + } +#endif + genalloc_free(diuint, &b->offsets) ; + genalloc_free(int, &b->fds) ; + stralloc_free(&b->data) ; + *b = unixmessage_sender_zero ; +} diff --git a/src/libunixonacid/unixmessage_sender_getfd.c b/src/libunixonacid/unixmessage_sender_getfd.c new file mode 100644 index 0000000..1f130eb --- /dev/null +++ b/src/libunixonacid/unixmessage_sender_getfd.c @@ -0,0 +1,8 @@ +/* ISC license. */ + +#include <skalibs/unixmessage.h> + +int unixmessage_sender_getfd (unixmessage_sender_t const *b) +{ + return b->fd ; +} diff --git a/src/libunixonacid/unixmessage_sender_init.c b/src/libunixonacid/unixmessage_sender_init.c new file mode 100644 index 0000000..07c0bc2 --- /dev/null +++ b/src/libunixonacid/unixmessage_sender_init.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/unixmessage.h> + +void unixmessage_sender_init (unixmessage_sender_t *b, int fd) +{ + b->fd = fd ; + b->data = stralloc_zero ; + b->fds = genalloc_zero ; + b->offsets = genalloc_zero ; + b->head = 0 ; +} diff --git a/src/libunixonacid/unixmessage_sender_timed_flush.c b/src/libunixonacid/unixmessage_sender_timed_flush.c new file mode 100644 index 0000000..74e4937 --- /dev/null +++ b/src/libunixonacid/unixmessage_sender_timed_flush.c @@ -0,0 +1,17 @@ +/* ISC license. */ + +#include <skalibs/functypes.h> +#include <skalibs/genalloc.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> +#include <skalibs/unixmessage.h> + +static int unixmessage_sender_isnonempty (unixmessage_sender_t *b) +{ + return !!genalloc_len(unsigned int, &b->offsets) ; +} + +int unixmessage_sender_timed_flush (unixmessage_sender_t *b, tain_t const *deadline, tain_t *stamp) +{ + return timed_flush(b, (initfunc_t_ref)&unixmessage_sender_getfd, (initfunc_t_ref)&unixmessage_sender_isnonempty, (initfunc_t_ref)&unixmessage_sender_flush, deadline, stamp) ; +} diff --git a/src/libunixonacid/unixmessage_sender_zero.c b/src/libunixonacid/unixmessage_sender_zero.c new file mode 100644 index 0000000..bda0a9b --- /dev/null +++ b/src/libunixonacid/unixmessage_sender_zero.c @@ -0,0 +1,5 @@ +/* ISC license. */ + +#include <skalibs/unixmessage.h> + +unixmessage_sender_t const unixmessage_sender_zero = UNIXMESSAGE_SENDER_ZERO ; diff --git a/src/libunixonacid/unixmessage_timed_handle.c b/src/libunixonacid/unixmessage_timed_handle.c new file mode 100644 index 0000000..5ac7ccd --- /dev/null +++ b/src/libunixonacid/unixmessage_timed_handle.c @@ -0,0 +1,30 @@ +/* ISC license. */ + +#include <skalibs/functypes.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> +#include <skalibs/unixmessage.h> + +typedef struct unixmessage_handler_blah_s unixmessage_handler_blah_t, *unixmessage_handler_blah_t_ref ; +struct unixmessage_handler_blah_s +{ + unixmessage_receiver_t *b ; + unixmessage_handler_func_t *f ; + void *p ; +} ; + +static int getfd (unixmessage_handler_blah_t *blah) +{ + return unixmessage_receiver_fd(blah->b) ; +} + +static int get (unixmessage_handler_blah_t *blah) +{ + return unixmessage_handle(blah->b, blah->f, blah->p) ; +} + +int unixmessage_timed_handle (unixmessage_receiver_t *b, unixmessage_handler_func_t *f, void *p, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_handler_blah_t blah = { .b = b, .f = f, .p = p } ; + return timed_get(&blah, (initfunc_t_ref)&getfd, (initfunc_t_ref)&get, deadline, stamp) ; +} diff --git a/src/libunixonacid/unixmessage_timed_receive.c b/src/libunixonacid/unixmessage_timed_receive.c new file mode 100644 index 0000000..3761d26 --- /dev/null +++ b/src/libunixonacid/unixmessage_timed_receive.c @@ -0,0 +1,29 @@ +/* ISC license. */ + +#include <skalibs/functypes.h> +#include <skalibs/tai.h> +#include <skalibs/unix-timed.h> +#include <skalibs/unixmessage.h> + +typedef struct unixmessage_get_s unixmessage_get_t, *unixmessage_get_t_ref ; +struct unixmessage_get_s +{ + unixmessage_receiver_t *b ; + unixmessage_t *m ; +} ; + +static int getfd (unixmessage_get_t *g) +{ + return unixmessage_receiver_fd(g->b) ; +} + +static int get (unixmessage_get_t *g) +{ + return unixmessage_receive(g->b, g->m) ; +} + +int unixmessage_timed_receive (unixmessage_receiver_t *b, unixmessage_t *m, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_get_t g = { .b = b, .m = m } ; + return timed_get(&g, (initfunc_t *)&getfd, (initfunc_t *)&get, deadline, stamp) ; +} diff --git a/src/libunixonacid/unixmessage_v_zero.c b/src/libunixonacid/unixmessage_v_zero.c new file mode 100644 index 0000000..b4ab13a --- /dev/null +++ b/src/libunixonacid/unixmessage_v_zero.c @@ -0,0 +1,5 @@ +/* ISC license. */ + +#include <skalibs/unixmessage.h> + +unixmessage_v_t const unixmessage_v_zero = UNIXMESSAGE_V_ZERO ; diff --git a/src/libunixonacid/unixmessage_zero.c b/src/libunixonacid/unixmessage_zero.c new file mode 100644 index 0000000..4cfb242 --- /dev/null +++ b/src/libunixonacid/unixmessage_zero.c @@ -0,0 +1,5 @@ +/* ISC license. */ + +#include <skalibs/unixmessage.h> + +unixmessage_t const unixmessage_zero = UNIXMESSAGE_ZERO ; |