mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-04-25 08:39:25 -04:00
An improved clean_fname() routine that is more efficient and will also
collapse ".." dirs that aren't at the start of the path. Care was taken to ensure that the cleaning of a name that goes over the socket is done in the same way as the old code (because both sides call clean_fname() on those file-list names). This ensures compatibility with older rsync versions.
This commit is contained in:
71
util.c
71
util.c
@@ -652,45 +652,52 @@ size_t stringjoin(char *dest, size_t destsize, ...)
|
||||
|
||||
void 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;
|
||||
|
||||
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 (*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;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p = strstr(name,"//")) != NULL) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[1];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(p = name, "./", 2) == 0) {
|
||||
modified = 1;
|
||||
do {
|
||||
p[0] = p[2];
|
||||
} while (*p++);
|
||||
}
|
||||
|
||||
l = strlen(p = name);
|
||||
if (l > 1 && p[l-1] == '/') {
|
||||
modified = 1;
|
||||
p[l-1] = 0;
|
||||
}
|
||||
while (*f && (*t++ = *f++) != '/') {}
|
||||
}
|
||||
|
||||
if (t > name+anchored && t[-1] == '/')
|
||||
t--;
|
||||
if (t == name)
|
||||
*t++ = '.';
|
||||
*t = '\0';
|
||||
}
|
||||
|
||||
/* Make path appear as if a chroot had occurred. This handles a leading
|
||||
|
||||
Reference in New Issue
Block a user