Welcome to little lamb

Code » limb » commit a7fa257

Refactor fdpatrim into buffer_* functions

author Olivier Brunel
2023-05-03 12:15:40 UTC
committer Olivier Brunel
2023-05-20 18:06:39 UTC
parent 426857f53ae2f6e6092a0fb9a525bc742514e9aa

Refactor fdpatrim into buffer_* functions

The whole fd-thing was a poor idea, since we have a much nicer interface
to deal with files: buffers.

So let's have some generic buffer_* functions to read/write our (generic)
headers (big-endian u32 magic & a pack-trimmed version), and some patrim
related functions.

src/doc/buffer.h.0.md +15 -0
src/doc/buffer.h/buffer_patrim_put.3.md +57 -0
src/doc/buffer.h/buffer_puthdr.3.md +48 -0
src/doc/patrim.5.md +7 -0
src/liblimb/buffer.h/buffer_gethdr.c +33 -0
src/liblimb/buffer.h/buffer_patrim_get.c +23 -0
src/liblimb/buffer.h/buffer_patrim_put.c +21 -0
src/liblimb/buffer.h/buffer_patrim_putv.c +23 -0
src/liblimb/{fdpatrim.h/fdpatrim_initw.c => buffer.h/buffer_puthdr.c} +5 -11
src/liblimb/fdpatrim.h/fdpatrim_add.c +0 -22
src/liblimb/fdpatrim.h/fdpatrim_addv.c +0 -25
src/liblimb/fdpatrim.h/fdpatrim_get.c +0 -25
src/liblimb/fdpatrim.h/fdpatrim_initr.c +0 -30
src/liblimb/include/limb/buffer.h +8 -0
src/liblimb/include/limb/fdpatrim.h +0 -17

diff --git a/src/doc/buffer.h.0.md b/src/doc/buffer.h.0.md
index 4cc0ee2..b185655 100644
--- a/src/doc/buffer.h.0.md
+++ b/src/doc/buffer.h.0.md
@@ -41,9 +41,21 @@ The following macros are defined :
 
 The following functions/macros are defined :
 
+: [buffer_gethdr](3)
+:: To read a file header of 32big big-endian magic & pack-trimmed version.
+
 : [buffer_getuptoc](3)
 :: To read data from buffer up to a given character.
 
+: [buffer_patrim_get](3)
+:: To read [patrim](5)-encoded data.
+
+: [buffer_patrim_put](3)
+:: To write given data in [patrim](5)-encoded format.
+
+: [buffer_patrim_putv](3)
+:: Similar to [buffer_patrim_put](3) put using *struct iovec* for actual data.
+
 : [buffer_putbase32](3)
 :: To write given data encoded in base32.
 
@@ -60,6 +72,9 @@ The following functions/macros are defined :
 : [buffer_putescs](3)
 :: Similar but for a NUL-terminated string.
 
+: [buffer_puthdr](3)
+:: To write a file header of 32bit big-endian magic & pack-trimmed version.
+
 : [buffer_puthex](3)
 :: To write given data as hexadecimal dump.
 
diff --git a/src/doc/buffer.h/buffer_patrim_put.3.md b/src/doc/buffer.h/buffer_patrim_put.3.md
new file mode 100644
index 0000000..5ca567b
--- /dev/null
+++ b/src/doc/buffer.h/buffer_patrim_put.3.md
@@ -0,0 +1,57 @@
+% limb manual
+% buffer_patrim_put(3)
+
+# NAME
+
+buffer\_patrim\_put, buffer\_patrim\_putv, buffer\_patrim\_get - write/read data
+in PATRIM format
+
+# SYNOPSIS
+
+    #include <limb/buffer.h>
+
+```pre hl
+ssize_t buffer_patrim_put(buffer *<em>buf</em>, u64 <em>id</em>, u64 <em>u</em>, const char *<em>data</em>)
+ssize_t buffer_patrim_putv(buffer *<em>buf</em>, u64 <em>id</em>, const struct iovec <em>v</em>[], unsigned int <em>n</em>)
+int buffer_patrim_get(buffer *<em>buf</em>, u64 *<em>id</em>, u64 *<em>u</em>)
+```
+
+# DESCRIPTION
+
+The `buffer_patrim_put`() function writes into the buffer `buf` the data for the
+given `id` and its associated value or length, `u`, encoded in [patrim](5)
+format.
+
+So `u` must be either the value for an integer, or the length of the byte array
+pointed by `data` for a blob.
+
+The `buffer_patrim_putv`() function is similar, but only works for `id`
+representing a blob, whose data must be pointed by the array `v` of length `n`.
+
+The `buffer_patrim_get`() function reads [patrim](5)-encoded data from the
+buffer `buf`, placing the ID in the value pointed by `id` and its associated
+value or length, depending whether the ID represents an integer or a blob, in
+the value pointed by `u`.
+
+In case of a blob, the actual content is not read, it is up to the caller to
+get as many bytes from `buf` as the value placed into `u`.
+
+# RETURN VALUE
+
+The `buffer_patrim_put`() and `buffer_patrim_putv`() functions return the number
+of bytes written on success. Otherwise they return -1 and set `errno` to
+indicate the error.
+
+The `buffer_patrim_get`() function returns 1 on success, 0 on failure.
+
+# ERRORS
+
+The `buffer_patrim_put`() and `buffer_patrim_putv`() functions may fail and set
+`errno` for any of the errors specified for [buffer_putv](3).
+
+The `buffer_patrim_get`() function may fail if :
+
+: *EPIPE*
+:: Not enough data could be read from the buffer before reaching end-of-file.
+
+It may also fail for any of the error specified for [buffer_fill](3).
diff --git a/src/doc/buffer.h/buffer_puthdr.3.md b/src/doc/buffer.h/buffer_puthdr.3.md
new file mode 100644
index 0000000..6cd8f31
--- /dev/null
+++ b/src/doc/buffer.h/buffer_puthdr.3.md
@@ -0,0 +1,48 @@
+% limb manual
+% buffer_puthdr(3)
+
+# NAME
+
+buffer\_puthdr, buffer\_gethdr - write/read file header
+
+# SYNOPSIS
+
+    #include <limb/buffer.h>
+
+```pre hl
+ssize_t buffer_puthdr(buffer *<em>buf</em>, u32 <em>magic</em>, u64 <em>ver</em>)
+int buffer_gethdr(buffer *<em>buf</em>, u32 *<em>magic</em>, u64 *<em>ver</em>)
+```
+
+# DESCRIPTION
+
+The `buffer_puthdr`() function writes into the buffer `buf` the magic `magic` as
+a 32bit unsigned integer in big-endian followed by the unsigned integer `ver` in
+pack-trimmed form, as described in [u64_pack_trim](3).
+
+Such a combinaison is intended to be used as a file header, used notably for
+files containing [patrim](5)-encoded data.
+
+The `buffer_get_hdr`() function reads such an header and places the 32bit magic
+number as the value pointed by `magic`, and the version number as the value
+pointer by `ver`.
+
+# RETURN VALUE
+
+The `buffer_puthdr`() function returns the number of bytes written into the
+buffer on success. Otherwise, it returns -1.
+
+The `buffer_gethdr`() function returns 1 on success, and 0 on failure.
+
+# ERRORS
+
+The `buffer_puthdr`() function may fail and set `errno` for any of the errors
+specified for [buffer_putv](3).
+
+The `buffer_gethdr`() function may fail if :
+
+: *EPIPE*
+:: Not enough data could be read from the buffer before reaching end-of-file.
+
+It may also fail for any of the error specified for [buffer_get](3) or
+[buffer_fill](3).
diff --git a/src/doc/patrim.5.md b/src/doc/patrim.5.md
index 8eac902..066c33c 100644
--- a/src/doc/patrim.5.md
+++ b/src/doc/patrim.5.md
@@ -28,6 +28,10 @@ The IDs are unsigned numbers to identify their associated value, with the least
 significant bit having a special meaning : if set, it represents a blob,
 otherwise an (unsigned) integer.
 
+! HINT:
+! Helpers functions are available, either directly (e.g. [patrim_put](3)) or
+! when using a buffer (e.g. [buffer_patrim_put](3)).
+
 That is all.
 
 # FILE FORMATS
@@ -39,3 +43,6 @@ header as such :
   The magic number should have certain bits set to indicate it is PATRIM
   encoded, specifically : `(magic & 0xf0f0f000) = 0xa0e0f000`
 - A version number, pack-trimmed.
+
+Helpers functions [buffer_puthdr](3) and [buffer_gethdr](3) are available to
+write and read such headers, respectively.
diff --git a/src/liblimb/buffer.h/buffer_gethdr.c b/src/liblimb/buffer.h/buffer_gethdr.c
new file mode 100644
index 0000000..a942b66
--- /dev/null
+++ b/src/liblimb/buffer.h/buffer_gethdr.c
@@ -0,0 +1,33 @@
+/* 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 <limb/buffer.h>
+#include <limb/siovec.h>
+#include <limb/u32.h>
+#include <limb/u64.h>
+
+int
+buffer_gethdr(buffer *b, u32 *magic, u64 *ver)
+{
+    int r;
+
+    /* magic number */
+    r = buffer_get(b, (char *) magic, sizeof(*magic));
+    if (r <= 0) return (!r) ? (errno = EPIPE, 0) : 0;
+    u32p_be(magic);
+
+    struct iovec v[2];
+    char buf[9];
+
+    /* peek into the buffer to unpack the version number */
+    do {
+        buffer_rpeek(b, v);
+        r = u64_unpack_trim(ver, buf, siov_gather(buf, sizeof(buf), v, 2));
+    } while (r < 0 && (r = buffer_fill(b)) > 0);
+    if (r <= 0) return (!r) ? (errno = EPIPE, 0) : 0;
+    /* we've only peeked into the buffer, actually consume read data */
+    buffer_rseek(b, r);
+
+    return 1;
+}
diff --git a/src/liblimb/buffer.h/buffer_patrim_get.c b/src/liblimb/buffer.h/buffer_patrim_get.c
new file mode 100644
index 0000000..b977f93
--- /dev/null
+++ b/src/liblimb/buffer.h/buffer_patrim_get.c
@@ -0,0 +1,23 @@
+/* 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 <limb/buffer.h>
+#include <limb/patrim.h>
+
+int
+buffer_patrim_get(buffer *b, u64 *id, u64 *u)
+{
+    struct iovec v[2];
+    char buf[18];
+    int r;
+
+    do {
+        buffer_rpeek(b, v);
+        r = patrim_get(id, u, buf, siov_gather(buf, sizeof(buf), v, 2), 0);
+    } while (r < 0 && (r = buffer_fill(b)) > 0);
+    if (r <= 0) return (!r) ? (errno = EPIPE, 0) : 0;
+
+    buffer_rseek(b, r);
+    return 1;
+}
diff --git a/src/liblimb/buffer.h/buffer_patrim_put.c b/src/liblimb/buffer.h/buffer_patrim_put.c
new file mode 100644
index 0000000..0d4d2b7
--- /dev/null
+++ b/src/liblimb/buffer.h/buffer_patrim_put.c
@@ -0,0 +1,21 @@
+/* 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/buffer.h>
+#include <limb/patrim.h>
+#include <limb/siovec.h>
+
+ssize_t
+buffer_patrim_put(buffer *b, u64 id, u64 u, const char *data)
+{
+    struct iovec v[2];
+    char buf[18];
+
+    v[0].iov_base = buf;
+    v[0].iov_len = patrim_put(buf, sizeof(buf), 0, id, u);
+
+    v[1].iov_base = (char *) data;
+    v[1].iov_len = (patrim_isblob(id)) ? u : 0;
+
+    return buffer_putv(b, v, 2);
+}
diff --git a/src/liblimb/buffer.h/buffer_patrim_putv.c b/src/liblimb/buffer.h/buffer_patrim_putv.c
new file mode 100644
index 0000000..7dae17d
--- /dev/null
+++ b/src/liblimb/buffer.h/buffer_patrim_putv.c
@@ -0,0 +1,23 @@
+/* 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 <limb/buffer.h>
+#include <limb/patrim.h>
+#include <limb/siovec.h>
+
+ssize_t
+buffer_patrim_putv(buffer *b, u64 id, const struct iovec v[], unsigned int n)
+{
+    if (!patrim_isblob(id)) return (errno = EINVAL, -1);
+
+    char buf[18];
+    struct iovec vv[1 + n];
+
+    vv[0].iov_base = buf;
+    vv[0].iov_len = patrim_put(buf, sizeof(buf), 0, id, siov_len(v, n));
+    memcpy(vv + 1, v, sizeof(*v) * n);
+
+    return buffer_putv(b, vv, 1 + n);
+}
diff --git a/src/liblimb/fdpatrim.h/fdpatrim_initw.c b/src/liblimb/buffer.h/buffer_puthdr.c
similarity index 56%
rename from src/liblimb/fdpatrim.h/fdpatrim_initw.c
rename to src/liblimb/buffer.h/buffer_puthdr.c
index 9155498..f69aa9b 100644
--- a/src/liblimb/fdpatrim.h/fdpatrim_initw.c
+++ b/src/liblimb/buffer.h/buffer_puthdr.c
@@ -1,28 +1,22 @@
 /* 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/fdpatrim.h>
-#include <limb/siovec.h>
+#include <limb/buffer.h>
 #include <limb/u32.h>
 #include <limb/u64.h>
 
-int
-fdpatrim_initw(int fd, u32 magic, u64 ver)
+ssize_t
+buffer_puthdr(buffer *b, u32 magic, u64 ver)
 {
     char buf[9];
     struct iovec v[2];
 
-    if (magic & 0xf0f0f000 != 0xa0e0f000)
-        return (errno = EINVAL, -1);
-
     u32p_be(&magic);
     v[0].iov_base = &magic;
-    v[0].iov_len = sizeof(u32);
+    v[0].iov_len = sizeof(magic);
 
     v[1].iov_base = buf;
     v[1].iov_len = u64_pack_trim(buf, sizeof(buf), ver);
 
-    return fd_writev(fd, v, 2) == (ssize_t) siov_len(v, 2);
+    return buffer_putv(b, v, 2);
 }
diff --git a/src/liblimb/fdpatrim.h/fdpatrim_add.c b/src/liblimb/fdpatrim.h/fdpatrim_add.c
deleted file mode 100644
index 6bde27f..0000000
--- a/src/liblimb/fdpatrim.h/fdpatrim_add.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* 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 <skalibs/allreadwrite.h>
-#include <limb/fdpatrim.h>
-#include <limb/patrim.h>
-
-int
-fdpatrim_add(int fd, u64 id, u64 u, const char *data)
-{
-    char buf[18];
-    int n;
-
-    n = patrim_put(buf, sizeof(buf), 0, id, u);
-    if (fd_write(fd, buf, n) != n)
-        return 0;
-
-    if (patrim_isblob(id) && fd_write(fd, data, (size_t) u) != (ssize_t) u)
-        return 0;
-
-    return 1;
-}
diff --git a/src/liblimb/fdpatrim.h/fdpatrim_addv.c b/src/liblimb/fdpatrim.h/fdpatrim_addv.c
deleted file mode 100644
index fab71f1..0000000
--- a/src/liblimb/fdpatrim.h/fdpatrim_addv.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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/fdpatrim.h>
-#include <limb/patrim.h>
-#include <limb/siovec.h>
-
-int
-fdpatrim_addv(int fd, u64 id, const struct iovec v[], unsigned int n)
-{
-    char buf[18];
-    u64 l;
-    int r;
-
-    if (!patrim_isblob(id)) return (errno = EINVAL, 0);
-
-    l = siov_len(v, n);
-    r = patrim_put(buf, sizeof(buf), 0, id, l);
-    if (fd_write(fd, buf, r) != r || fd_writev(fd, v, n) != (ssize_t) l)
-        return 0;
-
-    return 1;
-}
diff --git a/src/liblimb/fdpatrim.h/fdpatrim_get.c b/src/liblimb/fdpatrim.h/fdpatrim_get.c
deleted file mode 100644
index 7622dc4..0000000
--- a/src/liblimb/fdpatrim.h/fdpatrim_get.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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 <skalibs/allreadwrite.h>
-#include <limb/fdpatrim.h>
-#include <limb/u64.h>
-
-int
-fdpatrim_get(int fd, u64 *id, u64 *u)
-{
-    char buf[9];
-    int r = 0;
-
-    for (;;) {
-        if (fd_read(fd, buf + r++, 1) != 1)
-            return 0;
-        if (u64_unpack_trim(id, buf, r) == r) {
-            if (id == u) break;
-            id = u;
-            r = 0;
-        }
-    }
-
-    return 1;
-}
diff --git a/src/liblimb/fdpatrim.h/fdpatrim_initr.c b/src/liblimb/fdpatrim.h/fdpatrim_initr.c
deleted file mode 100644
index aaac438..0000000
--- a/src/liblimb/fdpatrim.h/fdpatrim_initr.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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/fdpatrim.h>
-#include <limb/u32.h>
-#include <limb/u64.h>
-
-int
-fdpatrim_initr(int fd, u32 *magic, u64 *ver)
-{
-    if (fd_read(fd, (char *) magic, sizeof(u32)) != sizeof(u32))
-        return 0;
-    u32p_be(magic);
-
-    if (*magic & 0xf0f0f000 != 0xa0e0f000)
-        return (errno = EINVAL, 0);
-
-    char buf[9];
-    int r = 0;
-    for (;;) {
-        if (fd_read(fd, buf + r++, 1) != 1)
-            return 0;
-        if (u64_unpack_trim(ver, buf, r) == r)
-            break;
-    }
-
-    return 1;
-}
diff --git a/src/liblimb/include/limb/buffer.h b/src/liblimb/include/limb/buffer.h
index 957d0f0..a6a3be6 100644
--- a/src/liblimb/include/limb/buffer.h
+++ b/src/liblimb/include/limb/buffer.h
@@ -6,6 +6,8 @@
 
 #include <skalibs/buffer.h>
 #include <limb/hex.h> /* HEX_* */
+#include <limb/int.h>
+#include <limb/siovec.h>
 
 /* special values usable as strings for buffer_putmsg() */
 #define PUTMSG_FLUSH        ((void *) 1)    /* flush buffer */
@@ -49,9 +51,15 @@ extern ssize_t buffer_putbase(buffer *b, const char *data, size_t dlen, base_fmt
 #define buffer_putbase32(b,d,l,p)   buffer_putbase(b, d, l, base32, 40, 64, p)
 #define buffer_putbase64(b,d,l,p)   buffer_putbase(b, d, l, base64, 42, 56, p)
 
+extern ssize_t buffer_puthdr(buffer *b, u32 magic, u64 ver);
+extern ssize_t buffer_patrim_put(buffer *b, u64 id, u64 u, const char *data);
+extern ssize_t buffer_patrim_putv(buffer *b, u64 id, const struct iovec v[], unsigned int n);
 
 /* Reading */
 
 extern int buffer_getuptoc(buffer *b, char *dst, size_t len, char c, size_t *got);
 
+extern int buffer_gethdr(buffer *b, u32 *magic, u64 *ver);
+extern int buffer_patrim_get(buffer *b, u64 *id, u64 *u);
+
 #endif /* LIMB_BUFFER_H */
diff --git a/src/liblimb/include/limb/fdpatrim.h b/src/liblimb/include/limb/fdpatrim.h
deleted file mode 100644
index 89fba54..0000000
--- a/src/liblimb/include/limb/fdpatrim.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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_FDPATRIM_H
-#define LIMB_FDPATRIM_H
-
-#include <limb/int.h>
-#include <limb/siovec.h>
-
-extern int fdpatrim_initw(int fd, u32 magic, u64 ver);
-extern int fdpatrim_add(int fd, u64 id, u64 u, const char *data);
-extern int fdpatrim_addv(int fd, u64 id, const struct iovec v[], unsigned int n);
-
-extern int fdpatrim_initr(int fd, u32 *magic, u64 *ver);
-extern int fdpatrim_get(int fd, u64 *id, u64 *u);
-
-#endif /* LIMB_FDPATRIM_H */