diff options
Diffstat (limited to 'doc/libstddjb')
-rw-r--r-- | doc/libstddjb/alloc.html | 98 | ||||
-rw-r--r-- | doc/libstddjb/allreadwrite.html | 145 | ||||
-rw-r--r-- | doc/libstddjb/bitarray.html | 131 | ||||
-rw-r--r-- | doc/libstddjb/djbtime.html | 201 | ||||
-rw-r--r-- | doc/libstddjb/djbunix.html | 760 | ||||
-rw-r--r-- | doc/libstddjb/gccattributes.html | 48 | ||||
-rw-r--r-- | doc/libstddjb/genalloc.html | 46 | ||||
-rw-r--r-- | doc/libstddjb/genwrite.html | 98 | ||||
-rw-r--r-- | doc/libstddjb/index.html | 125 | ||||
-rw-r--r-- | doc/libstddjb/iopause.html | 196 | ||||
-rw-r--r-- | doc/libstddjb/ip46.html | 172 | ||||
-rw-r--r-- | doc/libstddjb/lolstdio.html | 91 | ||||
-rw-r--r-- | doc/libstddjb/safewrappers.html | 91 | ||||
-rw-r--r-- | doc/libstddjb/selfpipe.html | 242 | ||||
-rw-r--r-- | doc/libstddjb/stralloc.html | 118 | ||||
-rw-r--r-- | doc/libstddjb/tai.html | 462 |
16 files changed, 3024 insertions, 0 deletions
diff --git a/doc/libstddjb/alloc.html b/doc/libstddjb/alloc.html new file mode 100644 index 0000000..e17fcc7 --- /dev/null +++ b/doc/libstddjb/alloc.html @@ -0,0 +1,98 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the alloc library interface</title> + <meta name="Description" content="skalibs: the alloc library interface" /> + <meta name="Keywords" content="skalibs c unix alloc library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>alloc</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/alloc.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>alloc</tt> is the skalibs heap memory manager. It's actually a +wrapper for the +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/malloc.html">malloc()</a> +series of functions; it unifies a few system-dependent <tt>malloc</tt> +behaviours. It's also the API to implement and preload if for some +reason you need to plug in your own allocator: replacing <tt>alloc()</tt> +is much easier than replacing <tt>malloc()</tt> safely. +</p> + +<p> +<strong> As a general rule, you should not be using the <tt>alloc</tt> +interface directly. </strong> Allocating and freeing individual cells +in the heap is a recipe for heap fragmentation, as well as cell +tracking nightmares leading to memory leaks. <strong> You should use +the higher-level <a href="stralloc.html">stralloc</a> and +<a href="genalloc.html">genalloc</a> interfaces </strong> to handle dynamic +arrays of objects. +</p> + +<p> + C's lack of automatic management of heap memory is not a drawback: it's +a feature of the language. It allows for code that is one or two orders +of magnitude faster than the equivalent in a higher-level language, +and very low on resources consumption. However, it requires more attention +from the programmer. Good APIs can significantly reduce the difficulty of +keeping track of every heap-allocated cell, and every smart programmer +should favor them over basic interfaces like <tt>malloc()</tt>. +</p> + +<p> + <tt>alloc</tt> is used internally by skalibs to implement +<a href="stralloc.html">stralloc</a>, and nowhere else. +</p> + +<h2> Functions </h2> + +<p> +<code> char *alloc (unsigned int len) </code> <br /> +Allocates a block of <em>len</em> bytes in the heap and returns a pointer +to the start of the block (or NULL if it failed). Though the pointer type +is <tt>char *</tt>, the block of memory is correctly aligned for any type +of object. If <em>len</em> is 0, the function returns a pointer that +cannot be written to, but that is <em>not null</em>. Note that this is +different from the required C99 behaviour for <tt>malloc()</tt>. +</p> + +<p> +<code> void alloc_free (void *p) </code> <br /> +Frees the block of heap memory pointed to by <em>p</em>. +</p> + +<p> +<code> int alloc_realloc (char **p, unsigned int newlen) </code> <br /> +Redimension the block of heap memory pointed to by *<em>p</em> to +<em>newlen</em> bytes. The block may have to be moved, in which case +*<em>p</em> will be modified. Normally returns 1; if an error occurred, +returns 0 and sets errno, and neither *<em>p</em> nor its contents are +modified. +</p> + +<p> +<code> int alloc_re (char **p, unsigned int oldlen, unsigned int newlen) </code> <br /> +Legacy interface for reallocation. It works like <tt>alloc_realloc</tt>, +except that the original block length must be provided as the <em>oldlen</em> +argument. +</p> + +</body> +</html> diff --git a/doc/libstddjb/allreadwrite.html b/doc/libstddjb/allreadwrite.html new file mode 100644 index 0000000..847c4e3 --- /dev/null +++ b/doc/libstddjb/allreadwrite.html @@ -0,0 +1,145 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the allreadwrite library interface</title> + <meta name="Description" content="skalibs: the allreadwrite library interface" /> + <meta name="Keywords" content="skalibs c unix allreadwrite library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>allreadwrite</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/allreadwrite.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>allreadwrite</tt> is a set of IO function helpers. It's the +basis for safe reading and writing, either in blocking or in +non-blocking mode. The <a href="buffer.html">buffer</a> interface +relies heavily on <tt>allreadwrite</tt>. +</p> + +<p> + Unless the IO you need is very simple, you generally should not +be using the <tt>allreadwrite</tt> functions directly; you should +use higher-level APIs such as <a href="buffer.html>buffer</a> and +<a href="bufalloc.html">bufalloc</a>. +</p> + +<h2> Function types </h2> + +<p> +<code> typedef int iofunc_t (int fd, char *buf, unsigned int len) </code> <br /> +This is the simplified type of IO functions such as +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/read.html">read()</a> +and +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/write.html">write()</a>. +Unless your system's <tt>int</tt> is 64-bit, skalibs - which has been +optimized for small systems - does not support IO operations of more than +2 GB of data, for the sake of simplicity. In any case, it's always +possible to send data in several smaller chunks. +</p> + +<p> +<code> typedef unsigned int alliofunc_t (int fd, char *buf, unsigned int len) </code> <br /> +This is the type of an IO operation that expects <em>all</em> of its +<em>len</em> bytes to be sent or received, and that will loop around a +lower-level IO function until either <em>len</em> bytes have been +transmitted or an error has occurred. The return value is the actual +number of transmitted bytes; if this value is lesser than <em>len</em>, +it means that an error has occurred and <tt>errno</tt> is set. +</p> + +<h2> Functions </h2> + +<p> +<code> int sanitize_read (int r) </code> <br /> +Reading functions such as <tt>read()</tt> and <tt>fd_read</tt> return +a positive number when they succeed, -1 when they fail, and 0 when they +read an EOF. No data available on the descriptor when reading in +non-blocking mode is treated as a failure: -1 EWOULDBLOCK. But sometimes +(namely, in asynchronous IO loops) it's preferrable to handle EOF as an +exception condition and EWOULDBLOCK as a normal condition. +<tt>sanitize_read()</tt>, when applied to the result of a basic reading +function, returns 0 if <em>r</em> is -1 and errno is EWOULDBLOCK (or +EAGAIN). If <em>r</em> is zero, it returns -1 EPIPE. Else it returns <em>r</em>. +</p> + +<p> + (No system reading function can ever set errno to EPIPE, and the +semantics are appropriate, so EPIPE is a good candidate to signal EOF +on reading.) +</p> + +<p> +<code> unsigned int allreadwrite (iofunc_t *f, int fd, char *s, unsigned int len) </code> <br /> +*<em>f</em> must be a basic reading or writing function such as +<tt>fd_read</tt> or <tt>fd_write</tt>. <tt>allreadwrite()</tt> performs +*<em>f</em> on <em>fd</em>, <em>s</em> and <em>len</em> until <em>len</em> +bytes have been read or written, or until an error occurs. It returns the +total number of handled bytes, and sets errno if this number is not +<em>len</em>. <tt>allreadwrite</tt> may block if <em>fd</em> is in +blocking mode; if <em>fd</em> is in non-blocking mode, it might +set errno to EWOULDBLOCK or EAGAIN. +</p> + +<p> +<code> int fd_read (int fd, char *s, unsigned int len) </code> <br /> +<a href="safewrappers.html">Safe wrapper</a> around the +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/read.html">read()</a> +function. +</p> + +<p> +<code> int fd_write (int fd, char const *s, unsigned int len) </code> <br /> +<a href="safewrappers.html">Safe wrapper</a> around the +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/write.html">write()</a> +function. +</p> + +<p> +<code> int fd_recv (int fd, char *s, unsigned int len, unsigned int flags) </code> <br /> +<a href="safewrappers.html">Safe wrapper</a> around the +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/recv.html">recv()</a> +function. +</p> + +<p> +<code> int fd_send (int fd, char const *s, unsigned int len, unsigned int flags) </code> <br /> +<a href="safewrappers.html">Safe wrapper</a> around the +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/send.html">send()</a> +function. +</p> + +<p> +<code> unsigned int allread (int fd, char *s, unsigned int len) </code> <br /> +Equivalent to <code> allreadwrite(&fd_read, fd, s, len) </code>: attempts +to read <em>len</em> bytes from <em>fd</em> into <em>s</em>, looping around +<tt>fd_read()</tt> if necessary, until either <em>len</em> bytes are read or +an error occurs. EOF is reported as EPIPE. +</p> + +<p> +<code> unsigned int allwrite (int fd, char const *s, unsigned int len) </code> <br /> +Equivalent to <code> allreadwrite((iofunc_t *)&fd_write, fd, s, len) </code>: +attempts to write <em>len</em> bytes from <em>s</em> to <em>fd</em>, looping +around <tt>fd_write()</tt> if necessary, until either <em>len</em> bytes are +written or an error occurs. +</p> + +</body> +</html> diff --git a/doc/libstddjb/bitarray.html b/doc/libstddjb/bitarray.html new file mode 100644 index 0000000..1f88c3d --- /dev/null +++ b/doc/libstddjb/bitarray.html @@ -0,0 +1,131 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the bitarray library interface</title> + <meta name="Description" content="skalibs: the bitarray library interface" /> + <meta name="Keywords" content="skalibs c unix bitarray library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>bitarray</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/bitarray.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>bitarray</tt> is a set of primitives to operate efficiently on +large bitfields. +</p> + +<p> + A bitfield is represented by a pre-allocated block of +<tt>unsigned char</tt>; <tt>bitarray</tt> does not care if that +block has been BSS-, stack- or heap-allocated. Bitfields that +can grow in size should be stored in a +<a href="stralloc.html">stralloc</a>. +</p> + +<p> + Bits in a bitfield of length <em>n</em> are numbered from 0 to <em>n</em>-1. +</p> + +<h2> Functions </h2> + +<p> +<code> unsigned int bitarray_div8 (unsigned int n) </code> <br /> +Returns the minimum number of bytes needed to store a field of <em>n</em> bits. + +</p> + +<p> +<code> void bitarray_clearsetn (unsigned char *s, unsigned int start, unsigned int len, int h) </code> <br /> +Sets (if <em>h</em> is nonzero) or clears (if <em>h</em> is zero) +<em>len</em> bits in field <em>s</em>, starting at bit <em>start</em>. +</p> + +<p> +<code> void bitarray_clearn (unsigned char *s, unsigned int start, unsigned int len) </code> <br /> +Clears <em>len</em> bits in field <em>s</em>, starting at bit <em>start</em>. +</p> + +<p> +<code> void bitarray_setn (unsigned char *s, unsigned int start, unsigned int len) </code> <br /> +Sets <em>len</em> bits in field <em>s</em>, starting at bit <em>start</em>. +</p> + +<p> +<code> int bitarray_peek (unsigned char const *s, unsigned int n) </code> <br /> +Returns the value of the <em>n</em>th bit in field <em>s</em>. +</p> + +<p> +<code> void bitarray_poke (unsigned char *s, unsigned int n, int h) </code> <br /> +Sets (if <em>h</em> is nonzero) or clears (if <em>h</em> is zero) +the <em>n</em>th bit in field <em>s</em>. +</p> + +<p> +<code> void bitarray_clear (unsigned char *s, unsigned int n) </code> <br /> +Clears the <em>n</em>th bit in field <em>s</em>. +</p> + +<p> +<code> void bitarray_set (unsigned char *s, unsigned int n) </code> <br /> +Sets the <em>n</em>th bit in field <em>s</em>. +</p> + +<p> +<code> int bitarray_testandpoke (unsigned char *s, unsigned int n, int h) </code> <br /> +Sets (if <em>h</em> is nonzero) or clears (if <em>h</em> is zero) +the <em>n</em>th bit in field <em>s</em>, +and returns the previous value of that bit. +</p> + +<p> +<code> int bitarray_testandclear (unsigned char *s, unsigned int n) </code> <br /> +Clear the <em>n</em>th bit in field <em>s</em>, +and returns the previous value of that bit. +</p> + +<p> +<code> int bitarray_testandset (unsigned char *s, unsigned int n) </code> <br /> +Sets the <em>n</em>th bit in field <em>s</em>, +and returns the previous value of that bit. +</p> + +<p> +<code> unsigned int bitarray_first (unsigned char const *s, unsigned int len, int h) </code> <br /> +Returns the number of the first set (if <em>h</em> is nonzero) or clear +(if <em>h</em> is zero) bit in <em>s</em>, <em>len</em> being +the total number of bits. If all bits in <em>s</em> are the negation of +<em>h</em>, then <em>len</em> is returned. +</p> + +<p> +<code> unsigned int bitarray_firstclear (unsigned char const *s, unsigned int len) </code> <br /> +Returns the number of the first clear bit in <em>s</em>, <em>len</em> being +the total number of bits. If all bits in <em>s</em> are set, <em>len</em> is returned. +</p> + +<p> +<code> unsigned int bitarray_firstset (unsigned char const *s, unsigned int len) </code> <br /> +Returns the number of the first set bit in <em>s</em>, <em>len</em> being +the total number of bits. If all bits in <em>s</em> are clear, <em>len</em> is returned. +</p> + +</body> +</html> diff --git a/doc/libstddjb/djbtime.html b/doc/libstddjb/djbtime.html new file mode 100644 index 0000000..45876c8 --- /dev/null +++ b/doc/libstddjb/djbtime.html @@ -0,0 +1,201 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the djbtime library interface</title> + <meta name="Description" content="skalibs: the djbtime library interface" /> + <meta name="Keywords" content="skalibs c unix djbtime library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">libstddjb</a><br /> +<a href="../libskarnet.html">skalibs</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>djbtime</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/djbtime.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>djbtime</tt> is a set of functions to convert +<a href="tai.html">tai_t and tain_t</a> structures, and +<a href="http://cr.yp.to/libtai/tai64.html">TAI time</a>, from and to +other time formats and user-friendly representations. +</p> + +<h2> The <tt>/etc/leapsecs.dat</tt> file </h2> + +<p> + User-friendly time is calculated from UTC. Internal time computations +should be performed on TAI time - because TAI flows linearly whereas +UTC does not. To convert between UTC and TAI time, you need a +<em>leap second table</em>. skalibs provides such a file in its +<tt>src/etc/leapsecs.dat</tt> subdirectory, which is copied +to <tt>/etc/leapsecs.dat</tt> at installation time (unless you specify +a --prefix or --datadir option to configure). +<strong>The <tt>/etc/leapsecs.dat</tt> file must remain accessible +on your system, else time conversions will not be computed +properly.</strong> +</p> + +<h2> Data structures </h2> + +<ul> + <li> TAI time with 1-second precision is represented as a <a href="tai.html">tai_t</a>. </li> + <li> TAI time with more precision is represented as a <a href="tai.html">tain_t</a>. </li> + <li> UTC time is represented as an <a href="headers.html#uint64">unsigned 64-bit integer</a> +equal to 2^62 added to the number of seconds since the Epoch. It's a trivial extension of +the standard 32-bit Unix time that will expire in 2038. </li> + <li> Broken-down GMT or local time with more than a 1-second precision is stored in a +<tt>localtmn_t</tt> structure, containing a <tt>struct tm</tt> <em>tm</em> +field and an unsigned long <em>nano</em> field. </li> +</ul> + +<h2> Functions </h2> + +<h3> UTC </h3> + +<p> +<code> int utc_from_tai (uint64 *u, tai_t const *t) </code> <br /> +Converts the absolute TAI64 time in *<em>t</em> to an UTC time, stored in +*<em>u</em> as an unsigned 64-bit integer. *<em>u</em> is actually 2^62 +plus the number of seconds since the Epoch. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs (for instance: the leap second table cannot be found). +</p> + +<p> +<code> int tai_from_utc (tai_t *t, uint64 u) </code> <br /> +Converts the UTC time in <em>u</em>, stored +as an unsigned 64-bit integer (2^62 plus the number of seconds since +the Epoch), to a TAI64 time in *<em>t</em>. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs (for instance: the leap second table cannot be found). +</p> + +<h3> NTP </h3> + +<p> +<code> int ntp_from_tain (uint64 *ntp, tain_t const *a) </code> <br /> +Converts the absolute TAI64N time in *<em>a</em> to a 64-bit NTP timestamp, +stored in *<em>ntp</em>. The higher 32 bits of *<em>ntp</em> represent a number +of seconds ; the lower 32 bits are the fractional part of the timestamp. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs (for instance: the leap second table cannot be found, or +*<em>a</em> cannot be represented in the valid NTP range). +</p> + +<p> +<code> int tain_from_ntp (tain_t *a, uint64 ntp) </code> <br /> +Converts the NTP timestamp in <em>ntp</em> to a TAI64N time in +*<em>a</em>. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs (for instance: the leap second table cannot be found). +</p> + +<h3> Local time </h3> + +<p> + The following functions convert time between an internal representation +and a broken-down <tt>struct tm</tt>. The +<a href="../flags.html#tzisright">--enable-right-tz</a> configure option is used in +determining how the conversion should proceed. If the <tt>--enable-tai-clock</tt> +and <tt>--enable-right-tz</tt> configure options have been both enabled +or both disabled, everything is naturally +converted as it should be. If only one of them has been enabled, +unholy magic happens here +to get the correct broken-down time despite the timezone definition being +wrong. +</p> + +<p> +<code> int localtm_from_tai (struct tm *tm, tai_t const *t, int lo) </code> <br /> +Converts the TAI time in *<em>t</em> to broken-down GMT (if +<em>lo</em> is zero) or local (if <em>lo</em> is nonzero) time in +*<em>tm</em>. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs (for instance: *<em>t</em> cannot be validly represented +in a struct tm). +</p> + +<p> +<code> int localtm_from_utc (struct tm *tm, uint64 u, int lo) </code> <br /> +Converts the UTC time in <em>u</em> to broken-down GMT (if +<em>lo</em> is zero) or local (if <em>lo</em> is nonzero) time in +*<em>tm</em>. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs (for instance: <em>u</em> cannot be validly represented +in a struct tm). +</p> + +<p> +<code> int localtm_from_sysclock (struct tm *tm, uint64 u, int lo) </code> <br /> +Converts the time in <em>u</em> to broken-down GMT (if +<em>lo</em> is zero) or local (if <em>lo</em> is nonzero) time in +*<em>tm</em>. <em>u</em> will be interpreted as a TAI-10 value (with +<tt>--enable-tai-clock</tt>) or as a UTC value (without <tt>--enable-tai-clock</tt>). +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs (for instance: <em>u</em> cannot be validly represented +in a struct tm). +</p> + +<p> +<code> int utc_from_localtm (uint64 *u, struct tm const *tm) </code> <br /> +Converts the broken-down local time in *<em>tm</em> to an UTC value +in *<em>u</em>. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs. +</p> + +<p> +<code> int tai_from_localtm (tai_t *t, struct tm const *tm) </code> <br /> +Converts the broken-down local time in *<em>tm</em> to a TAI value +in *<em>t</em>. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs. +</p> + +<p> +<code> int sysclock_from_localtm (uint64 *u, struct tm const *tm) </code> <br /> +Converts the broken-down local time in *<em>tm</em> to a value +in *<em>u</em> - either TAI-10 or UTC depending on your system clock. +The function returns 1 if it succeeds, or 0 (and sets errno) if an +error occurs. +</p> + +<p> + The following functions use the <tt>localtmn_t</tt> type to hold both +a broken-down time and a nanosecond count: +</p> + +<pre>typedef struct localtmn_s localtmn_t, *localtmn_t_ref ; +struct localtmn_s +{ + struct tm tm ; + uint32 nano ; +} ; +</pre> + +<p> + The prototypes are self-explaining: +</p> + +<p> +<code> int localtmn_from_tain (localtmn_t_ref tmn, tain_t const *a, int lo) ; <br /> +int tain_from_localtmn (tain_t *a, localtmn_t const *tmn) ; <br /> +int localtmn_from_sysclock (localtmn_t_ref tmn, tain_t const *a, int lo) ; <br /> +int sysclock_from_localtmn (tain_t *a, localtmn_t const *tmn) ; </code> <br /> +</p> + +</body> +</html> 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> diff --git a/doc/libstddjb/gccattributes.html b/doc/libstddjb/gccattributes.html new file mode 100644 index 0000000..6ee71ef --- /dev/null +++ b/doc/libstddjb/gccattributes.html @@ -0,0 +1,48 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the gccattributes header</title> + <meta name="Description" content="skalibs: the gccattributes header" /> + <meta name="Keywords" content="skalibs header gccattributes gcc attributes" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>skalibs/gccattributes.h</tt> header </h1> + +<p> + <tt>skalibs/gccattributes.h</tt> is a set of wrappers around +<a href="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html">gcc +attributes</a> (duh). It defines macros that are always valid, and +that have no effect if the compiler is not gcc or the used version +of gcc does not support the wanted attribute. +</p> + +<p> + For instance: +</p> + +<pre> + extern unsigned int str_len (char const *) gccattr_pure ; +</pre> + +<p> + defines the <tt>str_len</tt> function as <em>pure</em> if it is +supported. +</p> + +<p> + The source code is self-explanatory. +</p> + +</body> +</html> diff --git a/doc/libstddjb/genalloc.html b/doc/libstddjb/genalloc.html new file mode 100644 index 0000000..b9ab934 --- /dev/null +++ b/doc/libstddjb/genalloc.html @@ -0,0 +1,46 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the genalloc library interface</title> + <meta name="Description" content="skalibs: the genalloc library interface" /> + <meta name="Keywords" content="skalibs c unix genalloc library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>genalloc</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/genalloc.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>genalloc</tt> is the skalibs way of handling dynamic arrays, i.e. +dynamically growing arrays of fixed-size objects. Any array that needs +to be stored in heap memory can be implemented via genalloc. +</p> + +<p> + Most genalloc functions are just macro calls around +<a href="stralloc.html">stralloc</a> functions. +</p> + +<p> + The <tt>genalloc.h</tt> header is actually very simple and the +prototypes there are self-explaining. +</p> + +</body> +</html> diff --git a/doc/libstddjb/genwrite.html b/doc/libstddjb/genwrite.html new file mode 100644 index 0000000..33ff4d3 --- /dev/null +++ b/doc/libstddjb/genwrite.html @@ -0,0 +1,98 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the genwrite library interface</title> + <meta name="Description" content="skalibs: the genwrite library interface" /> + <meta name="Keywords" content="skalibs c unix genwrite buffer stralloc write library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>genwrite</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/genwrite.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>genwrite</tt> is syntactic sugar to help write functions that might +want to write either to memory or to a file descriptor. +</p> + +<p> + Writing to memory is achieved via appending to a +<a href="stralloc.html">stralloc</a>; writing to a file descriptor is achieved +via appending to a <a href="buffer.html">buffer</a> or a +<a href="bufalloc.html">bufalloc</a>. +</p> + +<h2> Usage </h2> + +<p> + A <tt>genwrite_t</tt> structure contains a pointer to a function that writes +stuff to the target without flushing it +(which can be <tt>genwrite_put_stralloc</tt>, <tt>genwrite_put_buffer</tt>, +<tt>genwrite_put_bufalloc</tt> or any +compatible user-defined function) in <tt>.put</tt>, a pointer to a function +that flushes the target (which can be <tt>genwrite_flush_stralloc</tt>, +<tt>genwrite_flush_buffer</tt>, <tt>genwrite_flush_bufalloc</tt> or any +compatible user-defined function) in <tt>.flush</tt>, and a pointer to +the target writing structure in <tt>.target</tt>. +</p> + +<p> + Users should define a <tt>genwrite_t</tt> first, using the provided functions, +and give applications a pointer <tt>gp</tt> to this structure. To write <em>len</em> +characters at position <em>s</em> to the target, the application should then call +<code>(*gp->put)(gp->target, s, len)</code>. When it is done writing, the +application should call <code>(*gp->flush)(gp->target)</code> to flush the +output. +</p> + +<p> + <tt>genwrite_stdout</tt> and <tt>genwrite_stderr</tt> are predefined; they +write to <tt>buffer_1</tt> and <tt>buffer_2</tt> respectively. +</p> + +<h2> Macros </h2> + +<p> +<code> GENWRITE_STRALLOC_INIT(sa) </code> <br /> +Declares a <tt>genwrite_t</tt> writing to the stralloc *<em>sa</em>. +</p> + +<p> +<code> GENWRITE_BUFFER_INIT(b) </code> <br /> +Declares a <tt>genwrite_t</tt> writing to the buffer *<em>b</em>. Use +of such a buffer might interact badly with nonblocking I/O. +</p> + +<p> +<code> GENWRITE_BUFALLOC_INIT(ba) </code> <br /> +Declares a <tt>genwrite_t</tt> writing to the bufalloc *<em>ba</em>. +</p> + +<h2> Note </h2> + +<p> +Object-oriented programming in C is inefficient and cumbersome. It is +usually possible to avoid it in Unix system programming, because Unix +primitives are often generic enough. Unfortunately, it is not the case +here: Unix does not provide an abstraction representing either a file +or a memory buffer. So an object-oriented approach is unavoidable. +</p> + +</body> +</html> diff --git a/doc/libstddjb/index.html b/doc/libstddjb/index.html new file mode 100644 index 0000000..e0853cc --- /dev/null +++ b/doc/libstddjb/index.html @@ -0,0 +1,125 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the stddjb library interface</title> + <meta name="Description" content="skalibs: the stddjb library interface" /> + <meta name="Keywords" content="skalibs stddjb libstddjb library interface" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<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/">www.skarnet.org</a> +</p> + +<h1> The <tt>stddjb</tt> library interface </h1> + +<p> + <tt>libstddjb</tt> is the base, and the most important part, of skalibs. +It is a set of general-purpose C functions wrapping some +system calls, hiding some Unix portability problems, providing some +basic low-level buffering functions and string handling, and generally +offering a nice API to Unix programming - in many ways nicer and safer +than the "standard" Unix APIs like <tt>stdio.h</tt>. +</p> + +<p> + It is mostly based on some excellent code written and placed into the +public domain by <a href="../djblegacy.html">D. J. Bernstein</a>. +</p> + +<h2> Compiling </h2> + +<ul> + <li> The libstddjb functions are available under the <tt>skalibs/stddjb.h</tt> +header, which includes a lot of lower-level headers. If you know what +lower-level headers to use, you might speed up your compilation process by +including them directly. </li> +</ul> + +<h2> Programming </h2> + +<ul> + <li> <a href="alloc.html">skalibs/alloc.h</a>: basic heap memory allocation primitives </li> + <li> <a href="allreadwrite.html">skalibs/allreadwrite.h</a>: <a href="safewrappers.html">safe +wrappers</a> around I/O functions, extra I/O functions </li> + <li> <a href="bitarray.html">skalibs/bitarray.h</a>: how to handle large arrays of bits </li> + <li> <a href="bufalloc.html">skalibs/bufalloc.h</a>: bufferized output (with dynamically allocated buffers)</li> + <li> <a href="buffer.html">skalibs/buffer.h</a>: bufferized I/O (with statically allocated buffers) </li> + <li> <a href="bytestr.html">skalibs/bytestr.h</a>: basic operations on strings and byte arrays </li> + <li> <a href="cdb.html">skalibs/cdb.h</a>: how to read +<a href="http://en.wikipedia.org/wiki/Cdb_%28software%29">cdb</a> files </li> + <li> <a href="cdb_make.html">skalibs/cdb_make.h</a>: how to write +<a href="http://en.wikipedia.org/wiki/Cdb_%28software%29">cdb</a> files </li> + <li> <a href="direntry.html">skalibs/direntry.h</a>: portable directory operations </li> + <li> <a href="djbtime.html">skalibs/djbtime.h</a>: conversions between date and time formats </li> + <li> <a href="djbunix.html">skalibs/djbunix.h</a>: management of basic Unix concepts </li> + <li> <a href="envalloc.html">skalibs/envalloc.h</a>: management of dynamically allocated <em>argv</em> and <em>envp</em> </li> + <li> <a href="env.html">skalibs/env.h</a>: management of <em>argv</em> and <em>envp</em> </li> + <li> <a href="fmtscan.html">skalibs/fmtscan.h</a>: formatters (printers) and scanners (parsers) for basic C types </li> + <li> <a href="genalloc.html">skalibs/genalloc.h</a>: generic advanced management of dynamically allocated structures </li> + <li> <a href="genwrite.html">skalibs/genwrite.h</a>: interface to generic writes either to strallocs or to buffers </li> + <li> <a href="getpeereid.html">skalibs/getpeereid.h</a>: the <tt>getpeereid()</tt> system call </li> + <li> <a href="iopause.html">skalibs/iopause.h</a>: the skalibs event loop selection function </li> + <li> <a href="iobuffer.html">skalibs/iobuffer.h</a>: optimized data transfer from a fd to another </li> + <li> <a href="lolstdio.html">skalibs/lolstdio.h</a>: +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html">printf</a>-like +functions writing into <a href="buffer.html">buffers</a> or <a href="bufalloc.html">bufallocs</a> </li> + <li> <a href="mininetstring.html">skalibs/mininetstring.h</a>: a protocol to transmit variable-length messages (limited to 64kB) </li> + <li> <a href="netstring.html">skalibs/netstring.h</a>: a protocol to transmit variable-length messages (limited to 2^32 bytes) </li> + <li> <a href="segfault.html">skalibs/segfault.h</a>: voluntary error generation </li> + <li> <a href="selfpipe.html">skalibs/selfpipe.h</a>: automated selfpipe trick (i.e. +how to safely handle signals in event loops) </li> + <li> <a href="sgetopt.html">skalibs/sgetopt.h</a>: <tt>getopt()</tt>-style command-line options management </li> + <li> <a href="sig.html">skalibs/sig.h</a>: safe signal management </li> + <li> <a href="skamisc.html">skalibs/skamisc.h</a>: general string quoting and parsing; miscellaneous, unclassifiable functions </li> + <li> <a href="socket.html">skalibs/socket.h</a>: INET domain sockets </li> + <li> <a href="stralloc.html">skalibs/stralloc.h</a>: advanced management of dynamically allocated strings </li> + <li> <a href="strerr.html">skalibs/strerr.h</a>: basic error messages </li> + <li> <a href="strerr2.html">skalibs/strerr2.h</a>: advanced error messages </li> + <li> <a href="tai.html">skalibs/tai.h</a>: time, timers and system clock </li> + <li> <a href="webipc.html">skalibs/webipc.h</a>: UNIX domain sockets </li> +</ul> + +<p> + The following headers are automatically generated at compile-time, when the +<em>headers</em> subsystem is made. The <tt>skalibs/stddjb.h</tt> file also +includes them. +</p> + +<ul> + <li> skalibs/uint16.h: operations with 16-bit unsigned integers </li> + <li> skalibs/uint32.h: operations with 32-bit unsigned integers </li> + <li> skalibs/uint64.h: operations with 64-bit unsigned integers </li> + <li> skalibs/ushort.h: portable helpers for the "unsigned short" basic type </li> + <li> skalibs/uint.h: portable helpers for the "unsigned int" basic type </li> + <li> skalibs/ulong.h: portable helpers for the "unsigned long" basic type </li> + <li> skalibs/error.h: portable macros for errno management </li> + <li> skalibs/gidstuff.h: helpers for the "gid_t" type </li> + <li> skalibs/setgroups.h: stub for the setgroups() function, for systems that do not define it</li> + <li> <a href="ip46.html">skalibs/ip46.h</a>: IPv4/IPv6 abstraction layer </li> +</ul> + +<p> + Additionally, <tt>stddjb.h</tt> also includes the following headers, which +are not associated with any code and are mostly self-explanatory: +</p> + +<ul> + <li> <a href="gccattributes.html">skalibs/gccattributes.h</a>: wrappers around a few GCC-specific optimizations </li> + <li> skalibs/diuint.h: for associative arrays of unsigned integers </li> + <li> skalibs/diuint32.h: for associative arrays of 32-bit unsigned integers </li> + <li> skalibs/environ.h: declaration of the <em>environ</em> variable </li> + <li> skalibs/nsig.h: the number of system signals, for systems that do not define it </li> + <li> skalibs/nonposix.h: feature test macros for non-POSIX-compliant systems </li> + <li> skalibs/siovec.h: +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_uio.h.html">iovec</a>-like +structure for scatter/gather IO operations </li> +</ul> + +</body> +</html> diff --git a/doc/libstddjb/iopause.html b/doc/libstddjb/iopause.html new file mode 100644 index 0000000..72eedde --- /dev/null +++ b/doc/libstddjb/iopause.html @@ -0,0 +1,196 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the iopause library interface</title> + <meta name="Description" content="skalibs: the iopause library interface" /> + <meta name="Keywords" content="skalibs c unix iopause library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>iopause</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/iopause.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>iopause</tt> is the skalibs API for event loop selection. It's a +wrapper around the system's +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/poll.html">poll()</a> +(if available) or +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/select.html">select()</a> +(if <tt>poll()</tt> is unavailable) function. It +works around some system-dependent quirks; also it works with +<em>absolute dates</em> instead of timeouts. This is a good thing: +see below. +</p> + +<p> + <tt>iopause</tt> is a derived work from Dan J. Bernstein's +<a href="http://cr.yp.to/lib/iopause.html">iopause</a> library, but the +skalibs implementation is subtly different. +</p> + +<h2> Data structures </h2> + +<p> + An <tt>iopause_fd</tt> structure is similar to a +<a href="http://www.opengroup.org/onlinepubs/9699919799/basedefs/poll.h.html">struct pollfd</a> +structure, and must be filled the same way. Usually, the user declares +an array of <tt>iopause_fd</tt> and fills it, one element per descriptor +to select on. If <em>x</em> is an <tt>iopause_fd</tt>: +</p> + +<ul> + <li> <em>x</em>.fd must be set to the fd number to select on. </li> + <li> <em>x</em>.events must be a disjunction of the following flags: + <ul> + <li> IOPAUSE_READ if the fd is to be selected for reading. </li> + <li> IOPAUSE_WRITE if the fd is to be selected for writing. </li> + </ul> </li> + <li> When the selection function returns, <em>x</em>.revents contains +a disjunction of the following flags: + <ul> + <li> IOPAUSE_READ if the fd is readable (this include reception of an EOF). </li> + <li> IOPAUSE_WRITE if the fd is writable. </li> + <li> IOPAUSE_EXCEPT if an exception (such as EOF or an error) occurred on the fd. </li> + </ul> </li> +</ul> + +<p> + Unlike <tt>poll()</tt> or <tt>select()</tt>, which use a <em>timeout</em> +argument, the <tt>iopause()</tt> function uses a <em>deadline</em> argument, +i.e. an absolute time at which it must return 0 if no event has happened +so far, as well as a <em>stamp</em> argument, i.e. an absolute time meaning +<em>now</em>. Those arguments are stored in +<a href="tai.html">tain_t</a>s. Here is why: +</p> + +<p> + The event loop pattern is mostly used to multiplex several asynchronous +events that can happen independently, at the same time or not. Let's +say you have 3 events, <em>x</em>, <em>y</em> and <em>z</em>. Each of +those has a separate timeout: if <em>x</em> happens before <em>x-timeout</em> +milliseconds, you call the <em>x-event-handler</em> function, but +if <em>x-timeout</em> milliseconds elapse without <em>x</em> happening, +you call <em>x-timeout-handler</em> function. And similarly with <em>y</em> +and <em>z</em>. +</p> + +<p> + But the selection function returning does not mean <em>x</em> has happened +or that <em>x</em> has timed out. It might also mean that <em>y</em> has +happened, that <em>y</em> has timed out, that <em>z</em> has happened, that +<em>z</em> has timed out, or something else entirely. In the post-selection +part of the loop, the proper handler is called for the event or timeout +that has happened; then the loop is executed again, and in the +pre-selection part of the loop, the array describing the events is filled, +and the selection timeout is computed. +</p> + +<p> + How are you going to compute that global selection timeout? Easy: it's the +shortest of the three. But we just spent some amount of time waiting, so the +individual timeouts must be recomputed! This means: +<ul> + <li> You need a way to know the time spent in a selection primitive, which +basically means getting a timestamp before the selection and once again +after the timestamp. </li> + <li> You need to recompute every individual timeout everytime you enter +the loop. </li> +</ul> + +<p> + That is really cumbersome. A much simpler way of doing things is: +</p> + +<ul> + <li> Always keep a reasonably accurate estimation of the current +time in a <em>stamp</em> variable. That means getting the current time +at the start of the process, and updating it <em>right after</em> any +action that takes a significant amount of time. When to update <em>stamp</em> +can be difficult to estimate in CPU-bound processes; fortunately, most +processes using an event loop are IO-bound, and the only actions that take +a non-negligible amount of time in an IO-bound process are the blocking +primitives. So, <em>stamp</em> must be updated <em>right after a selection +function returns</em>, and if the program has been correctly written and +cannot block anywhere else, it's the only place where it needs to be. </li> + <li> For every event, compute the <em>deadline</em> of that event: +<em>x-deadline</em> is <em>x-timeout</em> added to the current <em>stamp</em> +value when <em>x</em> enters the loop. This is done only once per event: +you never have to recompute event deadlines - unlike timeouts, which diminish +over time, deadlines do not change. </li> + <li> At every iteration, the selection deadline is the earliest of all the +available event deadlines. </li> + <li> As an added bonus: after the selection function returns and + <em>stamp</em> has been updated, it is easy to check which events have +timed out and which have not: <em>x</em> has timed out iff <em>x-deadline</em> +is earlier than <em>stamp</em>. </li> +</ul> + +<p> + Maintaining a global timestamp and using absolute times instead of relative +times really is the right way to work with event loops, and the <tt>iopause</tt> +interface reflects that. Of course, you need a reliable, bug-free time library +and a monotonic, constant system clock to handle absolute times correctly; +that is why <tt>iopause</tt> relies on the <a href="tai.html">tai</a> library. +</p> + +<h2> Functions </h2> + +<p> +<code> int iopause (iopause_fd *x, unsigned int len, tain_t const *deadline, tain_t const *stamp) </code> <br /> +Blocks until one of the events described in the <em>x</em> array, of length +<em>len</em>, happens, or until the absolute date *<em>deadline</em> is +reached. <em>deadline</em> may be null, in which case the function blocks +indefinitely until an event happens. If <em>deadline</em> is not null, then +<em>stamp</em> must not be null, and must contain an accurate estimation +of the current time. The function returns the number of events that have +happened, 0 for a timeout, or -1 (and sets errno) for an error. +</p> + +<p> +<code> int iopause_stamp (iopause_fd *x, unsigned int len, tain_t const *deadline, tain_t *stamp) </code> <br /> +Like <tt>iopause()</tt>, but if <em>stamp</em> is not null, it is updated +right before the function returns. This helps the user always keep a +reasonably accurate estimation of the current time in <em>stamp</em>; +it is recommended to use this function instead of the lower-level +<tt>iopause()</tt>. +</p> + +<h3> Underlying implementations </h3> + +<p> + <tt>iopause</tt> is an alias to either <tt>iopause_poll</tt> or +or <tt>iopause_select</tt>. By default, it is aliased to <tt>iopause_poll</tt>; to +alias it to <tt>iopause_select</tt> instead, configure skalibs with the +<tt>--enable-iopause-select</tt> option. +</p> + +<p> +Both <tt>iopause_poll</tt> and <tt>iopause_select</tt> are implemented on top of the +<a href="http://man7.org/linux/man-pages/man2/ppoll.2.html">ppoll()</a> system call +if it is available; but if it is not, then <tt>iopause_poll</tt> defaults to +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">poll()</a>, +which has a more comfortable API than +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html">select()</a>, +but a maximum precision of 1 millisecond which might not be enough for some applications; whereas +<tt>iopause_select<tt> defaults to select(), which incurs some CPU overhead for the +API conversion, but has a 1 microsecond precision. +</p> + +</body> +</html> diff --git a/doc/libstddjb/ip46.html b/doc/libstddjb/ip46.html new file mode 100644 index 0000000..ee2f31c --- /dev/null +++ b/doc/libstddjb/ip46.html @@ -0,0 +1,172 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the ip46 library interface</title> + <meta name="Description" content="skalibs: the ip46 library interface" /> + <meta name="Keywords" content="skalibs c unix ip46 library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>ip46</tt> library interface </h1> + +<p> + The following functions and structures are declared in the <tt>skalibs/ip46.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>ip46</tt> is a set of macros and functions to support both IPv4 +and IPv6 network operations in an abstracted way. +</p> + +<p> + If skalibs has been built with the <a href="../flags.html#noipv6">--disable-ipv6</a> +configure option, or it detects at build time than the target does not support IPv6, then +<tt>ip46</tt> structures and functions will be directly aliased to their +IPv4 implementations with no overhead at all. +</p> + +<h2> Data structures </h2> + +<p> + An <tt>ip46full_t</tt> is a structure that contains either an IPv4 or an IPv6 +address. + If <em>a</em> is an <tt>ip46full_t</tt>, then: +</p> + +<ul> + <li> ip46_is6(&<em>a</em>) is 1 if <em>a</em> is +IPv6 and 0 otherwise. </li> + <li> <em>a</em>.ip points to 16 (if IPv6) or 4 (if IPv4) bytes containing +the address, in network byte order. </li> +</ul> + +<p> + If skalibs has been build with IPv6 support, an <tt>ip46_t</tt> is +the same type as an <tt>ip46full_t</tt>. Otherwise, an <tt>ip46_t</tt> +is a structure that just contains an IPv4 address. +</p> + +<h2> Functions </h2> + +<p> +<code> int ip46_from_ip4 (ip46_t *a, char const *ip) </code> <br /> +Stores the IPv4 pointed to by <em>ip</em> into *<em>a</em>. Returns 1. +</p> + +<p> +<code> int ip46_from_ip6 (ip46_t *a, char const *ip) </code> <br /> +Stores the IPv6 pointed to by <em>ip</em> into *<em>a</em>. Returns 1, +except if IPv6 is unavailable, in which case it returns 0 ENOSYS. +</p> + +<p> +<code> unsigned int ip46_fmt (char *s, ip46_t const *a) </code> <br /> +Formats the address in *<em>a</em> into the string <em>s</em>, which +must be preallocated. Returns the number of bytes written. The address +will be accordingly formatted as IPv4 or IPv6. +</p> + +<p> +<code> unsigned int ip46_scan (char const *s, ip46_t *a) </code> <br /> +Scans the string <em>s</em> for an IPv4 or IPv6 address. If it finds +one, writes it into *<em>a</em> and returns the number of bytes read. +If it cannot, returns 0. +</p> + +<p> +<code> unsigned int ip46_scanlist (ip46_t *list, unsigned int max, char const *s, unsigned int *n) </code> <br /> +Scans the string <em>s</em> for a list of comma-, semicolon-, space-, tab- or +newline-separated IPv4 or IPv6 addresses, up to a maximum of <em>max</em>. It +stores them into the (preallocated) ip46_t array pointed to by <em>list</em>. +It returns the number of bytes read (0 if <em>s</em> does not contain a valid +IP list at all), and stores the number of found and scanned addresses into *<em>n</em>. +</p> + +<p> +<code> int socket_connect46 (int fd, ip46_t *a, uint16 port) </code> <br /> +Connects the socket <em>fd</em> to address *<em>a</em> and port <em>port</em>. +Returns 0 in case of success, and -1 (and sets errno) in case of failure. +</p> + +<p> +<code> int socket_bind46 (int fd, ip46_t *a, uint16 port) </code> <br /> +Binds the socket <em>fd</em> to address *<em>a</em> and port <em>port</em>. +Returns 0 in case of success, and -1 (and sets errno) in case of failure. +</p> + +<p> +<code> int socket_bind46_reuse (int fd, ip46_t *a, uint16 port) </code> <br /> +Same as the previous function, with the SO_REUSEADDR option. +</p> + +<p> +<code> int socket_deadlineconnstamp46 (int fd, ip46_t const *a, uint16 port, tain_t const *deadline, tain_t *stamp) </code> <br /> +Attempts to synchronously connect the socket <em>fd</em> to address a<em>a</em> +and port <em>port</em>. Returns 1 if it succeeds and 0 (and sets errno) +if it fails. <em>stamp</em> must contain an accurate enough +timestamp, and is updated when the function returns. If the connection is +still pending by <em>deadline</em>, then the attempt stops and the function +returns 0 ETIMEDOUT. +</p> + +<p> +<code> int socket_recv46 (int fd, char *s, unsigned int len, ip46_t *a, uint16 *port) </code> <br /> +Reads a datagram from socket <em>fd</em>. The message is stored into buffer <em>s</em> +of max length <em>len</em>, and stores the sender information into address *<em>a</em> +and port *<em>port</em>. Returns the length of the read datagram, or -1 if it fails. +</p> + +<p> +<code> int socket_send46 (int fd, char const *s, unsigned int len, ip46_t const *a, uint16 port) </code> <br /> +Writes a datagram to socket <em>fd</em>. The message is read from buffer <em>s</em> +of length <em>len</em>, and the recipient information is address *<em>a</em> +and port <em>port</em>. Returns the number of written bytes, or -1 if it fails. +</p> + +<p> +<code> int socket_local46 (int fd, ip46_t *a, uint16 *port) </code> <br /> +Gets the local information about bound socket <em>fd</em>: the local IP +address is stored into *<em>a</em> and the local port into *<em>port</em>. +Returns 0 in case of success, and -1 (and sets errno) in case of failure. +</p> + +<p> +<code> int socket_remote46 (int fd, ip46_t *a, uint16 *port) </code> <br /> +Gets the peer information about connected socket <em>fd</em>: the remote IP +address is stored into *<em>a</em> and the remote port into *<em>port</em>. +Returns 0 in case of success, and -1 (and sets errno) in case of failure. +</p> + +<p> +<code> int socket_recvnb46 (int fd, char *s, unsigned int len, ip46_t *a, uint16 *port, +tain_t const *deadline, tain_t *stamp) </code> <br /> +Like <tt>socket_recv46</tt>, except that the function blocks until a datagram +is received. *<em>stamp</em> must be an accurate enough approximation of the +current time, and is updated when the function returns. If no datagram has +arrived by absolute date *<em>deadline</em>, the function returns -1 ETIMEOUT. +</p> + +<p> +<code> int socket_sendnb46 (int fd, char const *s, unsigned int len, ip46_t const *a, uint16 port, +tain_t const *deadline, tain_t *stamp) </code> <br /> +Like <tt>socket_send46</tt>, except that the function blocks until a datagram +has been effectively sent. *<em>stamp</em> must be an accurate enough approximation of the +current time, and is updated when the function returns. If the message still has +not been sent by absolute date *<em>deadline</em>, the function returns -1 ETIMEOUT. +</p> + +</body> +</html> diff --git a/doc/libstddjb/lolstdio.html b/doc/libstddjb/lolstdio.html new file mode 100644 index 0000000..e059f24 --- /dev/null +++ b/doc/libstddjb/lolstdio.html @@ -0,0 +1,91 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the lolstdio library interface</title> + <meta name="Description" content="skalibs: the lolstdio library interface" /> + <meta name="Keywords" content="skalibs c unix stdio lol printf fprintf library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>lolstdio</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/lolstdio.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>lolstdio</tt> is a set of convenience functions providing +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html">printf</a>-style +formatting but interacting with <a href="buffer.html">buffers</a> or +<a href="bufalloc.html">bufallocs</a> instead of stdio FILEs. +</p> + +<p> + Like any printf-style functions, the lolstdio functions are rather +complex and inefficient, and not recommended for general use; they are +provided as a quick and dirty way to debug or test things. Programmers +are advised to use the <a href="fmtscan.html">type-specific formatting +functions</a> instead in production-quality code. +</p> + +<p> + Be aware that functions writing into buffers interact badly with +non-blocking fds (and asynchronism in general) - just as you cannot +use FILEs with non-blocking output. Functions writing into bufallocs, +however, are fine, because bufallocs are much more suited to asynchronous +writing than fixed-size buffers or FILEs are. +</p> + +<p> + The current lolstdio implementation relies on the libc's +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/vsnprintf.html">vsnprintf</a> +function. +</p> + +<h2> Functions </h2> + +<p> +<code> int vbprintf (buffer *b, char const *format, va_list args) </code> <br /> +Like <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/vfprintf.html">vfprintf</a> +except that the result is written to the buffer <em>b</em>. +</p> + +<p> +<code> int bprintf (buffer *b, char const *format, ...) </code> <br /> +Like <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html">fprintf</a> +except that the result is written to the buffer <em>b</em>. +</p> + +<p> +<code> int lolprintf (char const *format, ...) </code> <br /> +Like <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html">printf</a> +except that the result is written to the buffer <tt>buffer_1</tt>. +</p> + +<p> +<code> int vbaprintf (bufalloc *ba, char const *format, va_list args) </code> <br /> +Like <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/vfprintf.html">vfprintf</a> +except that the result is written to the bufalloc <em>ba</em>. +</p> + +<p> +<code> int baprintf (bufalloc *ba, char const *format, ...) </code> <br /> +Like <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html">fprintf</a> +except that the result is written to the bufalloc <em>ba</em>. +</p> + +</body> +</html> diff --git a/doc/libstddjb/safewrappers.html b/doc/libstddjb/safewrappers.html new file mode 100644 index 0000000..6d889d6 --- /dev/null +++ b/doc/libstddjb/safewrappers.html @@ -0,0 +1,91 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: safe wrappers</title> + <meta name="Description" content="skalibs: safe wrappers" /> + <meta name="Keywords" content="skalibs c unix safe wrappers safewrappers library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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> Safe wrappers </h1> + +<p> + Lots of functions in <tt>libstddjb</tt>, declared for instance in +<a href="allreadwrite.html">allreadwrite.h</a> or +<a href="djbunix.html">djbunix.h</a>, are just "safe wrappers" +around corresponding system functions. For instance, +<tt>fd_read()</tt> is a safe wrapper around the system <tt>read()</tt> +function. +</p> + +<h2> The problem </h2> + +<p> + Quite a lot of system calls are defined by +<a href="http://www.opengroup.org/onlinepubs/9699919799/nfindex.html">The +Open Group Base Specifications</a> as interruptible: when the process is in +the middle of such a system call and receives a signal that it does not +ignore, the system call immediately returns -1 EINTR (after the signal +handler, if any, has been executed). +</p> + +<p> + This means that the intended execution of the process is at the mercy +of a stray signal. If a signal happens at the wrong time, a system call +fails when it could have succeeded. This is not acceptable. +</p> + +<h2> The solution </h2> + +<p> + So, in order to be perfectly reliable, when a program makes an interruptible +system call, it <em>must</em> check whether the return value is -1 EINTR, +and restart the system call if it is the case. This is annoying to write; +so, <tt>libstddjb</tt> provides small wrappers around interruptible system +calls, so that programmers can just call those <em>safe wrappers</em> and +never bother with this again. +</p> + +<p> + The performance loss from having a wrapper layer is totally negligible +compared to the cost of using a system call in the first place. +</p> + +<h2> But isn't it what the SA_RESTART flag is meant to address? </h2> + +<p> + Yes, it is. Unfortunately, SA_RESTART only protects interruptible +system calls from signals you actually have control over, and set a +handler for with +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/sigaction.html">sigaction()</a>. +This is not enough. You cannot decide that <em>every</em> signal sent +to your process should have SA_RESTART behaviour; and the Single Unix +specification says nothing about signals you do not control. For instance, +you cannot trap SIGSTOP; SIGSTOP does not kill your process, which +should resume flawlessly at the next SIGCONT; and according to the +specification, it is valid for SIGSTOP and SIGCONT to <em>not</em> +have SA_RESTART behaviour. So if you get a SIGSTOP while performing +an interruptible system call, that system call may return -1 EINTR, +this is not an OS bug, and there's nothing you can do about it with +<tt>sigaction()</tt>. +</p> + +<p> + SA_RESTART is only a partial solution: in other words, it doesn't work. +Until the Single Unix specification explicitly states that untrapped +non-lethal signals MUST have SA_RESTART behaviour by default, you +<em>need</em> safe wrappers to protect interruptible system calls. +</p> + +</body> +</html> diff --git a/doc/libstddjb/selfpipe.html b/doc/libstddjb/selfpipe.html new file mode 100644 index 0000000..7eff430 --- /dev/null +++ b/doc/libstddjb/selfpipe.html @@ -0,0 +1,242 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the selfpipe library interface</title> + <meta name="Description" content="skalibs: the selfpipe library interface" /> + <meta name="Keywords" content="skalibs stddjb libstddjb selfpipe self-pipe library interface" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">libstddjb</a><br /> +<a href="../libskarnet.html">skalibs</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>selfpipe</tt> library interface </h1> + +<p> + The selfpipe functions are declared in the +<tt>skalibs/selfpipe.h</tt> header and implemented in the <tt>libskarnet.a</tt> +or <tt>libskarnet.so</tt> library. +</p> + +<h2> What does it do ? </h2> + +<p> +Signal handlers suck. +</p> + +<p> +They do. I don't care how experienced you are with C/Unix programming, +they do. You can be Ken Thompson, if you use signal handlers as a +regular part of your C programming model, you <em>are</em> going to +screw up, and write buggy code. +</p> + +<p> + Unix is tricky enough with interruptions. Most of libstddjb's wrappers +are there to protect system calls from EINTR. (And no, the SA_RESTART +option in sigaction() <a href="safewrappers.html">isn't protection +enough</a>.) But signal handlers are +more than just pesky interruptions: they can totally change the +execution flow. They mess up the logic of linear and structured code, +they introduce non-determinism; you always have to think "and what +if I get interrupted here and the flow goes into a handler...". This +is annoying. +</p> + +<p> + Moreover, signal handler code is <em>very</em> limited in what it can +do. It can't use any non-reentrant function! If you call a non-reentrant +function, and by chance you were precisely in that non-reentrant function +code when you got interrupted by a signal... you lose. That means, no +malloc(). No bufferized IO. No globals. The list goes on and on. <br /> + If you're going to catch signals, you'll want to handle them <em>outside</em> +the signal handler. You actually want to spend <em>the least possible +time</em> inside a signal handler - just enough to notify your main +execution flow that there's a signal to take care of. +</p> + +<p> + And, of course, signal handlers don't mix with event loops, which is +a classic source of headaches for programmers and led to the birth of +abominations such as +<a href="http://www.opengroup.org/onlinepubs/009695399/functions/pselect.html"> +pselect</a>. So much for the "everything is a file" concept that Unix was +built on. +</p> + +<p> + A signal should be an event like any other. +There should be a unified interface - receiving a signal should make some +fd readable or something. +</p> + +<p> + And that's exactly what the +<a href="http://cr.yp.to/docs/selfpipe.html">self-pipe trick</a>, invented +by <a href="../djblegacy.html">DJB</a>, does. +</p> + +<p> + As long as you're in some kind of event loop, the self-pipe trick allows +you to forget about signal handlers... <em>forever</em>. It works this way: +</p> + +<ol> + <li> Create a pipe <tt>p</tt>. Make both ends close-on-exec and nonblocking. </li> + <li> Write a tiny signal handler ("top half") for all the signals you want to +catch. This +signal handler should just write one byte into <tt>p[1]</tt>, and do nothing +more; ideally, the written byte identifies the signal. </li> + <li> In your event loop, add <tt>p[0]</tt> to the list of fds you're watching +for readability. </li> +</ol> + +<p> + When you get a signal, a byte will be written to the self-pipe, and your +execution flow will resume. When you next go through the event loop, +<tt>p[0]</tt> will be readable; you'll then be able to read a byte from +it, identify the signal, and handle it - in your unrestricted main +environment (the "bottom half" of the handler). +</p> + +<p> + The selfpipe library does it all for you - you don't even have to write +the top half yourself. You can forget their existence and recover +some peace of mind. Of course, you <em>still</em> need to protect your +system calls against EINTR: the self-pipe trick doesn't prevent signals +from happening. +</p> + +<h2> How do I use it ? </h2> + +<h3> Starting </h3> + +<pre> +int fd = selfpipe_init() ; +</pre> + +<p> +<tt>selfpipe_init()</tt> sets up a selfpipe. You must use that +function first. <br /> +If <tt>fd</tt> is -1, then an error occurred. Else <tt>fd</tt> is a +non-blocking descriptor that can be used in your event loop. It will +be selected for readability when you've caught a signal. +</p> + +<h3> Trapping/untrapping signals </h3> + +<pre> +int r = selfpipe_trap(SIGTERM) ; +</pre> + +<p> +<tt>selfpipe_trap()</tt> catches a signal and sends it to the selfpipe. +Uncaught signals won't trigger the selfpipe. <tt>r</tt> is 0 if +the operation succeeded, and -1 if it failed. If it succeeded, you +can forget about the trapped signal entirely. <br /> +In our example, if <tt>r</tt> is 0, then a SIGTERM will instantly +trigger readability on <tt>fd</tt>. +</p> + +<pre> +int r = selfpipe_untrap(SIGTERM) ; +</pre> + +<p> +Conversely, <tt>selfpipe_untrap()</tt> uncatches a signal; the selfpipe +will not manage it anymore. <tt>r</tt> is 0 if the operation succeeded +and -1 if it failed. +</p> + +<pre> +int r ; +sigset_t set ; +sigemptyset(&set) ; +sigaddset(&set, SIGTERM) ; +sigaddset(&set, SIGHUP) ; +r = selfpipe_trapset(&set) ; +</pre> + +<p> +<tt>selfpipe_trap()</tt> and <tt>selfpipe_untrap()</tt> handle signals one +by one. Alternatively (and often preferrably), you can use +<tt>selfpipe_trapset()</tt> to directly handle signal sets. When you call +<tt>selfpipe_trapset()</tt>, signals that are present in <tt>set</tt> will +be caught by the selfpipe, and signals that are absent from <tt>set</tt> +will be uncaught. <tt>r</tt> is 0 if the operation succeeded and -1 if it +failed. +</p> + +<h3> Handling events </h3> + +<pre> +int c = selfpipe_read() ; +</pre> + +<p> + Call <tt>selfpipe_read()</tt> when your <tt>fd</tt> is readable. +That's where you write your <em>real</em> signal handler: in the +body of your event loop, in a "normal" context. <br /> +<tt>c</tt> is -1 if an error occurred - in which case chances are +it's a serious one and your system has become very unstable. +<tt>c</tt> is 0 if there are no more pending signals. If <tt>c</tt> +is positive, it is the number of the signal that was caught. +</p> + +<h3> Finishing </h3> + +<pre> +selfpipe_finish() ; +</pre> + +<p> + Call <tt>selfpipe_finish()</tt> when you're done using the selfpipe. +Signal handlers will be restored to their previous value. +</p> + +<h2> Any limitations ? </h2> + +<p> + Some, as always. +</p> + +<ul> + <li> The selfpipe library uses a global pipe; +so, it's not safe for multithreading. I'm not sure how multithreaded +programs handle signals; I personally don't like multithreading and +never use it, so I'm not knowledgeable about it. Anyway, if your +program is multithreaded, chances are you don't have an asynchronous +event loop, so the self-pipe trick has less benefits for you. </li> + <li> In rare cases, the self-pipe can theoretically be filled, if some +application sends more than PIPE_BUF signals before you have time to +<tt>selfpipe_read()</tt>. On most Unix systems, PIPE_BUF is 4096, +so it's a very acceptable margin. Unless your code is waiting where +it should not be, only malicious applications will fill the self-pipe +- and malicious applications could just send you a SIGKILL and be done +with you, so this is not a concern. Protect yourself from malicious +applications with clever use of uids. </li> +</ul> + +<h2> Hey, Linux has <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/signalfd.2.html">signalfd()</a> for this ! </h2> + +<p> + Yes, the Linux team loves to gratuitously add new system calls to do +things that could already be done before without much effort. This +adds API complexity, which is not a sign of good engineering. +</p> + +<p> + However, now that <tt>signalfd()</tt> exists, it is indeed marginally more +efficient than a pipe, and it saves one fd: so the selfpipe library +is implemented via <tt>signalfd()</tt> when this call is available. +</p> + +</body> +</html> diff --git a/doc/libstddjb/stralloc.html b/doc/libstddjb/stralloc.html new file mode 100644 index 0000000..a5a1c7e --- /dev/null +++ b/doc/libstddjb/stralloc.html @@ -0,0 +1,118 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the stralloc library interface</title> + <meta name="Description" content="skalibs: the stralloc library interface" /> + <meta name="Keywords" content="skalibs c unix stralloc library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>stralloc</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/stralloc.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>stralloc</tt> is the preferred skalibs way of storing objects into +heap memory. It focuses on strings of <em>char</em>, which is the generic +way to handle any object. For easy structure manipulation, the +<a href="genalloc.html">genalloc</a> +series of functions can be used; those functions are mostly macros wrapping +calls to their stralloc counterparts. +</p> + +<p> + A stralloc is a structure containing the following fields: +</p> + +<ul> + <li> <em>s</em>: a pointer to a zone of heap memory. The stralloc +functions internally manipulate those via the +<a href="alloc.html">alloc</a> series of functions. It is recommended +to never modify that field manually. </li> + <li> <em>len</em>: the <strong>used</strong> length of the +allocated zone. It is the only field that the user can modify +directly. </li> + <li> <em>a</em>: the number of allocated bytes. The user should never +have to access that field, because the memory allocation management +should be entirely transparent. <em>len</em> cannot exceed <em>a</em>: +if an operation needs a bigger <em>len</em>, it will automatically +reallocate as needed. </li> +</ul> + +<p> + The benefits of using stralloc are as follows: +</p> + +<ul> + <li> Memory allocation is performed on-demand and automatically, with +a suitable size. Heuristics are used to accommodate constantly growing +strings while minimizing the amount of needed reallocations. </li> + <li> If every heap-allocated object is represented by a stralloc, then +it is very easy to identify what pointer is in the heap. When you stop +using a pointer <em>p</em>, should you free it ? Sometimes it's not +easy to find out. When you stop using a stralloc <em>sa</em>, you +<em>know</em> you must call <tt>stralloc_free(&sa)</tt>. Store +your strong references as strallocs and weak references as simple +pointers, and never free simple pointers. This policy allows me to +boast that <em>no skarnet.org software has ever leaked memory</em>. </li> + <li> Repeated for emphasis: +<strong> the golden rule for programming with strallocs is +<em>every pointer to the heap must be owned by a stralloc</em>. </strong> +Every pointer you handle yourself either does not point to the heap, +or is weak. That sometimes implies unusual programming practices, such +as having storage separated from structure, but it's hands down the +easiest way to keep control of your heap in complex situations. </li> +<li> The indirection layer makes weak references immune to +reallocation troubles. The <em>s</em> field may change when a +reallocation happens, but the stralloc structure's address never +changes. </li> +</ul> + +<p> + A stralloc can be declared anywhere: static/global data, stack or heap. (Of course, +as a general rule, you should favor the stack whenever possible.) +A stralloc should be initialized to STRALLOC_ZERO before its first use. +</p> + +<h2> Functions </h2> + +<p> +<code> int stralloc_catb (stralloc *sa, char const *s, unsigned int len) </code> <br /> +Appends the <em>len</em> bytes pointed to by <em>s</em> to the end of the +memory zone handled by *<em>sa</em>, automatically allocating more memory +if needed. Returns 1 if it succeeds, and 0 if it fails. +</p> + +<p> +<code> void stralloc_free (stralloc *sa) </code> <br /> +Frees <em>*sa</em>, i.e. calls <a href="alloc.html">alloc_free</a> +on <em>sa</em>→s then zeroes the structure. *<em>sa</em> is +then reusable. However, it is not good practice to call this function +if you're going to reuse *<em>sa</em> soon: it takes time and causes +memory fragmentation. Just setting <em>sa</em>→len to 0 allows +you to instantly reuse the allocated block of memory. +</p> + +<p> + The above are the most important and fundamental functions of +<tt>skalibs/stralloc.h</tt>. Other functions can be found in this header and +their prototypes are self-explaining. +</p> + +</body> +</html> diff --git a/doc/libstddjb/tai.html b/doc/libstddjb/tai.html new file mode 100644 index 0000000..3524c05 --- /dev/null +++ b/doc/libstddjb/tai.html @@ -0,0 +1,462 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>skalibs: the tai library interface</title> + <meta name="Description" content="skalibs: the tai library interface" /> + <meta name="Keywords" content="skalibs c unix tai library libstddjb" /> + <!-- <link rel="stylesheet" type="text/css" href="http://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>tai</tt> library interface </h1> + +<p> + The following functions are declared in the <tt>skalibs/tai.h</tt> header, +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> General information </h2> + +<p> + <tt>tai</tt> is a set of data structures and primitives to represent +and perform operations on time. +</p> + +<p> + The point of <tt>tai</tt> is to handle time without ever having to +deal with annoyances such as Y2K, Y2038, NTP limits, non-linear +clocks, and the like. By using the <tt>tai</tt> interface, you ensure +your program will behave properly no matter what. +</p> + +<h3> What is the problem ? </h3> + +<p> + The standard APIs for time management under Unix are broken in more +or less subtle ways. The most obvious thing is that they do not pass +year 2038. A less obvious problem is that they do not handle leap +seconds correctly. Here are a few references you should read to +understand what is going on: +</p> + +<ul> + <li> <a href="http://www.madore.org/~david/misc/time.html">David Madore's page +on time</a>. It's outdated (there was a leap second in 2009), but complete. </li> + <li> From David Madore again, more to the point: a +<a href="http://www.madore.org/~david/computers/unix-leap-seconds.html">page +about leap seconds, UTC and TAI</a>. </li> + <li> The skalibs <a href="../flags.html#clockistai">--enable-tai-clock</a> +and <a href="../flags.html#tzisright">--enable-right-tz</a> documentation. </li> + <li> <a href="http://cr.yp.to/proto/utctai.html">Dan J. Bernstein's page +on UTC, TAI and Unix time</a>. </li> +</ul> + +<p> + The meat and potatoes of all this is that programmers cannot simply rely on +standard Unix APIs such as +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/gettimeofday.html">gettimeofday()</a> +(which, by the way, is marked as obsolescent, but it's not going to disappear tomorrow) +to measure time intervals or even to give precise absolute time, and in +any case those APIs will become obsolete in 2038. +</p> + +<h3> So what does <tt>tai</tt> do ? </h3> + +<p> + <tt>tai</tt> implements - among other things - the +<a href="http://cr.yp.to/libtai/tai64.html">TAI64 and TAI64N</a> +formats, which are used in all of skalibs. This gives a programmer access +to precise <em>linear absolute time</em>, which is suitable for both +timestamping (<em>wallclock</em> usage) and time interval measurements +(<em>stopwatch</em> usage). Additionally, TAI64 passes Y2038 (it can +represent dates exceeding the estimated lifespan of the universe). +</p> + +<p> + <tt>tai</tt> has been inspired by Dan J. Bernstein's +<a href="http://cr.yp.to/libtai.html">libtai</a> library, but does not +borrow any code from it. +</p> + +<h2> Data structures </h2> + +<p> + A <tt>tai_t</tt> structure holds an absolute date with a one-second +precision. A <tt>tain_t</tt> structure holds an absolute date with a +maximum of one-nanosecond precision, as permitted by the underlying system +call. If <a href="../flags.html#usert">flag-usert</a> is clear, the system +clock will be read via +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/gettimeofday.html">gettimeofday()</a> +system call, which has a one-microsecond precision; if it is set, the +system clock will be read via the +<a href="http://www.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html">clock_gettime()</a> +system call, which has a one-nanosecond precision. In either case, a current +<tt>tain_t</tt> will be unable to be more precise than the underlying +implementation. +</p> + +<p> + A <tt>tai_t</tt>, as well as a <tt>tain_t</tt>, can also +hold a (possibly negative) relative time, i.e. a difference of absolute +dates. It is up to the programmer to make sure that a relative time is +never interpreted as an absolute TAI64 date, and vice-versa. +</p> + +<h3> The leap second table </h3> + +<p> + skalibs provides a <tt>src/etc/leapsecs.dat</tt> file, +which is copied to <tt>/etc/leapsecs.dat</tt> at installation time +(or wherever you specified with the <tt>--prefix</tt> or <tt>--datadir</tt> +options to configure). +<strong>Make sure this file is always present and readable.</strong> +This file contains the <em>leap second table</em>, which is needed for +conversions between TAI and UTC. If you call a function that needs such +a conversion (for instance, you call <tt>tain_sysclock()</tt> and your +system clock is set to UTC) and the file cannot be read, the function +call will fail. +</p> + +<p> + The leap second table is read once in every process that needs it +(the first time a TAI ↔ UTC conversion is made) and then is +stored in memory. If the <tt>leapsecs.dat</tt> file changes, long-lived +processes will need to be restarted to take the change into account. +</p> + +<h2> Functions </h2> + +<h3> Wallclock operations </h3> + +<p> +<code> int tai_now (tai_t *t) </code> <br /> +Writes the current time as a TAI value to *<em>t</em>, with a +1-second precision. The current time is based on the system clock. +Make sure skalibs has been compiled with or without the +<a href="../flags.html#clockistai">--enable-tai-clock</a> configure option according +to your system clock synchronization method: skalibs supports a +system clock set to TAI-10 or to UTC. +The function returns 1 if it succeeds, or 0 (and sets errno) if +it fails. +</p> + +<p> +<code> int sysclock_get (tain_t *a) </code> <br /> +Reads the current value of the system clock into *<em>a</em>, with +a 1-nanosecond (resp. 1-microsecond ) precision if skalibs has been +configured with (resp. without) the +<a href="../flags.html#usert">--enable-clock</a> option. +Returns 1 if it succeeds or 0 (and sets errno) if it +fails. Note that despite being a <tt>tain_t</tt>, *<em>a</em> +<strong>does not contain a TAI value</strong> - it only contains +an internal, Y2038-safe representation of the value of the system +clock, which should be either TAI-10 or UTC. You should not use +this function directly unless you know exactly what you are doing. +</p> + +<p> +<code> int sysclock_set (tain_t const *a) </code> <br /> +Sets the system clock to *<em>a</em>, provided *<em>a</em> has +the correct internal representation. You should not use this +function directly unless you know exactly what you are doing. +</p> + +<p> +<code> int tain_sysclock (tain_t *a) </code> <br /> +Reads the current time into *<em>a</em>, as a TAI64N value, +with a 1-nanosecond (resp. 1-microsecond) precision if skalibs +has been configured with (resp. without) the +<a href="../flags.html#usert">--enable-clock</a> +option. Returns 1 if it succeeds or 0 (and sets errno) if it +fails. + Here <em>a</em> contains a valid TAI stamp, no matter what the +system clock is set to: arithmetic operations can be performed +on it. +</p> + +<p> +<code> int tain_setnow (tain_t const *a) </code> <br /> +Sets the current time to *<em>a</em>, with a 1-nanosecond +(resp. 1-microsecond) precision if skalibs has been configured +with (resp. without) the +<a href="../flags.html#usert">--enable-clock</a> +option. Returns 1 if it succeeds or 0 (and sets errno) if it +fails. <em>a</em> must contain a valid TAI stamp; proper +operations will be automatically run to convert that stamp into +the right format for the system clock. +</p> + +<h3> Stopwatch operations </h3> + +<p> + The following 3 operations are only defined if your system +provides the +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html">clock_gettime()</a> +primitive with the CLOCK_MONOTONIC option. +</p> + +<p> +<code> int tain_clockmon_init (tain_t *offset) </code> <br /> +Initializes a stopwatch in *<em>offset</em>. The actual value of +*<em>offset</em> is meaningless to the user; <em>offset</em>'s only +use is to be given as a second parameter to <tt>tain_clockmon()</tt>. +The function returns 1 if it succeeds or 0 (and sets errno) if it fails. +</p> + +<p> + What <tt>tain_clockmon_init()</tt> does is synchronize the "stopwatch +clock" (CLOCK_MONOTONIC) to the system clock. Right after +<tt>tain_clockmon_init()</tt> has been called, the absolute times given +by <tt>tain_clockmon()</tt> and <tt>tain_sysclock()</tt> are similar. Then, +depending on the accuracy of the system clock, a drift may appear; calling +<tt>tain_clockmon_init()</tt> again resets that drift to zero. +</p> + +<p> +<code> int tain_clockmon (tain_t *a, tain_t const *offset) </code> <br /> + Gives the absolute time, as a TAI64N value, in *<em>a</em>. This +absolute time is computed as a linear increase (as measured with +CLOCK_MONOTONIC) since the last time <tt>tain_clockmon_init()</tt> +was called with parameter <em>offset</em>. <tt>tain_clockmon()</tt> +guarantees precise time interval measurements; however, the time it +gives can slightly differ from the result of <tt>tain_sysclock()</tt>. +The function returns 1 if it succeeds or 0 (and sets errno) if it fails. +</p> + +<h3> All-purpose time reading </h3> + +<p> +<code> int tain_init (void) </code> <br /> +If skalibs has been configured with the +<a href="../flags.html#usemon">--enable-monotonic</a> option: this +function initializes a process-global stopwatch, that future +<tt>tain_now</tt> invocations will depend on. +Without the <a href="../flags.html#usemon">--enable-monotonic</a> option: this +function does nothing. +The function returns 1 if it succeeds or 0 (and sets errno) if it fails. +</p> + +<p> +<code> int tain_now (tain_t *a) </code> <br /> +Writes the current time, as a TAI value, to *<em>a</em>. This is the +function you should use to read time by default. It returns 1 if it succeeds or +0 (and sets errno) if it fails. +</p> + +<p> + If skalibs has been configured with the +<a href="../flags.html#usemon">--enable-monotonic</a> option: +<tt>tain_now()</tt> is computed as a linear increase from the last time +<tt>tain_init()</tt> was called. (If <tt>tain_init()</tt> has never +been called before, the first invocation of <tt>tain_now()</tt> +automatically calls <tt>tain_init()</tt>.) + Without the <a href="../flags.html#usemon">--enable-monotonic</a> option: +<tt>tain_now()</tt> is the same as <tt>tain_sysclock()</tt>. +</p> + +<p> + If the above is unclear to you: just use <tt>tain_now()</tt> +everytime you need to read time, and you will always get a reasonable +approximation of the current time, in a format suited for arithmetic +computations. +</p> + +<h3> Converting to/from libc representations </h3> + +<p> +<code> int tai_from_timeval (tai_t *t, struct timeval const *tv) <br /> +int tai_from_timespec (tai_t *t, struct timespec const *ts) <br /> +int tai_relative_from_timeval (tai_t *t, struct timeval const *tv) <br /> +int tai_relative_from_timespec (tai_t *t, struct timespec const *ts) </code> <br /> +Those functions convert an absolute (resp. relative) time in a +struct timeval (resp. struct timespec) to an absolute (resp. relative) +time in a tai_t, with a 1-second precision. They return 1. +</p> + +<p> +<code> int timeval_from_tai (struct timeval *tv, tai_t const *t) <br /> +int timespec_from_tai (struct timespec *ts, tai_t const *t) <br /> +int timeval_from_tai_relative (struct timeval *tv, tai_t const *t) <br /> +int timespec_from_tai_relative (struct timespec *ts, tai_t const *t) </code> <br /> +Those functions do the opposite conversion. They normally return 1; +however, <tt>struct timeval</tt> and <tt>struct timespec</tt> cannot +represent an absolute date before the Epoch, or a negative relative time; +if *<em>t</em> cannot be converted, 0 EINVAL is returned. +</p> + +<p> +<code> int tain_from_timeval (tain_t *a, struct timeval const *tv) <br /> +int tain_from_timespec (tain_t *a, struct timespec const *ts) <br /> +int tain_relative_from_timeval (tain_t *a, struct timeval const *tv) <br /> +int tain_relative_from_timespec (tain_t *a, struct timespec const *ts) <br /> +int timeval_from_tain (struct timeval *tv, tain_t const *a) <br /> +int timespec_from_tain (struct timespec *ts, tain_t const *a) <br /> +int timeval_from_tain_relative (struct timeval *tv, tain_t const *a) <br /> +int timespec_from_tain_relative (struct timespec *ts, tain_t const *a) </code> <br /> +Same conversion operations, but with a <tt>tain_t</tt>. The 1-microsecond +(for <tt>struct timeval</tt>) or 1-nanosecond (for <tt>struct timespec</tt>) +precision is preserved. +</p> + +<p> +<code> void tain_uint (tain_t *a, unsigned int c) </code> <br /> +Stores a relative time of <em>c</em> seconds into <em>a</em>. +</p> + +<p> +<code> int tain_from_millisecs (tain_t *a, int ms) </code> <br /> +This function makes a <tt>tain_t</tt> representing a relative +time of <em>ms</em> milliseconds. <em>ms</em> must be non-negative. +The function returns 1, unless <em>ms</em> is negative, in which case +it returns 0 EINVAL. +</p> + +<p> +<code> int tain_to_millisecs (tain_t const *a) </code> <br /> +If *<em>a</em> contains a non-negative relative time that fits into +a 31-bit integer number of milliseconds, the function returns that +number. Else it returns -1 EINVAL. +</p> + +<h3> Time computations </h3> + +<p> +<code> void tai_add (tai_t *t, tai_t const *t1, tai_t const *t2) </code> <br /> +Stores *<em>t1</em> + *<em>t2</em> into <em>t</em>. Of course, *<em>t1</em> +and *<em>t2</em> must not both represent absolute times. +</p> + +<p> +<code> void tai_sub (tai_t *t, tai_t const *t1, tai_t const *t2) </code> <br /> +Stores *<em>t1</em> - *<em>t2</em> into <em>t</em>. Of course, *<em>t1</em> +and *<em>t2</em> must be of the same type (relative or absolute), and +*<em>t</em> will always be relative. +</p> + +<p> +<code> void tain_add (tain_t *a, tain_t const *a1, tain_t const *a2) <br /> +void tain_sub (tain_t *a, tain_t const *a1, tain_t const *a2) </code> <br /> +Same thing with <tt>tain_t</tt>. +</p> + +<p> +<code> void tain_addsec (tain_t *a, tain_t const *a1, int c) </code> <br /> +Adds <em>c</em> seconds to *<em>a1</em> and stores the result into <em>a</em>. +<em>c</em> may be negative. +</p> + +<p> +<code> void tain_half (tain_t *a, tain_t const *b) </code> <br /> +Stores *<em>b</em>/2 into <em>a</em>. *<em>b</em> must be relative. +</p> + +<h3> Comparing dates or durations </h3> + +<p> +<code> int tai_less (tai_t const *t1, tai_t const *t2) <br /> +int tain_less (tain_t const *t1, tain_t const *t2) </code> <br /> +Those functions return nonzero iff *<em>t1</em> is lesser than *<em>t2</em>. +*<em>t1</em> and *<em>t2</em> must be both relative, or both absolute. +</p> + +<h3> Packing and unpacking </h3> + +<p> +<code> void tai_pack (char *s, tai_t const *t) </code> <br /> +Marshals *<em>t</em> into the buffer <em>s</em> points to, which +must be preallocated with at least TAI_PACK (8) characters. Afterwards, +the buffer contains the +<a href="http://cr.yp.to/libtai/tai64.html#tai64">external TAI64 format</a> +representation of *<em>t</em>. +</p> + +<p> +<code> void tai_unpack (char const *s, tai_t *t) </code> <br /> +Unmarshals the +<a href="http://cr.yp.to/libtai/tai64.html#tai64">external TAI64 format</a> +label pointed to by <em>s</em> (at least TAI_PACK characters) and stores +the result into <em>t</em>. +</p> + +<p> +<code> void tain_pack (char *s, tain_t const *a) <br /> +void tain_unpack (char const *s, tain_t *a) <br /> +void tain_pack (char *s, tain_t const *a) <br /> +void tain_unpack (char const *s, tain_t *a) </code> <br /> +Same thing with +<a href="http://cr.yp.to/libtai/tai64.html#tai64n">external TAI64N format</a>, +using TAIN_PACK (12) characters. +</p> + +<h3> Formatting and scanning </h3> + +<p> +<code> unsigned int tain_fmt (char *s, tain_t const *a) </code> <br /> +Writes into <em>s</em> an ASCII representation of *<em>a</em> in external +TAI64N format. <em>s</em> must point to a preallocated buffer of at least +TAIN_PACK*2 (24) characters. The function returns the number of bytes that +have been written to <em>s</em> (24). +</p> + +<p> +<code> unsigned int tain_scan (char const *s, tain_t *a) </code> <br /> +Reads 24 characters from <em>s</em>; if those characters are a valid ASCII +representation of the external TAI64N format of some time value, this value +is stored into <em>a</em>, and 24 is returned. Else 0 is returned. +</p> + +<a name="timestamp"><h3> Timestamping </h3></a> + +<p> + A <em>TAI64N timestamp</em> is a string of 25 characters: a single '@' +character followed by the ASCII representation of the TAI64N external +format of an absolute date. +</p> + +<p> +<code> unsigned int timestamp_fmt (char *s, tain_t const *a) </code> <br /> +Writes a TAI64N timestamp representing the absolute date *<em>a</em> +into the 25 characters pointed to by <em>s</em>. Returns 25. +</p> + +<p> +<code> unsigned int timestamp_scan (char const *s, tain_t *a) </code> <br /> +Reads 25 characters at <em>s</em>. If those characters are a valid TAI64N +timestamp, stores the absolute date in <em>a</em> and returns 25. Else, +returns 0. +</p> + +<p> +<code> int timestamp (char *s) </code> <br /> +Writes the current time (read from the system clock) as a TAI64N timestamp +into <em>s</em>. Returns 1 if it succeeds or 0 (and sets errno) if it fails. +</p> + +<p> + TAI64N timestamps are an efficient, robust, and easy-to-use way of +timestampping log lines. They're easy to recognize in automatic data +parsers. Log files where every line starts with a TAI64N timestamp can +be merged and alphanumerically sorted: the resulting file will be +chronologically sorted. +</p> + +<p> + The <a href="http://skarnet.org/software/s6/">s6</a> package +provides tools to convert TAI64N timestamps into human-readable +dates. Please do not embed human-readable dates in your log files, +thus making parsing tools unnecessarily hard to write; +use TAI64N timestamps instead, design tools that can parse them, +and translate them to human-readable form at human analysis time. +</p> + +</body> +</html> |