Date: Tue, 8 Feb 2011 10:58:42 -0700 From: Shawn Webb <lattera@gmail.com> To: FreeBSD-current <freebsd-current@freebsd.org> Subject: setfacl Recursive Functionality Message-ID: <AANLkTi=%2BWtmRz07m=Cg7hbXJGw7eWRHC1ASGeufTSLBB@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
I've just finished a patch to add recursive functionality to setfacl. Before
I officially submit it, I'd like a few suggestions on how to improve the
patch.
The part I'm worried about involves the #define directive at top. I'm not
sure what ramifications using that define might have. I needed it for my
remove_invalid_inherit() function to work.
Thanks,
Shawn
attached: setfacl.patch (universal diff)
[-- Attachment #2 --]
--- /usr/src/bin/setfacl/setfacl.c 2011-02-03 12:11:02.303496318 -0700
+++ /tank/jails/dev/usr/src/bin/setfacl/setfacl.c 2011-02-08 10:47:18.190936489 -0700
@@ -23,7 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-
+#define _ACL_PRIVATE
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -32,6 +32,7 @@
#include <sys/stat.h>
#include <sys/acl.h>
#include <sys/queue.h>
+#include <dirent.h>
#include <err.h>
#include <errno.h>
@@ -44,6 +45,8 @@
static void add_filename(const char *filename);
static void usage(void);
+static void recurse_directory(const char *dirname, int r_flag);
+static acl_t remove_invalid_inherit(struct stat *sb, acl_t acl);
static void
add_filename(const char *filename)
@@ -63,19 +66,83 @@
usage(void)
{
- fprintf(stderr, "usage: setfacl [-bdhkn] [-a position entries] "
+ fprintf(stderr, "usage: setfacl [-bdhknR] [-a position entries] "
"[-m entries] [-M file] [-x entries] [-X file] [file ...]\n");
exit(1);
}
+static void
+recurse_directory(const char *dirname, int r_flag)
+{
+ DIR *dirp;
+ struct dirent *ent;
+ struct stat sb;
+ char newpath[PATH_MAX+1];
+
+ if (stat(dirname, &sb) == -1) {
+ warn("%s: stat() failed", dirname);
+ return;
+ }
+
+ add_filename(dirname);
+
+ if (r_flag == 0 || S_ISDIR(sb.st_mode) == 0)
+ return;
+
+ dirp = opendir(dirname);
+ while ((ent = readdir(dirp)) != NULL) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
+ continue;
+
+ snprintf(newpath, PATH_MAX, "%s/%s", dirname, ent->d_name);
+
+ if (stat(newpath, &sb) == -1) {
+ warn("%s: stat() failed", newpath);
+ continue;
+ }
+
+ if (S_ISDIR(sb.st_mode))
+ recurse_directory(newpath, r_flag);
+
+ add_filename(strdup(newpath));
+ }
+ closedir(dirp);
+}
+
+static acl_t
+remove_invalid_inherit(struct stat *sb, acl_t acl)
+{
+ acl_t acl_new;
+ int acl_brand;
+ acl_entry_t entry;
+ int entry_id;
+
+ acl_get_brand_np(acl, &acl_brand);
+ if (acl_brand != ACL_BRAND_NFS4)
+ 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;
+ entry->ae_flags = 0;
+ }
+
+ 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 h_flag, r_flag;
struct sf_file *file;
struct sf_entry *entry;
const char *fn_dup;
@@ -84,12 +151,12 @@
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 = 0;
TAILQ_INIT(&entrylist);
TAILQ_INIT(&filelist);
- while ((ch = getopt(argc, argv, "M:X:a:bdhkm:nx:")) != -1)
+ while ((ch = getopt(argc, argv, "RM:X:a:bdhkm:nx:")) != -1)
switch(ch) {
case 'M':
entry = zmalloc(sizeof(struct sf_entry));
@@ -167,6 +234,9 @@
}
TAILQ_INSERT_TAIL(&entrylist, entry, next);
break;
+ case 'R':
+ r_flag = 1;
+ break;
default:
usage();
break;
@@ -193,7 +263,7 @@
}
} else
for (i = 0; i < argc; i++)
- add_filename(argv[i]);
+ recurse_directory(argv[i], r_flag);
/* cycle through each file */
TAILQ_FOREACH(file, &filelist, next) {
@@ -250,12 +320,24 @@
switch(entry->op) {
case OP_ADD_ACL:
+ acl_backup = entry->acl;
+ entry->acl = remove_invalid_inherit(&sb, entry->acl);
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(&sb, entry->acl);
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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTi=%2BWtmRz07m=Cg7hbXJGw7eWRHC1ASGeufTSLBB>
