From owner-svn-src-head@FreeBSD.ORG Wed Sep 2 08:08:57 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BFCB3106566C; Wed, 2 Sep 2009 08:08:57 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AE5F98FC13; Wed, 2 Sep 2009 08:08:57 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n8288viJ086083; Wed, 2 Sep 2009 08:08:57 GMT (envelope-from trasz@svn.freebsd.org) Received: (from trasz@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n8288vJK086081; Wed, 2 Sep 2009 08:08:57 GMT (envelope-from trasz@svn.freebsd.org) Message-Id: <200909020808.n8288vJK086081@svn.freebsd.org> From: Edward Tomasz Napierala Date: Wed, 2 Sep 2009 08:08:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196754 - head/bin/cp X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Sep 2009 08:08:57 -0000 Author: trasz Date: Wed Sep 2 08:08:57 2009 New Revision: 196754 URL: http://svn.freebsd.org/changeset/base/196754 Log: Add NFSv4 ACL support to cp(1) and fix a few memory leaks. Note that this changes error reporting behaviour somewhat - before, no error was reported if ACL couldn't be copied because the target filesystem doesn't support ACLs. Now, it will be reported - of course, only if there actually is an ACL to copy. Reviewed by: rwatson Modified: head/bin/cp/utils.c Modified: head/bin/cp/utils.c ============================================================================== --- head/bin/cp/utils.c Wed Sep 2 05:26:59 2009 (r196753) +++ head/bin/cp/utils.c Wed Sep 2 08:08:57 2009 (r196754) @@ -377,24 +377,52 @@ setfile(struct stat *fs, int fd) int preserve_fd_acls(int source_fd, int dest_fd) { - struct acl *aclp; acl_t acl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; - if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 || - fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1) + 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", to.p_path); + return (1); + } + 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", + to.p_path); + return (1); + } + } + if (acl_supported == 0) return (0); - acl = acl_get_fd(source_fd); + + acl = acl_get_fd_np(source_fd, acl_type); if (acl == NULL) { warn("failed to get acl entries while setting %s", to.p_path); return (1); } - aclp = &acl->ats_acl; - if (aclp->acl_cnt == 3) + if (acl_is_trivial_np(acl, &trivial)) { + warn("acl_is_trivial() failed for %s", to.p_path); + acl_free(acl); + return (1); + } + if (trivial) { + acl_free(acl); return (0); - if (acl_set_fd(dest_fd, acl) < 0) { + } + if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) { warn("failed to set acl entries for %s", to.p_path); + acl_free(acl); return (1); } + acl_free(acl); return (0); } @@ -405,10 +433,31 @@ preserve_dir_acls(struct stat *fs, char int (*aclsetf)(const char *, acl_type_t, acl_t); struct acl *aclp; acl_t acl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; - if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 || - pathconf(dest_dir, _PC_ACL_EXTENDED) != 1) + ret = pathconf(source_dir, _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_dir); + return (1); + } + if (acl_supported == 0) { + ret = pathconf(source_dir, _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_dir); + return (1); + } + } + if (acl_supported == 0) return (0); + /* * If the file is a link we will not follow it */ @@ -419,34 +468,48 @@ preserve_dir_acls(struct stat *fs, char aclgetf = acl_get_file; aclsetf = acl_set_file; } - /* - * Even if there is no ACL_TYPE_DEFAULT entry here, a zero - * size ACL will be returned. So it is not safe to simply - * check the pointer to see if the default ACL is present. - */ - acl = aclgetf(source_dir, ACL_TYPE_DEFAULT); + if (acl_type == ACL_TYPE_ACCESS) { + /* + * Even if there is no ACL_TYPE_DEFAULT entry here, a zero + * size ACL will be returned. So it is not safe to simply + * check the pointer to see if the default ACL is present. + */ + acl = aclgetf(source_dir, ACL_TYPE_DEFAULT); + if (acl == NULL) { + warn("failed to get default acl entries on %s", + source_dir); + return (1); + } + aclp = &acl->ats_acl; + if (aclp->acl_cnt != 0 && aclsetf(dest_dir, + ACL_TYPE_DEFAULT, acl) < 0) { + warn("failed to set default acl entries on %s", + dest_dir); + acl_free(acl); + return (1); + } + acl_free(acl); + } + acl = aclgetf(source_dir, acl_type); if (acl == NULL) { - warn("failed to get default acl entries on %s", - source_dir); + warn("failed to get acl entries on %s", source_dir); return (1); } - aclp = &acl->ats_acl; - if (aclp->acl_cnt != 0 && aclsetf(dest_dir, - ACL_TYPE_DEFAULT, acl) < 0) { - warn("failed to set default acl entries on %s", - dest_dir); + if (acl_is_trivial_np(acl, &trivial)) { + warn("acl_is_trivial() failed on %s", source_dir); + acl_free(acl); return (1); } - acl = aclgetf(source_dir, ACL_TYPE_ACCESS); - if (acl == NULL) { - warn("failed to get acl entries on %s", source_dir); - return (1); + if (trivial) { + acl_free(acl); + return (0); } - aclp = &acl->ats_acl; - if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) { + if (aclsetf(dest_dir, acl_type, acl) < 0) { warn("failed to set acl entries on %s", dest_dir); + acl_free(acl); return (1); } + acl_free(acl); return (0); }