Update standardising path

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@4624 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-07-20 09:03:50 +00:00
parent 8d2d4c5ea7
commit b972d671c7

View file

@ -1905,70 +1905,150 @@ handle_printf_atsign (FILE *stream,
#if defined(__WIN32__) #if defined(__WIN32__)
return self; return self;
#else #else
const int MAX_PATH_LEN = 1024; const int MAX_PATH = 1024;
char new_buf[MAX_PATH];
#if HAVE_REALPATH #if HAVE_REALPATH
char new_buf[MAX_PATH_LEN];
if (realpath([self cString], new_buf) != 0) if (realpath([self cString], new_buf) == 0)
return [NSString stringWithCString: new_buf];
else
return self; return self;
#else #else
NSString *first_half = self; char extra[MAX_PATH];
NSString *second_half = @""; char *dest;
const char *tmp_cpath; const char *name = [self cString];
char tmp_buf[MAX_PATH_LEN]; const char *start;
int syscall_result; const char *end;
struct stat tmp_stat; unsigned num_links = 0;
while (1)
if (name[0] != '/')
{ {
tmp_cpath = [first_half cString]; if (!getcwd(new_buf, MAX_PATH))
return self; /* Couldn't get directory. */
dest = strchr(new_buf, '\0');
}
else
{
new_buf[0] = '/';
dest = &new_buf[1];
}
syscall_result = lstat(tmp_cpath, &tmp_stat); for (start = end = name; *start; start = end)
if (0 != syscall_result) {
return self ; struct stat st;
int n;
if ((tmp_stat.st_mode & S_IFLNK) int len;
&& ((syscall_result=readlink(tmp_cpath, tmp_buf, MAX_PATH_LEN)) != -1))
/* Elide repeated path separators */
while (*start == '/')
start++;
/* Locate end of path component */
end = start;
while (*end && *end != '/')
end++;
len = end - start;
if (len == 0)
{ {
/* break; /* End of path. */
* first half is a path to a symbolic link. }
else if (len == 1 && *start == '.')
{
/* Elide '/./' sequence by ignoring it. */
}
else if (len == 2 && strncmp(start, "..", len) == 0)
{
/*
* Backup - if we are not at the root, remove the last component.
*/ */
tmp_buf[syscall_result] = '\0'; // Make a C string if (dest > &new_buf[1])
second_half = [[NSString stringWithCString: tmp_buf] {
stringByAppendingPathComponent: second_half]; do
first_half = [first_half stringByDeletingLastPathComponent]; {
dest--;
}
while (dest[-1] != '/');
}
} }
else else
{ {
/* if (dest[-1] != '/')
* second_half is an absolute path *dest++ = '/';
*/
if ([second_half hasPrefix: pathSepString])
return [second_half stringByResolvingSymlinksInPath];
/* if (&dest[len] >= &new_buf[MAX_PATH])
* first half is NOT a path to a symbolic link return self; /* Resolved name would be too long. */
*/
second_half = [[first_half lastPathComponent]
stringByAppendingPathComponent: second_half];
first_half = [first_half stringByDeletingLastPathComponent];
}
/* BREAK CONDITION */ memcpy(dest, start, len);
if ([first_half length] == 0) dest += len;
break; *dest = '\0';
else if ([first_half length] == 1
&& [pathSeps() characterIsMember: [first_half characterAtIndex: 0]]) if (lstat(new_buf, &st) < 0)
{ return self; /* Unable to stat file. */
second_half = [pathSepString stringByAppendingPathComponent:
second_half]; if (S_ISLNK(st.st_mode))
break; {
} char buf[MAX_PATH];
if (++num_links > MAXSYMLINKS)
return self; /* Too many symbolic links. */
n = readlink(new_buf, buf, MAX_PATH);
if (n < 0)
return self; /* Couldn't resolve links. */
buf[n] = '\0';
if ((n + strlen(end)) >= MAX_PATH)
return self; /* Path would be too long. */
/*
* Concatenate the resolved name with the string still to
* be processed, and start using the result as input.
*/
strcat(buf, end);
strcpy(extra, buf);
name = end = extra;
if (buf[0] == '/')
{
/*
* For an absolute link, we start at root again.
*/
dest = new_buf + 1;
}
else
{
/*
* Backup - remove the last component.
*/
if (dest > new_buf + 1)
{
do
{
dest--;
}
while (dest[-1] != '/');
}
}
}
else
{
num_links = 0;
}
}
} }
return second_half; if (dest > new_buf + 1 && dest[-1] == '/')
--dest;
*dest = '\0';
#endif #endif
if (strncmp(new_buf, "/private/", 9) == 0)
{
struct stat st;
if (lstat(&new_buf[8], &st) == 0)
strcpy(new_buf, &new_buf[8]);
}
return [NSString stringWithCString: new_buf];
#endif /* (__WIN32__) */ #endif /* (__WIN32__) */
} }
@ -1984,38 +2064,31 @@ handle_printf_atsign (FILE *stream,
if ([s hasPrefix: @"/private"]) if ([s hasPrefix: @"/private"])
[s deleteCharactersInRange: ((NSRange){0,7})]; [s deleteCharactersInRange: ((NSRange){0,7})];
/* Condense `//' */ /* Condense `//' and '/./' */
r = NSMakeRange(0, [s length]); r = NSMakeRange(0, [s length]);
while ((r = [s rangeOfCharacterFromSet: pathSeps() while ((r = [s rangeOfCharacterFromSet: pathSeps()
options: 0 options: 0
range: r]).length) range: r]).length)
{ {
if (r.location + r.length + 1 <= [s length] unsigned length = [s length];
&& [pathSeps() characterIsMember: [s characterAtIndex: r.location + 1]]) unichar c1 = [s characterAtIndex: r.location + 1];
[s deleteCharactersInRange: r];
else
r.location++;
if ((r.length = [s length]) > r.location)
r.length -= r.location;
else
break;
}
/* Condense `/./' */ if (r.location + r.length + 1 <= length
r = NSMakeRange(0, [s length]); && [pathSeps() characterIsMember: c1])
while ((r = [s rangeOfCharacterFromSet: pathSeps() {
options: 0 [s deleteCharactersInRange: r];
range: r]).length) }
{ else if (r.location + r.length + 2 <= length
if (r.location + r.length + 2 <= [s length] && c1 == (unichar)'.'
&& [s characterAtIndex: r.location + 1] == (unichar)'.'
&& [pathSeps() characterIsMember: [s characterAtIndex: r.location + 2]]) && [pathSeps() characterIsMember: [s characterAtIndex: r.location + 2]])
{ {
r.length++; r.length++;
[s deleteCharactersInRange: r]; [s deleteCharactersInRange: r];
} }
else else
r.location++; {
r.location++;
}
if ((r.length = [s length]) > r.location) if ((r.length = [s length]) > r.location)
r.length -= r.location; r.length -= r.location;
else else
@ -2025,6 +2098,11 @@ handle_printf_atsign (FILE *stream,
if ([s isAbsolutePath] == NO) if ([s isAbsolutePath] == NO)
return s; return s;
/*
* For absolute paths, we must resolve symbolic links or (on win32)
* remove '/../' sequences and their matching parent directories.
*/
#if defined(__WIN32__)
/* Condense `/../' */ /* Condense `/../' */
r = NSMakeRange(0, [s length]); r = NSMakeRange(0, [s length]);
while ((r = [s rangeOfCharacterFromSet: pathSeps() while ((r = [s rangeOfCharacterFromSet: pathSeps()
@ -2057,6 +2135,9 @@ handle_printf_atsign (FILE *stream,
} }
return s; return s;
#else
return [s stringByResolvingSymlinksInPath];
#endif
} }
// private methods for Unicode level 3 implementation // private methods for Unicode level 3 implementation