changeset 791:126cd3b8015c

Fix xabspath() resolving symlink after .., and properly detecting failure for last entry after nondir.
author Rob Landley <rob@landley.net>
date Thu, 17 Jan 2013 23:16:38 -0600
parents 6aa6efdd5883
children 0027cfa330da
files lib/lib.c
diffstat 1 files changed, 19 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/lib/lib.c	Wed Jan 16 06:57:44 2013 -0600
+++ b/lib/lib.c	Thu Jan 17 23:16:38 2013 -0600
@@ -375,23 +375,32 @@
 
     // 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;
+      char *s = "..";
 
-      // 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;
+      // 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;