Add NFSv4 ACL support to mv(1).
Reviewed by: rwatson
This commit is contained in:
parent
81de4d9abd
commit
df693f271c
70
bin/mv/mv.c
70
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
|
||||
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user