author | Olivier Brunel
<jjk@jjacky.com> 2023-05-04 14:03:36 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-05-20 18:06:40 UTC |
parent | 7e759f64d3911b6d2fb294c0914637a40925d5a8 |
src/doc/posixplz.h.0.md | +28 | -0 |
src/doc/posixplz.h/mkfiletempat.3.md | +53 | -0 |
src/doc/posixplz.h/unlinkat_void.3.md | +19 | -0 |
src/liblimb/include/limb/posixplz.h | +14 | -0 |
src/liblimb/posixplz.h/mkfiletempat.c | +25 | -0 |
src/liblimb/posixplz.h/unlinkat_void.c | +14 | -0 |
src/liblimb/shldata-rw.h/shldata_write.c | +4 | -8 |
diff --git a/src/doc/posixplz.h.0.md b/src/doc/posixplz.h.0.md new file mode 100644 index 0000000..6b0d387 --- /dev/null +++ b/src/doc/posixplz.h.0.md @@ -0,0 +1,28 @@ +% limb manual +% posixplz.h(0) + +# NAME + +posixplz.h - functions that maybe should be in POSIX :-) + +# SYNOPSIS + + #include <limb/posixplz.h> + +# DESCRIPTION + +This header defines functions that aren't but maybe should be in POSIX. + +! INFO: skalibs +! This header is a complement to skalibs' own [skalibs/posixplz.h](0) and +! thusly includes said header. + +## Functions + +The following functions/macros are defined : + +: [mkfiletempat](3) +:: To open a new temporary file. + +: [unlinkat_void](3) +:: To remove a file without affecting `errno`. diff --git a/src/doc/posixplz.h/mkfiletempat.3.md b/src/doc/posixplz.h/mkfiletempat.3.md new file mode 100644 index 0000000..be15a17 --- /dev/null +++ b/src/doc/posixplz.h/mkfiletempat.3.md @@ -0,0 +1,53 @@ +% limb manual +% mkfiletempat(3) + +# NAME + +mkfiletempat - open a new temporary file + +# SYNOPSIS + + #include <limb/posixplz.h> + +```pre hl +typedef int (*createat_fn) (int <em>fd</em>, const char *<em>file</em>, mode_t <em>mode</em>, void *<em>data</em>) + +int mkfiletempat(int <em>bfd</em>, char *<em>name</em>, createat_fn <em>fn</em>, mode_t <em>mode</em>, void *<em>data</em>) +``` + +# DESCRIPTION + +The `mkfiletempat`() function will open a new temporary file using the function +pointed by `fn`, passing it the `bfd` argument and a file name based on the +template pointed by `name` - which must end with at least 6 characters `X` that +will be replaced by random (printable) characters - as well as the `mode` and +`data` arguments. + +The memory pointed by `name` will be modified, replacing the trailing `X` +characters so that `name` contains the name of the file actually opened. + +The `fn` function should create & open a file whose name is pointed by its +second argument, which, when specifying a relative path, should be determined +relative to the directory associated with the file descriptor `bfd`. +If passed the special value *AT_FDCWD* in the `bfd` parameter, the current +working directory should be used used. + +It should return the file descriptor of the newly created file on success, +otherwise returning -1 and setting `errno`. In case of failure due to *EEXIST* +a new file name will automatically be generated and a new call made. + +# RETURN VALUE + +The `mkfiletempat`() function returns the file descriptor to the newly created +temporary file, as returned by `fn`, on success. Otherwise it returns -1 and +sets `errno` to indicate the error. + +# ERRORS + +The `mkfiletempat`() function may fail if : + +: *EINVAL* +:: The template filename pointed by `name` did not end with at least 6 `X`. + +It may also fail and set `errno` for any of the errors described for the +function pointed by `fn`, save for *EEXIST*. diff --git a/src/doc/posixplz.h/unlinkat_void.3.md b/src/doc/posixplz.h/unlinkat_void.3.md new file mode 100644 index 0000000..561d91b --- /dev/null +++ b/src/doc/posixplz.h/unlinkat_void.3.md @@ -0,0 +1,19 @@ +% limb manual +% unlinkat_void(3) + +# NAME + +unlinkat_void - remove a file without affecting errno + +# SYNOPSIS + + #include <limb/posixplz.h> + +```pre hl +void unlinkat_void(int <em>bfd</em>, const char *<em>file</em>, int <em>flags</em>) +``` + +# DESCRIPTION + +The `unlinkat_void`() function calls [unlinkat](3) with arguments `bfd`, `file` +and `flags`, making sure the current value of `errno` will /not/ be changed. diff --git a/src/liblimb/include/limb/posixplz.h b/src/liblimb/include/limb/posixplz.h new file mode 100644 index 0000000..03fffca --- /dev/null +++ b/src/liblimb/include/limb/posixplz.h @@ -0,0 +1,14 @@ +/* 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 */ +#ifndef LIMB_POSIXPLZ_H +#define LIMB_POSIXPLZ_H + +#include <skalibs/posixplz.h> + +typedef int (*createat_fn) (int fd, const char *file, mode_t mode, void *data); + +extern int mkfiletempat(int bfd, char *name, createat_fn fn, mode_t mode, void *data); +extern void unlinkat_void(int bfd, const char *file, int flags); + +#endif /* LIMB_POSIXPLZ_H */ diff --git a/src/liblimb/posixplz.h/mkfiletempat.c b/src/liblimb/posixplz.h/mkfiletempat.c new file mode 100644 index 0000000..679a933 --- /dev/null +++ b/src/liblimb/posixplz.h/mkfiletempat.c @@ -0,0 +1,25 @@ +/* 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 <string.h> +#include <skalibs/random.h> +#include <limb/posixplz.h> + +int +mkfiletempat(int bfd, char *name, createat_fn fn, mode_t mode, void *data) +{ + size_t len = strlen (name); + size_t xlen; + + for (xlen = 0; xlen < len && name[len - 1 - xlen] == 'X'; ++xlen) + ; + if (xlen < 6) return (errno = EINVAL, -1); + + int r; + do { + random_name(name + len - xlen, xlen); + r = fn(bfd, name, mode, data); + } while (r < 0 && errno == EEXIST); + return r; +} diff --git a/src/liblimb/posixplz.h/unlinkat_void.c b/src/liblimb/posixplz.h/unlinkat_void.c new file mode 100644 index 0000000..95221e0 --- /dev/null +++ b/src/liblimb/posixplz.h/unlinkat_void.c @@ -0,0 +1,14 @@ +/* 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 <unistd.h> +#include <limb/posixplz.h> + +void +unlinkat_void(int bfd, const char *file, int flags) +{ + int e = errno; + unlinkat(bfd, file, flags); + errno = e; +} diff --git a/src/liblimb/shldata-rw.h/shldata_write.c b/src/liblimb/shldata-rw.h/shldata_write.c index b53f4ba..c146853 100644 --- a/src/liblimb/shldata-rw.h/shldata_write.c +++ b/src/liblimb/shldata-rw.h/shldata_write.c @@ -4,10 +4,10 @@ #include <errno.h> #include <unistd.h> #include <stdio.h> -#include <skalibs/random.h> #include <limb/buffer.h> #include <limb/buffer-shldata.h> #include <limb/djbunix.h> +#include <limb/posixplz.h> #include <limb/unix-transactional.h> #include <limb/shldata-rw.h> #include <limb/siovec.h> @@ -20,13 +20,9 @@ shldata_write(int bfd, const char *file, u32 magic, u64 ver, int ret = 0; char buf[4096]; buffer b = BUFFER_INIT(&buffer_write, -1, buf, sizeof(buf)); - char tmp[8]; + char tmp[] = ".tmp.shldata.XXXXXX"; - *tmp = '.'; - do { - random_name(tmp + 1, sizeof(tmp) - 1); - b.fd = open_exclat(bfd, tmp); - } while (b.fd < 0 && errno == EEXIST); + b.fd = mkfiletempat(bfd, tmp, (createat_fn) (void (*)(void)) open_exclat, 0, NULL); if (b.fd < 0) return 0; if (buffer_puthdr(&b, magic, ver) < 0) @@ -49,6 +45,6 @@ shldata_write(int bfd, const char *file, u32 magic, u64 ver, ret = 1; err: fd_close(b.fd); - if (*tmp) unlinkat(bfd, tmp, 0); + if (*tmp) unlinkat_void(bfd, tmp, 0); return ret; }