diff options
Diffstat (limited to 'winsup/utils')
-rw-r--r-- | winsup/utils/ChangeLog | 28 | ||||
-rw-r--r-- | winsup/utils/getfacl.c | 197 | ||||
-rw-r--r-- | winsup/utils/setfacl.c | 375 |
3 files changed, 407 insertions, 193 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index ac6eb98eb..104aae244 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,3 +1,31 @@ +2015-11-18 Corinna Vinschen <corinna@vinschen.de> + + Reapply POSIX ACL changes. + + * getfacl.c (main): Special-case SYSTEM and Admins group. Add comments. + + * setfacl.c: Align more to Linux tool. + (delacl): New function to delete acl entries only. + (modacl): Drop delete functionality. Add handling of recomputing the + mask and default mask values. + (delallacl): Rename from delacl. + (setfacl): Call delacl in Delete case. Call delallacl in DeleteAll + and DeleteDef case. + (usage): Accommodate new options. Rearrange and rephrase slightly. + (longopts): Emit 'x' in --delete case. Add --no-mask and --mask + options. + (opts): Add -x and -n options. + (main): Handle -d and -x the same. Handle -n and --mask options. + Drop handling for -r option. + + * getfacl.c (usage): Align more closely to Linux version. Add new + options -c, -e, -E. Change formatting to accommodate longer options. + (longopts): Rename --noname to --numeric. Keep --noname for backward + compatibility. Add --omit-header, --all-effective and --no-effective + options. + (opts): Add -c, -e and -E option. + (main): Handle new -c, -e, and -E options. + 2015-10-22 Yaakov Selkowitz <yselkowi@redhat.com> * getconf.c (conf_table): Add LEVEL*_CACHE_* variables. diff --git a/winsup/utils/getfacl.c b/winsup/utils/getfacl.c index 0bc484877..45e5e2090 100644 --- a/winsup/utils/getfacl.c +++ b/winsup/utils/getfacl.c @@ -66,61 +66,68 @@ static void usage (FILE * stream) { fprintf (stream, "Usage: %s [-adn] FILE [FILE2...]\n" - "\n" - "Display file and directory access control lists (ACLs).\n" - "\n" - " -a, --access display the file access control list\n" - " -d, --default display the default access control list\n" - " -h, --help print help explaining the command line options\n" - " -n, --noname display user and group IDs instead of names\n" - " -V, --version output version information and exit\n" - "\n" - "When multiple files are specified on the command line, a blank\n" - "line separates the ACLs for each file.\n", prog_name); + "\n" + "Display file and directory access control lists (ACLs).\n" + "\n" + " -a, --access display the file access control list only\n" + " -d, --default display the default access control list only\n" + " -c, --omit-header do not display the comment header\n" + " -e, --all-effective print all effective rights\n" + " -E, --no-effective print no effective rights\n" + " -n, --numeric print numeric user/group identifiers\n" + " -V, --version print version and exit\n" + " -h, --help this help text\n" + "\n" + "When multiple files are specified on the command line, a blank\n" + "line separates the ACLs for each file.\n", prog_name); if (stream == stdout) { fprintf (stream, "" - "For each argument that is a regular file, special file or\n" - "directory, getfacl displays the owner, the group, and the ACL.\n" - "For directories getfacl displays additionally the default ACL.\n" - "\n" - "With no options specified, getfacl displays the filename, the\n" - "owner, the group, the setuid (s), setgid (s), and sticky (t)\n" - "bits if available, and both the ACL and the default ACL, if it\n" - "exists.\n" - "\n" - "The format for ACL output is as follows:\n" - " # file: filename\n" - " # owner: name or uid\n" - " # group: name or uid\n" - " # flags: sst\n" - " user::perm\n" - " user:name or uid:perm\n" - " group::perm\n" - " group:name or gid:perm\n" - " mask:perm\n" - " other:perm\n" - " default:user::perm\n" - " default:user:name or uid:perm\n" - " default:group::perm\n" - " default:group:name or gid:perm\n" - " default:mask:perm\n" - " default:other:perm\n" - "\n"); + "For each argument that is a regular file, special file or\n" + "directory, getfacl displays the owner, the group, and the ACL.\n" + "For directories getfacl displays additionally the default ACL.\n" + "\n" + "With no options specified, getfacl displays the filename, the\n" + "owner, the group, the setuid (s), setgid (s), and sticky (t)\n" + "bits if available, and both the ACL and the default ACL, if it\n" + "exists.\n" + "\n" + "The format for ACL output is as follows:\n" + " # file: filename\n" + " # owner: name or uid\n" + " # group: name or uid\n" + " # flags: sst\n" + " user::perm\n" + " user:name or uid:perm\n" + " group::perm\n" + " group:name or gid:perm\n" + " mask:perm\n" + " other:perm\n" + " default:user::perm\n" + " default:user:name or uid:perm\n" + " default:group::perm\n" + " default:group:name or gid:perm\n" + " default:mask:perm\n" + " default:other:perm\n" + "\n"); } } struct option longopts[] = { {"access", no_argument, NULL, 'a'}, {"all", no_argument, NULL, 'a'}, + {"omit-header", no_argument, NULL, 'c'}, + {"all-effective", no_argument, NULL, 'e'}, + {"no-effective", no_argument, NULL, 'E'}, {"default", no_argument, NULL, 'd'}, {"dir", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, - {"noname", no_argument, NULL, 'n'}, + {"noname", no_argument, NULL, 'n'}, /* Backward compat */ + {"numeric", no_argument, NULL, 'n'}, {"version", no_argument, NULL, 'V'}, {0, no_argument, NULL, 0} }; -const char *opts = "adhnV"; +const char *opts = "acdeEhnV"; static void print_version () @@ -142,8 +149,11 @@ main (int argc, char **argv) int c; int ret = 0; int aopt = 0; + int copt = 0; + int eopt = 0; int dopt = 0; int nopt = 0; + int istty = isatty (fileno (stdout)); struct stat st; aclent_t acls[MAX_ACL_ENTRIES]; @@ -155,9 +165,18 @@ main (int argc, char **argv) case 'a': aopt = 1; break; + case 'c': + copt = 1; + break; case 'd': dopt = 1; break; + case 'e': + eopt = 1; + break; + case 'E': + eopt = -1; + break; case 'h': usage (stdout); return 0; @@ -179,6 +198,8 @@ main (int argc, char **argv) for (; optind < argc; ++optind) { int i, num_acls; + mode_t mask = S_IRWXO, def_mask = S_IRWXO; + if (stat (argv[optind], &st) || (num_acls = acl (argv[optind], GETACL, MAX_ACL_ENTRIES, acls)) < 0) { @@ -187,28 +208,42 @@ main (int argc, char **argv) ret = 2; continue; } - printf ("# file: %s\n", argv[optind]); - if (nopt) + if (!copt) { - printf ("# owner: %lu\n", (unsigned long)st.st_uid); - printf ("# group: %lu\n", (unsigned long)st.st_gid); + printf ("# file: %s\n", argv[optind]); + if (nopt) + { + printf ("# owner: %lu\n", (unsigned long)st.st_uid); + printf ("# group: %lu\n", (unsigned long)st.st_gid); + } + else + { + printf ("# owner: %s\n", username (st.st_uid)); + printf ("# group: %s\n", groupname (st.st_gid)); + } + if (st.st_mode & (S_ISUID | S_ISGID | S_ISVTX)) + printf ("# flags: %c%c%c\n", (st.st_mode & S_ISUID) ? 's' : '-', + (st.st_mode & S_ISGID) ? 's' : '-', + (st.st_mode & S_ISVTX) ? 't' : '-'); } - else + for (i = 0; i < num_acls; ++i) { - printf ("# owner: %s\n", username (st.st_uid)); - printf ("# group: %s\n", groupname (st.st_gid)); + if (acls[i].a_type == CLASS_OBJ) + mask = acls[i].a_perm; + else if (acls[i].a_type == DEF_CLASS_OBJ) + def_mask = acls[i].a_perm; } - if (st.st_mode & (S_ISUID | S_ISGID | S_ISVTX)) - printf ("# flags: %c%c%c\n", (st.st_mode & S_ISUID) ? 's' : '-', - (st.st_mode & S_ISGID) ? 's' : '-', - (st.st_mode & S_ISVTX) ? 't' : '-'); for (i = 0; i < num_acls; ++i) { + int n = 0; + int print_effective = 0; + mode_t effective = acls[i].a_perm; + if (acls[i].a_type & ACL_DEFAULT) { if (aopt) continue; - printf ("default:"); + n += printf ("default:"); } else if (dopt) continue; @@ -219,18 +254,18 @@ main (int argc, char **argv) break; case USER: if (nopt) - printf ("user:%lu:", (unsigned long)acls[i].a_id); + n += printf ("user:%lu:", (unsigned long)acls[i].a_id); else - printf ("user:%s:", username (acls[i].a_id)); + n += printf ("user:%s:", username (acls[i].a_id)); break; case GROUP_OBJ: - printf ("group::"); + n += printf ("group::"); break; case GROUP: if (nopt) - printf ("group:%lu:", (unsigned long)acls[i].a_id); + n += printf ("group:%lu:", (unsigned long)acls[i].a_id); else - printf ("group:%s:", groupname (acls[i].a_id)); + n += printf ("group:%s:", groupname (acls[i].a_id)); break; case CLASS_OBJ: printf ("mask:"); @@ -239,7 +274,53 @@ main (int argc, char **argv) printf ("other:"); break; } - printf ("%s\n", permstr (acls[i].a_perm)); + n += printf ("%s", permstr (acls[i].a_perm)); + switch (acls[i].a_type) + { + case USER: + case GROUP_OBJ: + effective = acls[i].a_perm & mask; + print_effective = 1; + break; + case GROUP: + /* Special case SYSTEM and Admins group: The mask only + applies to them as far as the execute bit is concerned. */ + if (acls[i].a_id == 18 || acls[i].a_id == 544) + effective = acls[i].a_perm & (mask | S_IROTH | S_IWOTH); + else + effective = acls[i].a_perm & mask; + print_effective = 1; + break; + case DEF_USER: + case DEF_GROUP_OBJ: + effective = acls[i].a_perm & def_mask; + print_effective = 1; + break; + case DEF_GROUP: + /* Special case SYSTEM and Admins group: The mask only + applies to them as far as the execute bit is concerned. */ + if (acls[i].a_id == 18 || acls[i].a_id == 544) + effective = acls[i].a_perm & (def_mask | S_IROTH | S_IWOTH); + else + effective = acls[i].a_perm & def_mask; + print_effective = 1; + break; + } + if (print_effective && eopt >= 0 + && (eopt > 0 || effective != acls[i].a_perm)) + { + if (istty) + { + n = 40 - n; + if (n <= 0) + n = 1; + printf ("%*s", n, " "); + } + else + putchar ('\t'); + printf ("#effective:%s", permstr (effective)); + } + putchar ('\n'); } putchar ('\n'); } diff --git a/winsup/utils/setfacl.c b/winsup/utils/setfacl.c index ba674d009..20a42f33c 100644 --- a/winsup/utils/setfacl.c +++ b/winsup/utils/setfacl.c @@ -1,7 +1,7 @@ /* setfacl.c - Copyright 2000, 2001, 2002, 2003, 2006, 2008, 2009, 2010, 2011, 2014 - Red Hat Inc. + Copyright 2000, 2001, 2002, 2003, 2006, 2008, 2009, 2010, 2011, 2014, + 2015 Red Hat Inc. Written by Corinna Vinschen <vinschen@redhat.com> @@ -53,6 +53,8 @@ typedef enum { SetFromFile } action_t; +int mask_opt = 0; + mode_t getperm (char *in) { if (isdigit ((unsigned char) *in) && !in[1]) @@ -239,7 +241,7 @@ searchace (aclent_t *aclp, int nentries, int type, int id) } int -modacl (aclent_t *tgt, int tcnt, aclent_t *src, int scnt) +delacl (aclent_t *tgt, int tcnt, aclent_t *src, int scnt) { int t, s, i; @@ -249,22 +251,112 @@ modacl (aclent_t *tgt, int tcnt, aclent_t *src, int scnt) (src[s].a_type & (USER | GROUP)) ? src[s].a_id : -1); if (t < 0) return -1; - if (src[s].a_perm == ILLEGAL_MODE) + if (t < tcnt) { - if (t < tcnt) - { - for (i = t + 1; i < tcnt; ++i) - tgt[i - 1] = tgt[i]; - --tcnt; - } + for (i = t + 1; i < tcnt; ++i) + tgt[i - 1] = tgt[i]; + --tcnt; } + } + return tcnt; +} + +int +modacl (aclent_t *tgt, int tcnt, aclent_t *src, int scnt) +{ + int t, s; + int recompute_mask = 0, recompute_def_mask = 0; + int need_mask = 0, need_def_mask = 0; + int has_mask = 0, has_def_mask = 0; + int mask_idx = -1, def_mask_idx = -1; + mode_t mask = 0, def_mask = 0; + + /* Replace or add given acl entries. */ + for (s = 0; s < scnt; ++s) + { + t = searchace (tgt, MAX_ACL_ENTRIES, src[s].a_type, + (src[s].a_type & (USER | GROUP)) ? src[s].a_id : -1); + if (t < 0) + return -1; + tgt[t] = src[s]; + if (t >= tcnt) + ++tcnt; + /* Note if CLASS_OBJ and/or DEF_CLASS_OBJ are present in input. */ + if (src[s].a_type == CLASS_OBJ) + has_mask = 1; + else if (src[s].a_type == DEF_CLASS_OBJ) + has_def_mask = 1; + else if (src[s].a_type & ACL_DEFAULT) + recompute_def_mask = 1; else + recompute_mask = 1; + } + /* Now recompute mask, if requested (default) */ + for (t = 0; t < tcnt; ++t) + { + switch (tgt[t].a_type) { - tgt[t] = src[s]; - if (t >= tcnt) - ++tcnt; + case USER: + case GROUP: + /* Do we need a CLASS_OBJ at all? */ + need_mask = 1; + /*FALLTHRU*/ + case GROUP_OBJ: + /* Compute resulting maximum mask. */ + mask |= tgt[t].a_perm; + break; + case CLASS_OBJ: + /* Do we already have a CLASS_OBJ? */ + mask_idx = t; + break; + case DEF_USER: + case DEF_GROUP: + /* Do we need a DEF_CLASS_OBJ at all? */ + need_def_mask = 1; + /*FALLTHRU*/ + case DEF_GROUP_OBJ: + /* Compute resulting maximum default mask. */ + def_mask |= tgt[t].a_perm; + break; + case DEF_CLASS_OBJ: + /* Do we already have a DEF_CLASS_OBJ? */ + def_mask_idx = t; + break; } } + /* Recompute mask, if requested */ + if (recompute_mask && need_mask && mask_opt >= 0 + && (mask_opt > 0 || !has_mask)) + { + if (mask_idx >= 0) + t = mask_idx; + else + t = searchace (tgt, MAX_ACL_ENTRIES, CLASS_OBJ, -1); + if (t < 0) + return -1; + if (t >= tcnt) + ++tcnt; + tgt[t].a_type = CLASS_OBJ; + tgt[t].a_id = -1; + tgt[t].a_perm = mask; + } + /* Recompute default mask, if requested */ + if (recompute_def_mask && need_def_mask && mask_opt >= 0 + && (mask_opt > 0 || !has_def_mask)) + { + if (def_mask_idx >= 0) + t = def_mask_idx; + else + t = searchace (tgt, MAX_ACL_ENTRIES, DEF_CLASS_OBJ, -1); + if (t < 0) + return -1; + if (t >= tcnt) + ++tcnt; + tgt[t].a_type = DEF_CLASS_OBJ; + tgt[t].a_id = -1; + tgt[t].a_perm = def_mask; + } + return tcnt; } @@ -333,7 +425,7 @@ addmissing (aclent_t *tgt, int tcnt) } int -delacl (aclent_t *tgt, int tcnt, action_t action) +delallacl (aclent_t *tgt, int tcnt, action_t action) { int t; @@ -369,7 +461,7 @@ setfacl (action_t action, const char *path, aclent_t *acls, int cnt) break; case Delete: if ((lcnt = acl (path, GETACL, MAX_ACL_ENTRIES, lacl)) < 0 - || (lcnt = modacl (lacl, lcnt, acls, cnt)) < 0 + || (lcnt = delacl (lacl, lcnt, acls, cnt)) < 0 || (lcnt = acl (path, SETACL, lcnt, lacl)) < 0) { perror (prog_name); @@ -379,7 +471,7 @@ setfacl (action_t action, const char *path, aclent_t *acls, int cnt) case DeleteAll: case DeleteDef: if ((lcnt = acl (path, GETACL, MAX_ACL_ENTRIES, lacl)) < 0 - || (lcnt = delacl (lacl, lcnt, action)) < 0 + || (lcnt = delallacl (lacl, lcnt, action)) < 0 || (lcnt = acl (path, SETACL, lcnt, lacl)) < 0) { perror (prog_name); @@ -404,114 +496,126 @@ static void usage (FILE *stream) { fprintf (stream, "" - "Usage: %s [-r] {-f ACL_FILE | -s acl_entries} FILE...\n" - " %s [-r] {-b|[-d acl_entries] [-m acl_entries]} FILE...\n" - "\n" - "Modify file and directory access control lists (ACLs)\n" - "\n" - " -b, --remove-all remove all extended ACL entries\n" - " -d, --delete delete one or more specified ACL entries\n" - " -f, --file set ACL entries for FILE to ACL entries read\n" - " from a ACL_FILE\n" - " -k, --remove-default\n" - " remove all default ACL entries\n" - " -m, --modify modify one or more specified ACL entries\n" - " -r, --replace replace mask entry with maximum permissions\n" - " needed for the file group class\n" - " -s, --substitute substitute specified ACL entries for the\n" - " ACL of FILE\n" - " -h, --help output usage information and exit\n" - " -V, --version output version information and exit\n" - "\n" - "At least one of (-b, -d, -f, -k, -m, -s) must be specified\n" - "\n", prog_name, prog_name); - if (stream == stdout) - { - printf("" - " Acl_entries are one or more comma-separated ACL entries \n" - " from the following list:\n" - "\n" - " u[ser]::perm\n" - " u[ser]:uid:perm\n" - " g[roup]::perm\n" - " g[roup]:gid:perm\n" - " m[ask]:perm\n" - " o[ther]:perm\n" - "\n" - " Default entries are like the above with the additional\n" - " default identifier. For example: \n" - "\n" - " d[efault]:u[ser]:uid:perm\n" - "\n" - " 'perm' is either a 3-char permissions string in the form\n" - " \"rwx\" with the character - for no permission\n" - " or it is the octal representation of the permissions, a\n" - " value from 0 (equivalent to \"---\") to 7 (\"rwx\").\n" - " 'uid' is a user name or a numerical uid.\n" - " 'gid' is a group name or a numerical gid.\n" - "\n" - "\n" - "For each file given as parameter, %s will either replace its\n" - "complete ACL (-s, -f), or it will add, modify, or delete ACL\n" - "entries.\n" - "\n" - "The following options are supported:\n" - "\n" - "-b Remove all extended ACL entries. The base ACL entries of the\n" - " owner, group and others are retained.\n" - "\n" - "-d Delete one or more specified entries from the file's ACL.\n" - " The owner, group and others entries must not be deleted.\n" - " Acl_entries to be deleted should be specified without\n" - " permissions, as in the following list:\n" - "\n" - " u[ser]:uid[:]\n" - " g[roup]:gid[:]\n" - " m[ask][:]\n" - " d[efault]:u[ser][:uid]\n" - " d[efault]:g[roup][:gid]\n" - " d[efault]:m[ask][:]\n" - " d[efault]:o[ther][:]\n" - "\n" - "-f Take the Acl_entries from ACL_FILE one per line. Whitespace\n" - " characters are ignored, and the character \"#\" may be used\n" - " to start a comment. The special filename \"-\" indicates\n" - " reading from stdin.\n" - " Required entries are\n" - " - One user entry for the owner of the file.\n" - " - One group entry for the group of the file.\n" - " - One other entry.\n" - " If additional user and group entries are given:\n" - " - A mask entry for the file group class of the file.\n" - " - No duplicate user or group entries with the same uid/gid.\n" - " If it is a directory:\n" - " - One default user entry for the owner of the file.\n" - " - One default group entry for the group of the file.\n" - " - One default mask entry for the file group class.\n" - " - One default other entry.\n" - "\n" - "-k Remove all default ACL entries. If no default ACL entries\n" - " exist, no warnings are issued.\n" - "\n" - "-m Add or modify one or more specified ACL entries.\n" - " Acl_entries is a comma-separated list of entries from the \n" - " same list as above.\n" - "\n" - "-r Causes the permissions specified in the mask entry to be\n" - " ignored and replaced by the maximum permissions needed for\n" - " the file group class.\n" - "\n" - "-s Like -f, but substitute the file's ACL with Acl_entries\n" - " specified in a comma-separated list on the command line.\n" - "\n" - "While the -d and -m options may be used in the same command, the\n" - "-f and -s options may be used only exclusively.\n" - "\n" - "Directories may contain default ACL entries. Files created\n" - "in a directory that contains default ACL entries will have\n" - "permissions according to the combination of the current umask,\n" - "the explicit permissions requested and the default ACL entries\n" - "\n", prog_name); + "Usage: %s {-f ACL_FILE | -s acl_entries} FILE...\n" + " %s {-b|[-x acl_entries] [-m acl_entries]} FILE...\n" + "\n" + "Modify file and directory access control lists (ACLs)\n" + "\n" + " -b, --remove-all remove all extended ACL entries\n" + " -x, --delete delete one or more specified ACL entries\n" + " -f, --file set ACL entries for FILE to ACL entries read\n" + " from ACL_FILE\n" + " -k, --remove-default remove all default ACL entries\n" + " -m, --modify modify one or more specified ACL entries\n" + " -n, --no-mask don't recalculate the effective rights mask\n" + " --mask do recalculate the effective rights mask\n" + " -s, --substitute substitute specified ACL entries on FILE\n" + " -V, --version print version and exit\n" + " -h, --help this help text\n" + "\n" + "At least one of (-b, -x, -f, -k, -m, -s) must be specified\n" + "\n", prog_name, prog_name); + if (stream == stdout) + { + printf("" + " Acl_entries are one or more comma-separated ACL entries \n" + " from the following list:\n" + "\n" + " u[ser]::perm\n" + " u[ser]:uid:perm\n" + " g[roup]::perm\n" + " g[roup]:gid:perm\n" + " m[ask]:perm\n" + " o[ther]:perm\n" + "\n" + " Default entries are like the above with the additional\n" + " default identifier. For example: \n" + "\n" + " d[efault]:u[ser]:uid:perm\n" + "\n" + " 'perm' is either a 3-char permissions string in the form\n" + " \"rwx\" with the character - for no permission\n" + " or it is the octal representation of the permissions, a\n" + " value from 0 (equivalent to \"---\") to 7 (\"rwx\").\n" + " 'uid' is a user name or a numerical uid.\n" + " 'gid' is a group name or a numerical gid.\n" + "\n" + "\n" + "For each file given as parameter, %s will either replace its\n" + "complete ACL (-s, -f), or it will add, modify, or delete ACL\n" + "entries.\n" + "\n" + "The following options are supported:\n" + "\n" + "-b, --remove-all\n" + " Remove all extended ACL entries. The base ACL entries of the\n" + " owner, group and others are retained.\n" + "\n" + "-x, --delete\n" + " Delete one or more specified entries from the file's ACL.\n" + " The owner, group and others entries must not be deleted.\n" + " Acl_entries to be deleted should be specified without\n" + " permissions, as in the following list:\n" + "\n" + " u[ser]:uid[:]\n" + " g[roup]:gid[:]\n" + " m[ask][:]\n" + " d[efault]:u[ser][:uid]\n" + " d[efault]:g[roup][:gid]\n" + " d[efault]:m[ask][:]\n" + " d[efault]:o[ther][:]\n" + "\n" + "-f, --file\n" + " Take the Acl_entries from ACL_FILE one per line. Whitespace\n" + " characters are ignored, and the character \"#\" may be used\n" + " to start a comment. The special filename \"-\" indicates\n" + " reading from stdin.\n" + " Required entries are\n" + " - One user entry for the owner of the file.\n" + " - One group entry for the group of the file.\n" + " - One other entry.\n" + " If additional user and group entries are given:\n" + " - A mask entry for the file group class of the file.\n" + " - No duplicate user or group entries with the same uid/gid.\n" + " If it is a directory:\n" + " - One default user entry for the owner of the file.\n" + " - One default group entry for the group of the file.\n" + " - One default mask entry for the file group class.\n" + " - One default other entry.\n" + "\n" + "-k, --remove-default\n" + " Remove all default ACL entries. If no default ACL entries exist,\n" + " no warnings are issued.\n" + "\n" + "-m, --modify\n" + " Add or modify one or more specified ACL entries. Acl_entries is\n" + " a comma-separated list of entries from the same list as above.\n" + "\n" + "-n, --no-mask\n" + " Valid in conjunction with -m. Do not recalculate the effective\n" + " rights mask. The default behavior of setfacl is to recalculate the\n" + " ACL mask entry, unless a mask entry was explicitly given. The\n" + " mask entry is set to the union of all permissions of the owning\n" + " group, and all named user and group entries. (These are exactly\n" + " the entries affected by the mask entry).\n" + "\n" + "--mask\n" + " Valid in conjunction with -m. Do recalculate the effective rights\n" + " mask, even if an ACL mask entry was explicitly given. (See the\n" + " -n option.)\n" + "\n" + "-s, --substitute\n" + " Like -f, but substitute the file's ACL with ACL entries\n" + " specified in a comma-separated list on the command line.\n" + "\n" + "While the -x and -m options may be used in the same command, the\n" + "-f and -s options may be used only exclusively.\n" + "\n" + "Directories may contain default ACL entries. Files created\n" + "in a directory that contains default ACL entries will have\n" + "permissions according to the combination of the current umask,\n" + "the explicit permissions requested and the default ACL entries\n" + "\n", prog_name); } else fprintf(stream, "Try '%s --help' for more information.\n", prog_name); @@ -519,17 +623,19 @@ usage (FILE *stream) struct option longopts[] = { {"remove-all", no_argument, NULL, 'b'}, - {"delete", required_argument, NULL, 'd'}, + {"delete", required_argument, NULL, 'x'}, {"file", required_argument, NULL, 'f'}, {"remove-default", no_argument, NULL, 'k'}, {"modify", required_argument, NULL, 'm'}, + {"no-mask", required_argument, NULL, 'n'}, + {"mask", required_argument, NULL, '\n'}, {"replace", no_argument, NULL, 'r'}, {"substitute", required_argument, NULL, 's'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {0, no_argument, NULL, 0} }; -const char *opts = "bd:f:hkm:rs:V"; +const char *opts = "bd:f:hkm:nrs:Vx"; static void print_version () @@ -550,7 +656,6 @@ main (int argc, char **argv) { int c; action_t action = NoAction; - int ropt = 0; aclent_t acls[MAX_ACL_ENTRIES]; int aclidx = 0; int ret = 0; @@ -570,7 +675,8 @@ main (int argc, char **argv) return 1; } break; - case 'd': + case 'd': /* Backward compat */ + case 'x': if (action == NoAction) action = Delete; else if (action == Modify) @@ -628,14 +734,13 @@ main (int argc, char **argv) return 2; } break; + case 'n': + mask_opt = -1; + break; + case '\n': + mask_opt = 1; + break; case 'r': - if (!ropt) - ropt = 1; - else - { - usage (stderr); - return 1; - } break; case 's': if (action == NoAction) |