author | Olivier Brunel
<jjk@jjacky.com> 2023-05-13 07:52:10 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-07-05 07:37:02 UTC |
parent | 54ef7d834621f78f5bf10351ff6c313b559ba02f |
src/doc/unix-transactional.h.0.md | +15 | -0 |
src/doc/unix-transactional.h/open_read_closeat.3.md | +54 | -0 |
src/doc/unix-transactional.h/open_tmpat.3.md | +44 | -0 |
src/doc/unix-transactional.h/open_write_closeat.3.md | +46 | -0 |
src/liblimb/include/limb/unix-transactional.h | +9 | -0 |
src/liblimb/unix-transactional.h/open_read_closeat.c | +29 | -0 |
src/liblimb/unix-transactional.h/open_slurp_closeat.c | +16 | -0 |
src/liblimb/unix-transactional.h/open_write_closeat.c | +26 | -0 |
src/liblimb/unix-transactional.h/open_writev_closeat.c | +27 | -0 |
diff --git a/src/doc/unix-transactional.h.0.md b/src/doc/unix-transactional.h.0.md index e0afbe3..49b5504 100644 --- a/src/doc/unix-transactional.h.0.md +++ b/src/doc/unix-transactional.h.0.md @@ -40,3 +40,18 @@ The following functions are defined : : [openc_exclat](3) :: Same as [openc_excl](3) but relative path are based of given file descriptor + +: [open_tmpat](3) +:: Same as [open_tmp](3) but relative path are based of given file descriptor. + +: [open_read_closeat](3) +:: Open, read & close a file into memory. + +: [open_slurp_closeat](3) +:: Open, read & close a file into a *stralloc*. + +: [open_write_closeat](3) +:: Open, write & close a file with data from pointed memory. + +: [open_writev_closeat](3) +:: Open, write & close a file with data from array of vectors. diff --git a/src/doc/unix-transactional.h/open_read_closeat.3.md b/src/doc/unix-transactional.h/open_read_closeat.3.md new file mode 100644 index 0000000..5870ee2 --- /dev/null +++ b/src/doc/unix-transactional.h/open_read_closeat.3.md @@ -0,0 +1,54 @@ +% limb manual +% open_read_closeat(3) + +# NAME + +open\_read\_closeat, open\_slurp\_closeat - open, read & close a file + +# SYNOPSIS + + #include <limb/unix-transactional.h> + +```pre hl +ssize_t open_read_closeat(char *<em>dst</em>, size_t <em>dlen</em>, int <em>fd</em>, const char *<em>file</em>) +int open_slurp_closeat(stralloc *<em>sa</em>, int <em>fd</em>, const char *<em>file</em>) +``` + +# DESCRIPTION + +The `open_read_closeat`() function will open the file named `file` for reading +in blocking mode. If `file` describes a relative path, it is relative to the +directory associated with the file descriptor `fd`, which may be *AT_FDCWD* to +use the current working directory. + +The content of the file will be read and copied into the memory pointed by `dst` +up to a maximum of `dlen` bytes, and the file be closed. + +The `open_slurp_closeat`() function is similar, only the entirety of the file +will be placed into the *stralloc* pointed by `sa`, allocating as much memory as +needed. + +# RETURN VALUE + +The `open_read_closeat`() function returns the amount of data read from the +file, and written into `dst`, on success. Otherwise it returns -1 and sets +`errno` to indicate the error. + +The `open_slurp_closeat`() function returns 1 on success. Otherwise it returns 0 +and sets `errno` to indicate the error. + +# ERRORS + +The `open_read_closeat`() and `open_slurp_closeat`() function may fail and set +`errno` for the errors described for [openb_readat](3). + +The `open_read_closeat`() function may also fail if : + +: *ENOBUFS* +:: Not enough space available in `dst` to store the entire file. + +The `open_read_closeat`() may also fail and set `errno` for the errors described +for [read](3). + +The `open_slurp_closeat`() may also fail and set `errno` for the errors +described for [slurp](3). diff --git a/src/doc/unix-transactional.h/open_tmpat.3.md b/src/doc/unix-transactional.h/open_tmpat.3.md new file mode 100644 index 0000000..ce76948 --- /dev/null +++ b/src/doc/unix-transactional.h/open_tmpat.3.md @@ -0,0 +1,44 @@ +% limb manual +% open_tmpat(3) + +# NAME + +open\_tmpat - open a new temporary file + +# SYNOPSIS + + #include <limb/unix-transactional.h> + +```pre hl +int open_tmpat(int <em>fd</em>, char *<em>name</em>) +``` + +# DESCRIPTION + +The `open_tmpat`() function opens a new temporary file for writing, using a name +based on the template pointed by `name` - which must end with at least 6 +characters `X` that will be replaced with random (printable) characters. + +The memory pointed by `name` will be modified, replacing the trailing `X` +characters so that `name` contains the name of the file actually opened. + +If `name` describes a relative path, it is relative to the directory associated +with the file descriptor `fd`, which may be *AT_FDCWD* to use the current working +directory. + +! NOTE: +! It is actually implemented as a macro to [mkfiletempat](3). + +# RETURN VALUE + +The `open_tmpat`() function returns the opened file descriptor on success. +Otherwise it returns -1 and sets `errno` to indicate the error. + +# ERRORS + +The `open_tmpat`() function may fail if : + +: *EINVAL* +:: The template pointed by `name` does not end with at least 6 `X`. + +It may also fail and set `errno` for the errors described for [open_exclat](3). diff --git a/src/doc/unix-transactional.h/open_write_closeat.3.md b/src/doc/unix-transactional.h/open_write_closeat.3.md new file mode 100644 index 0000000..35b2059 --- /dev/null +++ b/src/doc/unix-transactional.h/open_write_closeat.3.md @@ -0,0 +1,46 @@ +% limb manual +% open_write_closeat(3) + +# NAME + +open\_write_closeat, open\_writev\_closetat - open, write & close a file + +# SYNOPSIS + + #include <limb/unix-transactional.h> + +```pre hl +int open_write_closeat(int <em>fd</em>, const char *<em>file</em>, const char *<em>data</em>, size_t <em>dlen</em>) +int open_writev_closeat(int <em>fd</em>, const char *<em>file</em>, const struct iovec *<em>v</em>, unsigned <em>n</em>) +``` + +# DESCRIPTION + +The `open_write_closeat`() function will write the data pointed by `data` of +length `dlen` bytes into a file named `file`. If `file` describes a relative +path, it is relative to the directory associated with the file descriptor `fd`, +which may be *AT_FDCWD* to use the current working directory. + +It actually creates a new temporary file into which all data is written first, +and then renames it to `file`. As such, any error will leave any previously +existing file of the same name unchanged (and the temporary file will have been +removed). + +The `open_writev_closeat`() function is similar, only the data to be written +will be gathered from the array of vectors pointed by `v` of `n` elements. + +# RETURN VALUE + +These functions return 1 on success. Otherwise they return 0 and set `errno` to +indicate the error. + +# ERRORS + +These functions may fail and set `errno` for the errors described for +[open_tmpat](3) and [renameat](3). + +The `open_write_closeat`() function may also fail and set `errno` for the errors +described for [write](3). + +The `open_writev_closeat`() function may also fail and set `errno` for the +errors described for [writev](3). diff --git a/src/liblimb/include/limb/unix-transactional.h b/src/liblimb/include/limb/unix-transactional.h index 5fff355..d965036 100644 --- a/src/liblimb/include/limb/unix-transactional.h +++ b/src/liblimb/include/limb/unix-transactional.h @@ -5,6 +5,8 @@ #define LIMB_UNIXTRANSACTIONAL_H #include <skalibs/unix-transactional.h> +#include <limb/posixplz.h> +#include <limb/siovec.h> extern int openb_readat(int fd, const char *file); extern int openbc_readat(int fd, const char *file); @@ -14,4 +16,11 @@ extern int open_createat(int fd, const char *file); extern int openc_exclat(int fd, const char *file); extern int open_exclat(int fd, const char *file); +#define open_tmpat(fd,tmp) mkfiletempat(fd, tmp, (createat_fn) (void (*)(void)) open_exclat, 0, NULL) + +extern ssize_t open_read_closeat(char *dst, size_t dlen, int bfd, const char *file); +extern int open_slurp_closeat(stralloc *sa, int bfd, const char *file); +extern int open_write_closeat(int fd, const char *file, const char *data, size_t dlen); +extern int open_writev_closeat(int fd, const char *file, const struct iovec *v, unsigned n); + #endif /* LIMB_UNIXTRANSACTIONAL_H */ diff --git a/src/liblimb/unix-transactional.h/open_read_closeat.c b/src/liblimb/unix-transactional.h/open_read_closeat.c new file mode 100644 index 0000000..010809d --- /dev/null +++ b/src/liblimb/unix-transactional.h/open_read_closeat.c @@ -0,0 +1,29 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <errno.h> +#include <skalibs/allreadwrite.h> +#include <limb/djbunix.h> +#include <limb/unix-transactional.h> + +ssize_t +open_read_closeat(char *dst, size_t dlen, int bfd, const char *file) +{ + int fd = openb_readat(bfd, file); + if (fd < 0) return -1; + + errno = 0; + ssize_t r = allread(fd, dst, dlen); + if (errno) goto err; + + if ((size_t) r == dlen) { + char c; + ssize_t rr = fd_read(fd, &c, 1); + if (rr < 0) r = rr; + else if (rr == 1) (errno = ENOBUFS, r = -1); + } + +err: + fd_close(fd); + return r; +} diff --git a/src/liblimb/unix-transactional.h/open_slurp_closeat.c b/src/liblimb/unix-transactional.h/open_slurp_closeat.c new file mode 100644 index 0000000..16ff4ff --- /dev/null +++ b/src/liblimb/unix-transactional.h/open_slurp_closeat.c @@ -0,0 +1,16 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <limb/djbunix.h> +#include <limb/unix-transactional.h> + +int +open_slurp_closeat(stralloc *sa, int bfd, const char *file) +{ + int fd = openb_readat(bfd, file); + if (fd < 0) return -1; + + int r = slurp(sa, fd); + fd_close(fd); + return r; +} diff --git a/src/liblimb/unix-transactional.h/open_write_closeat.c b/src/liblimb/unix-transactional.h/open_write_closeat.c new file mode 100644 index 0000000..0ee3cdc --- /dev/null +++ b/src/liblimb/unix-transactional.h/open_write_closeat.c @@ -0,0 +1,26 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <stdio.h> +#include <skalibs/allreadwrite.h> +#include <limb/djbunix.h> +#include <limb/unix-transactional.h> + +int +open_write_closeat(int bfd, const char *file, const char *data, size_t dlen) +{ + char tmp[] = ".tmp.limb.XXXXXX"; + int fd = open_tmpat(bfd, tmp); + if (fd < 0) return 0; + + if (allwrite(fd, data, dlen) < dlen || renameat(bfd, tmp, bfd, file) < 0) + goto err; + + fd_close(fd); + return 1; + +err: + fd_close(fd); + unlinkat_void(bfd, tmp, 0); + return 0; +} diff --git a/src/liblimb/unix-transactional.h/open_writev_closeat.c b/src/liblimb/unix-transactional.h/open_writev_closeat.c new file mode 100644 index 0000000..c48744a --- /dev/null +++ b/src/liblimb/unix-transactional.h/open_writev_closeat.c @@ -0,0 +1,27 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <stdio.h> +#include <skalibs/allreadwrite.h> +#include <limb/djbunix.h> +#include <limb/siovec.h> +#include <limb/unix-transactional.h> + +int +open_writev_closeat(int bfd, const char *file, const struct iovec *v, unsigned n) +{ + char tmp[] = ".tmp.limb.XXXXXX"; + int fd = open_tmpat(bfd, tmp); + if (fd < 0) return 0; + + if (allwritev(fd, v, n) < siov_len(v, n) || renameat(bfd, tmp, bfd, file) < 0) + goto err; + + fd_close(fd); + return 1; + +err: + fd_close(fd); + unlinkat_void(bfd, tmp, 0); + return 0; +}