2 * paths.c - Path manipulation routines
6 * Copyright (C) 2012, 2013 Eric Biggers
8 * This file is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at your option) any
13 * This file is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this file; if not, see http://www.gnu.org/licenses/.
29 #include "wimlib/paths.h"
30 #include "wimlib/util.h"
32 /* Like the basename() function, but does not modify @path; it just returns a
33 * pointer to it. This assumes the path separator is the
34 * OS_PREFERRED_PATH_SEPARATOR. */
36 path_basename(const tchar *path)
38 return path_basename_with_len(path, tstrlen(path));
41 /* Like path_basename(), but take an explicit string length. */
43 path_basename_with_len(const tchar *path, size_t len)
45 const tchar *p = &path[len];
50 } while (*--p == OS_PREFERRED_PATH_SEPARATOR);
55 } while (*--p != OS_PREFERRED_PATH_SEPARATOR);
61 /* Returns a pointer to the part of @path following the first colon in the last
62 * path component, or NULL if the last path component does not contain a colon
63 * or has no characters following the first colon. */
65 path_stream_name(const tchar *path)
67 const tchar *base = path_basename(path);
68 const tchar *stream_name = tstrchr(base, T(':'));
69 if (stream_name == NULL || *(stream_name + 1) == T('\0'))
72 return stream_name + 1;
75 /* Collapse and translate path separators, and strip trailing slashes. Doesn't
76 * add or delete a leading slash.
81 do_canonicalize_path(const tchar *in, tchar *out)
83 tchar *orig_out = out;
86 if (is_any_path_separator(*in)) {
87 /* Collapse multiple path separators into one */
88 *out++ = WIM_PATH_SEPARATOR;
91 } while (is_any_path_separator(*in));
93 /* Copy non-path-separator character */
98 /* Remove trailing slash if existent */
99 if (out - orig_out > 1 && *(out - 1) == WIM_PATH_SEPARATOR)
106 * canonicalize_wim_path() - Given a user-provided path to a file within a WIM
107 * image, translate it into a "canonical" path.
109 * - Translate both types of slash into a consistent type (WIM_PATH_SEPARATOR).
110 * - Collapse path separators.
111 * - Add leading slash if missing.
112 * - Strip trailing slashes.
114 * Examples (with WIM_PATH_SEPARATOR == '/'):
116 * => / [ either NULL or empty string ]
124 * /hello//1 => /hello/1
125 * \\hello\\1\\ => /hello/1
128 canonicalize_wim_path(const tchar *wim_path)
138 result = MALLOC((1 + tstrlen(in) + 1) * sizeof(result[0]));
144 /* Add leading slash if missing */
145 if (!is_any_path_separator(*in))
146 *out++ = WIM_PATH_SEPARATOR;
148 do_canonicalize_path(in, out);