return ret;
}
-void clean_fname(char *name)
+unsigned int clean_fname(char *name)
{
- char *p;
- int l;
- int modified = 1;
+ char *limit = name, *t = name, *f = name;
+ int anchored;
if (!name)
- return;
-
- while (modified) {
- modified = 0;
+ return 0;
- if ((p = strstr(name,"/./")) != NULL) {
- modified = 1;
- while (*p) {
- p[0] = p[2];
- p++;
- }
+ if ((anchored = *f == '/') != 0)
+ *t++ = *f++;
+ while (*f) {
+ /* discard extra slashes */
+ if (*f == '/') {
+ f++;
+ continue;
}
-
- if ((p = strstr(name,"//")) != NULL) {
- modified = 1;
- while (*p) {
- p[0] = p[1];
- p++;
+ if (*f == '.') {
+ /* discard "." dirs (but NOT a trailing '.'!) */
+ if (f[1] == '/') {
+ f++; /* not += 2! */
+ continue;
+ }
+ /* collapse ".." dirs */
+ if (f[1] == '.' && (f[2] == '/' || !f[2])) {
+ char *s = t - 1;
+ if (s == name && anchored) {
+ f += 2;
+ continue;
+ }
+ while (s > limit && *--s != '/') {}
+ if (s != t - 1 && *s == '/') {
+ t = s + 1;
+ f += 2;
+ continue;
+ }
+ *t++ = *f++;
+ *t++ = *f++;
+ limit = t;
}
}
+ while (*f && (*t++ = *f++) != '/') {}
+ }
- if (strncmp(p = name, "./", 2) == 0) {
- modified = 1;
- do {
- p[0] = p[2];
- } while (*p++);
- }
+ if (t > name+anchored && t[-1] == '/')
+ t--;
+ if (t == name)
+ *t++ = '.';
+ *t = '\0';
- l = strlen(p = name);
- if (l > 1 && p[l-1] == '/') {
- modified = 1;
- p[l-1] = 0;
- }
- }
+ return t - name;
}
/* Make path appear as if a chroot had occurred. This handles a leading
curr_dir_len += len;
}
- clean_fname(curr_dir);
+ curr_dir_len = clean_fname(curr_dir);
return 1;
}