[newlib-cygwin] Add mask recomputation as on Linux

Corinna Vinschen corinna@sourceware.org
Thu Apr 16 15:58:00 GMT 2015


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=baacff7c79d9837d59e1b1c2060eea054e534e5c

commit baacff7c79d9837d59e1b1c2060eea054e534e5c
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Thu Apr 16 17:57:53 2015 +0200

    Add mask recomputation as on Linux
    
            * 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.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/doc/ChangeLog   |   4 +
 winsup/doc/utils.xml   | 100 +++++++------
 winsup/utils/ChangeLog |  16 +++
 winsup/utils/setfacl.c | 375 +++++++++++++++++++++++++++++++------------------
 4 files changed, 314 insertions(+), 181 deletions(-)

diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog
index 05cf519..fdf3708 100644
--- a/winsup/doc/ChangeLog
+++ b/winsup/doc/ChangeLog
@@ -1,5 +1,9 @@
 2015-04-16  Corinna Vinschen  <corinna@vinschen.de>
 
+	* utils.xml (setfacl): Show new option output.
+
+2015-04-16  Corinna Vinschen  <corinna@vinschen.de>
+
 	* utils.xml (getfacl): Show new option output.
 
 2015-04-10  Corinna Vinschen  <corinna@vinschen.de>
diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index d711cf2..09df8e0 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -1698,34 +1698,31 @@ Example: regtool.exe get '\user\software\Microsoft\Clock\iFormat'
     <title>setfacl</title>
 
     <screen>
-Usage: setfacl [-r] {-f ACL_FILE | -s acl_entries} FILE...
-       setfacl [-r] {-b|[-d acl_entries] [-m acl_entries]} FILE...
-
-
-Modify file and directory access control lists (ACLs)
-
-  -b, --remove-all remove all extended ACL entries
-  -d, --delete     delete one or more specified ACL entries
-  -f, --file       set ACL entries for FILE to ACL entries read
-                   from a ACL_FILE
-  -k, --remove-default
-		   remove all default ACL entries
-  -m, --modify     modify one or more specified ACL entries
-  -r, --replace    replace mask entry with maximum permissions
-                   needed for the file group class
-  -s, --substitute substitute specified ACL entries for the
-                   ACL of FILE
-  -h, --help       output usage information and exit
-  -V, --version    output version information and exit
-
-At least one of (-b, -d, -f, -k, -m, -s) must be specified
+Usage: %s {-f ACL_FILE | -s acl_entries} FILE...\n"
+       %s {-b|[-x acl_entries] [-m acl_entries]} FILE...\n"
+
+Modify file and directory access control lists (ACLs)\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"
+
+At least one of (-b, -x, -f, -k, -m, -s) must be specified\n"
 </screen>
 
     <para> For each file given as parameter, <command>setfacl</command> will
       either replace its complete ACL (<literal>-s</literal>,
       <literal>-f</literal>), or it will add, modify, or delete ACL entries.
-      For more information on Cygwin and Windows ACLs, see see <xref
-      linkend="ntsec"/> in the Cygwin User's Guide. </para>
+      For more information on Cygwin and Windows ACLs, see
+      <xref linkend="ntsec"/> in the Cygwin User's Guide. </para>
 
     <para> Acl_entries are one or more comma-separated ACL entries from the
       following list:
@@ -1752,13 +1749,14 @@ At least one of (-b, -d, -f, -k, -m, -s) must be specified
 
     <para> The following options are supported: </para>
 
-    <para> <literal>-b</literal> Remove all extended ACL entries.  The base
-      ACL entries of the owner, group and others are retained.</para>
+    <para> <literal>-b</literal>,<literal>--remove-all</literal> Remove all
+      extended ACL entries.  The base ACL entries of the owner, group and
+      others are retained.</para>
 
-    <para> <literal>-d</literal> Delete one or more specified entries from the
-      file's ACL. The owner, group and others entries must not be deleted.
-      Acl_entries to be deleted should be specified without permissions, as in
-      the following list:
+    <para> <literal>-x</literal>,<literal>--delete</literal> Delete one or
+      more specified entries from the file's ACL. The owner, group and others
+      entries must not be deleted.  Acl_entries to be deleted should be
+      specified without permissions, as in the following list:
       <screen>
          u[ser]:uid[:]
          g[roup]:gid[:]
@@ -1769,11 +1767,12 @@ At least one of (-b, -d, -f, -k, -m, -s) must be specified
          d[efault]:o[ther][:]
 </screen> </para>
 
-    <para> <literal>-f</literal> Take the Acl_entries from ACL_FILE one per
-      line. Whitespace characters are ignored, and the character "#" may be
-      used to start a comment. The special filename "-" indicates reading from
-      stdin. Note that you can use this with <command>getfacl</command> and
-      <command>setfacl</command> to copy ACLs from one file to another:
+    <para> <literal>-f</literal>,<literal>--file</literal> Take the Acl_entries
+      from ACL_FILE one per line. Whitespace characters are ignored, and the
+      character "#" may be used to start a comment. The special filename "-"
+      indicates reading from stdin. Note that you can use this with
+      <command>getfacl</command> and <command>setfacl</command> to copy ACLs
+      from one file to another:
       <screen>
 $ getfacl source_file | setfacl -f - target_file
 </screen> </para>
@@ -1789,22 +1788,31 @@ $ getfacl source_file | setfacl -f - target_file
       file, one default group entry for the group of the file, one default mask
       entry for the file group class, and one default other entry. </para>
 
-    <para> <literal>-k</literal> Remove all default ACL entries. If no default
-      ACL entries exist, no warnings are issued. </para>
+    <para> <literal>-k</literal>,<literal>--remove-default</literal> Remove all
+      default ACL entries. If no default ACL entries exist, no warnings are
+      issued. </para>
 
-    <para> <literal>-m</literal> Add or modify one or more specified ACL
-      entries. Acl_entries is a comma-separated list of entries from the same
-      list as above. </para>
+    <para> <literal>-m</literal>,<literal>--modify</literal> Add or modify one
+      or more specified ACL entries. Acl_entries is a comma-separated list of
+      entries from the same list as above. </para>
 
-    <para> <literal>-r</literal> Causes the permissions specified in the mask
-      entry to be ignored and replaced by the maximum permissions needed for
-      the file group class. </para>
+    <para> <literal>-n</literal>,<literal>--no-mask</literal> Valid in
+      conjunction with -m.  Do not recalculate the effective rights mask.
+      The default behavior of setfacl is to recalculate the ACL mask entry,
+      unless a mask entry was explicitly given.  The mask entry is set to
+      the union of all permissions of the owning group, and all named user
+      and group entries.  (These are exactly the entries affected by the
+      mask entry). </para>
 
-    <para> <literal>-s</literal> Like <literal>-f</literal>, but substitute the
-      file's ACL with Acl_entries specified in a comma-separated list on the
-      command line. </para>
+    <para> <literal>--mask</literal> Valid in conjunction with -m.  Do
+      recalculate the effective rights mask, even if an ACL mask entry was
+      explicitly given. (See the -n option.) </para>
 
-    <para> While the <literal>-d</literal> and <literal>-m</literal> options
+    <para> <literal>-s</literal>,<literal>--substitute</literal> Like
+      <literal>-f</literal>, but substitute the file's ACL with Acl_entries
+      specified in a comma-separated list on the command line. </para>
+
+    <para> While the <literal>-x</literal> and <literal>-m</literal> options
       may be used in the same command, the <literal>-f</literal> and
       <literal>-s</literal> options may be used only exclusively. </para>
 
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog
index 5e7025d..a48f869 100644
--- a/winsup/utils/ChangeLog
+++ b/winsup/utils/ChangeLog
@@ -1,5 +1,21 @@
 2015-04-16  Corinna Vinschen  <corinna@vinschen.de>
 
+	* 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.
+
+2015-04-16  Corinna Vinschen  <corinna@vinschen.de>
+
 	* 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
diff --git a/winsup/utils/setfacl.c b/winsup/utils/setfacl.c
index ba674d0..20a42f3 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)



More information about the Cygwin-cvs mailing list