X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Fapply-default-acl.c;h=a520aa9b6d4ebdc43b5055772292c1efe4b2b822;hb=45d4e8bba034c22c317fbd20c629589e35d97683;hp=e5b989ad9a585fe6224f16da93e969b34d07358c;hpb=a662358647653b8d7f4f2dbfc5ca2802f38c60c8;p=apply-default-acl.git diff --git a/src/apply-default-acl.c b/src/apply-default-acl.c index e5b989a..a520aa9 100644 --- a/src/apply-default-acl.c +++ b/src/apply-default-acl.c @@ -9,6 +9,7 @@ #define _XOPEN_SOURCE 500 #define _GNU_SOURCE +#include /* EINVAL */ #include /* AT_FOO constants */ #include /* nftw() et al. */ #include /* getopt_long() */ @@ -19,6 +20,11 @@ #include "libadacl.h" +/* We exit with EXIT_FAILURE for small errors, but we need something + * else for big ones. */ +#define EXIT_ERROR 2 + +#define NFTW_ERROR -1 /** @@ -62,10 +68,15 @@ 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] [ [ ...]]\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"); @@ -87,16 +98,24 @@ void usage(const char* program_name) { * */ int apply_default_acl_nftw(const char *target, - const struct stat *sp, - int info, - struct FTW *ftw) { - - if (apply_default_acl_ex(target, sp, false)) { - return FTW_CONTINUE; + const struct stat *sp, + int info, + struct FTW *ftw) { + + if (target == NULL) { + errno = EINVAL; + perror("apply_default_acl_nftw (args)"); + return ACL_ERROR; } - else { - return FTW_STOP; + + + 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; } @@ -109,16 +128,23 @@ int apply_default_acl_nftw(const char *target, * */ int apply_default_acl_nftw_x(const char *target, - const struct stat *sp, - int info, - struct FTW *ftw) { - - if (apply_default_acl_ex(target, sp, true)) { - return FTW_CONTINUE; + const struct stat *sp, + int info, + struct FTW *ftw) { + + if (target == NULL) { + errno = EINVAL; + perror("apply_default_acl_nftw_x (args)"); + return ACL_ERROR; } - else { - return FTW_STOP; + + 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; } @@ -130,8 +156,6 @@ int apply_default_acl_nftw_x(const char *target, * 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. * @@ -139,17 +163,18 @@ int apply_default_acl_nftw_x(const char *target, * 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. + * If @c nftw() fails with a serious error (returns NFTW_ERROR), + * then we return @c ACL_ERROR. Otherwise, we return @c ACL_SUCCESS. */ -bool apply_default_acl_recursive(const char *target, bool no_exec_mask) { +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_PHYS; /* Don't follow links. */ + 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(), @@ -161,20 +186,16 @@ bool apply_default_acl_recursive(const char *target, bool no_exec_mask) { 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. - */ + /* 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; } - return false; + /* Beware: nftw indicates success with 0, but ACL_SUCCESS != 0. */ + return ACL_SUCCESS; } @@ -229,7 +250,6 @@ int main(int argc, char* argv[]) { int arg_index = 1; 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 +257,23 @@ 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, no_exec_mask); - } + int (*f)(const char *, bool) = recursive ? apply_default_acl_recursive + : apply_default_acl; + int reapp_result = f(target, no_exec_mask); - 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;