X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=ff7e4b23cdbbcc140440fc288a35911cc2f358dd;hb=c1d3d134939d48e921b981f400808663f4e74001;hp=f81111f197d53c53c4321668f13e58ca2b9c4324;hpb=67b4f3519d838c6f16f5b6b63c0b9b8669fb3dd9;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index f81111f..ff7e4b2 100644 --- a/src/misc.c +++ b/src/misc.c @@ -25,7 +25,6 @@ #include #include #include -#include #if HAVE_STROPTS_H # include @@ -34,6 +33,10 @@ # include #endif +#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT +# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 +#endif + /* Handling strings. */ @@ -230,10 +233,99 @@ zap_slashes (char *name) return name; } +/* Normalize NAME by resolving any relative references and + removing trailing slashes. Destructive version: modifies its argument. */ +int +normalize_filename_x (char *name) +{ + char *p, *q; + + p = name; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && ISSLASH (*p)) + p++; + + /* Remove /./, resolve /../ and compress sequences of slashes */ + for (q = p; *q; ) + { + if (ISSLASH (*q)) + { + *p++ = *q++; + while (ISSLASH (*q)) + q++; + continue; + } + else if (p == name) + { + if (*q == '.') + { + if (ISSLASH (q[1])) + { + q += 2; + continue; + } + if (q[1] == '.' && ISSLASH (q[2])) + return 1; + } + } + else + { + if (*q == '.' && ISSLASH (p[-1])) + { + if (ISSLASH (q[1])) + { + q += 2; + while (ISSLASH (*q)) + q++; + continue; + } + else if (q[1] == '.' && ISSLASH (q[2])) + { + do + { + --p; + } + while (p > name && !ISSLASH (p[-1])); + q += 3; + continue; + } + } + } + *p++ = *q++; + } + + /* Remove trailing slashes */ + while (p - 1 > name && ISSLASH (p[-1])) + p--; + + *p = 0; + return 0; +} + +/* Normalize NAME by resolving any relative references, removing trailing + slashes, and converting it to absolute file name. Return the normalized + name, or NULL in case of error. */ + char * normalize_filename (const char *name) { - return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING)); + char *copy; + + if (name[0] != '/') + { + copy = xgetcwd (); + copy = xrealloc (copy, strlen (copy) + strlen (name) + 2); + + strcat (copy, "/"); + strcat (copy, name); + } + else + copy = xstrdup (name); + if (normalize_filename_x (copy)) + { + free (copy); + return NULL; + } + return xrealloc (copy, strlen (copy) + 1); } @@ -870,5 +962,3 @@ namebuf_name (namebuf_t buf, const char *name) return buf->buffer; } - -