*
*/
-/* 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() */
* else for big ones. */
#define EXIT_ERROR 2
-#define NFTW_ERROR -1
+/* Prototypes */
+bool path_accessible(const char* path);
+void usage(const char* 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 (target == NULL) {
- errno = EINVAL;
- perror("apply_default_acl_nftw (args)");
- return ACL_ERROR;
- }
-
-
- if (apply_default_acl_ex(target, sp, false) == ACL_ERROR) {
- /* I guess we do want to bail out for serious/unexpected errors? */
- return ACL_ERROR;
- }
-
- /* We don't want to kill the tree walk because we it a symlink. */
- return 0;
-}
-
-
-
-/**
- * @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 (target == NULL) {
- errno = EINVAL;
- perror("apply_default_acl_nftw_x (args)");
- return ACL_ERROR;
- }
-
- if (apply_default_acl_ex(target, sp, true) == ACL_ERROR) {
- /* I guess we do want to bail out for serious/unexpected errors? */
- return ACL_ERROR;
- }
-
- /* We don't want to kill the tree walk because we it a symlink. */
- return 0;
-}
-
-
-
-/**
- * @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().
- *
- * @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 nftw() fails with a serious error (returns NFTW_ERROR),
- * then we return @c ACL_ERROR. Otherwise, we return @c ACL_SUCCESS.
- */
-int apply_default_acl_recursive(const char *target, bool no_exec_mask) {
- if (target == NULL) {
- errno = EINVAL;
- perror("apply_default_acl_recursive (args)");
- return ACL_ERROR;
- }
-
- int max_levels = 256;
- int flags = FTW_MOUNT | FTW_PHYS;
-
- /* 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);
-
- /* nftw will itself return NFTW_ERROR on errors like malloc failure,
- and since the only non-success value that "fn" can return us
- ACL_ERROR == NFTW_ERROR, this covers all error cases. */
- if (nftw_result == NFTW_ERROR) {
- perror("apply_default_acl_recursive (nftw)");
- return ACL_ERROR;
- }
-
- /* Beware: nftw indicates success with 0, but ACL_SUCCESS != 0. */
- return ACL_SUCCESS;
-}
-
/**
}
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}
};
case 'r':
recursive = true;
break;
- case 'x':
- no_exec_mask = true;
- break;
default:
usage(argv[0]);
return EXIT_FAILURE;
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];
continue;
}
- int (*f)(const char *, bool) = recursive ? apply_default_acl_recursive
- : apply_default_acl;
- int reapp_result = f(target, no_exec_mask);
+ reapp_result = apply_default_acl(target, recursive);
if (result == EXIT_SUCCESS && reapp_result == ACL_FAILURE) {
/* We don't want to turn an error into a (less-severe) failure. */