X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Freapply_default_acl.c;h=c48f828674e4a3e47b8b93f3e6e149e7e46d3b98;hb=9e17a644dfc33bba278205305b308d6d2874d2c1;hp=7d638993a91a11b936d8e7946405e469586b4003;hpb=3a4c697a608a23e11b84d897883b2870f9587dfa;p=apply-default-acl.git diff --git a/src/reapply_default_acl.c b/src/reapply_default_acl.c index 7d63899..c48f828 100644 --- a/src/reapply_default_acl.c +++ b/src/reapply_default_acl.c @@ -1,6 +1,11 @@ +/* On Linux, ftw.h needs this special voodoo to work. */ +#define _XOPEN_SOURCE 500 + #include -#include /* dirname() */ -#include /* PATH_MAX */ +#include /* nftw() et al. */ +#include +#include /* dirname() */ +#include /* PATH_MAX */ #include #include #include @@ -540,22 +545,63 @@ void usage(char* program_name) { */ printf("Reapply any applicable default ACLs to the given files or " "directories.\n\n"); - printf("Usage: %s [ [ ...]]\n", program_name); + printf("Usage: %s [flags] [ [ ...]]\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[]) { - /* - * Check argv for either form of the "help" flag, -h or --help. +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. */ - 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; - } + 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; @@ -571,17 +617,46 @@ int main(int argc, char* argv[]) { return EXIT_FAILURE; } - if (asked_for_help(argc, argv)) { - usage(argv[0]); - return EXIT_SUCCESS; + + bool recursive = false; + + struct option long_options[] = { + /* These options set a flag. */ + {"help", no_argument, NULL, 'h'}, + {"recursive", no_argument, NULL, 'r'}, + {NULL, 0, NULL, 0} + }; + + int opt = 0; + + while ((opt = getopt_long(argc, argv, "hr", long_options, NULL)) != -1) { + switch (opt) { + case 'h': + usage(argv[0]); + return EXIT_SUCCESS; + case 'r': + recursive = true; + break; + default: + usage(argv[0]); + return EXIT_FAILURE; + } } int result = EXIT_SUCCESS; int arg_index = 1; - for (arg_index = 1; arg_index < argc; arg_index++) { + for (arg_index = optind; arg_index < argc; arg_index++) { 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;