]> gitweb.michael.orlitzky.com - apply-default-acl.git/blobdiff - src/libadacl.c
src/libadacl.c: fix two comment typos.
[apply-default-acl.git] / src / libadacl.c
index 1b31938666c9aab2aab84f4bdd3087bb7561b079..5eec14440f92d945e45fce1ec4b61f9038098c4f 100644 (file)
@@ -170,25 +170,24 @@ int safe_open(const char* pathname, int flags) {
     return OPEN_ERROR;
   }
 
-  int fd = 0;
-  if (strcmp(abspath, "/") == 0) {
-    fd = open("/", flags | O_DIRECTORY);
-  }
-  else {
+  bool abspath_is_root = (strcmp(abspath, "/") == 0);
+  int rootflags = flags | O_DIRECTORY;
+  if (!abspath_is_root) {
     /* Use O_PATH for some added safety if "/" is not our target */
-    fd = open("/", flags | O_DIRECTORY | O_PATH);
+    rootflags |= O_PATH;
   }
-  if (fd == OPEN_ERROR) {
+  int rootfd = open("/", rootflags);
+  if (rootfd == OPEN_ERROR) {
     perror("safe_open (open)");
     return OPEN_ERROR;
   }
 
-  if (strcmp(abspath, "/") == 0) {
-    return fd;
+  if (abspath_is_root) {
+    return rootfd;
   }
 
-  int result = safe_open_ex(fd, abspath+1, flags);
-  if (close(fd) == CLOSE_ERROR) {
+  int result = safe_open_ex(rootfd, abspath+1, flags);
+  if (close(rootfd) == CLOSE_ERROR) {
     perror("safe_open (close)");
     return OPEN_ERROR;
   }
@@ -673,14 +672,19 @@ int apply_default_acl_ex(const char* path,
   /* The file descriptor for the directory containing "path" */
   int parent_fd = 0;
 
+  /* dirname() and basename() mangle their arguments, so we need
+     to make copies of "path" before using them. */
+  char* dirname_path_copy = NULL;
+  char* basename_path_copy = NULL;
+
   /* Get the parent directory of "path" with dirname(), which happens
    * to murder its argument and necessitates a path_copy. */
-  char* path_copy = strdup(path);
-  if (path_copy == NULL) {
+  dirname_path_copy = strdup(path);
+  if (dirname_path_copy == NULL) {
     perror("apply_default_acl_ex (strdup)");
     return ACL_ERROR;
   }
-  char* parent = dirname(path_copy);
+  char* parent = dirname(dirname_path_copy);
   parent_fd = safe_open(parent, O_DIRECTORY | O_NOFOLLOW);
   if (parent_fd == OPEN_ERROR) {
     if (errno == ELOOP || errno == ENOTDIR) {
@@ -703,7 +707,16 @@ int apply_default_acl_ex(const char* path,
     goto cleanup;
   }
 
-  fd = safe_open(path, O_NOFOLLOW);
+  /* We already obtained the parent fd safely, so if we use the
+     basename of path here instead of the full thing, then we can get
+     away with using openat() and spare ourselves the slowness of
+     another safe_open(). */
+  basename_path_copy = strdup(path);
+  if (basename_path_copy == NULL) {
+    perror("apply_default_acl_ex (strdup)");
+    return ACL_ERROR;
+  }
+  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)
@@ -790,7 +803,7 @@ int apply_default_acl_ex(const char* path,
   }
 
   /* There's a good reason why we saved the ACL above, even though
-   * we're about tto read it back into memory and mess with it on the
+   * we're about to read it back into memory and mess with it on the
    * next line. The acl_copy_xattr() function is already a hack to let
    * us copy default ACLs without resorting to path names; we simply
    * have no way to read the parent's default ACL into memory using
@@ -801,7 +814,7 @@ int apply_default_acl_ex(const char* path,
   */
 
   /* Now we potentially need to mask the execute permissions in the
-     ACL on fd; or maybe now. */
+     ACL on fd; or maybe not. */
   if (allow_exec) {
     goto cleanup;
   }
@@ -891,7 +904,8 @@ int apply_default_acl_ex(const char* path,
   }
 
  cleanup:
-  free(path_copy);
+  free(dirname_path_copy);
+  free(basename_path_copy);
   if (new_acl != (acl_t)NULL) {
     acl_free(new_acl);
   }