aboutsummaryrefslogtreecommitdiff
path: root/bin/mv
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2009-09-04 21:49:37 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2009-09-04 21:49:37 +0000
commit62efc229e7698562fbbdc9e0df27ebcb9a6e09b0 (patch)
tree0a759bb9e31373535be53c709c8eca9acaea5416 /bin/mv
parent6b2eaa836f7e9985b3c25d1688103fccbbf37a81 (diff)
downloadsrc-62efc229e7698562fbbdc9e0df27ebcb9a6e09b0.tar.gz
src-62efc229e7698562fbbdc9e0df27ebcb9a6e09b0.zip
Add NFSv4 ACL support to mv(1).
Reviewed by: rwatson
Notes
Notes: svn path=/head/; revision=196841
Diffstat (limited to 'bin/mv')
-rw-r--r--bin/mv/mv.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/bin/mv/mv.c b/bin/mv/mv.c
index 22bdec19a457..1f98f94657f4 100644
--- a/bin/mv/mv.c
+++ b/bin/mv/mv.c
@@ -74,6 +74,8 @@ static int copy(const char *, const char *);
static int do_move(const char *, const char *);
static int fastcopy(const char *, const char *, struct stat *);
static void usage(void);
+static void preserve_fd_acls(int source_fd, int dest_fd, const char *source_path,
+ const char *dest_path);
int
main(int argc, char *argv[])
@@ -260,7 +262,6 @@ fastcopy(const char *from, const char *to, struct stat *sbp)
struct timeval tval[2];
static u_int blen;
static char *bp;
- acl_t acl;
mode_t oldmode;
int nread, from_fd, to_fd;
@@ -311,23 +312,15 @@ err: if (unlink(to))
sbp->st_mode &= ~(S_ISUID | S_ISGID);
}
}
+ if (fchmod(to_fd, sbp->st_mode))
+ warn("%s: set mode (was: 0%03o)", to, oldmode);
/*
* POSIX 1003.2c states that if _POSIX_ACL_EXTENDED is in effect
* for dest_file, then its ACLs shall reflect the ACLs of the
* source_file.
*/
- if (fpathconf(to_fd, _PC_ACL_EXTENDED) == 1 &&
- fpathconf(from_fd, _PC_ACL_EXTENDED) == 1) {
- acl = acl_get_fd(from_fd);
- if (acl == NULL)
- warn("failed to get acl entries while setting %s",
- from);
- else if (acl_set_fd(to_fd, acl) < 0)
- warn("failed to set acl entries for %s", to);
- }
+ preserve_fd_acls(from_fd, to_fd, from, to);
(void)close(from_fd);
- if (fchmod(to_fd, sbp->st_mode))
- warn("%s: set mode (was: 0%03o)", to, oldmode);
/*
* XXX
* NFS doesn't support chflags; ignore errors unless there's reason
@@ -439,6 +432,59 @@ copy(const char *from, const char *to)
}
static void
+preserve_fd_acls(int source_fd, int dest_fd, const char *source_path,
+ const char *dest_path)
+{
+ acl_t acl;
+ acl_type_t acl_type;
+ int acl_supported = 0, ret, trivial;
+
+ ret = fpathconf(source_fd, _PC_ACL_NFS4);
+ if (ret > 0 ) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_NFS4;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("fpathconf(..., _PC_ACL_NFS4) failed for %s",
+ source_path);
+ return;
+ }
+ if (acl_supported == 0) {
+ ret = fpathconf(source_fd, _PC_ACL_EXTENDED);
+ if (ret > 0 ) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_ACCESS;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s",
+ source_path);
+ return;
+ }
+ }
+ if (acl_supported == 0)
+ return;
+
+ acl = acl_get_fd_np(source_fd, acl_type);
+ if (acl == NULL) {
+ warn("failed to get acl entries for %s", source_path);
+ return;
+ }
+ if (acl_is_trivial_np(acl, &trivial)) {
+ warn("acl_is_trivial() failed for %s", source_path);
+ acl_free(acl);
+ return;
+ }
+ if (trivial) {
+ acl_free(acl);
+ return;
+ }
+ if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) {
+ warn("failed to set acl entries for %s", dest_path);
+ acl_free(acl);
+ return;
+ }
+ acl_free(acl);
+}
+
+static void
usage(void)
{