libstddjb
libskarnet
skalibs
Software
skarnet.org
The following functions are declared in the skalibs/djbunix.h header, and implemented in the libskarnet.a or libskarnet.so library.
djbunix is an alternative API to management of basic Unix concepts: file descriptors, files, environment, and so on. It is a rather chaotic mix of safe wrappers around Unix system calls, better reimplementations of standard libc functionalities, and higher-level manipulations of Unix concepts.
Understanding djbunix is essential to understanding any piece of code depending on skalibs.
int coe (int fd)
Sets the close-on-exec flag on fd.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int uncoe (int fd)
Clears the close-on-exec flag on fd.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int ndelay_on (int fd)
Sets the O_NONBLOCK flag on fd: sets it to non-blocking mode.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int ndelay_off (int fd)
Clears the O_NONBLOCK flag on fd: sets it to blocking mode.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int pipenb (int *p)
Like
pipe(),
but both ends of the created pipe are in non-blocking mode.
int pipecoe (int *p)
Like
pipe(),
but both ends of the created pipe are close-on-exec.
int pipenbcoe (int *p)
Like
pipe(),
but both ends of the created pipe are in non-blocking mode and close-on-exec.
int fd_copy (int to, int from)
Copies the open fd from to number to. to
must not refer to an already open fd.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int fd_copy2 (int to1, int from1, int to2, int from2)
Copies the open fd from1 to number to2. Also copies
from2 to to2 at the same time.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int fd_move (int to, int from)
Moves the open fd from to number to. to
must not refer to an already open fd, unless it's equal to from.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int fd_move2 (int to1, int from1, int to2, int from2)
Moves the open fd from to number to. Also moves
from2 to to2 at the same time. This is useful for instance
when you want to swap two fds: fd_move2 will handle the situation
correctly.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int fd_close (int fd)
Closes fd.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
This is a safe wrapper around
close(),
or rather as safe a wrapper as is possible to write: the close()
specification does not allow a 100% safe behaviour. So, in rare cases
it is possible for fd_close() 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 fd_close() is
always a static programming error.
int fd_chmod (int fd, unsigned int mode)
Safe wrapper around
fchmod().
int fd_chown (int fd, unsigned int uid, unsigned int gid)
Safe wrapper around
fchown().
This function requires root privileges.
int fd_sync (int fd)
Safe wrapper around
fsync().
int fd_chdir (int fd)
Safe wrapper around
fchdir().
int fd_cat (int from, int to)
Synchronously copies data from fd from to fd to,
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.
When the underlying OS allows it, zero-copy transmission is performed. Currently, the following zero-copy implementations are supported:
unsigned int fd_catn (int from, int to, unsigned int n)
Synchronously copies at most n bytes from fd from to fd to.
Returns the total number of transmitted bytes; sets errno if this number
is lesser than n. EOF is reported as EPIPE. See above for zero-copy
transmission; zero-copy transmission is not attempted for less than 64k of data.
int fd_ensure_open (int fd, int w)
If fd is not open, opens it to /dev/null,
for reading if w is zero, and for writing otherwise.
Returns 1 if it succeeds and 0 if it fails.
int fd_sanitize (void)
Ensures stdin and stdout are open. If one of those
file descriptors was closed, it now points to /dev/null.
Returns 1 if it succeeds and 0 if it fails.
int lock_ex (int fd)
Gets an exclusive advisory lock on fd. fd 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.
int lock_exnb (int fd)
Gets an exclusive advisory lock on fd. fd 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.
int lock_sh (int fd)
Gets a shared advisory lock on fd. fd 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.
int lock_shnb (int fd)
Gets a shared advisory lock on fd. fd 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.
int lock_un (int fd)
Releases a previously held lock on fd.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int open2 (char const *file, unsigned int flags)
Safe wrapper around
open()
when it takes 2 arguments.
int open3 (char const *file, unsigned int flags)
Safe wrapper around
open()
when it takes 3 arguments.
int open_read (char const *file)
Opens file in read-only, non-blocking mode.
Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
int open_readb (char const *file)
Opens file in read-only, blocking mode.
Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
This call does not block. The
open()
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.
int open_excl (char const *file)
Opens file 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.
int open_append (char const *file)
Opens file 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.
int open_trunc (char const *file)
Opens file 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.
int open_create (char const *file)
Opens file 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.
int open_write (char const *file)
Opens file in write-only, non-blocking mode.
Returns a valid fd number if it succeeds, or -1 (and sets errno) if it fails.
long seek_cur (int fd)
Returns the current file offset for descriptor fd.
int seek_set (int fd, long pos)
Sets the current file offset for fd to pos.
Returns 0 if it succeeds, or -1 (and sets errno) if it fails.
int prot_readgroups (char const *name, gid_t *tab, unsigned int max)
Reads the group database (normally /etc/group, but it can be
altered via NSS) to get the list of supplementary groups for user name.
Stores that list into the array pointed to by tab, which must be
preallocated. Stores at most max elements into tab.
Returns -1 and sets errno if it fails; else, returns the number of elements actually
stored into tab.
int prot_grps (char const *name)
Sets the kernel-maintained list of supplementary groups for the current process
to the list of supplementary groups for user name according to the
group database. This is a privileged operation.
Returns -1 and sets errno if it fails; returns 0 if it succeeds.
int prot_gid (int gid)
Alias to setgid.
int prot_uid (int uid)
Alias to setuid.
void execvep (char const *file, char const *const *argv, char const *const *envp, char const *path)
Executes into the executable file at file, with the command line
set to argv and the environment set to envp.
If file is not an absolute path, it is searched in the
path 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.
void pathexec_run (char const *file, char const *const *argv, char const *const *envp)
Performs execvep(file, argv, envp, path), path being the
contents of the PATH environment variable. If PATH is not set, path
is set to the contents of the conf-compile/conf-defaultpath file in
the skalibs distribution.
The function returns if it fails, and sets errno appropriately.
pathexec_run() is the standard skalibs API to perform an exec call with a path search. It is recommended that you use it instead of the Single Unix execvp() or execlp() functions, because execvp and execlp default to execution of the /bin/sh interpreter with file as an argument if they cannot find a suitable executable file, and this is:
execvep() and pathexec_run() just fail with ENOENT when they cannot find a file to exec into, which is the sensible behaviour.
void pathexec0_run (char const *const *argv, char const *const *envp)
Performs pathexec_run(argv[0], argv, envp). If argv is empty, i.e.
argv[0] is null, the process exits 0 instead. Rationale: executing
the empty command line should amount to executing true, i.e.
simply exiting 0.
void pathexec_r_name (char const *file, char const *const *argv, char const *const *envp, unsigned int envlen, char const *modifs, unsigned int modiflen)
Alters envp (which does not have to be NULL-terminated, but the
number envlen of elements must be provided) with the modifier
string modifs of length modiflen, then performs
pathexec_run(file, argv, altered-envp).
void pathexec_r (char const *const *argv, char const *const *envp, unsigned int envlen, char const *modifs, unsigned int modiflen)
Same as pathexec_r_name, except that the file argument is read from argv[0].
int pathexec_env (char const *var, char const *value)
Adds the "add variable var with value value" instruction
(if value is not null) or the "unset var" instruction
(if value 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.
void pathexec_fromenv (char const *const *argv, char const *const *envp, unsigned int envlen)
Performs pathexec_r() with the given arguments and the hidden modifier
string.
void pathexec (char const *const *argv)
Executes into the argv command line, with the current environment
modified by the hidden modifier string.
void pathexec0 (char const *const *argv)
Executes into the argv command line, with the current environment
modified by the hidden modifier string. If this command line is empty,
exit 0 instead.
The env library interface provides additional functions to manipulate modifier strings and environments.
int doublefork ()
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.
pid_t child_spawn0 (char const *file, char const *const *argv, char const *const *envp)
Forks and executes a child as with pathexec_run(file, argv, envp).
Returns 0 if it fails, and the pid of the child if it succeeds.
Implemented via posix_spawn()
on systems that support it.
pid_t child_spawn1_pipe (char const *file, char const *const *argv, char const *const *envp, int *fd, int w)
Like child_spawn0(), except that a pipe is created between the child's
stdin (if w is 0) or stdout (if w is nonzero) and the parent.
The parent's end of the pipe will be stored in *fd.
pid_t child_spawn1_socket (char const *file, char const *const *argv, char const *const *envp, int *fd)
Like child_spawn0, except that a socket is created between the parent
and the child. Both the child's stdin and stdout point to the socket; the parent has
its end of the socket available in *fd.
pid_t child_spawn (char const *file, char const *const *argv, char const *const *envp, int *fds, unsigned int nfds)
More generic spawning function. fds must point to an array of at least nfds 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.
unsigned int wait_reap ()
Instantly reaps all the pending zombies, without blocking, without a look at
the exit codes.
Returns the number of reaped zombies.
int waitn (pid_t *pids, unsigned int n)
Waits until all processes whose PIDs are stored in the
pids array, of size n, have died.
Returns 1 if it succeeds, and 0 (and sets errno) if it fails. The
pid array is not guaranteed to be unchanged.
int waitn_reap (pid_t *pids, unsigned int n)
Instantly reaps all zombies whose PIDs are stored in the
pids array, of size n.
Returns -1 (and sets errno) if it fails, and the number of reaped
zombies if it succeeds. The pid array is not guaranteed to
be unchanged.
int wait_nohang (int *wstat)
Instantly reaps one zombie, and stores the status information into
*wstat.
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.
int waitpid_nointr (pid_t pid, int *wstat, int flags)
Safe wrapper around
waitpid().
int wait_pid_nohang (pid_t pid, int *wstat)
Instantly reaps an undetermined number of zombies until it finds pid.
Stores the status information for dead pid into *wstat.
Returns pid 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.
int wait_pids_nohang (pid_t const *pids, unsigned int len, int *wstat)
Instantly reaps an undetermined number of zombies until it finds one whose
PID is in the pids array, of size len.
Stores the status information for that dead process into *wstat.
Returns the index of the found PID in pids, 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.
When asynchronously dealing with a child (resp. several children) and getting a SIGCHLD - which should be handled via a selfpipe - it is generally a good idea to use the wait_pid_nohang() (resp. wait_pids_nohang()) function over the basic Unix APIs. This allows a program to:
int slurp (stralloc *sa, int fd)
Slurps the contents of open descriptor fd into
the *sa stralloc. If you are
doing this, you should either have full control over the slurped
file, or run your process with suitable
limits
to the amount of heap memory it can get.
The function returns 1 if it succeeds, or 0 (and sets errno) if it fails.
int openslurpclose (stralloc *sa, char const *file)
Slurps the contents of file file into *sa.
Returns 1 if it succeeds, and 0 (and sets errno) if it fails.
int openreadclose (char const *file, stralloc *sa, unsigned int dummy)
Legacy interface for openslurpclose(sa, file)
. The dummy
argument is unused. Returns 0 if it succeeds, and -1 (and sets errno) if it fails.
int openreadnclose (char const *file, char *s, unsigned int n)
Reads at most n bytes from file file into preallocated
buffer s. Returns -1 (and sets errno) if it fails; else returns the
number of read bytes. If that number is not n, errno is set to EPIPE.
int openreadfileclose (char const *file, stralloc *sa, unsigned int n)
Reads at most n bytes from file file into the *sa
stralloc, which is grown (if needed) to just accommodate the file
size. Returns 1 if it succeeds and 0 (and sets errno) if it fails.
int openwritenclose_unsafe_internal (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, unsigned char dosync)
Writes the n bytes stored at s into file file.
The previous contents of file are destroyed even if the function
fails. If dosync is nonzero, the new contents of file
are synced to disk before the function returns. If dev and ino
are not null, they're used to store the device and inode number of file.
The function returns 1 if it succeeds, or 0 (and sets errno) if it fails.
int openwritenclose_unsafe (char const *file, char const *s, unsigned int len)
int openwritenclose_unsafe_sync (char const *file, char const *s, unsigned int len)
int openwritenclose_unsafe_devino (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino)
int openwritenclose_unsafe_devino_sync (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino)
Trivial shortcuts around openwritenclose_unsafe_internal(). The
reader can easily figure out what they do.
int openwritenclose_suffix_internal (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, unsigned char dosync, char const *suffix)
Writes the n bytes stored at s into file file,
by first writing into filesuffix and atomically renaming
filesuffix to file. IOW, the old contents of file
are preserved if the operation fails, and are atomically replaced with the
new contents if the operation succeeds.
If dosync is nonzero, the new contents of filesuffix
are synced to disk before the atomic replace. If dev and ino
are not null, they're used to store the device and inode number of file.
The function returns 1 if it succeeds, or 0 (and sets errno) if it fails.
int openwritenclose_suffix (char const *file, char const *s, unsigned int len, char const *suffix)
int openwritenclose_suffix_sync (char const *file, char const *s, unsigned int len, char const *suffix)
int openwritenclose_suffix_devino (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, char const *suffix)
int openwritenclose_suffix_devino_sync (char const *file, char const *s, unsigned int len, uint64 *dev, uint64 *ino, char const *suffix)
Trivial shortcuts around openwritenclose_suffix_internal(). The
reader can easily figure out what they do.
The following operations are not atomic, so if they fail, the relevant subtree might end up partially deleted.
int rm_rf (char const *path)
Deletes the filesystem subtree at path.
Returns 0 if it succeeds or -1 (and sets errno) if it fails.
int rm_rf_tmp (char const *path, stralloc *tmp)
Deletes the filesystem subtree at path, using *tmp
as heap-allocated temporary space.
Returns 0 if it succeeds or -1 (and sets errno) if it fails.
int rm_rf_in_tmp (stralloc *tmp, unsigned int n)
Deletes a filesystem subtree, using *tmp
as heap-allocated temporary space.
Returns 0 if it succeeds or -1 (and sets errno) if it fails.
When the function is called, *tmp must contain the
null-terminated name of the subtree to delete at offset n.
int rmstar (char const *dir)
Deletes all the filesystem subtrees in directory dir.
Returns 0 if it succeeds or -1 (and sets errno) if it fails.
int rmstar_tmp (char const *dir, stralloc *tmp)
Deletes all the filesystem subtrees in directory dir,
using *tmp as heap-allocated temporary space.
Returns 0 if it succeeds or -1 (and sets errno) if it fails.
int sarealpath (stralloc *sa, char const *path)
Resolves path into a symlink-free absolute path, appending
the result to the *sa
stralloc.
Returns 0 if it succeeds and -1 (and sets errno) if it fails.
int sarealpath_tmp (stralloc *sa, char const *path, stralloc *tmp)
Resolves path into a symlink-free absolute path, appending
the result to *sa. Uses *tmp as heap-allocated
temporary space.
Returns 0 if it succeeds and -1 (and sets errno) if it fails.
int sabasename (stralloc *sa, char const *s, unsigned int len)
Appends the basename of filename s (of length len)
to *sa.
Returns 1 if it succeeds and 0 (and sets errno) if it fails.
int sadirname (stralloc *sa, char const *s, unsigned int len)
Appends the dirname of filename s (of length len)
to *sa.
Returns 1 if it succeeds and 0 (and sets errno) if it fails.
int sagetcwd (stralloc *sa)
Appends the current working directory to *sa.
Returns 0 if it succeeds and -1 (and sets errno) if it fails.
int sareadlink (stralloc *sa, char const *link)
Appends the contents of symbolic link link to *sa.
Returns 0 if it succeeds and -1 (and sets errno) if it fails.
int sagethostname (stralloc *sa)
Appends the machine's hostname to *sa.
Returns 0 if it succeeds and -1 (and sets errno) if it fails.
void deepsleepuntil (tain_t const *deadline, tain_t *stamp)
Sleeps until the absolute time represented by the
tain_t *deadline. *stamp
must contain the current time. When the function returns, *stamp
has been updated to reflect the new current time.
void deepsleep (unsigned int n)
Sleeps n seconds. Signals received during that time are handled,
but do not interrupt the sleep.
void deepmillisleep (unsigned long n)
Sleeps n milliseconds. Signals received during that time are handled,
but do not interrupt the sleep.