]> gitweb.michael.orlitzky.com - apply-default-acl.git/commitdiff
Add the acl_execute_masked() function.
authorMichael Orlitzky <michael@orlitzky.com>
Wed, 9 Jan 2013 20:08:23 +0000 (15:08 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Wed, 9 Jan 2013 20:08:23 +0000 (15:08 -0500)
Rename any_can_execute to any_can_execute_or_dir().
Don't mask the execute bit if the target is a directory (more-closely follows setfacl's "X" behavior).

src/apply-default-acl.c

index 10bdb328a487bc4696af11424e85801129b63453..2111e0eeda08b1b16335710b82a4936f2e353ae7 100644 (file)
@@ -231,10 +231,83 @@ int acl_is_minimal(acl_t* acl) {
 }
 
 
-int any_can_execute(const char* path) {
-  /* Returns 1 if any ACL entry has execute access, 0 if none do, and
+int acl_execute_masked(const char* path) {
+  /* Returns 1 i the given path has an ACL mask which denies
+     execute. Returns 0 if it does not (or if it has no ACL/mask at
+     all), and -1 on error. */
+
+  acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS);
+
+  if (acl == (acl_t)NULL) {
+    return 0;
+  }
+
+  /* Our return value. */
+  int result = 0;
+
+  acl_entry_t entry;
+  int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
+
+  while (ge_result == 1) {
+    acl_tag_t tag = ACL_UNDEFINED_TAG;
+    int tag_result = acl_get_tag_type(entry, &tag);
+
+    if (tag_result == -1) {
+       perror("acl_execute_masked (acl_get_tag_type)");
+       result = -1;
+       goto cleanup;
+    }
+
+    if (tag == ACL_MASK) {
+      /* This is the mask entry, get its permissions, and see if
+        execute is specified. */
+      acl_permset_t permset;
+
+      int ps_result = acl_get_permset(entry, &permset);
+      if (ps_result == -1) {
+       perror("acl_execute_masked (acl_get_permset)");
+       result = -1;
+       goto cleanup;
+      }
+
+      int gp_result = acl_get_perm(permset, ACL_EXECUTE);
+      if (gp_result == -1) {
+       perror("acl_execute_masked (acl_get_perm)");
+       result = -1;
+       goto cleanup;
+      }
+
+      if (gp_result == 0) {
+       /* No execute bit set in the mask; execute not allowed. */
+       return 1;
+      }
+    }
+
+    ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
+  }
+
+ cleanup:
+  acl_free(acl);
+  return result;
+}
+
+
+int any_can_execute_or_dir(const char* path) {
+  /* If the given path is a directory, returns 1. Otherwise, returns 1
+   * if any ACL entry has EFFECTIVE execute access, 0 if none do, and
    * -1 on error.
+   *
+   * This is meant to somewhat mimic setfacl's handling of the capital
+   * 'X' perm, which allows execute access if the target is a
+   * directory or someone can already execute it. We differ in that we
+   * check the effective execute rather than just the execute bits.
    */
+
+  if (is_directory(path)) {
+    /* That was easy... */
+    return 1;
+  }
+
   acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS);
 
   if (acl == (acl_t)NULL) {
@@ -264,28 +337,31 @@ int any_can_execute(const char* path) {
 
     int ps_result = acl_get_permset(entry, &permset);
     if (ps_result == -1) {
-      perror("any_can_execute (acl_get_permset)");
+      perror("any_can_execute_or_dir (acl_get_permset)");
       result = -1;
       goto cleanup;
     }
 
     int gp_result = acl_get_perm(permset, ACL_EXECUTE);
     if (gp_result == -1) {
-      perror("any_can_execute (acl_get_perm)");
+      perror("any_can_execute_or_dir (acl_get_perm)");
       result = -1;
       goto cleanup;
     }
 
     if (gp_result == 1) {
-      result = 1;
-      goto cleanup;
+      /* Only return one if this execute bit is not masked. */
+      if (acl_execute_masked(path) != 1) {
+       result = 1;
+       goto cleanup;
+      }
     }
 
     ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
   }
 
   if (ge_result == -1) {
-    perror("any_can_execute (acl_get_entry)");
+    perror("any_can_execute_or_dir (acl_get_entry)");
     result = -1;
     goto cleanup;
   }
@@ -418,9 +494,9 @@ int apply_default_acl(const char* path) {
     return 0;
   }
 
-  int ace_result = any_can_execute(path);
+  int ace_result = any_can_execute_or_dir(path);
   if (ace_result == -1) {
-    perror("apply_default_acl (any_can_execute)");
+    perror("apply_default_acl (any_can_execute_or_dir)");
     return -1;
   }
 
@@ -467,7 +543,7 @@ int apply_default_acl(const char* path) {
     int tag_result = acl_get_tag_type(entry, &tag);
 
     if (tag_result == -1) {
-       perror("has_default_tag_acl (acl_get_tag_type)");
+       perror("apply_default_acl (acl_get_tag_type)");
        result = -1;
        goto cleanup;
     }