summary refs log tree commit diff
path: root/misc
diff options
context:
space:
mode:
authorRichard Nyberg <rnyberg@murmeldjur.se>2006-10-14 21:29:25 +0000
committerRichard Nyberg <rnyberg@murmeldjur.se>2006-10-14 21:29:25 +0000
commit29495ab53bebbdfde86dc9488acfe236d3669e57 (patch)
tree127829bf7f28b11e1c72ce61e3b3b90f3bb0c3e7 /misc
parent25788505fae8dee663f122817363271d48bd7d9a (diff)
downloadbtpd-29495ab53bebbdfde86dc9488acfe236d3669e57.tar.gz
btpd-29495ab53bebbdfde86dc9488acfe236d3669e57.zip
Add and use the function make_abs_path. realpath didn't fit my needs.
make_abs_path doesn't need the directories to actually exist in the
file system.

Diffstat (limited to 'misc')
-rw-r--r--misc/subr.c104
-rw-r--r--misc/subr.h1
2 files changed, 105 insertions, 0 deletions
diff --git a/misc/subr.c b/misc/subr.c
index bc11d16..70a04af 100644
--- a/misc/subr.c
+++ b/misc/subr.c
@@ -276,3 +276,107 @@ find_btpd_dir(void)
         asprintf(&res, "%s/.btpd", home);
     return res;
 }
+
+int
+make_abs_path(const char *in, char *out)
+{
+    int ii = 0, oi = 0, lastsep = 0;
+    switch (in[0]) {
+    case '\0':
+        return EINVAL;
+    case '/':
+        if (strlen(in) >= PATH_MAX)
+            return ENAMETOOLONG;
+        out[0] = '/';
+        oi++;
+        ii++;
+        break;
+    default:
+        if (getcwd(out, PATH_MAX) == NULL)
+            return errno;
+        oi = strlen(out);
+        if (oi + strlen(in) + 1 >= PATH_MAX)
+            return ENAMETOOLONG;
+        out[oi] = '/';
+        lastsep = oi;
+        oi++;
+        break;
+    }
+after_slash:
+    while (in[ii] == '/')
+        ii++;
+    switch(in[ii]) {
+    case '\0':
+        goto end;
+    case '.':
+        ii++;
+        goto one_dot;
+    default:
+        goto normal;
+    }
+one_dot:
+    switch (in[ii]) {
+    case '\0':
+        goto end;
+    case '/':
+        ii++;
+        goto after_slash;
+    case '.':
+        ii++;
+        goto two_dot;
+    default:
+        out[oi] = '.';
+        oi++;
+        goto normal;
+    }
+two_dot:
+    switch (in[ii]) {
+    case '\0':
+        if (lastsep == 0)
+            oi = 1;
+        else {
+            oi = lastsep;
+            while (out[oi - 1] != '/')
+                oi--;
+            lastsep = oi - 1;
+        }
+        goto end;
+    case '/':
+        if (lastsep == 0)
+            oi = 1;
+        else {
+            oi = lastsep;
+            while (out[oi - 1] != '/')
+                oi--;
+            lastsep = oi - 1;
+        }
+        ii++;
+        goto after_slash;
+    default:
+        out[oi] = '.';
+        out[oi + 1] = '.';
+        oi += 2;
+        goto normal;
+    }
+normal:
+    switch (in[ii]) {
+    case '\0':
+        goto end;
+    case '/':
+        out[oi] = '/';
+        lastsep = oi;
+        oi++;
+        ii++;
+        goto after_slash;
+    default:
+        out[oi] = in[ii];
+        oi++;
+        ii++;
+        goto normal;
+    }
+end:
+    if (oi == lastsep + 1 && lastsep != 0)
+        oi = lastsep;
+    out[oi] = '\0';
+    return 0;
+}
diff --git a/misc/subr.h b/misc/subr.h
index 8ef962c..fd9e002 100644
--- a/misc/subr.h
+++ b/misc/subr.h
@@ -36,5 +36,6 @@ int write_fully(int fd, const void *buf, size_t len);
 void *read_file(const char *path, void *buf, size_t *size);
 
 char *find_btpd_dir(void);
+int make_abs_path(const char *in, char *out);
 
 #endif