summaryrefslogtreecommitdiff
path: root/bin/chmod
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2009-07-01 15:52:19 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2009-07-01 15:52:19 +0000
commitdeda5987bc6e3a94f2ae3a854fa944b60ac5eca1 (patch)
tree9061a434c397b22d8c234fdf2d0ba619b111d22b /bin/chmod
parent422d78667687764f4f5f84e8e6b81ef8c79e9b18 (diff)
Notes
Diffstat (limited to 'bin/chmod')
-rw-r--r--bin/chmod/chmod.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/bin/chmod/chmod.c b/bin/chmod/chmod.c
index 6736032466cc..d003b5fbc86f 100644
--- a/bin/chmod/chmod.c
+++ b/bin/chmod/chmod.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
static void usage(void);
+static int may_have_nfs4acl(const FTSENT *ent);
int
main(int argc, char *argv[])
@@ -180,8 +181,14 @@ done: argv += optind;
break;
}
newmode = getmode(set, p->fts_statp->st_mode);
- if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
- continue;
+ /*
+ * With NFSv4 ACLs, it is possible that applying a mode
+ * identical to the one computed from an ACL will change
+ * that ACL.
+ */
+ if (may_have_nfs4acl(p) == 0 &&
+ (newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
+ continue;
if ((*change_mode)(p->fts_accpath, newmode) && !fflag) {
warn("%s", p->fts_path);
rval = 1;
@@ -219,3 +226,24 @@ usage(void)
"usage: chmod [-fhv] [-R [-H | -L | -P]] mode file ...\n");
exit(1);
}
+
+static int
+may_have_nfs4acl(const FTSENT *ent)
+{
+ int ret;
+ static dev_t previous_dev = (dev_t)-1;
+ static int supports_acls = -1;
+
+ if (previous_dev != ent->fts_statp->st_dev) {
+ previous_dev = ent->fts_statp->st_dev;
+ supports_acls = 0;
+
+ ret = pathconf(ent->fts_accpath, _PC_ACL_NFS4);
+ if (ret > 0)
+ supports_acls = 1;
+ else if (ret < 0 && errno != EINVAL)
+ warn("%s", ent->fts_path);
+ }
+
+ return (supports_acls);
+}