]> gitweb.michael.orlitzky.com - apply-default-acl.git/commitdiff
Add a --recursive option.
authorMichael Orlitzky <michael@orlitzky.com>
Tue, 18 Dec 2012 04:07:09 +0000 (23:07 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Tue, 18 Dec 2012 04:07:09 +0000 (23:07 -0500)
Update the usage() and option parsing for the new flag.

src/reapply_default_acl.c

index 7d638993a91a11b936d8e7946405e469586b4003..a5e9d6cecc0f5ade5cb773f73a69a191dee5171f 100644 (file)
@@ -1,6 +1,10 @@
+/* On Linux, ftw.h needs this special voodoo to work. */
+#define _XOPEN_SOURCE 500
+
 #include <errno.h>
-#include <libgen.h> /* dirname() */
-#include <limits.h> /* PATH_MAX */
+#include <ftw.h>    /* nftw() et al. */
+#include <libgen.h> /* dirname()     */
+#include <limits.h> /* PATH_MAX      */
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -540,20 +544,55 @@ void usage(char* program_name) {
    */
   printf("Reapply any applicable default ACLs to the given files or "
         "directories.\n\n");
-  printf("Usage: %s <target1> [<target2> [ <target3>...]]\n", program_name);
+  printf("Usage: %s [flags] <target1> [<target2> [ <target3>...]]\n\n",
+        program_name);
+  printf("Flags:\n");
+  printf(" -h, --help         Print this help message\n");
+  printf(" -r, --recursive    Act on any given directories recursively\n");
 }
 
 
-bool asked_for_help(int argc, char* argv[]) {
+bool asked_for_flag(int argc,
+                   char* argv[],
+                   const char* short_flag,
+                   const char* long_flag) {
   /*
-   * Check argv for either form of the "help" flag, -h or --help.
+   * Check argv for either form of the flag, e.g. -h or --help.
    */
   int arg_index = 1;
   for (arg_index = 1; arg_index < argc; arg_index++) {
-    if (!strcmp(argv[arg_index], "-h")) {
+    if (!strcmp(argv[arg_index], short_flag)) {
+      return true;
+    }
+    if (!strcmp(argv[arg_index], long_flag)) {
       return true;
     }
-    if (!strcmp(argv[arg_index], "--help")) {
+  }
+
+  return false;
+}
+
+
+bool asked_for_help(int argc, char* argv[]) {
+  return asked_for_flag(argc, argv, "-h", "--help");
+}
+
+bool asked_for_recursive(int argc, char* argv[]) {
+  return asked_for_flag(argc, argv, "-r", "--recursive");
+}
+
+bool is_flag(const char* arg) {
+  /*
+   * Is arg a command-line flag (e.g. --recursive)?
+   */
+  char valid_flags[4][32] = { "-h",
+                             "--help",
+                             "-r",
+                             "--recursive" };
+
+  int flag_index = 0;
+  for (flag_index = 0; flag_index < 4; flag_index++) {
+    if (!strcmp(arg, valid_flags[flag_index])) {
       return true;
     }
   }
@@ -562,6 +601,61 @@ bool asked_for_help(int argc, char* argv[]) {
 }
 
 
+int reapply_default_acl_nftw(const char *target,
+                            const struct stat *s,
+                            int info,
+                            struct FTW *ftw) {
+  /* A wrapper around the reapply_default_acl() function for use with
+   * nftw(). We need to adjust the return value so that nftw() doesn't
+   * think we've failed.
+   */
+  bool reapp_result = reapply_default_acl(target);
+  if (reapp_result) {
+    return 0;
+  }
+  else {
+    return 1;
+  }
+}
+
+
+bool reapply_default_acl_recursive(const char *target) {
+  /* Attempt to reapply default ACLs recursively. If target is a
+   * directory, we recurse through its entries. If not, we just
+   * reapply the default ACL to target.
+   *
+   * We ignore symlinks for consistency with chmod -r.
+   *
+   */
+  if (!is_directory(target)) {
+    return reapply_default_acl(target);
+  }
+
+  int max_levels = 256;
+  int flags = FTW_PHYS; /* Don't follow links. */
+
+  int nftw_result = nftw(target,
+                        reapply_default_acl_nftw,
+                        max_levels,
+                        flags);
+
+  if (nftw_result == 0) {
+    /* Success */
+    return true;
+  }
+
+  /* nftw will return -1 on error, or if the supplied function
+   * (reapply_default_acl_nftw) returns a non-zero result, nftw will
+   * return that.
+   */
+  if (nftw_result == -1) {
+    perror("reapply_default_acl_recursive (nftw)");
+  }
+
+  return false;
+}
+
+
 int main(int argc, char* argv[]) {
   /*
    * Call reapply_default_acl on each command-line argument.
@@ -578,10 +672,27 @@ int main(int argc, char* argv[]) {
 
   int result = EXIT_SUCCESS;
 
+  bool recursive = asked_for_recursive(argc, argv);
+
   int arg_index = 1;
   for (arg_index = 1; arg_index < argc; arg_index++) {
+    /* Don't bother stripping the flags from argv; just ignore
+     * an argument if it's one of our flags.
+     */
+    if (is_flag(argv[arg_index])) {
+      continue;
+    }
+
     const char* target = argv[arg_index];
-    bool reapp_result = reapply_default_acl(target);
+    bool reapp_result = false;
+
+    if (recursive) {
+      reapp_result = reapply_default_acl_recursive(target);
+    }
+    else {
+      /* It's either normal file, or we're not operating recursively. */
+      reapp_result = reapply_default_acl(target);
+    }
 
     if (!reapp_result) {
       result = EXIT_FAILURE;