]> gitweb.michael.orlitzky.com - apply-default-acl.git/blobdiff - src/libadacl.c
src/libadacl.c: remove two NULL checks around acl_free() calls.
[apply-default-acl.git] / src / libadacl.c
index 22f5d7b3ad900dbcc5f8bb9c01d90e62bb897a96..b8f609989f8e962e37bb2ce95c3154131f777947 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;
   }
@@ -567,7 +566,7 @@ int acl_copy_xattr(int src_fd,
     return ACL_ERROR;
   }
 
-  size_t src_size_guess = fgetxattr(src_fd, src_name, NULL, 0);
+  ssize_t src_size_guess = fgetxattr(src_fd, src_name, NULL, 0);
   if (src_size_guess == XATTR_ERROR) {
     if (errno == ENODATA) {
       /* A missing ACL isn't really an error. ENOATTR and ENODATA are
@@ -580,7 +579,7 @@ int acl_copy_xattr(int src_fd,
   }
   char* src_acl_p = alloca(src_size_guess);
   /* The actual size may be smaller than our guess? I don't know. */
-  size_t src_size = fgetxattr(src_fd, src_name, src_acl_p, (int)src_size_guess);
+  ssize_t src_size = fgetxattr(src_fd, src_name, src_acl_p, src_size_guess);
   if (src_size == XATTR_ERROR) {
     if (errno == ENODATA) {
       /* A missing ACL isn't an 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,13 +904,11 @@ int apply_default_acl_ex(const char* path,
   }
 
  cleanup:
-  free(path_copy);
-  if (new_acl != (acl_t)NULL) {
-    acl_free(new_acl);
-  }
-  if (new_acl_unmasked != (acl_t)NULL) {
-    acl_free(new_acl_unmasked);
-  }
+  free(dirname_path_copy);
+  free(basename_path_copy);
+  acl_free(new_acl);
+  acl_free(new_acl_unmasked);
+
   if (fd > 0 && close(fd) == CLOSE_ERROR) {
     perror("apply_default_acl_ex (close fd)");
     result = ACL_ERROR;