aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2013-01-17 23:16:38 -0600
committerRob Landley <rob@landley.net>2013-01-17 23:16:38 -0600
commit7c0e2803d2bff7022637fb418de571b470dee2f6 (patch)
tree4c6372c1e87ecda9c3cc95fa3c6461f8a427cedc
parent6be5ac6a9287f4c48daf60d36eae44f04d7f9a80 (diff)
downloadtoybox-7c0e2803d2bff7022637fb418de571b470dee2f6.tar.gz
Fix xabspath() resolving symlink after .., and properly detecting failure for last entry after nondir.
-rw-r--r--lib/lib.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/lib/lib.c b/lib/lib.c
index a21f6024..1defe1e4 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -375,23 +375,32 @@ char *xabspath(char *path, int exact)
// Removable path componenents.
if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) {
- if (new->str[1] && done) free(llist_pop(&done));
+ int x = new->str[1];
+
free(new);
- continue;
- }
+ if (x) {
+ if (done) free(llist_pop(&done));
+ len = 0;
+ } else continue;
// Is this a symlink?
- len=readlinkat(dirfd, new->str, buf, 4096);
+ } else len=readlinkat(dirfd, new->str, buf, 4096);
+
if (len>4095) goto error;
if (len<1) {
int fd;
-
- // Not a symlink: add to linked list, move dirfd, fail if error
- if ((exact || todo) && errno != EINVAL) goto error;
- new->next = done;
- done = new;
- fd = openat(dirfd, new->str, O_DIRECTORY);
- if (fd == -1 && (exact || todo)) goto error;
+ char *s = "..";
+
+ // For .. just move dirfd
+ if (len) {
+ // Not a symlink: add to linked list, move dirfd, fail if error
+ if ((exact || todo) && errno != EINVAL) goto error;
+ new->next = done;
+ done = new;
+ s = new->str;
+ }
+ fd = openat(dirfd, s, 0);
+ if (fd == -1 && (exact || todo || errno != ENOENT)) goto error;
close(dirfd);
dirfd = fd;
continue;