From: Michael Orlitzky Date: Tue, 18 Dec 2012 04:07:09 +0000 (-0500) Subject: Add a --recursive option. X-Git-Tag: v0.0.2~7 X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=0175b9b5a508c68a9a34de46cfb6fe3b0c917c77;p=apply-default-acl.git Add a --recursive option. Update the usage() and option parsing for the new flag. --- diff --git a/src/reapply_default_acl.c b/src/reapply_default_acl.c index 7d63899..a5e9d6c 100644 --- a/src/reapply_default_acl.c +++ b/src/reapply_default_acl.c @@ -1,6 +1,10 @@ +/* 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 /* dirname() */ +#include /* PATH_MAX */ #include #include #include @@ -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 [ [ ...]]\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[]) { +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;