Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 5 Aug 2008 17:12:35 GMT
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 146714 for review
Message-ID:  <200808051712.m75HCZoF031670@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=146714

Change 146714 by trasz@trasz_traszkan on 2008/08/05 17:11:50

	Add support for NFS4 ACLs to cp(1) and mv(1).

Affected files ...

.. //depot/projects/soc2008/trasz_nfs4acl/TODO#32 edit
.. //depot/projects/soc2008/trasz_nfs4acl/bin/cp/utils.c#2 edit
.. //depot/projects/soc2008/trasz_nfs4acl/bin/mv/mv.c#3 edit

Differences ...

==== //depot/projects/soc2008/trasz_nfs4acl/TODO#32 (text+ko) ====

@@ -2,7 +2,7 @@
 
 - Make setfacl(1) error messages more user friendly.
 
-- Add support for NFS4 ACLs to cp(1), mv(1) and tar(1).
+- Add support for NFS4 ACLs to tar(1).
 
 - Clean up #defines.  For example, make VREAD_NAMED_ATTRS equal
   to ACL_READ_NAMED_ATTRS, so there is no need for translation

==== //depot/projects/soc2008/trasz_nfs4acl/bin/cp/utils.c#2 (text+ko) ====

@@ -211,7 +211,6 @@
 			rval = 1;
 		}
 	}
-	(void)close(from_fd);
 	
 	/*
 	 * Don't remove the target even after an error.  The target might
@@ -231,6 +230,9 @@
 			rval = 1;
 		}
 	}
+
+	(void)close(from_fd);
+
 	return (rval);
 }
 
@@ -351,21 +353,52 @@
 int
 preserve_fd_acls(int source_fd, int dest_fd)
 {
-	struct acl *aclp;
 	acl_t acl;
+	acl_type_t source_type, dest_type;
+	int source_acl_supported = 0, dest_acl_supported = 0;
+
+	if (fpathconf(source_fd, _PC_ACL_EXTENDED) == 1) {
+		source_acl_supported = 1;
+		source_type = ACL_TYPE_ACCESS;
+	}
+
+	if (fpathconf(source_fd, _PC_EXTENDED_SECURITY_NP) == 1) {
+		source_acl_supported = 1;
+		source_type = ACL_TYPE_NFS4;
+	}
+
+	if (fpathconf(dest_fd, _PC_ACL_EXTENDED) == 1) {
+		dest_acl_supported = 1;
+		dest_type = ACL_TYPE_ACCESS;
+	}
+
+	if (fpathconf(dest_fd, _PC_EXTENDED_SECURITY_NP) == 1) {
+		dest_acl_supported = 1;
+		dest_type = ACL_TYPE_NFS4;
+	}
 
-	if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 ||
-	    fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1)
+	if (!source_acl_supported || !dest_acl_supported)
 		return (0);
-	acl = acl_get_fd(source_fd);
+
+	acl = acl_get_fd_np(source_fd, source_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))
+		return (0);
+
+	if (source_type != dest_type) {
+		warnx("ACL brand of source is %s, but destination is %s; "
+		    "ACL not copied",
+		    source_type == ACL_TYPE_NFS4 ? "NFS4" : "POSIX",
+		    dest_type == ACL_TYPE_NFS4 ? "NFS4" : "POSIX");
+
 		return (0);
-	if (acl_set_fd(dest_fd, acl) < 0) {
+	}
+
+	if (acl_set_fd_np(dest_fd, acl, dest_type) < 0) {
 		warn("failed to set acl entries for %s", to.p_path);
 		return (1);
 	}
@@ -379,10 +412,41 @@
 	int (*aclsetf)(const char *, acl_type_t, acl_t);
 	struct acl *aclp;
 	acl_t acl;
+	acl_type_t source_type, dest_type;
+	int source_acl_supported = 0, dest_acl_supported = 0;
+
+	if (pathconf(source_dir, _PC_ACL_EXTENDED) == 1) {
+		source_acl_supported = 1;
+		source_type = ACL_TYPE_ACCESS;
+	}
+
+	if (pathconf(source_dir, _PC_EXTENDED_SECURITY_NP) == 1) {
+		source_acl_supported = 1;
+		source_type = ACL_TYPE_NFS4;
+	}
+
+	if (pathconf(dest_dir, _PC_ACL_EXTENDED) == 1) {
+		dest_acl_supported = 1;
+		dest_type = ACL_TYPE_ACCESS;
+	}
+
+	if (pathconf(dest_dir, _PC_EXTENDED_SECURITY_NP) == 1) {
+		dest_acl_supported = 1;
+		dest_type = ACL_TYPE_NFS4;
+	}
+
+	if (!source_acl_supported || !dest_acl_supported)
+		return (0);
+
+	if (source_type != dest_type) {
+		warnx("ACL brand of source is %s, but destination is %s; "
+		    "ACL not copied",
+		    source_type == ACL_TYPE_NFS4 ? "NFS4" : "POSIX",
+		    dest_type == ACL_TYPE_NFS4 ? "NFS4" : "POSIX");
 
-	if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 ||
-	    pathconf(dest_dir, _PC_ACL_EXTENDED) != 1)
 		return (0);
+	}
+
 	/*
 	 * If the file is a link we will not follow it
 	 */
@@ -393,31 +457,35 @@
 		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 == NULL) {
-		warn("failed to get default acl entries on %s",
-		    source_dir);
-		return (1);
+
+	if (source_type != ACL_TYPE_NFS4) {
+		/*
+		 * 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);
+			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);
-		return (1);
-	}
-	acl = aclgetf(source_dir, ACL_TYPE_ACCESS);
+
+	acl = aclgetf(source_dir, source_type);
 	if (acl == NULL) {
 		warn("failed to get acl entries on %s", source_dir);
 		return (1);
 	}
 	aclp = &acl->ats_acl;
-	if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) {
+	if (aclsetf(dest_dir, dest_type, acl) < 0) {
 		warn("failed to set acl entries on %s", dest_dir);
 		return (1);
 	}

==== //depot/projects/soc2008/trasz_nfs4acl/bin/mv/mv.c#3 (text+ko) ====

@@ -74,6 +74,8 @@
 static int	do_move(const char *, const char *);
 static int	fastcopy(const char *, const char *, struct stat *);
 static void	usage(void);
+static int	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 @@
 	struct timeval tval[2];
 	static u_int blen;
 	static char *bp;
-	acl_t acl;
 	mode_t oldmode;
 	int nread, from_fd, to_fd;
 
@@ -316,15 +317,8 @@
 	 * 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);
@@ -438,6 +432,62 @@
 	return (0);
 }
 
+static int
+preserve_fd_acls(int source_fd, int dest_fd, const char *source_path,
+    const char *dest_path)
+{
+	acl_t acl;
+	acl_type_t source_type, dest_type;
+	int source_acl_supported = 0, dest_acl_supported = 0;
+
+	if (fpathconf(source_fd, _PC_ACL_EXTENDED) == 1) {
+		source_acl_supported = 1;
+		source_type = ACL_TYPE_ACCESS;
+	}
+
+	if (fpathconf(source_fd, _PC_EXTENDED_SECURITY_NP) == 1) {
+		source_acl_supported = 1;
+		source_type = ACL_TYPE_NFS4;
+	}
+
+	if (fpathconf(dest_fd, _PC_ACL_EXTENDED) == 1) {
+		dest_acl_supported = 1;
+		dest_type = ACL_TYPE_ACCESS;
+	}
+
+	if (fpathconf(dest_fd, _PC_EXTENDED_SECURITY_NP) == 1) {
+		dest_acl_supported = 1;
+		dest_type = ACL_TYPE_NFS4;
+	}
+
+	if (!source_acl_supported || !dest_acl_supported)
+		return (0);
+
+	acl = acl_get_fd_np(source_fd, source_type);
+	if (acl == NULL) {
+		warn("failed to get acl entries while setting %s", source_path);
+		return (1);
+	}
+
+	if (acl_is_trivial_np(acl))
+		return (0);
+
+	if (source_type != dest_type) {
+		warnx("ACL brand of source is %s, but destination is %s; "
+		    "ACL not copied",
+		    source_type == ACL_TYPE_NFS4 ? "NFS4" : "POSIX",
+		    dest_type == ACL_TYPE_NFS4 ? "NFS4" : "POSIX");
+
+		return (0);
+	}
+
+	if (acl_set_fd_np(dest_fd, acl, dest_type) < 0) {
+		warn("failed to set acl entries for %s", dest_path);
+		return (1);
+	}
+	return (0);
+}
+
 static void
 usage(void)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200808051712.m75HCZoF031670>