This was sent privately, Danny later said he meant to send to the list,
any message mangling is entirely the fault of my mail tool. I expect we
will get something based on this into the tree fairly soon (is anyone
in Australia listening? hint hint).
Steve
------- Forwarded Message
Date: Fri, 20 Jul 2001 12:35:35 -0400
From: Danny Cox <danscox@xxxxxxxxxxxxxx>
To: Steve Lord <lord@xxxxxxx>
Subject: Re: Anyone using XFS ACLs?
This is a multi-part message in MIME format.
- --------------4E072E6D209773EBBDAD1589
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Steve,
Steve Lord wrote:
> The other option here is for someone to take the source of something
> like chown which has a -R option, and chacl which does not. Merge the
> two and send in a patch. This is the sort of project which would be
> fairly easy for someone to tackle, would solve a problem. We are
> very tight on resources here and cannot be relied upon for things
> like bells and whistle extensions to commands like this.
Steve, here is a patch that adds an '-r' arg to chacl, and decends
(depth first) a directory tree changing ACLs as it goes. It doesn't
attempt to list them recursively, as that is a little trickier (and
neither chown nor chmod attempt this).
I did have a little problem. The "Makefile" uses the
'-D_FILE_OFFSET_BITS=64' which comes from ../include/builddefs, which
comes from ../include/builddefs.in, and causes the readdir to not work
correctly. The included file "<dirents.h>" gets the wrong size, which
doesn't agree with my libc (I'm using RedHat 6.2, and it's standard
glibc). When I recompiled without that flag, it works like a champ.
Short of defining 'struct dirent' myself (HACK!), I don't know how to
work around this other than how I did (remove the flag, which probably
breaks something else).
Anyway, the patch is attached.
Oh, by the way, I did take the liberty of adding spaces where I thought
they should be, providing a little more consistency. Ignore them if you
wish.
- --
"Men occasionally stumble over the truth, but most of them pick
themselves up and hurry off as if nothing had happened."
-- Winston Churchill
Danny
- --------------4E072E6D209773EBBDAD1589
Content-Type: text/plain; charset=us-ascii;
name="chacl.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="chacl.patch"
- --- cmd/acl/chacl/chacl.c.orig Fri Jul 20 11:04:45 2001
+++ cmd/acl/chacl/chacl.c Fri Jul 20 12:30:09 2001
@@ -36,6 +36,7 @@
*/
#include <sys/types.h>
+#include <sys/stat.h>
#include <acl.h>
#include <stdlib.h>
#include <string.h>
@@ -43,10 +44,17 @@
#include <getopt.h>
#include <stdio.h>
#include <errno.h>
+#include <dirent.h>
static int acl_delete_file (const char * path, acl_type_t type);
- -static int list_acl(char *file);
+static int list_acl (char *file);
+static int set_acl (acl_t acl, acl_t dacl, const char *fname);
+static int isdir (const char *fname);
+static int walk_dir (acl_t acl, acl_t dacl, const char *fname);
+static void *emalloc (int len);
+
static char *program;
+static int Recurse = 0;
static void
usage (void)
@@ -59,6 +67,7 @@
fprintf (stderr, "\t%s -D pathname ...\n", program);
fprintf (stderr, "\t%s -B pathname ...\n", program);
fprintf (stderr, "\t%s -l pathname ...\n", program);
+ fprintf (stderr, "\t%s -r pathname ...\n", program);
exit (1);
}
@@ -70,7 +79,7 @@
int switch_flag = 0; /* ensure only one switch is used */
int args_required = 1;
int failed = 0; /* exit status */
- - int c; /* For use by getopt(3) */
+ int c; /* For use by getopt(3) */
int dflag = 0; /* a Default ACL is desired */
int bflag = 0; /* a both ACLs are desired */
int Rflag = 0; /* set to true to remove an acl */
@@ -82,25 +91,26 @@
/* create program name */
p = strrchr (argv[0], '/');
- - program = p != NULL ? p + 1 : argv[0];
+ program = (p != NULL) ? p + 1 : argv[0];
- - acl_set_compat(ACL_COMPAT_IRIXGET);
+ acl_set_compat (ACL_COMPAT_IRIXGET);
/* parse arguments */
- - while ((c = getopt (argc, argv, "bdlRDB")) != -1)
+ while ((c = getopt (argc, argv, "bdlRDBr")) != -1)
{
- - if (switch_flag) usage();
- - switch_flag=1;
+ if (switch_flag)
+ usage();
+ switch_flag = 1;
switch (c)
{
case 'b':
bflag = 1;
- - args_required=3;
+ args_required = 3;
break;
case 'd':
dflag = 1;
- - args_required=2;
+ args_required = 2;
break;
case 'R':
Rflag = 1;
@@ -114,6 +124,9 @@
case 'l':
lflag = 1;
break;
+ case 'r':
+ Recurse = 1;
+ break;
default:
usage ();
break;
@@ -121,16 +134,16 @@
}
/* if not enough arguments quit */
- - if ((argc-optind) < args_required)
+ if ((argc - optind) < args_required)
usage ();
/* list the acls */
- - if ( lflag )
+ if (lflag)
{
- - for (;optind < argc;optind++)
+ for (; optind < argc; optind++)
{
char *file = argv[optind];
- - if (!list_acl(file))
+ if (!list_acl (file))
{
failed++;
}
@@ -139,20 +152,20 @@
}
/* remove the acls */
- - if ( Rflag || Dflag || Bflag )
+ if (Rflag || Dflag || Bflag)
{
- - for (;optind < argc;optind++)
+ for (; optind < argc; optind++)
{
if (!Dflag && acl_delete_file (argv[optind], ACL_TYPE_A
CCESS) == -1)
{
- - fprintf (stderr,"%s: error removing access acl
on \"%s\": %s\n",
- - program, argv[optind],strerror(errno));
+ fprintf (stderr, "%s: error removing access acl
on \"%s\": %s\n",
+ program, argv[optind], strerror (errno)
);
failed++;
}
if (!Rflag && acl_delete_file (argv[optind], ACL_TYPE_D
EFAULT) == -1)
{
- - fprintf (stderr,"%s: error removing default acl
on \"%s\": %s\n",
- - program, argv[optind],strerror(errno));
+ fprintf (stderr, "%s: error removing default ac
l on \"%s\": %s\n",
+ program, argv[optind], strerror (errno)
);
failed++;
}
}
@@ -163,7 +176,7 @@
/* file access acl */
if (! dflag) {
acl = acl_from_text (argv[optind]);
- - if (acl == NULL || acl_valid(acl) == -1)
+ if (acl == NULL || acl_valid (acl) == -1)
{
fprintf (stderr, inv_acl, program, argv[optind]);
return (1);
@@ -175,7 +188,7 @@
/* directory default acl */
if (bflag || dflag) {
dacl = acl_from_text (argv[optind]);
- - if (dacl == NULL || acl_valid(dacl) == -1)
+ if (dacl == NULL || acl_valid (dacl) == -1)
{
fprintf (stderr, inv_acl, program, argv[optind]);
return (1);
@@ -185,24 +198,9 @@
/* place acls on files */
- - for (;optind < argc;optind++)
+ for (; optind < argc; optind++)
{
- - /* set regular acl */
- - if (acl &&
- - acl_set_file (argv[optind], ACL_TYPE_ACCESS, acl) == -1)
- - {
- - fprintf (stderr,"%s: error setting access acl on \"%s\"
: %s\n",
- - program, argv[optind],strerror(errno));
- - failed++;
- - }
- - /* set default acl */
- - if (dacl &&
- - acl_set_file (argv[optind], ACL_TYPE_DEFAULT, dacl) == -1)
- - {
- - fprintf (stderr,"%s: error setting default acl on \"%s\
": %s\n",
- - program, argv[optind],strerror(errno));
- - failed++;
- - }
+ failed += set_acl (acl, dacl, argv[optind]);
}
if (acl)
@@ -220,11 +218,11 @@
acl_delete_file (const char * path, acl_type_t type)
{
struct acl acl;
- - int error=0;
+ int error = 0;
acl.acl_cnt = ACL_NOT_PRESENT;
- - error = acl_set_file( path,type,&acl) ;
+ error = acl_set_file (path, type, &acl) ;
return(error);
}
@@ -242,10 +240,10 @@
char *buf_acl = NULL;
char *buf_dacl = NULL;
- - acl = acl_get_file(file, ACL_TYPE_ACCESS);
+ acl = acl_get_file (file, ACL_TYPE_ACCESS);
if (acl == NULL) {
fprintf (stderr, "%s: error getting ACL on \"%s\": %s\n",
- - program, file, strerror(errno));
+ program, file, strerror (errno));
return 0;
}
if (acl->acl_cnt != ACL_NOT_PRESENT) {
@@ -253,15 +251,15 @@
if (buf_acl == NULL) {
fprintf (stderr, "%s: error converting ACL to short text "
"for file \"%s\": %s\n",
- - program, file, strerror(errno));
+ program, file, strerror (errno));
return 0;
}
}
- - dacl = acl_get_file(file, ACL_TYPE_DEFAULT);
+ dacl = acl_get_file (file, ACL_TYPE_DEFAULT);
if (dacl == NULL) {
fprintf (stderr, "%s: error getting default ACL on \"%s\": %s\n",
- - program, file, strerror(errno));
+ program, file, strerror (errno));
return 0;
}
if (dacl->acl_cnt > 0) {
@@ -269,7 +267,7 @@
if (buf_dacl == NULL) {
fprintf (stderr, "%s: error converting default ACL to short tex
t "
"for file \"%s\": %s\n",
- - program, file, strerror(errno));
+ program, file, strerror (errno));
return 0;
}
}
@@ -294,5 +292,101 @@
if (buf_dacl)
acl_free(buf_dacl);
- - return(1);
+ return (1);
+}
+
+static int
+set_acl (acl_t acl, acl_t dacl, const char *fname)
+{
+ int failed = 0;
+
+ /* set regular acl */
+ if (acl && acl_set_file (fname, ACL_TYPE_ACCESS, acl) == -1)
+ {
+ fprintf (stderr,"%s: error setting access acl on \"%s\": %s\n",
+ program, fname, strerror (errno));
+ failed++;
+ }
+ /* set default acl */
+ if (dacl && acl_set_file (fname, ACL_TYPE_DEFAULT, dacl) == -1)
+ {
+ fprintf (stderr,"%s: error setting default acl on \"%s\": %s\n"
,
+ program, fname, strerror (errno));
+ failed++;
+ }
+
+ if (Recurse && isdir (fname))
+ {
+ failed += walk_dir (acl, dacl, fname);
+ }
+
+ return (failed);
+}
+
+/* is fname a directory? */
+
+static int
+isdir (const char *fname)
+{
+ struct stat st;
+
+ if (stat (fname, &st) == -1)
+ {
+ return (0);
+ }
+
+ return (S_ISDIR (st.st_mode));
+}
+
+/* step through entries in a directory */
+
+static int
+walk_dir (acl_t acl, acl_t dacl, const char *fname)
+{
+ int failed = 0;
+ DIR *dir;
+ struct dirent *d;
+
+ if ((dir = opendir (fname)) == NULL)
+ {
+ fprintf (stderr, "%s: error opening \"%s\": %s\n", program,
+ fname, strerror (errno));
+ return (0);
+ }
+
+ while ((d = readdir (dir)) != NULL)
+ {
+ char *new;
+
+ /* skip "." and ".." entries */
+ if (strcmp (d->d_name, ".") == 0 ||
+ strcmp (d->d_name, "..") == 0)
+ continue;
+
+ new = emalloc (strlen (fname) + strlen (d->d_name) + 2);
+ sprintf (new, "%s/%s", fname, d->d_name);
+
+ failed += set_acl (acl, dacl, new);
+ free (new);
+ }
+
+ closedir (dir);
+
+ return (failed);
+}
+
+static void *
+emalloc (int len)
+{
+ void *p;
+
+ p = malloc (len);
+ if (p == NULL)
+ {
+ fprintf (stderr, "%s: malloc error: %s\n", program,
+ strerror (errno));
+ exit (255);
+ }
+
+ return (p);
}
- --------------4E072E6D209773EBBDAD1589--
------- End of Forwarded Message
|