Welcome to little lamb

Code » limb » commit 784e0e1

Add allreadwrite.h & related functions

author Olivier Brunel
2023-07-04 17:54:59 UTC
committer Olivier Brunel
2023-07-24 10:16:42 UTC
parent b97040555b4bfd5d4d3b6f2120609c58ae751cfb

Add allreadwrite.h & related functions

src/doc/allreadwrite.h.0.md +65 -0
src/doc/allreadwrite.h/allread.3.md +33 -0
src/doc/allreadwrite.h/allreadv.3.md +1 -0
src/doc/allreadwrite.h/allreadwrite.3.md +45 -0
src/doc/allreadwrite.h/allreadwritev.3.md +1 -0
src/doc/allreadwrite.h/allwrite.3.md +28 -0
src/doc/allreadwrite.h/allwritev.3.md +1 -0
src/doc/allreadwrite.h/fd_read.3.md +34 -0
src/doc/allreadwrite.h/fd_readv.3.md +1 -0
src/doc/allreadwrite.h/fd_write.3.md +34 -0
src/doc/allreadwrite.h/fd_writev.3.md +1 -0
src/doc/allreadwrite.h/sanitize_read.3.md +46 -0
src/doc/allreadwrite.h/unsanitize_read.3.md +1 -0
src/liblimb/djbunix.h/open_read_closeat.c +1 -1
src/liblimb/djbunix.h/open_write_closeat.c +1 -1
src/liblimb/djbunix.h/open_writev_closeat.c +1 -1
src/liblimb/include/limb/allreadwrite.h +9 -0

diff --git a/src/doc/allreadwrite.h.0.md b/src/doc/allreadwrite.h.0.md
new file mode 100644
index 0000000..9ddec25
--- /dev/null
+++ b/src/doc/allreadwrite.h.0.md
@@ -0,0 +1,65 @@
+% limb manual
+% allreadwrite.h(0)
+
+# NAME
+
+allreadwrite.h - safe I/O interface
+
+
+# SYNOPSIS
+
+    #include <limb/allreadwrite.h>
+
+
+# DESCRIPTION
+
+The header defines the needed functions to perform safe I/O operations.
+
+<inc skalibs.md>
+
+! INFO: Low-level API
+! Note that you probably don't want/need to use the functions below, and should
+! probably use a higher-level interface such as [buffer.h](0).
+
+## Functions
+
+The following functions/macros are defined :
+
+: [allread](3)
+:: Read from given file descriptor until requested length as been reached.
+
+: [allreadv](3)
+:: Similar to [allread](3) but using vectors.
+
+: [allwrite](3)
+:: Write to given file descriptor until requested length as been reached.
+
+: [allwritev](3)
+:: Similar to [allwrite](3) but using vectors.
+
+
+: [allreadwrite](3)
+:: Perform specified I/O operation until requested length as been reached.
+
+: [allreadwritev](3)
+:: Similar to [allreadwrite](3) but using vectors.
+
+
+: [fd_read](3)
+:: Safe wrapper around [read](3), i.e. can't be interrupted by signals.
+
+: [fd_readv](3)
+:: Safe wrapper around [readv](3), i.e. can't be interrupted by signals.
+
+: [fd_write](3)
+:: Safe wrapper around [write](3), i.e. can't be interrupted by signals.
+
+: [fd_writev](3)
+:: Safe wrapper around [writev](3), i.e. can't be interrupted by signals.
+
+
+: [sanitize_read](3)
+:: Sanitize return code from functions such as [read](3).
+
+: [unsanitize_read](3)
+:: Reverse the operation performed by [sanitize_read](3).
diff --git a/src/doc/allreadwrite.h/allread.3.md b/src/doc/allreadwrite.h/allread.3.md
new file mode 100644
index 0000000..4cf2c3a
--- /dev/null
+++ b/src/doc/allreadwrite.h/allread.3.md
@@ -0,0 +1,33 @@
+% limb manual
+% allread(3)
+
+# NAME
+
+allread, allreadv - read requested amount of data from a file
+
+# SYNOPSIS
+
+    #include <limb/djbunix.h>
+
+```pre hl
+size_t allread(int <em>fd</em>, char *<em>dst</em>, size_t <em>dlen</em>)
+size_t allreadv(int <em>fd</em>, const struct iovec *<em>v</em>, unsigned <em>n</em>)
+```
+
+# DESCRIPTION
+
+The `allread`() function will attempt to read `dlen` bytes from the file
+associated with file descriptor `fd` and copy them into the memory pointed by
+`dst`.
+
+The `allreadv`() function is similar only placing the data into the memory
+described by the array `v` of `n` vectors.
+
+# RETURN VALUE
+
+These functions return the number of bytes read, which may be less than `dlen`
+(even 0) in case of error, or if end-of-file was reached prior.
+
+! HINT:
+! To know whether an error occurred or not, you might want to set `errno` to 0
+! prior to the call, and check it afterwards.
diff --git a/src/doc/allreadwrite.h/allreadv.3.md b/src/doc/allreadwrite.h/allreadv.3.md
new file mode 120000
index 0000000..3fb646b
--- /dev/null
+++ b/src/doc/allreadwrite.h/allreadv.3.md
@@ -0,0 +1 @@
+allread.3.md
\ No newline at end of file
diff --git a/src/doc/allreadwrite.h/allreadwrite.3.md b/src/doc/allreadwrite.h/allreadwrite.3.md
new file mode 100644
index 0000000..ff1f47f
--- /dev/null
+++ b/src/doc/allreadwrite.h/allreadwrite.3.md
@@ -0,0 +1,45 @@
+% limb manual
+% allreadwrite(3)
+
+# NAME
+
+allreadwrite, allreadwritev - perform specified I/O operation until fully
+completed
+
+# SYNOPSIS
+
+    #include <limb/djbunix.h>
+
+```pre hl
+ssize_t (*io_func) (int <em>fd</em>, char *<em>data</em>, size_t <em>dlen</em>)
+ssize_t (*iov_func) (int <em>fd</em>, const struct iovec *<em>v</em>, unsigned <em>n</em>)
+
+size_t allreadwrite(io_func <em>op</em>, int <em>fd</em>, char *<em>data</em>, size_t <em>dlen</em>)
+size_t allreadwritev(iov_func <em>op</em>, int <em>fd</em>, const struct iovec *<em>v</em>, unsigned <em>n</em>)
+```
+
+# DESCRIPTION
+
+The `allreadwrite`() function will call `op` with `fd`, `data` and `dlen` as
+arguments, expecting it to perform the requested I/O operation, returning the
+amount of bytes read/written on success, or -1 on error (setting `errno` to
+indicate the error).
+
+If less than `dlen` bytes have been processed, it will call `op` again (updating
+its arguments `data` and `dlen` appropriately), until either `dlen` bytes have
+been processed in total, end-of-file has been reached, or an error occurred.
+
+The `allreadwritev`() function is similar, except that the arguments given to
+`op` are `fd` and the pointer to an internal array of *struct iovec* and its
+number of elements, originally similar to `v` and `n` but later adjusted as
+needed. The original array `v` remains unchanged.
+
+# RETURN VALUE
+
+These functions return the number of bytes processed, which may be less than
+`dlen` (even 0).
+
+! HINT:
+! To know whether an error occurred or not, you might want to set `errno` to 0
+! prior to the call, and checking afterwards if it was set or not by the `op`
+! function.
diff --git a/src/doc/allreadwrite.h/allreadwritev.3.md b/src/doc/allreadwrite.h/allreadwritev.3.md
new file mode 120000
index 0000000..13794a9
--- /dev/null
+++ b/src/doc/allreadwrite.h/allreadwritev.3.md
@@ -0,0 +1 @@
+allreadwrite.3.md
\ No newline at end of file
diff --git a/src/doc/allreadwrite.h/allwrite.3.md b/src/doc/allreadwrite.h/allwrite.3.md
new file mode 100644
index 0000000..d93de57
--- /dev/null
+++ b/src/doc/allreadwrite.h/allwrite.3.md
@@ -0,0 +1,28 @@
+% limb manual
+% allwrite(3)
+
+# NAME
+
+allwrite, allwritev - write requested amount of data to a file
+
+# SYNOPSIS
+
+    #include <limb/djbunix.h>
+
+```pre hl
+size_t allwrite(int <em>fd</em>, const char *<em>data</em>, size_t <em>dlen</em>)
+size_t allwritev(int <em>fd</em>, const struct iovec *<em>v</em>, unsigned <em>n</em>)
+```
+
+# DESCRIPTION
+
+The `allwrite`() function will attempt to write `dlen` bytes from the memory
+pointed by `data` to the file associated with file descriptor `fd`.
+
+The `allwritev`() function is similar only writing data as described by the
+array `v` of `n` vectors.
+
+# RETURN VALUE
+
+These functions return the number of bytes written, which may be less than `dlen`
+(even 0) in case of error.
diff --git a/src/doc/allreadwrite.h/allwritev.3.md b/src/doc/allreadwrite.h/allwritev.3.md
new file mode 120000
index 0000000..861ac47
--- /dev/null
+++ b/src/doc/allreadwrite.h/allwritev.3.md
@@ -0,0 +1 @@
+allwrite.3.md
\ No newline at end of file
diff --git a/src/doc/allreadwrite.h/fd_read.3.md b/src/doc/allreadwrite.h/fd_read.3.md
new file mode 100644
index 0000000..f5a08b7
--- /dev/null
+++ b/src/doc/allreadwrite.h/fd_read.3.md
@@ -0,0 +1,34 @@
+% limb manual
+% fd_read(3)
+
+# NAME
+
+fd_read, fd_readv - safe wrappers for reading files
+
+# SYNOPSIS
+
+    #include <limb/djbunix.h>
+
+```pre hl
+ssize_t fd_read(int <em>fd</em>, char *<em>dst</em>, size_t <em>dlen</em>)
+ssize_t fd_readv(int <em>fd</em>, const struct iovec *<em>v</em>, unsigned <em>n</em>)
+```
+
+# DESCRIPTION
+
+The `fd_read`() function is a safe wrapper around [read](3), i.e. it cannot be
+interrupted by signals. More precisely, if [read](3) fails with *EINTR* it is
+automatically called again until it succeeds or fails with another error.
+
+The `fd_readv`() function is similar, but around [readv](3).
+
+# RETURN VALUE
+
+These functions return the number of bytes read from `fd` and copied into memory
+on success. Otherwise they return -1 and set `errno` to indicate the error.
+
+# ERRORS
+
+The `fd_read`() and `fd_readv`() functions may fail and set `errno` for any of
+the errors described for [read](3) and [readv](3), respectively, except for
+*EINTR*.
diff --git a/src/doc/allreadwrite.h/fd_readv.3.md b/src/doc/allreadwrite.h/fd_readv.3.md
new file mode 120000
index 0000000..8806a49
--- /dev/null
+++ b/src/doc/allreadwrite.h/fd_readv.3.md
@@ -0,0 +1 @@
+fd_read.3.md
\ No newline at end of file
diff --git a/src/doc/allreadwrite.h/fd_write.3.md b/src/doc/allreadwrite.h/fd_write.3.md
new file mode 100644
index 0000000..b14f437
--- /dev/null
+++ b/src/doc/allreadwrite.h/fd_write.3.md
@@ -0,0 +1,34 @@
+% limb manual
+% fd_write(3)
+
+# NAME
+
+fd_write, fd_writev - safe wrappers for writing files
+
+# SYNOPSIS
+
+    #include <limb/djbunix.h>
+
+```pre hl
+ssize_t fd_write(int <em>fd</em>, char *<em>dst</em>, size_t <em>dlen</em>)
+ssize_t fd_writev(int <em>fd</em>, const struct iovec *<em>v</em>, unsigned <em>n</em>)
+```
+
+# DESCRIPTION
+
+The `fd_write`() function is a safe wrapper around [write](3), i.e. it cannot be
+interrupted by signals. More precisely, if [write](3) fails with *EINTR* it is
+automatically called again until it succeeds or fails with another error.
+
+The `fd_writev`() function is similar, but around [writev](3).
+
+# RETURN VALUE
+
+These functions return the number of bytes written to `fd` on success. Otherwise
+they return -1 and set `errno` to indicate the error.
+
+# ERRORS
+
+The `fd_write`() and `fd_writev`() functions may fail and set `errno` for any of
+the errors described for [write](3) and [writev](3), respectively, except for
+*EINTR*.
diff --git a/src/doc/allreadwrite.h/fd_writev.3.md b/src/doc/allreadwrite.h/fd_writev.3.md
new file mode 120000
index 0000000..2454269
--- /dev/null
+++ b/src/doc/allreadwrite.h/fd_writev.3.md
@@ -0,0 +1 @@
+fd_write.3.md
\ No newline at end of file
diff --git a/src/doc/allreadwrite.h/sanitize_read.3.md b/src/doc/allreadwrite.h/sanitize_read.3.md
new file mode 100644
index 0000000..3e4e4fb
--- /dev/null
+++ b/src/doc/allreadwrite.h/sanitize_read.3.md
@@ -0,0 +1,46 @@
+% limb manual
+% sanitize_read(3)
+
+# NAME
+
+sanitize_read, unsanitize_read - (un)sanitize return code from standard I/O
+functions
+
+# SYNOPSIS
+
+    #include <limb/djbunix.h>
+
+```pre hl
+ssize_t sanitize_read(ssize_t <em>r</em>)
+ssize_t unsanitize_read(ssize_t <em>r</em>)
+```
+
+# DESCRIPTION
+
+Standard I/O functions (such as [read](3) or its safe wrapper [fd_read](3))
+return -1 on error and 0 when reaching end-of-file.
+
+A lack of data available when attempting to read in non-blocking mode is treated
+as an error (*EWOULDBLOCK*). However, it is sometimes preferable to handle EOF
+as the exception and *EWOULDBLOCK* as a normal condition, whilst waiting for
+data to become available.
+
+The `sanitize_read`() function aims to "correct" this by turning a value of -1
+with *EWOULDBLOCK* or *EAGAIN* into a 0 (as no data was read), whilst turning a
+value of 0 into -1 with *EPIPE* to indicate end-of-file.
+
+! NOTE:
+! Standard system reading functions never set `errno` to *EPIPE* making it
+! thusly a proper candidate for such a case.
+
+The `unsanitize_read`() function does the reverse of `sanitize_read`().
+
+# RETURN VALUE
+
+The `sanitize_read`() returns 0 and sets `errno` to 0 if `r` is -1 and `errno`
+is set to *EWOULDBLOCK* or *EAGAIN*; It returns -1 and sets `errno` to *EPIPE*
+if `r` if 0; Otherwise it returns `r` leaving `errno` unchanged.
+
+The `unsanitize_read`() returns 0 and sets `errno` to 0 if `r` is -1 and `errno`
+is set to *EPIPE*; It returns -1 and sets `errno` to *EWOULDBLOCK* if `r` is 0;
+Otherwise it returns `r` leaving `errno` unchanged.
diff --git a/src/doc/allreadwrite.h/unsanitize_read.3.md b/src/doc/allreadwrite.h/unsanitize_read.3.md
new file mode 120000
index 0000000..62d1b64
--- /dev/null
+++ b/src/doc/allreadwrite.h/unsanitize_read.3.md
@@ -0,0 +1 @@
+sanitize_read.3.md
\ No newline at end of file
diff --git a/src/liblimb/djbunix.h/open_read_closeat.c b/src/liblimb/djbunix.h/open_read_closeat.c
index 1839b51..4f4441e 100644
--- a/src/liblimb/djbunix.h/open_read_closeat.c
+++ b/src/liblimb/djbunix.h/open_read_closeat.c
@@ -2,7 +2,7 @@
  * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
 /* SPDX-License-Identifier: GPL-2.0-only */
 #include <errno.h>
-#include <skalibs/allreadwrite.h>
+#include <limb/allreadwrite.h>
 #include <limb/djbunix.h>
 
 ssize_t
diff --git a/src/liblimb/djbunix.h/open_write_closeat.c b/src/liblimb/djbunix.h/open_write_closeat.c
index 7aeddb2..33f0b97 100644
--- a/src/liblimb/djbunix.h/open_write_closeat.c
+++ b/src/liblimb/djbunix.h/open_write_closeat.c
@@ -2,7 +2,7 @@
  * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
 /* SPDX-License-Identifier: GPL-2.0-only */
 #include <stdio.h>
-#include <skalibs/allreadwrite.h>
+#include <limb/allreadwrite.h>
 #include <limb/djbunix.h>
 
 int
diff --git a/src/liblimb/djbunix.h/open_writev_closeat.c b/src/liblimb/djbunix.h/open_writev_closeat.c
index 5c65a43..452f193 100644
--- a/src/liblimb/djbunix.h/open_writev_closeat.c
+++ b/src/liblimb/djbunix.h/open_writev_closeat.c
@@ -2,7 +2,7 @@
  * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
 /* SPDX-License-Identifier: GPL-2.0-only */
 #include <stdio.h>
-#include <skalibs/allreadwrite.h>
+#include <limb/allreadwrite.h>
 #include <limb/djbunix.h>
 #include <limb/siovec.h>
 
diff --git a/src/liblimb/include/limb/allreadwrite.h b/src/liblimb/include/limb/allreadwrite.h
new file mode 100644
index 0000000..52378cf
--- /dev/null
+++ b/src/liblimb/include/limb/allreadwrite.h
@@ -0,0 +1,9 @@
+/* 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_ALLREADWRITE_H
+#define LIMB_ALLREADWRITE_H
+
+#include <skalibs/allreadwrite.h>
+
+#endif /* LIMB_ALLREADWRITE_H */