]> gitweb.michael.orlitzky.com - apply-default-acl.git/blobdiff - src/aclq.c
Fix command-line error handling.
[apply-default-acl.git] / src / aclq.c
index a50d33f8249971d6a54c187be65351b7defb4ae5..a2b4307475752b061fd5304ffca8a18a6382bc05 100644 (file)
@@ -15,6 +15,9 @@
 
 
 mode_t get_mode(const char* path) {
+  /*
+   * Get the mode bits from path.
+   */
   if (path == NULL) {
     errno = ENOENT;
     return -1;
@@ -34,6 +37,9 @@ mode_t get_mode(const char* path) {
 
 
 bool is_regular_file(const char* path) {
+  /*
+   * Returns true if path is a regular file, false otherwise.
+   */
   if (path == NULL) {
     return false;
   }
@@ -49,6 +55,9 @@ bool is_regular_file(const char* path) {
 }
 
 bool is_directory(const char* path) {
+  /*
+   * Returns true if path is a directory, false otherwise.
+   */
   if (path == NULL) {
     return false;
   }
@@ -67,7 +76,9 @@ bool is_directory(const char* path) {
 
 int acl_set_entry(acl_t* aclp,
                  acl_entry_t entry) {
-  /* Update or create the given entry. */
+  /*
+   * Update or create the given entry.
+   */
 
   acl_tag_t entry_tag;
   int gt_result = acl_get_tag_type(entry, &entry_tag);
@@ -133,6 +144,8 @@ int acl_set_entry(acl_t* aclp,
   /* If we've made it this far, we need to add a new entry to the
      ACL. */
   acl_entry_t new_entry;
+
+  /* We allocate memory here that we should release! */
   int c_result = acl_create_entry(aclp, &new_entry);
   if (c_result == -1) {
     perror("acl_set_entry (acl_create_entry)");
@@ -172,7 +185,9 @@ int acl_set_entry(acl_t* aclp,
 
 
 int acl_entry_count(acl_t* acl) {
-  /* Return the number of entries in ACL, or -1 on error. */
+  /*
+   * Return the number of entries in acl, or -1 on error.
+   */
   acl_entry_t entry;
   int entry_count = 0;
   int result = acl_get_entry(*acl, ACL_FIRST_ENTRY, &entry);
@@ -193,7 +208,8 @@ int acl_entry_count(acl_t* acl) {
 
 int acl_is_minimal(acl_t* acl) {
   /* An ACL is minimal if it has fewer than four entries. Return 0 for
-     false, 1 for true, and -1 on error. */
+   * false, 1 for true, and -1 on error.
+   */
 
   int ec = acl_entry_count(acl);
   if (ec == -1) {
@@ -212,61 +228,77 @@ 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
-     -1 on error. */
+   * -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;
+
   if (acl_is_minimal(&acl)) {
     mode_t mode = get_mode(path);
     if (mode & (S_IXUSR | S_IXOTH | S_IXGRP)) {
-      return 1;
+      result = 1;
+      goto cleanup;
     }
     else {
-      return 0;
+      result = 0;
+      goto cleanup;
     }
   }
 
-  if (acl == (acl_t)NULL) {
-    return 0;
-  }
-
   acl_entry_t entry;
-  int result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
+  int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
 
-  while (result == 1) {
+  while (ge_result == 1) {
     acl_permset_t permset;
 
     int ps_result = acl_get_permset(entry, &permset);
     if (ps_result == -1) {
       perror("any_can_execute (acl_get_permset)");
-      return -1;
+      result = -1;
+      goto cleanup;
     }
 
     int gp_result = acl_get_perm(permset, ACL_EXECUTE);
     if (gp_result == -1) {
       perror("any_can_execute (acl_get_perm)");
-      return -1;
+      result = -1;
+      goto cleanup;
     }
 
     if (gp_result == 1) {
-      return 1;
+      result = 1;
+      goto cleanup;
     }
 
-    result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
+    ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
   }
 
-  if (result == -1) {
+  if (ge_result == -1) {
     perror("any_can_execute (acl_get_entry)");
-    return -1;
+    result = -1;
+    goto cleanup;
   }
 
-  return 0;
+ cleanup:
+  acl_free(acl);
+  return result;
 }
 
 
 int inherit_default_acl(const char* path, const char* parent) {
   /* Inherit the default ACL from parent to path. This overwrites any
-     existing default ACL. Returns 1 for success, 0 for failure, and
-     -1 on error. */
+   * existing default ACL. Returns 1 for success, 0 for failure, and
+   * -1 on error.
+   */
+
+  /* Our return value. */
+  int result = 1;
 
   if (path == NULL) {
     errno = ENOENT;
@@ -278,21 +310,28 @@ int inherit_default_acl(const char* path, const char* parent) {
   }
 
   acl_t parent_acl = acl_get_file(parent, ACL_TYPE_DEFAULT);
+  if (parent_acl == (acl_t)NULL) {
+    return 0;
+  }
+
   acl_t path_acl = acl_dup(parent_acl);
 
   if (path_acl == (acl_t)NULL) {
     perror("inherit_default_acl (acl_dup)");
+    acl_free(parent_acl);
     return -1;
   }
 
   int sf_result = acl_set_file(path, ACL_TYPE_DEFAULT, path_acl);
   if (sf_result == -1) {
     perror("inherit_default_acl (acl_set_file)");
-    return -1;
+    result = -1;
+    goto cleanup;
   }
 
+ cleanup:
   acl_free(path_acl);
-  return 1;
+  return result;
 }
 
 
@@ -312,40 +351,49 @@ int wipe_acls(const char* path) {
     return -1;
   }
 
+  /* Our return value. */
+  int result = 1;
+
   acl_entry_t entry;
-  int result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
+  int ge_result = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
 
-  while (result == 1) {
+  while (ge_result == 1) {
     int d_result = acl_delete_entry(acl, entry);
     if (d_result == -1) {
       perror("wipe_acls (acl_delete_entry)");
-      return -1;
+      result = -1;
+      goto cleanup;
     }
 
-    result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
+    ge_result = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
   }
 
   /* Catches the first acl_get_entry as well as the ones at the end of
      the loop. */
-  if (result == -1) {
-    perror("reapply_default_acl_ng (acl_get_entry)");
-    return -1;
+  if (ge_result == -1) {
+    perror("wipe_acls (acl_get_entry)");
+    result = -1;
+    goto cleanup;
   }
 
   int sf_result = acl_set_file(path, ACL_TYPE_ACCESS, acl);
   if (sf_result == -1) {
     perror("wipe_acls (acl_set_file)");
-    return -1;
+    result = -1;
+    goto cleanup;
   }
 
-  return 1;
+ cleanup:
+  acl_free(acl);
+  return result;
 }
 
 
 int reapply_default_acl(const char* path) {
   /* Really reapply the default ACL by looping through it. Returns one
-     for success, zero for failure (i.e. no ACL), and -1 on unexpected
-     errors. */
+   * for success, zero for failure (i.e. no ACL), and -1 on unexpected
+   * errors.
+   */
   if (path == NULL) {
     return 0;
   }
@@ -380,10 +428,14 @@ int reapply_default_acl(const char* path) {
     return -1;
   }
 
+  /* Our return value. */
+  int result = 1;
+
   int wipe_result = wipe_acls(path);
   if (wipe_result == -1) {
     perror("reapply_default_acl_ng (wipe_acls)");
-    return -1;
+    result = -1;
+    goto cleanup;
   }
 
   /* Do this after wipe_acls(), otherwise we'll overwrite the wiped
@@ -398,19 +450,21 @@ int reapply_default_acl(const char* path) {
   int inherit_result = inherit_default_acl(path, parent);
   if (inherit_result == -1) {
     perror("reapply_default_acl_ng (inherit_acls)");
-    return -1;
+    result = -1;
+    goto cleanup;
   }
 
   acl_entry_t entry;
-  int result = acl_get_entry(defacl, ACL_FIRST_ENTRY, &entry);
+  int ge_result = acl_get_entry(defacl, ACL_FIRST_ENTRY, &entry);
 
-  while (result == 1) {
+  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("has_default_tag_acl (acl_get_tag_type)");
-       return -1;
+       result = -1;
+       goto cleanup;
     }
 
 
@@ -419,7 +473,8 @@ int reapply_default_acl(const char* path) {
     int ps_result = acl_get_permset(entry, &permset);
     if (ps_result == -1) {
       perror("reapply_default_acl_ng (acl_get_permset)");
-      return -1;
+      result = -1;
+      goto cleanup;
     }
 
     /* If this is a default mask, fix it up. */
@@ -434,13 +489,15 @@ int reapply_default_acl(const char* path) {
        int d_result = acl_delete_perm(permset, ACL_EXECUTE);
        if (d_result == -1) {
          perror("reapply_default_acl_ng (acl_delete_perm)");
-         return -1;
+         result = -1;
+         goto cleanup;
        }
 
        int sp_result = acl_set_permset(entry, permset);
        if (sp_result == -1) {
          perror("reapply_default_acl_ng (acl_set_permset)");
-         return -1;
+         result = -1;
+         goto cleanup;
        }
       }
     }
@@ -449,39 +506,87 @@ int reapply_default_acl(const char* path) {
     int set_result = acl_set_entry(&acl, entry);
     if (set_result == -1) {
       perror("reapply_default_acl_ng (acl_set_entry)");
-      return -1;
+      result = -1;
+      goto cleanup;
     }
 
-    result = acl_get_entry(defacl, ACL_NEXT_ENTRY, &entry);
+    ge_result = acl_get_entry(defacl, ACL_NEXT_ENTRY, &entry);
   }
 
   /* Catches the first acl_get_entry as well as the ones at the end of
      the loop. */
-  if (result == -1) {
+  if (ge_result == -1) {
     perror("reapply_default_acl_ng (acl_get_entry)");
-    return -1;
+    result = -1;
+    goto cleanup;
   }
 
   int sf_result = acl_set_file(path, ACL_TYPE_ACCESS, acl);
   if (sf_result == -1) {
     perror("reapply_default_acl_ng (acl_set_file)");
-    return -1;
+    result = -1;
+    goto cleanup;
   }
 
-  return 1;
+ cleanup:
+  acl_free(defacl);
+  return result;
 }
 
 
+void usage(char* program_name) {
+  /*
+   * Print usage information.
+   */
+  printf("Reapply any applicable default ACLs to the given files or "
+        "directories.\n\n");
+  printf("Usage: %s <target1> [<target2> [ <target3>...]]\n", program_name);
+}
+
+
+bool asked_for_help(int argc, char* argv[]) {
+  /*
+   * Check argv for either form of the "help" flag, -h or --help.
+   */
+  int arg_index = 1;
+  for (arg_index = 1; arg_index < argc; arg_index++) {
+    if (!strcmp(argv[arg_index], "-h")) {
+      return true;
+    }
+    if (!strcmp(argv[arg_index], "--help")) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 
 int main(int argc, char* argv[]) {
-   const char* target = argv[1];
+  /*
+   * Call reapply_default_acl on each command-line argument.
+   */
+  if (argc < 2) {
+    usage(argv[0]);
+    return EXIT_FAILURE;
+  }
+
+  if (asked_for_help(argc, argv)) {
+    usage(argv[0]);
+    return EXIT_SUCCESS;
+  }
+
+  int result = EXIT_SUCCESS;
 
-   bool result = reapply_default_acl(target);
+  int arg_index = 1;
+  for (arg_index = 1; arg_index < argc; arg_index++) {
+    const char* target = argv[arg_index];
+    bool reapp_result = reapply_default_acl(target);
+
+    if (!reapp_result) {
+      result = EXIT_FAILURE;
+    }
+  }
 
-   if (result) {
-     return EXIT_SUCCESS;
-   }
-   else {
-     return EXIT_FAILURE;
-   }
+  return result;
 }