X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fpaths.c;h=db0b68275a8e35d8de137204721ad4b05d343fde;hb=3ee9acdab75547655dd7fb9d3c423daeb3051642;hp=68942f20265862c40923ffe64ba64fc184ef3d32;hpb=316a01ab8a1e418a095c72e235281d89cc51f513;p=wimlib diff --git a/src/paths.c b/src/paths.c index 68942f20..db0b6827 100644 --- a/src/paths.c +++ b/src/paths.c @@ -74,51 +74,80 @@ path_stream_name(const tchar *path) return stream_name + 1; } -/* Duplicate a path; return empty string for NULL input. */ -tchar * -canonicalize_fs_path(const tchar *fs_path) +/* Collapse and translate path separators, and strip trailing slashes. Doesn't + * add or delete a leading slash. + * + * @in may alias @out. + */ +void +do_canonicalize_path(const tchar *in, tchar *out) { - if (fs_path == NULL) - fs_path = T(""); - return TSTRDUP(fs_path); + tchar *orig_out = out; + + while (*in) { + if (is_any_path_separator(*in)) { + /* Collapse multiple path separators into one */ + *out++ = WIM_PATH_SEPARATOR; + do { + in++; + } while (is_any_path_separator(*in)); + } else { + /* Copy non-path-separator character */ + *out++ = *in++; + } + } + + /* Remove trailing slash if existent */ + if (out - orig_out > 1 && *(out - 1) == WIM_PATH_SEPARATOR) + --out; + + *out = T('\0'); } /* * canonicalize_wim_path() - Given a user-provided path to a file within a WIM * image, translate it into a "canonical" path. * - * To do this, translate all supported path separators (is_any_path_separator()) - * into the WIM_PATH_SEPARATOR, and strip any leading and trailing slashes. The - * returned string is allocated. Note that there still may be consecutive path - * separators within the string. Furthermore, the string may be empty, which - * indicates the root dentry of the WIM image. + * - Translate both types of slash into a consistent type (WIM_PATH_SEPARATOR). + * - Collapse path separators. + * - Add leading slash if missing. + * - Strip trailing slashes. + * + * Examples (with WIM_PATH_SEPARATOR == '/'): + * + * => / [ either NULL or empty string ] + * / => / + * \ => / + * hello => /hello + * \hello => /hello + * \hello => /hello + * /hello/ => /hello + * \hello/ => /hello + * /hello//1 => /hello/1 + * \\hello\\1\\ => /hello/1 */ tchar * canonicalize_wim_path(const tchar *wim_path) { - tchar *canonical_path; - tchar *p; - - if (wim_path == NULL) { - wim_path = T(""); - } else { - /* Strip leading path separators. */ - while (is_any_path_separator(*wim_path)) - wim_path++; - } + const tchar *in; + tchar *out; + tchar *result; - canonical_path = TSTRDUP(wim_path); - if (canonical_path == NULL) + in = wim_path; + if (!in) + in = T(""); + + result = MALLOC((1 + tstrlen(in) + 1) * sizeof(result[0])); + if (!result) return NULL; - /* Translate all path separators to WIM_PATH_SEPARATOR. */ - for (p = canonical_path; *p; p++) - if (is_any_path_separator(*p)) - *p = WIM_PATH_SEPARATOR; + out = result; + + /* Add leading slash if missing */ + if (!is_any_path_separator(*in)) + *out++ = WIM_PATH_SEPARATOR; - /* Strip trailing path separators. */ - while (p > canonical_path && *--p == WIM_PATH_SEPARATOR) - *p = T('\0'); + do_canonicalize_path(in, out); - return canonical_path; + return result; }