summaryrefslogtreecommitdiff
path: root/util/cleanname.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-09-27 02:15:04 +0200
committerTor Andersson <tor@ghostscript.com>2004-09-27 02:15:04 +0200
commit6ddde92a3a45e970b05770633dc6a337d5d013c5 (patch)
tree1dec4612d7469839478e72d16d30a0da5755243c /util/cleanname.c
downloadmupdf-6ddde92a3a45e970b05770633dc6a337d5d013c5.tar.xz
Initial import
Diffstat (limited to 'util/cleanname.c')
-rw-r--r--util/cleanname.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/util/cleanname.c b/util/cleanname.c
new file mode 100644
index 00000000..e8a8ed86
--- /dev/null
+++ b/util/cleanname.c
@@ -0,0 +1,63 @@
+/*
+ * In place, rewrite name to compress multiple /, eliminate ., and process ..
+ */
+
+#define SEP(x) ((x)=='/' || (x) == 0)
+
+char *
+cleanname(char *name)
+{
+ char *p, *q, *dotdot;
+ int rooted;
+
+ rooted = name[0] == '/';
+
+ /*
+ * invariants:
+ * p points at beginning of path element we're considering.
+ * q points just past the last path element we wrote (no slash).
+ * dotdot points just past the point where .. cannot backtrack
+ * any further (no slash).
+ */
+
+ p = q = dotdot = name + rooted;
+
+ while (*p)
+ {
+ if (p[0] == '/') /* null element */
+ p++;
+
+ else if (p[0] == '.' && SEP(p[1]))
+ p += 1; /* don't count the separator in case it is nul */
+
+ else if (p[0] == '.' && p[1] == '.' && SEP(p[2]))
+ {
+ p += 2;
+ if (q > dotdot) { /* can backtrack */
+ while (--q > dotdot && *q != '/')
+ ;
+ } else if (!rooted) { /* /.. is / but ./../ is .. */
+ if (q != name)
+ *q++ = '/';
+ *q++ = '.';
+ *q++ = '.';
+ dotdot = q;
+ }
+ }
+
+ else { /* real path element */
+ if (q != name + rooted)
+ *q++ = '/';
+ while ((*q = *p) != '/' && *q != 0)
+ p++, q++;
+ }
+ }
+
+ if (q == name) /* empty string is really ``.'' */
+ *q++ = '.';
+
+ *q = '\0';
+
+ return name;
+}
+