author | Olivier Brunel
<jjk@jjacky.com> 2023-07-04 17:54:59 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-07-24 10:16:42 UTC |
parent | b97040555b4bfd5d4d3b6f2120609c58ae751cfb |
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 */