diff options
author | David Reiss <dreiss@facebook.com> | 2008-05-19 23:48:54 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-05-23 14:11:20 -0700 |
commit | ae299be0e5e610027e6492d48d70c1cbb0e9edd8 (patch) | |
tree | 247e12f709c96df4eea12e5759c689a630b02143 /path.c | |
parent | 377d9c409ffe0f0d994b929aeb94716139207b9d (diff) | |
download | git-ae299be0e5e610027e6492d48d70c1cbb0e9edd8.tar.gz |
Implement normalize_absolute_path
normalize_absolute_path removes several oddities form absolute paths,
giving nice clean paths like "/dir/sub1/sub2". Also add a test case
for this utility, based on a new test program (in the style of test-sha1).
Signed-off-by: David Reiss <dreiss@facebook.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'path.c')
-rw-r--r-- | path.c | 53 |
1 files changed, 53 insertions, 0 deletions
@@ -357,3 +357,56 @@ const char *make_absolute_path(const char *path) return buf; } + +/* + * path = absolute path + * buf = buffer of at least max(2, strlen(path)+1) bytes + * It is okay if buf == path, but they should not overlap otherwise. + * + * Performs the following normalizations on path, storing the result in buf: + * - Removes trailing slashes. + * - Removes empty components. + * - Removes "." components. + * - Removes ".." components, and the components the precede them. + * "" and paths that contain only slashes are normalized to "/". + * Returns the length of the output. + * + * Note that this function is purely textual. It does not follow symlinks, + * verify the existence of the path, or make any system calls. + */ +int normalize_absolute_path(char *buf, const char *path) +{ + const char *comp_start = path, *comp_end = path; + char *dst = buf; + int comp_len; + assert(buf); + assert(path); + + while (*comp_start) { + assert(*comp_start == '/'); + while (*++comp_end && *comp_end != '/') + ; /* nothing */ + comp_len = comp_end - comp_start; + + if (!strncmp("/", comp_start, comp_len) || + !strncmp("/.", comp_start, comp_len)) + goto next; + + if (!strncmp("/..", comp_start, comp_len)) { + while (dst > buf && *--dst != '/') + ; /* nothing */ + goto next; + } + + memcpy(dst, comp_start, comp_len); + dst += comp_len; + next: + comp_start = comp_end; + } + + if (dst == buf) + *dst++ = '/'; + + *dst = '\0'; + return dst - buf; +} |