X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Freapply_default_acl.c;h=c48f828674e4a3e47b8b93f3e6e149e7e46d3b98;hb=e3baab78731e28c32d9d9b8948fc7bed0f280277;hp=a2b4307475752b061fd5304ffca8a18a6382bc05;hpb=9b560cbf082997fed089cbc24e994f94691fcd28;p=apply-default-acl.git diff --git a/src/reapply_default_acl.c b/src/reapply_default_acl.c index a2b4307..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 @@ -415,7 +420,7 @@ int reapply_default_acl(const char* path) { int ace_result = any_can_execute(path); if (ace_result == -1) { - perror("reapply_default_acl_ng (any_can_execute)"); + perror("reapply_default_acl (any_can_execute)"); return -1; } @@ -424,7 +429,7 @@ int reapply_default_acl(const char* path) { acl_t defacl = acl_get_file(parent, ACL_TYPE_DEFAULT); if (defacl == (acl_t)NULL) { - perror("reapply_default_acl_ng (acl_get_file)"); + perror("reapply_default_acl (acl_get_file)"); return -1; } @@ -433,7 +438,7 @@ int reapply_default_acl(const char* path) { int wipe_result = wipe_acls(path); if (wipe_result == -1) { - perror("reapply_default_acl_ng (wipe_acls)"); + perror("reapply_default_acl (wipe_acls)"); result = -1; goto cleanup; } @@ -442,14 +447,14 @@ int reapply_default_acl(const char* path) { ACL with this one. */ acl_t acl = acl_get_file(path, ACL_TYPE_ACCESS); if (acl == (acl_t)NULL) { - perror("reapply_default_acl_ng (acl_get_file)"); + perror("reapply_default_acl (acl_get_file)"); return -1; } /* If it's a directory, inherit the parent's default. */ int inherit_result = inherit_default_acl(path, parent); if (inherit_result == -1) { - perror("reapply_default_acl_ng (inherit_acls)"); + perror("reapply_default_acl (inherit_acls)"); result = -1; goto cleanup; } @@ -472,7 +477,7 @@ int reapply_default_acl(const char* path) { acl_permset_t permset; int ps_result = acl_get_permset(entry, &permset); if (ps_result == -1) { - perror("reapply_default_acl_ng (acl_get_permset)"); + perror("reapply_default_acl (acl_get_permset)"); result = -1; goto cleanup; } @@ -488,14 +493,14 @@ int reapply_default_acl(const char* path) { masked, we have to do it manually. */ int d_result = acl_delete_perm(permset, ACL_EXECUTE); if (d_result == -1) { - perror("reapply_default_acl_ng (acl_delete_perm)"); + perror("reapply_default_acl (acl_delete_perm)"); result = -1; goto cleanup; } int sp_result = acl_set_permset(entry, permset); if (sp_result == -1) { - perror("reapply_default_acl_ng (acl_set_permset)"); + perror("reapply_default_acl (acl_set_permset)"); result = -1; goto cleanup; } @@ -505,7 +510,7 @@ int reapply_default_acl(const char* path) { /* Finally, add the permset to the access ACL. */ int set_result = acl_set_entry(&acl, entry); if (set_result == -1) { - perror("reapply_default_acl_ng (acl_set_entry)"); + perror("reapply_default_acl (acl_set_entry)"); result = -1; goto cleanup; } @@ -516,14 +521,14 @@ int reapply_default_acl(const char* path) { /* Catches the first acl_get_entry as well as the ones at the end of the loop. */ if (ge_result == -1) { - perror("reapply_default_acl_ng (acl_get_entry)"); + perror("reapply_default_acl (acl_get_entry)"); result = -1; goto cleanup; } int sf_result = acl_set_file(path, ACL_TYPE_ACCESS, acl); if (sf_result == -1) { - perror("reapply_default_acl_ng (acl_set_file)"); + perror("reapply_default_acl (acl_set_file)"); result = -1; goto cleanup; } @@ -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;