Add NFSv4 ACL support to mv(1).

Reviewed by:	rwatson
This commit is contained in:
Edward Tomasz Napierala 2009-09-04 21:49:37 +00:00
parent 6b2eaa836f
commit 62efc229e7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196841

View File

@ -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
@ -438,6 +431,59 @@ copy(const char *from, const char *to)
return (0);
}
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)
{