From nobody@FreeBSD.org  Tue Mar  1 16:55:49 2011
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 55558106564A
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  1 Mar 2011 16:55:49 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 441458FC13
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  1 Mar 2011 16:55:49 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id p21GtnMq000662
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 1 Mar 2011 16:55:49 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id p21Gtm1U000661;
	Tue, 1 Mar 2011 16:55:48 GMT
	(envelope-from nobody)
Message-Id: <201103011655.p21Gtm1U000661@red.freebsd.org>
Date: Tue, 1 Mar 2011 16:55:48 GMT
From: Shawn Webb <lattera@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Add Recursive Functionality to setfacl
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         155163
>Category:       bin
>Synopsis:       [patch] Add Recursive Functionality to setfacl(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    trasz
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 01 17:00:17 UTC 2011
>Closed-Date:    
>Last-Modified:  Sun May 04 04:11:15 UTC 2014
>Originator:     Shawn Webb
>Release:        8.2
>Organization:
HotlinkHR
>Environment:
FreeBSD shawnwork 8.2-RELEASE FreeBSD 8.2-RELEASE #1 r218738=2ec1cbd-dirty: Tue Feb 22 15:05:26 MST 2011     shawn@shawnwork:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
The setfacl command is missing recursive functionality. The proposed and attached patch implements said functionality.

Included in the patch is also an enhancement to the -k switch. Solaris allows for zero-number ACL entries on objects stored in ZFS datasets via `chmod A= /path/to/file". FreeBSD does not support zero-number ACL entries so I give owner@ full permissions. This enhancement depends upon another bug report I sent that allows use of ACL sets (read_set, write_set, modify_set, full_set) in ZFS NFSv4 ACLs.
>How-To-Repeat:

>Fix:
Patch included.

Patch attached with submission follows:

diff --git a/bin/setfacl/setfacl.c b/bin/setfacl/setfacl.c
index a0f937c..2532188 100644
--- a/bin/setfacl/setfacl.c
+++ b/bin/setfacl/setfacl.c
@@ -32,6 +32,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/stat.h>
 #include <sys/acl.h>
 #include <sys/queue.h>
+#include <fts.h>
+#include <dirent.h>
 
 #include <err.h>
 #include <errno.h>
@@ -44,6 +46,8 @@ __FBSDID("$FreeBSD$");
 
 static void	add_filename(const char *filename);
 static void	usage(void);
+static void	recurse_directory(char *const *paths, int r_flag, int l_flag, int big_h_flag);
+static acl_t	remove_invalid_inherit(const char *path, acl_t acl, int l_flag);
 
 static void
 add_filename(const char *filename)
@@ -62,34 +66,112 @@ add_filename(const char *filename)
 static void
 usage(void)
 {
-
-	fprintf(stderr, "usage: setfacl [-bdhkn] [-a position entries] "
+	fprintf(stderr, "usage: setfacl [-bdhkLnR] [-a position entries] "
 	    "[-m entries] [-M file] [-x entries] [-X file] [file ...]\n");
 	exit(1);
 }
 
+static void
+recurse_directory(char *const *paths, int r_flag, int l_flag, int big_h_flag)
+{
+	FTS *ftsp;
+	FTSENT *p, *chp;
+	int fts_options = FTS_NOCHDIR;
+	unsigned int i;
+	
+	fts_options |= (l_flag == 1) ? FTS_LOGICAL : FTS_PHYSICAL;
+	if (big_h_flag)
+		fts_options |= FTS_COMFOLLOW;
+	
+	if (r_flag)
+	{
+		ftsp = fts_open(paths, fts_options, NULL);
+		if (ftsp == NULL)
+			return;
+		
+		chp = fts_children(ftsp, 0);
+		if (chp == NULL)
+			return;
+		
+		while ((p = fts_read(ftsp)) != NULL) {
+			if (l_flag == 0 && p->fts_info & FTS_D)
+				continue;
+			else if (l_flag == 1 && p->fts_info & FTS_DP)
+				continue;
+			
+			add_filename(strdup(p->fts_path));
+		}
+		
+		fts_close(ftsp);
+	} else
+		for (i = 0; paths[i] != NULL; i++)
+			add_filename(paths[i]);
+}
+
+static acl_t
+remove_invalid_inherit(const char *path, acl_t acl, int l_flag)
+{
+	acl_t acl_new;
+	int acl_brand;
+	acl_entry_t entry;
+	int entry_id;
+	acl_flagset_t flagset;
+	struct stat sb;
+	
+	acl_get_brand_np(acl, &acl_brand);
+	if (acl_brand != ACL_BRAND_NFS4)
+		return acl;
+	
+	if (l_flag == 1) {
+		if (stat(path, &sb) == -1)
+			return acl;
+	} else
+		if (lstat(path, &sb) == -1)
+			return acl;
+	
+	if (S_ISDIR(sb.st_mode) != 0)
+		return acl;
+	
+	acl_new = acl_dup(acl);
+	
+	entry_id = ACL_FIRST_ENTRY;
+	while (acl_get_entry(acl_new, entry_id, &entry) == 1) {
+		entry_id = ACL_NEXT_ENTRY;
+		acl_get_flagset_np(entry, &flagset);
+		if (acl_get_flag_np(flagset, ACL_ENTRY_INHERIT_ONLY)) {
+			acl_delete_entry(acl_new, entry);
+			continue;
+		}
+		acl_delete_flag_np(flagset, ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | ACL_ENTRY_NO_PROPAGATE_INHERIT);
+	}
+	
+	return acl_new;
+}
+
 int
 main(int argc, char *argv[])
 {
-	acl_t acl;
+	acl_t acl, acl_backup;
 	acl_type_t acl_type;
 	char filename[PATH_MAX];
-	int local_error, carried_error, ch, i, entry_number, ret;
-	int h_flag;
+	int local_error, carried_error, ch, entry_number, ret;
+	int h_flag, r_flag, l_flag, big_h_flag;
 	struct sf_file *file;
 	struct sf_entry *entry;
-	const char *fn_dup;
+	char *fn_dup;
 	char *end;
+	char **files=NULL;
+	unsigned int numfiles=0;
 	struct stat sb;
 
 	acl_type = ACL_TYPE_ACCESS;
 	carried_error = local_error = 0;
-	h_flag = have_mask = have_stdin = n_flag = need_mask = 0;
+	h_flag = have_mask = have_stdin = n_flag = need_mask = r_flag = l_flag = big_h_flag = 0;
 
 	TAILQ_INIT(&entrylist);
 	TAILQ_INIT(&filelist);
 
-	while ((ch = getopt(argc, argv, "M:X:a:bdhkm:nx:")) != -1)
+	while ((ch = getopt(argc, argv, "HLRM:X:a:bdhkm:nx:")) != -1)
 		switch(ch) {
 		case 'M':
 			entry = zmalloc(sizeof(struct sf_entry));
@@ -167,6 +249,15 @@ main(int argc, char *argv[])
 			}
 			TAILQ_INSERT_TAIL(&entrylist, entry, next);
 			break;
+		case 'R':
+			r_flag = 1;
+			break;
+		case 'L':
+			l_flag = 1;
+			break;
+		case 'H':
+			big_h_flag = 1;
+			break;
 		default:
 			usage();
 			break;
@@ -189,11 +280,18 @@ main(int argc, char *argv[])
 			fn_dup = strdup(filename);
 			if (fn_dup == NULL)
 				err(1, "strdup() failed");
-			add_filename(fn_dup);
+			files = realloc(files, ++numfiles * sizeof(char **));
+			if (files == NULL)
+				err(1, "realloc() failed");
+			files[numfiles-1] = (char *)fn_dup;
 		}
+		
+		files = realloc(files, ++numfiles * sizeof(char **));
+		files[numfiles-1] = NULL;
 	} else
-		for (i = 0; i < argc; i++)
-			add_filename(argv[i]);
+		files = argv;
+	
+	recurse_directory(files, r_flag, l_flag, big_h_flag);
 
 	/* cycle through each file */
 	TAILQ_FOREACH(file, &filelist, next) {
@@ -201,14 +299,12 @@ main(int argc, char *argv[])
 
 		if (stat(file->filename, &sb) == -1) {
 			warn("%s: stat() failed", file->filename);
-			carried_error++;
 			continue;
 		}
 
 		if (acl_type == ACL_TYPE_DEFAULT && S_ISDIR(sb.st_mode) == 0) {
 			warnx("%s: default ACL may only be set on a directory",
 			    file->filename);
-			carried_error++;
 			continue;
 		}
 
@@ -220,7 +316,6 @@ main(int argc, char *argv[])
 			if (acl_type == ACL_TYPE_DEFAULT) {
 				warnx("%s: there are no default entries "
 			           "in NFSv4 ACLs", file->filename);
-				carried_error++;
 				continue;
 			}
 			acl_type = ACL_TYPE_NFS4;
@@ -243,7 +338,6 @@ main(int argc, char *argv[])
 			else
 				warn("%s: acl_get_file() failed",
 				    file->filename);
-			carried_error++;
 			continue;
 		}
 
@@ -254,12 +348,24 @@ main(int argc, char *argv[])
 
 			switch(entry->op) {
 			case OP_ADD_ACL:
+				acl_backup = entry->acl;
+				entry->acl = remove_invalid_inherit(file->filename, entry->acl, l_flag);
 				local_error += add_acl(entry->acl,
 				    entry->entry_number, &acl, file->filename);
+				if (entry->acl != acl_backup) {
+					acl_free(entry->acl);
+					entry->acl = acl_backup;
+				}
 				break;
 			case OP_MERGE_ACL:
+				acl_backup = entry->acl;
+				entry->acl = remove_invalid_inherit(file->filename, entry->acl, l_flag);
 				local_error += merge_acl(entry->acl, &acl,
 				    file->filename);
+				if (entry->acl != acl_backup) {
+					acl_free(entry->acl);
+					entry->acl = acl_backup;
+				}
 				need_mask = 1;
 				break;
 			case OP_REMOVE_EXT:
@@ -267,20 +373,20 @@ main(int argc, char *argv[])
 				need_mask = 0;
 				break;
 			case OP_REMOVE_DEF:
-				if (acl_type == ACL_TYPE_NFS4) {
-					warnx("%s: there are no default entries in NFSv4 ACLs; "
-					    "cannot remove", file->filename);
-					local_error++;
-					break;
-				}
-				if (acl_delete_def_file(file->filename) == -1) {
-					warn("%s: acl_delete_def_file() failed",
-					    file->filename);
-					local_error++;
+				if (acl_type != ACL_TYPE_NFS4) {
+					if (acl_delete_def_file(file->filename) == -1) {
+						warn("%s: acl_delete_def_file() failed",
+							file->filename);
+						local_error++;
+					}
+					if (acl_type == ACL_TYPE_DEFAULT)
+						local_error += remove_default(&acl,
+							file->filename);
+				} else {
+					/* FreeBSD does not support a zero amount of ACL entries like Solaris, give owner@ full permissions */
+					acl_free(acl);
+					acl = acl_from_text("owner@:full_set::allow");
 				}
-				if (acl_type == ACL_TYPE_DEFAULT)
-					local_error += remove_default(&acl,
-					    file->filename);
 				need_mask = 0;
 				break;
 			case OP_REMOVE_ACL:


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->trasz 
Responsible-Changed-By: trasz 
Responsible-Changed-When: Wed Mar 2 07:25:28 UTC 2011 
Responsible-Changed-Why:  
I'll take it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=155163 

From: Claudiu Vasadi <c.vasadi@myphotobook.de>
To: bug-followup@FreeBSD.org, lattera@gmail.com
Cc:  
Subject: Re: bin/155163: [patch] Add Recursive Functionality to setfacl
Date: Wed, 24 Apr 2013 10:02:35 +0200

 This is a multi-part message in MIME format.
 --------------070804040701010903090102
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 8bit
 
 Hi,
 
 I tried the patch on a 9.0-RELEASE and it applies without any problems.
 On 9.1-STABLE (r246451) however, that patch had to be adjusted a bit
 (see the new patch below). Attached, you may also find the patch for the
 man page.
 
 Feel free to modify if necessary.
 
 PS: Any chance this will be imported?
 
 -- 
 Claudiu Vasadi
 System Administrator
 
 myphotobook
 Oranienstrae 183
 10999 Berlin
 Germany
 
 Tel.:+49 (0)30 616 508 120
 Fax: +49 (0)30 616 508 250
 c.vasadi@myphotobook.de
 
 Authorised Executives: Vanessa Dill
 Trade Register: HRB 94377, Berlin
 
 
 --------------070804040701010903090102
 Content-Type: text/plain; charset=us-ascii;
  name="patch_acl_recursive_9.1-STABLE_r246451.txt"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="patch_acl_recursive_9.1-STABLE_r246451.txt"
 
 --- setfacl.c_bak	2013-04-24 00:48:57.006930908 +0000
 +++ setfacl.c	2013-04-24 00:56:31.067008935 +0000
 @@ -32,6 +32,8 @@
  #include <sys/stat.h>
  #include <sys/acl.h>
  #include <sys/queue.h>
 +#include <fts.h>
 +#include <dirent.h>
  
  #include <err.h>
  #include <errno.h>
 @@ -44,6 +46,8 @@
  
  static void	add_filename(const char *filename);
  static void	usage(void);
 +static void	recurse_directory(char *const *paths, int r_flag, int l_flag, int big_h_flag);
 +static acl_t	remove_invalid_inherit(const char *path, acl_t acl, int l_flag);
  
  static void
  add_filename(const char *filename)
 @@ -62,35 +66,113 @@
  static void
  usage(void)
  {
 -
 -	fprintf(stderr, "usage: setfacl [-bdhkn] [-a position entries] "
 +	fprintf(stderr, "usage: setfacl [-bdhkLnR] [-a position entries] "
  	    "[-m entries] [-M file] [-x entries] [-X file] [file ...]\n");
  	exit(1);
  }
  
 +static void
 +recurse_directory(char *const *paths, int r_flag, int l_flag, int big_h_flag)
 +{
 +	FTS *ftsp;
 +	FTSENT *p, *chp;
 +	int fts_options = FTS_NOCHDIR;
 +	unsigned int i;
 +	
 +	fts_options |= (l_flag == 1) ? FTS_LOGICAL : FTS_PHYSICAL;
 +	if (big_h_flag)
 +		fts_options |= FTS_COMFOLLOW;
 +	
 +	if (r_flag)
 +	{
 +		ftsp = fts_open(paths, fts_options, NULL);
 +		if (ftsp == NULL)
 +			return;
 +		
 +		chp = fts_children(ftsp, 0);
 +		if (chp == NULL)
 +			return;
 +		
 +		while ((p = fts_read(ftsp)) != NULL) {
 +			if (l_flag == 0 && p->fts_info & FTS_D)
 +				continue;
 +			else if (l_flag == 1 && p->fts_info & FTS_DP)
 +				continue;
 +			
 +			add_filename(strdup(p->fts_path));
 +		}
 +		
 +		fts_close(ftsp);
 +	} else
 +		for (i = 0; paths[i] != NULL; i++)
 +			add_filename(paths[i]);
 +}
 +
 +static acl_t
 +remove_invalid_inherit(const char *path, acl_t acl, int l_flag)
 +{
 +	acl_t acl_new;
 +	int acl_brand;
 +	acl_entry_t entry;
 +	int entry_id;
 +	acl_flagset_t flagset;
 +	struct stat sb;
 +	
 +	acl_get_brand_np(acl, &acl_brand);
 +	if (acl_brand != ACL_BRAND_NFS4)
 +		return acl;
 +	
 +	if (l_flag == 1) {
 +		if (stat(path, &sb) == -1)
 +			return acl;
 +	} else
 +		if (lstat(path, &sb) == -1)
 +			return acl;
 +	
 +	if (S_ISDIR(sb.st_mode) != 0)
 +		return acl;
 +	
 +	acl_new = acl_dup(acl);
 +	
 +	entry_id = ACL_FIRST_ENTRY;
 +	while (acl_get_entry(acl_new, entry_id, &entry) == 1) {
 +		entry_id = ACL_NEXT_ENTRY;
 +		acl_get_flagset_np(entry, &flagset);
 +		if (acl_get_flag_np(flagset, ACL_ENTRY_INHERIT_ONLY)) {
 +			acl_delete_entry(acl_new, entry);
 +			continue;
 +		}
 +		acl_delete_flag_np(flagset, ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | ACL_ENTRY_NO_PROPAGATE_INHERIT);
 +	}
 +	
 +	return acl_new;
 +}
 +
  int
  main(int argc, char *argv[])
  {
 -	acl_t acl;
 +	acl_t acl, acl_backup;
  	acl_type_t acl_type;
  	acl_entry_t unused_entry;
  	char filename[PATH_MAX];
 -	int local_error, carried_error, ch, i, entry_number, ret;
 -	int h_flag;
 +	int local_error, carried_error, ch, entry_number, ret;
 +	int h_flag, r_flag, l_flag, big_h_flag;
  	struct sf_file *file;
  	struct sf_entry *entry;
 -	const char *fn_dup;
 +	char *fn_dup;
  	char *end;
 +	char **files=NULL;
 +	unsigned int numfiles=0;
  	struct stat sb;
  
  	acl_type = ACL_TYPE_ACCESS;
  	carried_error = local_error = 0;
 -	h_flag = have_mask = have_stdin = n_flag = need_mask = 0;
 +	h_flag = have_mask = have_stdin = n_flag = need_mask = r_flag = l_flag = big_h_flag = 0;
  
  	TAILQ_INIT(&entrylist);
  	TAILQ_INIT(&filelist);
  
 -	while ((ch = getopt(argc, argv, "M:X:a:bdhkm:nx:")) != -1)
 +	while ((ch = getopt(argc, argv, "HLRM:X:a:bdhkm:nx:")) != -1)
  		switch(ch) {
  		case 'M':
  			entry = zmalloc(sizeof(struct sf_entry));
 @@ -168,6 +250,15 @@
  			}
  			TAILQ_INSERT_TAIL(&entrylist, entry, next);
  			break;
 +		case 'R':
 +			r_flag = 1;
 +			break;
 +		case 'L':
 +			l_flag = 1;
 +			break;
 +		case 'H':
 +			big_h_flag = 1;
 +			break;
  		default:
  			usage();
  			break;
 @@ -190,11 +281,18 @@
  			fn_dup = strdup(filename);
  			if (fn_dup == NULL)
  				err(1, "strdup() failed");
 -			add_filename(fn_dup);
 +			files = realloc(files, ++numfiles * sizeof(char **));
 +			if (files == NULL)
 +				err(1, "realloc() failed");
 +			files[numfiles-1] = (char *)fn_dup;
  		}
 +		
 +		files = realloc(files, ++numfiles * sizeof(char **));
 +		files[numfiles-1] = NULL;
  	} else
 -		for (i = 0; i < argc; i++)
 -			add_filename(argv[i]);
 +		files = argv;
 +	
 +	recurse_directory(files, r_flag, l_flag, big_h_flag);
  
  	/* cycle through each file */
  	TAILQ_FOREACH(file, &filelist, next) {
 @@ -202,14 +300,12 @@
  
  		if (stat(file->filename, &sb) == -1) {
  			warn("%s: stat() failed", file->filename);
 -			carried_error++;
  			continue;
  		}
  
  		if (acl_type == ACL_TYPE_DEFAULT && S_ISDIR(sb.st_mode) == 0) {
  			warnx("%s: default ACL may only be set on a directory",
  			    file->filename);
 -			carried_error++;
  			continue;
  		}
  
 @@ -221,7 +317,6 @@
  			if (acl_type == ACL_TYPE_DEFAULT) {
  				warnx("%s: there are no default entries "
  			           "in NFSv4 ACLs", file->filename);
 -				carried_error++;
  				continue;
  			}
  			acl_type = ACL_TYPE_NFS4;
 @@ -244,7 +339,6 @@
  			else
  				warn("%s: acl_get_file() failed",
  				    file->filename);
 -			carried_error++;
  			continue;
  		}
  
 @@ -255,12 +349,24 @@
  
  			switch(entry->op) {
  			case OP_ADD_ACL:
 +				acl_backup = entry->acl;
 +				entry->acl = remove_invalid_inherit(file->filename, entry->acl, l_flag);
  				local_error += add_acl(entry->acl,
  				    entry->entry_number, &acl, file->filename);
 +				if (entry->acl != acl_backup) {
 +					acl_free(entry->acl);
 +					entry->acl = acl_backup;
 +				}
  				break;
  			case OP_MERGE_ACL:
 +				acl_backup = entry->acl;
 +				entry->acl = remove_invalid_inherit(file->filename, entry->acl, l_flag);
  				local_error += merge_acl(entry->acl, &acl,
  				    file->filename);
 +				if (entry->acl != acl_backup) {
 +					acl_free(entry->acl);
 +					entry->acl = acl_backup;
 +				}
  				need_mask = 1;
  				break;
  			case OP_REMOVE_EXT:
 @@ -279,12 +385,7 @@
  				need_mask = 0;
  				break;
  			case OP_REMOVE_DEF:
 -				if (acl_type == ACL_TYPE_NFS4) {
 -					warnx("%s: there are no default entries in NFSv4 ACLs; "
 -					    "cannot remove", file->filename);
 -					local_error++;
 -					break;
 -				}
 +				if (acl_type != ACL_TYPE_NFS4) {
  				if (acl_delete_def_file(file->filename) == -1) {
  					warn("%s: acl_delete_def_file() failed",
  					    file->filename);
 @@ -293,6 +394,11 @@
  				if (acl_type == ACL_TYPE_DEFAULT)
  					local_error += remove_default(&acl,
  					    file->filename);
 +				} else {
 +					/* FreeBSD does not support a zero amount of ACL entries like Solaris, give owner@ full permissions */
 +					acl_free(acl);
 +					acl = acl_from_text("owner@:full_set::allow");
 +				}
  				need_mask = 0;
  				break;
  			case OP_REMOVE_ACL:
 
 --------------070804040701010903090102
 Content-Type: text/plain; charset=us-ascii;
  name="patch_acl_recursive_MAN_PAGE_9.1-STABLE_r246451.txt"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="patch_acl_recursive_MAN_PAGE_9.1-STABLE_r246451.txt"
 
 --- setfacl.1_bak	2013-04-24 09:13:22.000000000 +0200
 +++ setfacl.1	2013-04-24 09:18:12.000000000 +0200
 @@ -34,7 +34,7 @@
  .Nd set ACL information
  .Sh SYNOPSIS
  .Nm
 -.Op Fl bdhkn
 +.Op Fl bdhknR
  .Op Fl a Ar position entries
  .Op Fl m Ar entries
  .Op Fl M Ar file
 @@ -108,6 +108,8 @@
  .It Fl n
  Do not recalculate the permissions associated with the ACL
  mask entry.  This option is not applicable to NFSv4 ACLs.
 +.It Fl R
 +Recursively set the ACL entries.
  .It Fl x Ar entries | position
  If
  .Ar entries
 
 --------------070804040701010903090102--
>Unformatted:
