diff options
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | doc/index.html | 2 | ||||
-rw-r--r-- | doc/libstddjb/djbunix.html | 13 | ||||
-rw-r--r-- | doc/upgrade.html | 6 | ||||
-rw-r--r-- | package/deps.mak | 1 | ||||
-rw-r--r-- | package/info | 2 | ||||
-rw-r--r-- | src/include/skalibs/djbunix.h | 2 | ||||
-rw-r--r-- | src/libstddjb/path_canonicalize.c | 69 |
8 files changed, 99 insertions, 2 deletions
@@ -1,5 +1,11 @@ Changelog for skalibs. +In 2.9.1.0 +---------- + + - Added path_canonicalize() + + In 2.9.0.0 ---------- diff --git a/doc/index.html b/doc/index.html index 18fa214..8a903f1 100644 --- a/doc/index.html +++ b/doc/index.html @@ -60,7 +60,7 @@ with a standard C development environment </li> <h3> Download </h3> <ul> - <li> The current released version of skalibs is <a href="skalibs-2.9.0.0.tar.gz">2.9.0.0</a>. </li> + <li> The current released version of skalibs is <a href="skalibs-2.9.1.0.tar.gz">2.9.1.0</a>. </li> <li> Alternatively, you can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/skalibs/">skalibs git repository</a>: diff --git a/doc/libstddjb/djbunix.html b/doc/libstddjb/djbunix.html index dca3a2c..6223bf4 100644 --- a/doc/libstddjb/djbunix.html +++ b/doc/libstddjb/djbunix.html @@ -808,5 +808,18 @@ Sleeps <em>n</em> milliseconds. Signals received during that time are handled, but <em>do not</em> interrupt the sleep. </p> +<h3> Miscellaneous functions </h3> + +<p> +<code> size_t path_canonicalize (char *out, char const *in, int check) </code> <br /> +Writes into <em>out</em> the canonical form of the Unix path given in +<em>in</em>. The <em>out</em> array must be preallocated with at least +<tt>strlen(in)+2</tt> bytes. Returns the length of the <em>out</em> path, without +counting the terminating null byte. If <em>check</em> is nonzero, <em>in</em> is tested +for every <tt>foobar/..</tt> element, and the function returns 0, and sets errno +appropriately, if <tt>foobar</tt> is not a valid directory; in that case, <em>out</em> +contains the problematic path. +</p> + </body> </html> diff --git a/doc/upgrade.html b/doc/upgrade.html index b5f7031..314a3ce 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -16,6 +16,12 @@ <a href="//skarnet.org/">skarnet.org</a> </p> +<h2> in 2.9.1.0 </h2> + +<ul> + <li> New function: <tt>path_canonicalize</tt> </li> +</ul> + <h2> in 2.9.0.0 </h2> <ul> diff --git a/package/deps.mak b/package/deps.mak index 5970bb9..77008c8 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -458,6 +458,7 @@ src/libstddjb/openwritenclose_unsafe.o src/libstddjb/openwritenclose_unsafe.lo: src/libstddjb/openwritevnclose.o src/libstddjb/openwritevnclose.lo: src/libstddjb/openwritevnclose.c src/include/skalibs/djbunix.h src/libstddjb/openwritevnclose_suffix.o src/libstddjb/openwritevnclose_suffix.lo: src/libstddjb/openwritevnclose_suffix.c src/include/skalibs/djbunix.h src/libstddjb/openwritevnclose_unsafe.o src/libstddjb/openwritevnclose_unsafe.lo: src/libstddjb/openwritevnclose_unsafe.c src/include/skalibs/allreadwrite.h src/include/skalibs/djbunix.h +src/libstddjb/path_canonicalize.o src/libstddjb/path_canonicalize.lo: src/libstddjb/path_canonicalize.c src/include/skalibs/djbunix.h src/libstddjb/pathexec.o src/libstddjb/pathexec.lo: src/libstddjb/pathexec.c src/include/skalibs/djbunix.h src/include/skalibs/env.h src/include/skalibs/posixplz.h src/libstddjb/pathexec0.o src/libstddjb/pathexec0.lo: src/libstddjb/pathexec0.c src/include/skalibs/djbunix.h src/libstddjb/pathexec0_run.o src/libstddjb/pathexec0_run.lo: src/libstddjb/pathexec0_run.c src/include/skalibs/djbunix.h diff --git a/package/info b/package/info index ab9f643..403794d 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=skalibs -version=2.9.0.0 +version=2.9.1.0 category=prog package_macro_name=SKALIBS diff --git a/src/include/skalibs/djbunix.h b/src/include/skalibs/djbunix.h index d39df3f..fe8c2f9 100644 --- a/src/include/skalibs/djbunix.h +++ b/src/include/skalibs/djbunix.h @@ -53,6 +53,8 @@ extern int open_write (char const *) ; extern int socket_internal (int, int, int, unsigned int) ; extern int socketpair_internal (int, int, int, unsigned int, int *) ; +extern size_t path_canonicalize (char *, char const *, int) ; + extern int pathexec_env (char const *, char const *) ; extern void pathexec_r (char const *const *, char const *const *, size_t, char const *, size_t) ; extern void pathexec_r_name (char const *, char const *const *, char const *const *, size_t, char const *, size_t) ; diff --git a/src/libstddjb/path_canonicalize.c b/src/libstddjb/path_canonicalize.c new file mode 100644 index 0000000..c30f9f4 --- /dev/null +++ b/src/libstddjb/path_canonicalize.c @@ -0,0 +1,69 @@ +/* ISC license. */ + +#include <errno.h> +#include <sys/stat.h> + +#include <skalibs/djbunix.h> + +static unsigned char cclass (char c) +{ + switch (c) + { + case 0 : return 0 ; + case '/' : return 1 ; + case '.' : return 2 ; + default : return 3 ; + } +} + + /* out must be at least strlen(in) + 2 bytes */ + +size_t path_canonicalize (char *out, char const *in, int check) +{ + static unsigned char const table[4][4] = + { + { 0x04, 0x00, 0x12, 0x11 }, + { 0x04, 0x50, 0x11, 0x11 }, + { 0x24, 0x20, 0x13, 0x11 }, + { 0xa4, 0xa0, 0x11, 0x11 } + } ; + int isabsolute = in[0] == '/' ; + size_t j = 0 ; + unsigned int depth = 0 ; + unsigned char state = 0 ; + + if (isabsolute) *out++ = *in++ ; + while (state < 4) + { + char c = *in++ ; + unsigned char what = table[state][cclass(c)] ; + state = what & 0x07 ; + if (what & 0x80) + { + if (depth) + { + depth-- ; + j -= 3 ; + if (check) + { + struct stat st ; + out[j] = 0 ; + if (stat(out - isabsolute, &st) < 0) return 0 ; + if (!S_ISDIR(st.st_mode)) return (errno = ENOTDIR, 0) ; + } + } + else if (!isabsolute) + { + out[j++] = '/' ; + out[j++] = '.' ; + } + } + if (what & 0x40) depth++ ; + if (what & 0x20) while (j && out[j-1] != '/') j-- ; + if (what & 0x10) out[j++] = c ; + } + if (j && out[j-1] == '/') j-- ; + if (!j && !isabsolute) out[j++] = '.' ; + out[j] = 0 ; + return j ; +} |