]> gitweb.michael.orlitzky.com - apply-default-acl.git/blobdiff - src/apply-default-acl.c
doc/COPYING: add one to state the "or later" bit
[apply-default-acl.git] / src / apply-default-acl.c
index f8ae4cd7126f7330a815ed3fe18511a75c5e70b2..7989c985ab8bbf4a8329a64bedab1b7330336f71 100644 (file)
@@ -5,12 +5,8 @@
  *
  */
 
-/* On Linux, ftw.h needs this special voodoo to work. */
-#define _XOPEN_SOURCE 500
-#define _GNU_SOURCE
-
+#include <errno.h>   /* EINVAL */
 #include <fcntl.h>   /* AT_FOO constants */
-#include <ftw.h>     /* nftw() et al. */
 #include <getopt.h>  /* getopt_long() */
 #include <stdbool.h> /* the "bool" type */
 #include <stdio.h>   /* perror() */
 
 #include "libadacl.h"
 
+/* We exit with EXIT_FAILURE for small errors, but we need something
+ * else for big ones. */
+#define EXIT_ERROR 2
+
+/* Prototypes */
+bool path_accessible(const char* path);
+void usage(const char* program_name);
 
 
 /**
@@ -62,121 +65,23 @@ bool path_accessible(const char* path) {
  *
  */
 void usage(const char* program_name) {
+  if (program_name == NULL) {
+    /* ??? */
+    return;
+  }
+
   printf("Apply any applicable default ACLs to the given files or "
-        "directories.\n\n");
+         "directories.\n\n");
   printf("Usage: %s [flags] <target1> [<target2> [ <target3>...]]\n\n",
-        program_name);
+         program_name);
   printf("Flags:\n");
   printf(" -h, --help         Print this help message\n");
   printf(" -r, --recursive    Act on any given directories recursively\n");
-  printf(" -x, --no-exec-mask Apply execute permissions unconditionally\n");
 
   return;
 }
 
 
-/**
- * @brief Wrapper around @c apply_default_acl() for use with @c nftw().
- *
- * For parameter information, see the @c nftw man page.
- *
- * @return If the ACL was applied to @c target successfully, we return
- *   @c FTW_CONTINUE to signal to @ nftw() that we should proceed onto
- *   the next file or directory. Otherwise, we return @c FTW_STOP to
- *   signal failure.
- *
- */
-int apply_default_acl_nftw(const char *target,
-                          const struct stat *sp,
-                          int info,
-                          struct FTW *ftw) {
-
-  if (apply_default_acl(target, sp, false)) {
-    return FTW_CONTINUE;
-  }
-  else {
-    return FTW_STOP;
-  }
-}
-
-
-
-/**
- * @brief Wrapper around @c apply_default_acl() for use with @c nftw().
- *
- * This is identical to @c apply_default_acl_nftw(), except it passes
- * @c true to @c apply_default_acl() as its no_exec_mask argument.
- *
- */
-int apply_default_acl_nftw_x(const char *target,
-                            const struct stat *sp,
-                            int info,
-                            struct FTW *ftw) {
-
-  if (apply_default_acl(target, sp, true)) {
-    return FTW_CONTINUE;
-  }
-  else {
-    return FTW_STOP;
-  }
-}
-
-
-
-/**
- * @brief Recursive version of @c apply_default_acl().
- *
- * If @c target is a directory, we use @c nftw() to call @c
- * apply_default_acl() recursively on all of its children. Otherwise,
- * we just delegate to @c apply_default_acl().
- *
- * We ignore symlinks for consistency with chmod -r.
- *
- * @param target
- *   The root (path) of the recursive application.
- *
- * @param no_exec_mask
- *   The value (either true or false) of the --no-exec-mask flag.
- *
- * @return
- *   If @c target is not a directory, we return the result of
- *   calling @c apply_default_acl() on @c target. Otherwise, we convert
- *   the return value of @c nftw(). If @c nftw() succeeds (returns 0),
- *   then we return @c true. Otherwise, we return @c false.
- *   \n\n
- *   If there is an error, it will be reported via @c perror, but
- *   we still return @c false.
- */
-bool apply_default_acl_recursive(const char *target, bool no_exec_mask) {
-  int max_levels = 256;
-  int flags = FTW_PHYS; /* Don't follow links. */
-
-  /* There are two separate functions that could be passed to
-     nftw(). One passes no_exec_mask = true to apply_default_acl(),
-     and the other passes no_exec_mask = false. Since the function we
-     pass to nftw() cannot have parameters, we have to create separate
-     options and make the decision here. */
-  int (*fn)(const char *, const struct stat *, int, struct FTW *) = NULL;
-  fn = no_exec_mask ? apply_default_acl_nftw_x : apply_default_acl_nftw;
-
-  int nftw_result = nftw(target, fn, max_levels, flags);
-
-  if (nftw_result == 0) {
-    /* Success */
-    return true;
-  }
-
-  /* nftw will return NFTW_ERROR on error, or if the supplied function
-   * (apply_default_acl_nftw) returns a non-zero result, nftw will
-   * return that.
-   */
-  if (nftw_result == NFTW_ERROR) {
-    perror("apply_default_acl_recursive (nftw)");
-  }
-
-  return false;
-}
-
 
 
 /**
@@ -195,13 +100,11 @@ int main(int argc, char* argv[]) {
   }
 
   bool recursive = false;
-  bool no_exec_mask = false;
 
   struct option long_options[] = {
     /* These options set a flag. */
     {"help",      no_argument, NULL, 'h'},
     {"recursive", no_argument, NULL, 'r'},
-    {"no-exec-mask", no_argument, NULL, 'x'},
     {NULL,        0,           NULL, 0}
   };
 
@@ -215,9 +118,6 @@ int main(int argc, char* argv[]) {
     case 'r':
       recursive = true;
       break;
-    case 'x':
-      no_exec_mask = true;
-      break;
     default:
       usage(argv[0]);
       return EXIT_FAILURE;
@@ -227,9 +127,9 @@ int main(int argc, char* argv[]) {
   int result = EXIT_SUCCESS;
 
   int arg_index = 1;
+  int reapp_result = ACL_SUCCESS;
   for (arg_index = optind; arg_index < argc; arg_index++) {
     const char* target = argv[arg_index];
-    bool reapp_result = false;
 
     /* Make sure we can access the given path before we go out of our
      * way to please it. Doing this check outside of
@@ -237,22 +137,21 @@ int main(int argc, char* argv[]) {
      * typos, too.
      */
     if (!path_accessible(target)) {
-      fprintf(stderr, "%s: %s: No such file or directory\n", argv[0], target);
+      perror(target);
       result = EXIT_FAILURE;
       continue;
     }
 
-    if (recursive) {
-      reapp_result = apply_default_acl_recursive(target, no_exec_mask);
-    }
-    else {
-      /* It's either a normal file, or we're not operating recursively. */
-      reapp_result = apply_default_acl(target, NULL, no_exec_mask);
-    }
+    reapp_result = apply_default_acl(target, recursive);
 
-    if (!reapp_result) {
+    if (result == EXIT_SUCCESS && reapp_result == ACL_FAILURE) {
+      /* We don't want to turn an error into a (less-severe) failure. */
       result = EXIT_FAILURE;
     }
+    if (reapp_result == ACL_ERROR) {
+      /* Turn both success and failure into an error, if we encounter one. */
+      result = EXIT_ERROR;
+    }
   }
 
   return result;