summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--doc/index.html2
-rw-r--r--doc/libstddjb/djbunix.html13
-rw-r--r--doc/upgrade.html6
-rw-r--r--package/deps.mak1
-rw-r--r--package/info2
-rw-r--r--src/include/skalibs/djbunix.h2
-rw-r--r--src/libstddjb/path_canonicalize.c69
8 files changed, 99 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 27b7eae..8ed0191 100644
--- a/NEWS
+++ b/NEWS
@@ -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 ;
+}