mirror of
https://github.com/MidnightCommander/mc
synced 2025-01-08 20:41:59 +03:00
* utilunix.c (canonicalize_pathname): Clean rewrite from
scratch. The old implementation had memory problems with "/.." and didn't actually strip the leading "./" from path. Remove support for obsolete Qnet paths.
This commit is contained in:
parent
7cdbc354c2
commit
cf432c1d8a
@ -1,3 +1,10 @@
|
|||||||
|
2003-03-10 Pavel Roskin <proski@gnu.org>
|
||||||
|
|
||||||
|
* utilunix.c (canonicalize_pathname): Clean rewrite from
|
||||||
|
scratch. The old implementation had memory problems with "/.."
|
||||||
|
and didn't actually strip the leading "./" from path. Remove
|
||||||
|
support for obsolete Qnet paths.
|
||||||
|
|
||||||
2003-03-05 Pavel Roskin <proski@gnu.org>
|
2003-03-05 Pavel Roskin <proski@gnu.org>
|
||||||
|
|
||||||
* subshell.c (init_subshell_child): Set environment variable
|
* subshell.c (init_subshell_child): Set environment variable
|
||||||
|
183
src/utilunix.c
183
src/utilunix.c
@ -604,99 +604,120 @@ int mc_doublepclose (int pipe, pid_t pid)
|
|||||||
Trailing `/'s are removed.
|
Trailing `/'s are removed.
|
||||||
Non-leading `../'s and trailing `..'s are handled by removing
|
Non-leading `../'s and trailing `..'s are handled by removing
|
||||||
portions of the path. */
|
portions of the path. */
|
||||||
char *canonicalize_pathname (char *path)
|
char *
|
||||||
|
canonicalize_pathname (char *path)
|
||||||
{
|
{
|
||||||
int i, start;
|
char *p, *s;
|
||||||
char stub_char;
|
int len;
|
||||||
|
|
||||||
if (!*path)
|
if (!path[0] || !path[1])
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
stub_char = (*path == PATH_SEP) ? PATH_SEP : '.';
|
/* Collapse multiple slashes */
|
||||||
|
p = path;
|
||||||
/* Walk along path looking for things to compact. */
|
while (*p) {
|
||||||
i = 0;
|
if (p[0] == PATH_SEP && p[1] == PATH_SEP) {
|
||||||
while (path[i]) {
|
s = p + 1;
|
||||||
|
while (*(++s) == PATH_SEP);
|
||||||
while (path[i] && path[i] != PATH_SEP)
|
strcpy (p + 1, s);
|
||||||
i++;
|
|
||||||
|
|
||||||
start = i++;
|
|
||||||
|
|
||||||
/* If we didn't find any slashes, then there is nothing left to do. */
|
|
||||||
if (!path[start])
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if defined(__QNX__) && !defined(__QNXNTO__)
|
|
||||||
/*
|
|
||||||
** QNX accesses the directories of nodes on its peer-to-peer
|
|
||||||
** network (Qnet) by prefixing their directories with "//[nid]".
|
|
||||||
** We don't want to collapse two '/'s if they're at the start
|
|
||||||
** of the path, followed by digits, and ending with a '/'.
|
|
||||||
*/
|
|
||||||
if (start == 0 && path[1] == PATH_SEP) {
|
|
||||||
char *p = path + 2;
|
|
||||||
char *q = strchr (p, PATH_SEP);
|
|
||||||
|
|
||||||
if (q > p) {
|
|
||||||
*q = 0;
|
|
||||||
if (!strcspn (p, "0123456789")) {
|
|
||||||
start = q - path;
|
|
||||||
i = start + 1;
|
|
||||||
}
|
}
|
||||||
*q = PATH_SEP;
|
p++;
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Handle multiple `/'s in a row. */
|
|
||||||
while (path[i] == PATH_SEP)
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if ((start + 1) != i) {
|
|
||||||
strcpy (path + start + 1, path + i);
|
|
||||||
i = start + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for trailing `/'. */
|
/* Collapse "/./" -> "/" */
|
||||||
if (start && !path[i]) {
|
p = path;
|
||||||
zero_last:
|
while (*p) {
|
||||||
path[--i] = '\0';
|
if (p[0] == PATH_SEP && p[1] == '.' && p[2] == PATH_SEP)
|
||||||
|
strcpy (p, p + 2);
|
||||||
|
else
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove trailing slashes */
|
||||||
|
p = path + strlen (path) - 1;
|
||||||
|
while (p > path && *p == PATH_SEP)
|
||||||
|
*p-- = 0;
|
||||||
|
|
||||||
|
/* Remove leading "./" */
|
||||||
|
if (path[0] == '.' && path[1] == PATH_SEP) {
|
||||||
|
if (path[2] == 0) {
|
||||||
|
path[1] = 0;
|
||||||
|
return path;
|
||||||
|
} else {
|
||||||
|
strcpy (path, path + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove trailing "/" or "/." */
|
||||||
|
len = strlen (path);
|
||||||
|
if (len < 2)
|
||||||
|
return path;
|
||||||
|
if (path[len - 1] == PATH_SEP) {
|
||||||
|
path[len - 1] = 0;
|
||||||
|
} else {
|
||||||
|
if (path[len - 1] == '.' && path[len - 2] == PATH_SEP) {
|
||||||
|
if (len == 2) {
|
||||||
|
path[1] = 0;
|
||||||
|
return path;
|
||||||
|
} else {
|
||||||
|
path[len - 2] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collapse "/.." with the previous part of path */
|
||||||
|
p = path;
|
||||||
|
while (p[0] && p[1] && p[2]) {
|
||||||
|
if ((p[0] != PATH_SEP || p[1] != '.' || p[2] != '.')
|
||||||
|
|| (p[3] != PATH_SEP && p[3] != 0)) {
|
||||||
|
p++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search for the previous token */
|
||||||
|
s = p - 1;
|
||||||
|
while (s >= path && *s != PATH_SEP)
|
||||||
|
s--;
|
||||||
|
|
||||||
|
s++;
|
||||||
|
|
||||||
|
/* If the previous token is "..", we cannot collapse it */
|
||||||
|
if (s[0] == '.' && s[1] == '.' && s + 2 == p) {
|
||||||
|
p += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p[3] != 0) {
|
||||||
|
if (s == path && *s == PATH_SEP) {
|
||||||
|
/* "/../foo" -> "/foo" */
|
||||||
|
strcpy (s + 1, p + 4);
|
||||||
|
} else {
|
||||||
|
/* "token/../foo" -> "foo" */
|
||||||
|
strcpy (s, p + 4);
|
||||||
|
}
|
||||||
|
p = (s > path) ? s - 1 : s;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trailing ".." */
|
||||||
|
if (s == path) {
|
||||||
|
/* "token/.." -> "." */
|
||||||
|
if (path[0] != PATH_SEP) {
|
||||||
|
path[0] = '.';
|
||||||
|
}
|
||||||
|
path[1] = 0;
|
||||||
|
} else {
|
||||||
|
/* "foo/token/.." -> "foo" */
|
||||||
|
if (s == path + 1)
|
||||||
|
s[0] = 0;
|
||||||
|
else
|
||||||
|
s[-1] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for `../', `./' or trailing `.' by itself. */
|
return path;
|
||||||
if (path[i] == '.') {
|
|
||||||
/* Handle trailing `.' by itself. */
|
|
||||||
if (!path[i + 1])
|
|
||||||
goto zero_last;
|
|
||||||
|
|
||||||
/* Handle `./'. */
|
|
||||||
if (path[i + 1] == PATH_SEP) {
|
|
||||||
strcpy (path + i, path + i + 1);
|
|
||||||
i = start;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle `../' or trailing `..' by itself.
|
|
||||||
Remove the previous ?/ part with the exception of
|
|
||||||
../, which we should leave intact. */
|
|
||||||
if (path[i + 1] == '.'
|
|
||||||
&& (path[i + 2] == PATH_SEP || !path[i + 2])) {
|
|
||||||
while (--start > -1 && path[start] != PATH_SEP);
|
|
||||||
if (!strncmp (path + start + 1, "../", 3))
|
|
||||||
continue;
|
|
||||||
strcpy (path + start + 1, path + i + 2);
|
|
||||||
i = start;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*path) {
|
|
||||||
*path = stub_char;
|
|
||||||
path[1] = '\0';
|
|
||||||
}
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user