return cnt;
}
-/* Turns multiple adjacent slashes into a single slash, gets rid of "./"
- * elements, collapses ".." elements except for those at the start of
- * the string. If the resulting path would be empty, change it into a
- * ".". */
+/* Turns multiple adjacent slashes into a single slash; gets rid of "./"
+ * elements; collapses ".." elements except for those at the start of the
+ * string; removes a trailing slash. If the resulting name would be empty,
+ * change it into a ".". */
unsigned int clean_fname(char *name)
{
char *limit = name - 1, *t = name, *f = name;
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
{
char *start, *sanp;
- int allowdotdot = 0;
int rlen = 0;
if (dest != p) {
}
start = sanp = dest + rlen;
- while (*p == '/') {
- /* remove leading slashes */
- p++;
- }
while (*p != '\0') {
+ /* discard leading or extra slashes */
+ if (*p == '/') {
+ p++;
+ continue;
+ }
/* this loop iterates once per filename component in p.
* both p (and sanp if the original had a slash) should
* always be left pointing after a slash
*/
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
/* skip "." component */
- while (*++p == '/') {
- /* skip following slashes */
- ;
- }
+ p++;
continue;
}
- allowdotdot = 0;
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
/* ".." component followed by slash or end */
- if (depth > 0 && sanp == start) {
- /* allow depth levels of .. at the beginning */
- --depth;
- allowdotdot = 1;
- } else {
+ if (depth <= 0 || sanp != start) {
p += 2;
- while (*p == '/') p++;
if (sanp != start) {
/* back up sanp one level */
--sanp; /* now pointing at slash */
}
continue;
}
- }
- while (1) {
- /* copy one component through next slash */
- *sanp++ = *p++;
- if (*p == '\0' || p[-1] == '/') {
- while (*p == '/') {
- /* skip multiple slashes */
- p++;
- }
- break;
- }
- }
- if (allowdotdot) {
+ /* allow depth levels of .. at the beginning */
+ depth--;
/* move the virtual beginning to leave the .. alone */
- start = sanp;
+ start = sanp + 3;
}
+ /* copy one component through next slash */
+ while (*p && (*sanp++ = *p++) != '/') {}
}
if (sanp == dest) {
/* ended up with nothing, so put in "." component */