]> gitweb.michael.orlitzky.com - apply-default-acl.git/commitdiff
src/libadacl.c: add a special case for the path "." as an argument.
authorMichael Orlitzky <michael@orlitzky.com>
Sun, 17 Jun 2018 23:43:21 +0000 (19:43 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 18 Jun 2018 00:55:22 +0000 (20:55 -0400)
There's a bug (exposed by the most recent test case) in the way the
path "." is handled. Specifically, the dirname() function miscomputes
its parent path as ".", which is clearly not correct.

In this commit, a special case is added for the path ".", and the test
suite passes once more. The implementation is a bit of a hack, however,
and will be improved once the same issue with ".." has been dealt with.

src/libadacl.c

index f20d4a393c26f4e22a8e1cb77947214539b6fb5e..a43afa5c1b203a63e7d905296a56719fa0a43d49 100644 (file)
@@ -1003,7 +1003,22 @@ int apply_default_acl(const char* path, bool recursive) {
     return ACL_ERROR;
   }
   char* parent = dirname(dirname_path_copy);
-  parent_fd = safe_open(parent, O_DIRECTORY | O_NOFOLLOW);
+
+  /* Just kidding, if the path is ".", then dirname will do the wrong
+   * thing and give us "." as its parent, too. So, we handle that as a
+   * special case.
+   *
+   * WARNING: it is important that "parent" itself is not used after
+   * this point; otherwise we would need to store the correct parent
+   * path in there. But since everything uses file descriptors from
+   * now on, we only need to ensure that we get the correct parent_fd
+   * below. */
+  if (strcmp(path, ".") == 0 && strcmp(parent, ".") == 0) {
+    parent_fd = safe_open("..", O_DIRECTORY | O_NOFOLLOW);
+  }
+  else {
+    parent_fd = safe_open(parent, O_DIRECTORY | O_NOFOLLOW);
+  }
   if (parent_fd == OPEN_ERROR) {
     if (errno == ELOOP || errno == ENOTDIR) {
       /* We hit a symlink, either in the last path component (ELOOP)
@@ -1028,7 +1043,16 @@ int apply_default_acl(const char* path, bool recursive) {
     result = ACL_ERROR;
     goto cleanup;
   }
-  fd = openat(parent_fd, basename(basename_path_copy), O_NOFOLLOW);
+
+  /* If the basename is ".", then we don't want to open "." relative
+     to the parent_fd, so we need another special case for that
+     path. */
+  if (strcmp(path, ".") == 0 && strcmp(parent, ".") == 0) {
+    fd = open(".", O_NOFOLLOW);
+  }
+  else {
+    fd = openat(parent_fd, basename(basename_path_copy), O_NOFOLLOW);
+  }
   if (fd == OPEN_ERROR) {
     if (errno == ELOOP || errno == ENOTDIR) {
       /* We hit a symlink, either in the last path component (ELOOP)