Welcome to little lamb

Code » limb » commit 20b9643

Add posixplz.h & related functions

author Olivier Brunel
2023-05-04 14:03:36 UTC
committer Olivier Brunel
2023-05-20 18:06:40 UTC
parent 7e759f64d3911b6d2fb294c0914637a40925d5a8

Add posixplz.h & related functions

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;
 }