summaryrefslogtreecommitdiff
path: root/doc/libstddjb/djbunix.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/libstddjb/djbunix.html')
-rw-r--r--doc/libstddjb/djbunix.html760
1 files changed, 760 insertions, 0 deletions
diff --git a/doc/libstddjb/djbunix.html b/doc/libstddjb/djbunix.html
new file mode 100644
index 0000000..0d6c89f
--- /dev/null
+++ b/doc/libstddjb/djbunix.html
@@ -0,0 +1,760 @@
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>skalibs: the djbunix library interface</title>
+ <meta name="Description" content="skalibs: the djbunix library interface" />
+ <meta name="Keywords" content="skalibs c unix djbunix library libstddjb" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://www.skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">libstddjb</a><br />
+<a href="../libskarnet.html">libskarnet</a><br />
+<a href="../index.html">skalibs</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>djbunix</tt> library interface </h1>
+
+<p>
+ The following functions are declared in the <tt>skalibs/djbunix.h</tt> header,
+and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library.
+</p>
+
+<h2> General information </h2>
+
+<p>
+ <tt>djbunix</tt> is an alternative API to management of basic Unix
+concepts: file descriptors, files, environment, and so on. It is a
+rather chaotic mix of <a href="safewrappers.html">safe wrappers</a>
+around Unix system calls, better reimplementations of standard libc
+functionalities, and higher-level manipulations of Unix concepts.
+</p>
+
+<p>
+ Understanding <tt>djbunix</tt> is essential to understanding any piece
+of code depending on skalibs.
+</p>
+
+<h2> Functions </h2>
+
+<h3> Basic fd operations </h3>
+
+<p>
+<code> int coe (int fd) </code> <br />
+Sets the close-on-exec flag on <em>fd</em>.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int uncoe (int fd) </code> <br />
+Clears the close-on-exec flag on <em>fd</em>.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int ndelay_on (int fd) </code> <br />
+Sets the O_NONBLOCK flag on <em>fd</em>: sets it to non-blocking mode.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int ndelay_off (int fd) </code> <br />
+Clears the O_NONBLOCK flag on <em>fd</em>: sets it to blocking mode.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int pipenb (int *p) </code> <br />
+Like
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html">pipe()</a>,
+but both ends of the created pipe are in non-blocking mode.
+</p>
+
+<p>
+<code> int pipecoe (int *p) </code> <br />
+Like
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html">pipe()</a>,
+but both ends of the created pipe are close-on-exec.
+</p>
+
+<p>
+<code> int pipenbcoe (int *p) </code> <br />
+Like
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html">pipe()</a>,
+but both ends of the created pipe are in non-blocking mode <em>and</em> close-on-exec.
+</p>
+
+<p>
+<code> int fd_copy (int to, int from) </code> <br />
+Copies the open fd <em>from</em> to number <em>to</em>. <em>to</em>
+must not refer to an already open fd.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int fd_copy2 (int to1, int from1, int to2, int from2) </code> <br />
+Copies the open fd <em>from1</em> to number <em>to2</em>. Also copies
+<em>from2</em> to <em>to2</em> at the same time.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int fd_move (int to, int from) </code> <br />
+Moves the open fd <em>from</em> to number <em>to</em>. <em>to</em>
+must not refer to an already open fd, unless it's equal to <em>from</em>.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int fd_move2 (int to1, int from1, int to2, int from2) </code> <br />
+Moves the open fd <em>from</em> to number <em>to</em>. Also moves
+<em>from2</em> to <em>to2</em> at the same time. This is useful for instance
+when you want to swap two fds: <tt>fd_move2</tt> will handle the situation
+correctly.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int fd_close (int fd) </code> <br />
+Closes <em>fd</em>.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+This is a <a href="safewrappers.html">safe wrapper</a> around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/close.html">close()</a>,
+or rather as safe a wrapper as is possible to write: the <tt>close()</tt>
+specification does not allow a 100% safe behaviour. So, in rare cases
+it is possible for <tt>fd_close()</tt> to return 0 (instead of -1 EBADF)
+when it is provided an argument that is not an open fd. This should not
+be a problem, because giving wrong arguments to <tt>fd_close()</tt> is
+always a static programming error.
+</p>
+
+<p>
+<code> int fd_chmod (int fd, unsigned int mode) </code> <br />
+Safe wrapper around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/fchmod.html">fchmod()</a>.
+</p>
+
+<p>
+<code> int fd_chown (int fd, unsigned int uid, unsigned int gid) </code> <br />
+Safe wrapper around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/fchown.html">fchown()</a>.
+This function requires root privileges.
+</p>
+
+<p>
+<code> int fd_sync (int fd) </code> <br />
+Safe wrapper around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/fsync.html">fsync()</a>.
+</p>
+
+<p>
+<code> int fd_chdir (int fd) </code> <br />
+Safe wrapper around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/fchdir.html">fchdir()</a>.
+</p>
+
+<p>
+<code> int fd_cat (int from, int to) </code> <br />
+Synchronously copies data from fd <em>from</em> to fd <em>to</em>,
+until it encounters EOF or an error. Returns -1 (and sets errno) if
+it fails; returns the number of transmitted bytes if it gets an EOF.
+</p>
+
+<p>
+When the underlying OS allows it, zero-copy transmission is
+performed. Currently, the following zero-copy implementations are
+supported:
+</p>
+
+<ul>
+ <li> <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/splice.2.html">splice()</a>,
+in Linux 2.6.17 and later </li>
+</ul>
+
+<p>
+<code> unsigned int fd_catn (int from, int to, unsigned int n) </code> <br />
+Synchronously copies at most <em>n</em> bytes from fd <em>from</em> to fd <em>to</em>.
+Returns the total number of transmitted bytes; sets errno if this number
+is lesser than <em>n</em>. EOF is reported as EPIPE. See above for zero-copy
+transmission; zero-copy transmission is not attempted for less than 64k of data.
+</p>
+
+<p>
+<code> int fd_ensure_open (int fd, int w) </code> <br />
+If <em>fd</em> is not open, opens it to <tt>/dev/null</tt>,
+for reading if <em>w</em> is zero, and for writing otherwise.
+Returns 1 if it succeeds and 0 if it fails.
+</p>
+
+<p>
+<code> int fd_sanitize (void) </code> <br />
+Ensures stdin and stdout are open. If one of those
+file descriptors was closed, it now points to <tt>/dev/null</tt>.
+Returns 1 if it succeeds and 0 if it fails.
+</p>
+
+<p>
+<code> int lock_ex (int fd) </code> <br />
+Gets an exclusive advisory lock on <em>fd</em>. <em>fd</em> must point to
+a regular file, open for writing. Blocks until the lock can be obtained.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int lock_exnb (int fd) </code> <br />
+Gets an exclusive advisory lock on <em>fd</em>. <em>fd</em> must point to
+a regular file, open for writing.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails. If the lock
+is held and the function would block, it immediately returns with -1 EWOULDBLOCK.
+</p>
+
+<p>
+<code> int lock_sh (int fd) </code> <br />
+Gets a shared advisory lock on <em>fd</em>. <em>fd</em> must point to
+a regular file, open for reading. Blocks until the lock can be obtained.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int lock_shnb (int fd) </code> <br />
+Gets a shared advisory lock on <em>fd</em>. <em>fd</em> must point to
+a regular file, open for reading.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails. If the lock
+is held and the function would block, it immediately returns with -1 EWOULDBLOCK.
+</p>
+
+<p>
+<code> int lock_un (int fd) </code> <br />
+Releases a previously held lock on <em>fd</em>.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int open2 (char const *file, unsigned int flags) </code> <br />
+Safe wrapper around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/open.html">open()</a>
+when it takes 2 arguments.
+</p>
+
+<p>
+<code> int open3 (char const *file, unsigned int flags) </code> <br />
+Safe wrapper around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/open.html">open()</a>
+when it takes 3 arguments.
+</p>
+
+<p>
+<code> int open_read (char const *file) </code> <br />
+Opens <em>file</em> in read-only, non-blocking mode.
+Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int open_readb (char const *file) </code> <br />
+Opens <em>file</em> in read-only, blocking mode.
+Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
+<em>This call does not block.</em> The
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/open.html">open()</a>
+system call is actually performed with the O_NONBLOCK option, and blocking mode
+is set afterwards; this behaviour allows for more transparent interactions
+with FIFOs.
+</p>
+
+<p>
+<code> int open_excl (char const *file) </code> <br />
+Opens <em>file</em> in write-only, non-blocking mode, with the
+additional O_EXCL and O_CREAT flags.
+Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int open_append (char const *file) </code> <br />
+Opens <em>file</em> in write-only, non-blocking mode, with the
+additional O_APPEND and O_CREAT flags.
+Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int open_trunc (char const *file) </code> <br />
+Opens <em>file</em> in write-only, non-blocking mode, with the
+additional O_TRUNC and O_CREAT flags.
+Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int open_create (char const *file) </code> <br />
+Opens <em>file</em> in write-only, non-blocking mode, with the
+additional O_CREAT flag.
+Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int open_write (char const *file) </code> <br />
+Opens <em>file</em> in write-only, non-blocking mode.
+Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<h3> Seek operations </h3>
+
+<p>
+<code> long seek_cur (int fd) </code> <br />
+Returns the current file offset for descriptor <em>fd</em>.
+</p>
+
+<p>
+<code> int seek_set (int fd, long pos) </code> <br />
+Sets the current file offset for <em>fd</em> to <em>pos</em>.
+Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
+</p>
+
+<h3> Privilege management </h3>
+
+<p>
+<code> int prot_readgroups (char const *name, gid_t *tab, unsigned int max) </code> <br />
+Reads the group database (normally <tt>/etc/group</tt>, but it can be
+altered via NSS) to get the list of supplementary groups for user <em>name</em>.
+Stores that list into the array pointed to by <em>tab</em>, which must be
+preallocated. Stores at most <em>max</em> elements into <em>tab</em>.
+Returns -1 and sets errno if it fails; else, returns the number of elements actually
+stored into <em>tab</em>.
+</p>
+
+<p>
+<code> int prot_grps (char const *name) </code> <br />
+Sets the kernel-maintained list of supplementary groups for the current process
+to the list of supplementary groups for user <em>name</em> according to the
+group database. This is a privileged operation.
+Returns -1 and sets errno if it fails; returns 0 if it succeeds.
+</p>
+
+<p>
+<code> int prot_gid (int gid) </code> <br />
+Alias to <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html">setgid</a>.
+</p>
+
+<p>
+<code> int prot_uid (int uid) </code> <br />
+Alias to <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html">setuid</a>.
+</p>
+
+<h3> Executable search and execution, and environment </h3>
+
+<p>
+<code> void execvep (char const *file, char const *const *argv, char const *const *envp, char const *path) </code> <br />
+Executes into the executable file at <em>file</em>, with the command line
+set to <em>argv</em> and the environment set to <em>envp</em>.
+If <em>file</em> is not an absolute path, it is searched in the
+<em>path</em> string, which must contain a colon-separated list of
+search directories such as the contents of the PATH environment variable.
+The function returns if it fails, and sets errno to the most relevant
+error that happened.
+</p>
+
+<p>
+<code> void pathexec_run (char const *file, char const *const *argv, char const *const *envp) </code> <br />
+Performs <tt>execvep(file, argv, envp, path)</tt>, <em>path</em> being the
+contents of the PATH environment variable. If PATH is not set, <em>path</em>
+is set to the contents of the <tt>conf-compile/conf-defaultpath</tt> file in
+the skalibs distribution.
+The function returns if it fails, and sets errno appropriately.
+</p>
+
+<p>
+ <tt>pathexec_run()</tt> is the standard skalibs API to perform an
+<tt>exec</tt> call with a path search. It is recommended that you use
+it instead of the Single Unix
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/execvp.html">execvp()</a> or
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/execlp.html">execlp()</a>
+functions, because <tt>execvp</tt> and <tt>execlp</tt> default to execution of
+the <tt>/bin/sh</tt> interpreter with <em>file</em> as an argument if they
+cannot find a suitable executable <em>file</em>, and this is:
+</p>
+
+<ol>
+ <li> a security risk, </li>
+ <li> probably not what you want. </li>
+</ol>
+
+<p>
+ <tt>execvep()</tt> and <tt>pathexec_run()</tt> just fail with ENOENT
+when they cannot find a <em>file</em> to exec into, which is the
+sensible behaviour.
+</p>
+
+<p>
+<code> void pathexec0_run (char const *const *argv, char const *const *envp) </code> <br />
+Performs <tt>pathexec_run(argv[0], argv, envp)</tt>. If <em>argv</em> is empty, i.e.
+<em>argv</em>[0] is null, the process exits 0 instead. Rationale: executing
+the empty command line should amount to executing <tt>true</tt>, i.e.
+simply exiting 0.
+</p>
+
+<p>
+<code> void pathexec_r_name (char const *file, char const *const *argv, char const *const *envp, unsigned int envlen, char const *modifs, unsigned int modiflen) </code> <br />
+Alters <em>envp</em> (which does not have to be NULL-terminated, but the
+number <em>envlen</em> of elements must be provided) with the modifier
+string <em>modifs</em> of length <em>modiflen</em>, then performs
+<tt>pathexec_run(file, argv, altered-envp)</tt>.
+</p>
+
+<p>
+<code> void pathexec_r (char const *const *argv, char const *const *envp, unsigned int envlen, char const *modifs, unsigned int modiflen) </code> <br />
+Same as <tt>pathexec_r_name</tt>, except that the <em>file</em> argument is read from <em>argv</em>[0].
+</p>
+
+<p>
+<code> int pathexec_env (char const *var, char const *value) </code> <br />
+Adds the "add variable <em>var</em> with value <em>value</em>" instruction
+(if <em>value</em> is not null) or the "unset <em>var</em>" instruction
+(if <em>value</em> is null) to a static hidden modifier string, used by the
+following three functions.
+Returns 1 if it succeeds and 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> void pathexec_fromenv (char const *const *argv, char const *const *envp, unsigned int envlen) </code> <br />
+Performs <tt>pathexec_r()</tt> with the given arguments and the hidden modifier
+string.
+</p>
+
+<p>
+<code> void pathexec (char const *const *argv) </code> <br />
+Executes into the <em>argv</em> command line, with the current environment
+modified by the hidden modifier string.
+</p>
+
+<p>
+<code> void pathexec0 (char const *const *argv) </code> <br />
+Executes into the <em>argv</em> command line, with the current environment
+modified by the hidden modifier string. If this command line is empty,
+exit 0 instead.
+</p>
+
+<p>
+ The <a href="env.html">env</a> library interface provides additional functions
+to manipulate modifier strings and environments.
+</p>
+
+<h3> Forking children </h3>
+
+<p>
+<code> int doublefork () </code> <br />
+Performs a double fork. Returns -1 if it fails (and
+sets errno, EINTR meaning that the intermediate process
+was killed by a signal), 0 if the current process is the grandchild,
+and the grandchild's PID if the current process is the parent.
+</p>
+
+<p>
+<code> pid_t child_spawn0 (char const *file, char const *const *argv, char const *const *envp) </code> <br />
+Forks and executes a child as with <tt>pathexec_run(file, argv, envp)</tt>.
+Returns 0 if it fails, and the pid of the child if it succeeds.
+Implemented via <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html">posix_spawn()</a>
+on systems that support it.
+</p>
+
+<p>
+<code> pid_t child_spawn1 (char const *file, char const *const *argv, char const *const *envp, int *fd, int w) </code> <br />
+Like <tt>child_spawn0()</tt>, except that a pipe is created between the child's
+stdin (if <em>w</em> is 0) or stdout (if <em>w</em> is nonzero) and the parent.
+The parent's end of the pipe will be stored in *<em>fd</em>.
+</p>
+
+<p>
+<code> pid_t child_spawn (char const *file, char const *const *argv, char const *const *envp, int *fds, unsigned int nfds) </code> <br />
+More generic spawning function. <em>fds</em> must point to an array of at least <em>nfds</em> ints;
+file descriptors reading from or writing to the child will be stored there. The function returns
+0 on failure or the pid of the child on success.
+</p>
+<ul>
+ <li> If <em>nfds</em> is 0, then the function behaves like <tt>child_spawn0</tt>, except
+all signals will be reset to the default behaviour in the child </li>
+ <li> If <em>nfds</em> is 1, then <em>fds</em>[0] will contain a Unix domain socket
+connected to the child's stdin and stdout. </li>
+ <li> If <em>nfds</em> is 2 or more, then <em>fds</em> will contain pipes between the
+child and the parent. The parent will read on even-numbered ones (starting on <em>fds</em>[0])
+and write on odd-numbered ones. </li>
+</ul>
+
+<h3> Waiting for children </h3>
+
+<p>
+<code> unsigned int wait_reap () </code> <br />
+Instantly reaps all the pending zombies, without blocking, without a look at
+the exit codes.
+Returns the number of reaped zombies.
+</p>
+
+<p>
+<code> int waitn (pid_t *pids, unsigned int n) </code> <br />
+Waits until all processes whose PIDs are stored in the
+<em>pids</em> array, of size <em>n</em>, have died.
+Returns 1 if it succeeds, and 0 (and sets errno) if it fails. The
+<em>pid</em> array is not guaranteed to be unchanged.
+</p>
+
+<p>
+<code> int waitn_reap (pid_t *pids, unsigned int n) </code> <br />
+Instantly reaps all zombies whose PIDs are stored in the
+<em>pids</em> array, of size <em>n</em>.
+Returns -1 (and sets errno) if it fails, and the number of reaped
+zombies if it succeeds. The <em>pid</em> array is not guaranteed to
+be unchanged.
+</p>
+
+<p>
+<code> int wait_nohang (int *wstat) </code> <br />
+Instantly reaps one zombie, and stores the status information into
+*<em>wstat</em>.
+Returns the PID of the reaped zombie if it succeeds, 0 if there was
+nothing to reap (and the current process still has children), -1 ECHILD
+if there was nothing to reap (and the current process has no children),
+or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int waitpid_nointr (pid_t pid, int *wstat, int flags) </code> <br />
+Safe wrapper around
+<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/waitpid.html">waitpid()</a>.
+</p>
+
+<p>
+<code> int wait_pid_nohang (pid_t pid, int *wstat) </code> <br />
+Instantly reaps an undetermined number of zombies until it finds <em>pid</em>.
+Stores the status information for dead <em>pid</em> into *<em>wstat</em>.
+Returns <em>pid</em> if it succeeds, 0 if there was
+nothing to reap (and the current process still has children), -1 ECHILD
+if there was nothing to reap (and the current process has no children),
+or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int wait_pids_nohang (pid_t const *pids, unsigned int len, int *wstat) </code> <br />
+Instantly reaps an undetermined number of zombies until it finds one whose
+PID is in the <em>pids</em> array, of size <em>len</em>.
+Stores the status information for that dead process into *<em>wstat</em>.
+Returns the index of the found PID in <em>pids</em>, starting at 1.
+Returns 0 if there was
+nothing to reap (and the current process still has children), -1 ECHILD
+if there was nothing to reap (and the current process has no children),
+or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+ When asynchronously dealing with a child (resp. several children) and
+getting a SIGCHLD - which should be handled via a
+<a href="selfpipe.html">selfpipe</a> - it is generally a good idea to
+use the <tt>wait_pid_nohang()</tt> (resp. <tt>wait_pids_nohang()</tt>)
+function over the basic Unix APIs. This allows a program to:
+</p>
+
+<ul>
+ <li> Automatically and silently take care of children it does not know
+it has. This situation can happen when a process forks and the parent
+execs. When the child dies, the new parent process has to drag the
+"zombie bastard" along, which is ugly; <tt>wait_pids_nohang()</tt>
+prevents this. </li>
+ <li> Still take appropriate care of its legitimate children, in
+any order. </li>
+</ul>
+
+<h3> Reading and writing whole files </h3>
+
+<p>
+<code> int slurp (stralloc *sa, int fd) </code> <br />
+Slurps the contents of open descriptor <em>fd</em> into
+the *<em>sa</em> <a href="stralloc.html">stralloc</a>. If you are
+doing this, you should either have full control over the slurped
+file, or run your process with suitable
+<a href="http://www.skarnet.org/software/s6/s6-softlimit.html">limits</a>
+to the amount of heap memory it can get.
+The function returns 1 if it succeeds, or 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int openslurpclose (stralloc *sa, char const *file) </code> <br />
+Slurps the contents of file <em>file</em> into *<em>sa</em>.
+Returns 1 if it succeeds, and 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int openreadclose (char const *file, stralloc *sa, unsigned int dummy) </code> <br />
+Legacy interface for <code>openslurpclose(sa, file)</code>. The <em>dummy</em>
+argument is unused. Returns 0 if it succeeds, and -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int openreadnclose (char const *file, char *s, unsigned int n) </code> <br />
+Reads at most <em>n</em> bytes from file <em>file</em> into preallocated
+buffer <em>s</em>. Returns -1 (and sets errno) if it fails; else returns the
+number of read bytes. If that number is not <em>n</em>, errno is set to EPIPE.
+</p>
+
+<p>
+<code> int openreadfileclose (char const *file, stralloc *sa, unsigned int n) </code> <br />
+Reads at most <em>n</em> bytes from file <em>file</em> into the *<em>sa</em>
+stralloc, which is grown (if needed) to <em>just</em> accommodate the file
+size. Returns 1 if it succeeds and 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int openwritenclose_unsafe_internal (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, unsigned char dosync) </code> <br />
+Writes the <em>n</em> bytes stored at <em>s</em> into file <em>file</em>.
+The previous contents of <em>file</em> are destroyed even if the function
+fails. If <em>dosync</em> is nonzero, the new contents of <em>file</em>
+are synced to disk before the function returns. If <em>dev</em> and <em>ino</em>
+are not null, they're used to store the device and inode number of <em>file</em>.
+The function returns 1 if it succeeds, or 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int openwritenclose_unsafe (char const *file, char const *s, unsigned int len) <br />
+int openwritenclose_unsafe_sync (char const *file, char const *s, unsigned int len) <br />
+int openwritenclose_unsafe_devino (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino) <br />
+int openwritenclose_unsafe_devino_sync (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino) </code> <br />
+Trivial shortcuts around <tt>openwritenclose_unsafe_internal()</tt>. The
+reader can easily figure out what they do.
+</p>
+
+<p>
+<code> int openwritenclose_suffix_internal (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, unsigned char dosync, char const *suffix) </code> <br />
+Writes the <em>n</em> bytes stored at <em>s</em> into file <em>file</em>,
+by first writing into <em>filesuffix</em> and atomically renaming
+<em>filesuffix</em> to <em>file</em>. IOW, the old contents of <em>file</em>
+are preserved if the operation fails, and are atomically replaced with the
+new contents if the operation succeeds.
+If <em>dosync</em> is nonzero, the new contents of <em>filesuffix</em>
+are synced to disk before the atomic replace. If <em>dev</em> and <em>ino</em>
+are not null, they're used to store the device and inode number of <em>file</em>.
+The function returns 1 if it succeeds, or 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int openwritenclose_suffix (char const *file, char const *s, unsigned int len, char const *suffix) <br />
+int openwritenclose_suffix_sync (char const *file, char const *s, unsigned int len, char const *suffix) <br />
+int openwritenclose_suffix_devino (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, char const *suffix) <br />
+int openwritenclose_suffix_devino_sync (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, char const *suffix) </code> <br />
+Trivial shortcuts around <tt>openwritenclose_suffix_internal()</tt>. The
+reader can easily figure out what they do.
+</p>
+
+<h3> Filesystem deletion </h3>
+
+<p>
+The following operations are not atomic, so if they fail, the
+relevant subtree might end up partially deleted.
+</p>
+
+<p>
+<code> int rm_rf (char const *path) </code> <br />
+Deletes the filesystem subtree at <em>path</em>.
+Returns 0 if it succeeds or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int rm_rf_tmp (char const *path, stralloc *tmp) </code> <br />
+Deletes the filesystem subtree at <em>path</em>, using *<em>tmp</em>
+as heap-allocated temporary space.
+Returns 0 if it succeeds or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int rm_rf_in_tmp (stralloc *tmp, unsigned int n) </code> <br />
+Deletes a filesystem subtree, using *<em>tmp</em>
+as heap-allocated temporary space.
+Returns 0 if it succeeds or -1 (and sets errno) if it fails.
+When the function is called, *<em>tmp</em> must contain the
+null-terminated name of the subtree to delete at offset <em>n</em>.
+</p>
+
+<p>
+<code> int rmstar (char const *dir) </code> <br />
+Deletes all the filesystem subtrees in directory <em>dir</em>.
+Returns 0 if it succeeds or -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int rmstar_tmp (char const *dir, stralloc *tmp) </code> <br />
+Deletes all the filesystem subtrees in directory <em>dir</em>,
+using *<em>tmp</em> as heap-allocated temporary space.
+Returns 0 if it succeeds or -1 (and sets errno) if it fails.
+</p>
+
+<h3> Variable length wrappers around Single Unix calls </h3>
+
+<p>
+<code> int sarealpath (stralloc *sa, char const *path) </code> <br />
+Resolves <em>path</em> into a symlink-free absolute path, appending
+the result to the *<em>sa</em>
+<a href="stralloc.html">stralloc</a>.
+Returns 0 if it succeeds and -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int sarealpath_tmp (stralloc *sa, char const *path, stralloc *tmp) </code> <br />
+Resolves <em>path</em> into a symlink-free absolute path, appending
+the result to *<em>sa</em>. Uses *<em>tmp</em> as heap-allocated
+temporary space.
+Returns 0 if it succeeds and -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int sabasename (stralloc *sa, char const *s, unsigned int len) </code> <br />
+Appends the basename of filename <em>s</em> (of length <em>len</em>)
+to *<em>sa</em>.
+Returns 1 if it succeeds and 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int sadirname (stralloc *sa, char const *s, unsigned int len) </code> <br />
+Appends the dirname of filename <em>s</em> (of length <em>len</em>)
+to *<em>sa</em>.
+Returns 1 if it succeeds and 0 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int sagetcwd (stralloc *sa) </code> <br />
+Appends the current working directory to *<em>sa</em>.
+Returns 0 if it succeeds and -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int sareadlink (stralloc *sa, char const *link) </code> <br />
+Appends the contents of symbolic link <em>link</em> to *<em>sa</em>.
+Returns 0 if it succeeds and -1 (and sets errno) if it fails.
+</p>
+
+<p>
+<code> int sagethostname (stralloc *sa) </code> <br />
+Appends the machine's hostname to *<em>sa</em>.
+Returns 0 if it succeeds and -1 (and sets errno) if it fails.
+</p>
+
+<h3> Temporization </h3>
+
+<p>
+<code> void deepsleepuntil (tain_t const *deadline, tain_t *stamp) </code> <br />
+Sleeps until the absolute time represented by the
+<a href="tai.html">tain_t</a> *<em>deadline</em>. *<em>stamp</em>
+must contain the current time. When the function returns, *<em>stamp</em>
+has been updated to reflect the new current time.
+</p>
+
+<p>
+<code> void deepsleep (unsigned int n) </code> <br />
+Sleeps <em>n</em> seconds. Signals received during that time are handled,
+but <em>do not</em> interrupt the sleep.
+</p>
+
+<p>
+<code> void deepmillisleep (unsigned long n) </code> <br />
+Sleeps <em>n</em> milliseconds. Signals received during that time are handled,
+but <em>do not</em> interrupt the sleep.
+</p>
+
+</body>
+</html>