Welcome to little lamb

Code » limb » commit d8b445a

Add open_read_closeat(), open_write_closeat() & ..

author Olivier Brunel
2023-05-13 07:52:10 UTC
committer Olivier Brunel
2023-07-05 07:37:02 UTC
parent 54ef7d834621f78f5bf10351ff6c313b559ba02f

Add open_read_closeat(), open_write_closeat() & ..

..open_slurp_closeat() & open_writev_closeat(), as well as macro
open_tmpat()

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