--- //depot/projects/trustedbsd/base/bin/getfacl/getfacl.1	2002/11/04 06:15:46
+++ //depot/projects/trustedbsd/acl/bin/getfacl/getfacl.1	2002/12/23 18:42:03
@@ -38,7 +38,7 @@
 .Nd get ACL information
 .Sh SYNOPSIS
 .Nm
-.Op Fl d
+.Op Fl dh
 .Op Ar
 .Sh DESCRIPTION
 The
@@ -61,6 +61,9 @@
 access ACL.
 An error is generated if a default ACL cannot be associated with
 .Ar file .
+.It Fl h
+If the target of the operation is a symbolic link, return the ACL from
+the symbol link itself rather than following the link.
 .El
 .Pp
 The following operand is available:
--- //depot/projects/trustedbsd/base/bin/getfacl/getfacl.c	2002/11/04 06:15:46
+++ //depot/projects/trustedbsd/acl/bin/getfacl/getfacl.c	2002/12/23 20:19:27
@@ -52,7 +52,7 @@
 usage(void)
 {
 
-	fprintf(stderr, "getfacl [-d] [files ...]\n");
+	fprintf(stderr, "getfacl [-dh] [files ...]\n");
 }
 
 /*
@@ -147,14 +147,17 @@
 }
 
 static int
-print_acl(char *path, acl_type_t type)
+print_acl(char *path, acl_type_t type, int hflag)
 {
 	struct stat	sb;
 	acl_t	acl;
 	char	*acl_text;
 	int	error;
 
-	error = stat(path, &sb);
+	if (hflag)
+		error = lstat(path, &sb);
+	else
+		error = stat(path, &sb);
 	if (error == -1) {
 		warn("%s", path);
 		return(-1);
@@ -167,7 +170,10 @@
 
 	printf("#file:%s\n#owner:%d\n#group:%d\n", path, sb.st_uid, sb.st_gid);
 
-	acl = acl_get_file(path, type);
+	if (hflag)
+		acl = acl_get_link_np(path, type);
+	else
+		acl = acl_get_file(path, type);
 	if (!acl) {
 		if (errno != EOPNOTSUPP) {
 			warn("%s", path);
@@ -198,7 +204,7 @@
 }
 
 static int
-print_acl_from_stdin(acl_type_t type)
+print_acl_from_stdin(acl_type_t type, int hflag)
 {
 	char	*p, pathname[PATH_MAX];
 	int	carried_error = 0;
@@ -206,7 +212,7 @@
 	while (fgets(pathname, (int)sizeof(pathname), stdin)) {
 		if ((p = strchr(pathname, '\n')) != NULL)
 			*p = '\0';
-		if (print_acl(pathname, type) == -1) {
+		if (print_acl(pathname, type, hflag) == -1) {
 			carried_error = -1;
 		}
 	}
@@ -220,12 +226,17 @@
 	acl_type_t	type = ACL_TYPE_ACCESS;
 	int	carried_error = 0;
 	int	ch, error, i;
+	int	hflag;
 
-	while ((ch = getopt(argc, argv, "d")) != -1)
+	hflag = 0;
+	while ((ch = getopt(argc, argv, "dh")) != -1)
 		switch(ch) {
 		case 'd':
 			type = ACL_TYPE_DEFAULT;
 			break;
+		case 'h':
+			hflag = 1;
+			break;
 		default:
 			usage();
 			return(-1);
@@ -234,17 +245,17 @@
 	argv += optind;
 
 	if (argc == 0) {
-		error = print_acl_from_stdin(type);
+		error = print_acl_from_stdin(type, hflag);
 		return(error ? 1 : 0);
 	}
 
 	for (i = 0; i < argc; i++) {
 		if (!strcmp(argv[i], "-")) {
-			error = print_acl_from_stdin(type);
+			error = print_acl_from_stdin(type, hflag);
 			if (error == -1)
 				carried_error = -1;
 		} else {
-			error = print_acl(argv[i], type);
+			error = print_acl(argv[i], type, hflag);
 			if (error == -1)
 				carried_error = -1;
 		}
--- //depot/projects/trustedbsd/base/bin/setfacl/setfacl.1	2001/12/04 07:58:41
+++ //depot/projects/trustedbsd/acl/bin/setfacl/setfacl.1	2002/12/23 18:42:03
@@ -33,7 +33,7 @@
 .Nd set ACL information
 .Sh SYNOPSIS
 .Nm
-.Op Fl bdkn
+.Op Fl bdhkn
 .Op Fl m Ar entries
 .Op Fl M Ar file1
 .Op Fl x Ar entries
@@ -63,6 +63,9 @@
 The operations apply to the default ACL entries instead of
 access ACL entries.  Currently only directories may have
 default ACL's.
+.It Fl h
+If the target of the operation is a symbolic link, perform the operation
+on the symbolic link itself, rather than following the link.
 .It Fl k
 Delete any default ACL entries on the specified files.  It
 is not considered an error if the specified files do not have
--- //depot/projects/trustedbsd/base/bin/setfacl/setfacl.c	2002/07/26 22:29:05
+++ //depot/projects/trustedbsd/acl/bin/setfacl/setfacl.c	2002/12/23 20:14:00
@@ -71,11 +71,19 @@
 	}
 
 	acl = zmalloc(sizeof(acl_t) * 2);
-	acl[ACCESS_ACL] = acl_get_file(filename, ACL_TYPE_ACCESS);
+	if (h_flag)
+		acl[ACCESS_ACL] = acl_get_link_np(filename, ACL_TYPE_ACCESS);
+	else
+		acl[ACCESS_ACL] = acl_get_file(filename, ACL_TYPE_ACCESS);
 	if (acl[ACCESS_ACL] == NULL)
 		err(1, "acl_get_file() failed");
 	if (S_ISDIR(sb.st_mode)) {
-		acl[DEFAULT_ACL] = acl_get_file(filename, ACL_TYPE_DEFAULT);
+		if (h_flag)
+			acl[DEFAULT_ACL] = acl_get_link_np(filename,
+			    ACL_TYPE_DEFAULT);
+		else
+			acl[DEFAULT_ACL] = acl_get_file(filename,
+			    ACL_TYPE_DEFAULT);
 		if (acl[DEFAULT_ACL] == NULL)
 			err(1, "acl_get_file() failed");
 	} else
@@ -88,7 +96,7 @@
 usage(void)
 {
 
-	fprintf(stderr, "usage: setfacl [-bdknv] [-m entries] [-M file1] "
+	fprintf(stderr, "usage: setfacl [-bdhknv] [-m entries] [-M file1] "
 	    "[-x entries] [-X file2] [file ...]\n");
 	exit(1);
 }
@@ -104,12 +112,12 @@
 
 	acl_type = ACL_TYPE_ACCESS;
 	carried_error = local_error = 0;
-	have_mask = have_stdin = n_flag = need_mask = 0;
+	h_flag = have_mask = have_stdin = n_flag = need_mask = 0;
 
 	TAILQ_INIT(&entrylist);
 	TAILQ_INIT(&filelist);
 
-	while ((ch = getopt(argc, argv, "M:X:bdkm:nx:")) != -1)
+	while ((ch = getopt(argc, argv, "M:X:bdhkm:nx:")) != -1)
 		switch(ch) {
 		case 'M':
 			entry = zmalloc(sizeof(struct sf_entry));
@@ -133,6 +141,9 @@
 		case 'd':
 			acl_type = ACL_TYPE_DEFAULT;
 			break;
+		case 'h':
+			h_flag = 1;
+			break;
 		case 'k':
 			entry = zmalloc(sizeof(struct sf_entry));
 			entry->op = OP_REMOVE_DEF;
--- //depot/projects/trustedbsd/base/bin/setfacl/setfacl.h	2001/12/04 07:58:41
+++ //depot/projects/trustedbsd/acl/bin/setfacl/setfacl.h	2002/12/23 18:42:03
@@ -75,6 +75,7 @@
 uint       have_mask;
 uint       need_mask;
 uint       have_stdin;
+uint       h_flag;
 uint       n_flag;
 
 #endif /* _SETFACL_H */
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl.3	2002/11/08 20:01:36
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl.3	2002/12/18 20:18:53
@@ -2,6 +2,8 @@
 .\" Copyright (c) 2000, 2001, 2002 Robert N. M. Watson
 .\" All rights reserved.
 .\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
@@ -25,7 +27,7 @@
 .\"
 .\" $FreeBSD: src/lib/libc/posix1e/acl.3,v 1.19 2002/11/08 15:01:28 rwatson Exp $
 .\"
-.Dd January 28, 2000
+.Dd December 18, 2002
 .Dt ACL 3
 .Os
 .Sh NAME
@@ -82,8 +84,10 @@
 and may be used to create an empty entry in an ACL.
 .It Xo
 .Fn acl_delete_def_file ,
+.Fn acl_delete_def_link_np ,
+.Fn acl_delete_fd_np ,
 .Fn acl_delete_file_np ,
-.Fn acl_delete_fd_np
+.Fn acl_delete_link_np
 .Xc
 These functions are described in
 .Xr acl_delete 3 ,
@@ -114,9 +118,10 @@
 .Xr acl_get_entry 3 ,
 and may be used to retrieve a designated ACL entry from an ACL.
 .It Xo
+.Fn acl_get_fd ,
+.Fn acl_get_fd_np ,
 .Fn acl_get_file ,
-.Fn acl_get_fd ,
-.Fn acl_get_fd_np
+.Fn acl_get_link_np
 .Xc
 These functions are described in
 .Xr acl_get 3 ,
@@ -138,9 +143,10 @@
 .Xr acl_init 3 ,
 and may be used to allocate a fresh (empty) ACL structure.
 .It Xo
+.Fn acl_set_fd ,
+.Fn acl_set_fd_np ,
 .Fn acl_set_file ,
-.Fn acl_set_fd ,
-.Fn acl_set_fd_np
+.Fn acl_set_link_np
 .Xc
 These functions are described in
 .Xr acl_set 3 ,
@@ -163,8 +169,9 @@
 and may be used to generate a text-form of a POSIX.1e semantics ACL.
 .It Xo
 .Fn acl_valid ,
+.Fn acl_valid_fd_np ,
 .Fn acl_valid_file_np ,
-.Fn acl_valid_fd_np
+.Fn acl_valid_link_np
 .Xc
 These functions are described in
 .Xr acl_valid 3 ,
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_delete.3	2001/11/08 13:33:34
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_delete.3	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 .\"-
-.\" Copyright (c) 2000 Robert N. M. Watson
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
 .\" All rights reserved.
 .\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
@@ -30,8 +32,10 @@
 .Os
 .Sh NAME
 .Nm acl_delete_def_file ,
+.Nm acl_delete_def_link_np ,
 .Nm acl_delete_fd_np ,
 .Nm acl_delete_file_np
+.Nm acl_delete_link_np
 .Nd delete an ACL from a file
 .Sh LIBRARY
 .Lb libc
@@ -41,21 +45,33 @@
 .Ft int
 .Fn acl_delete_def_file "const char *path_p"
 .Ft int
+.Fn acl_delete_def_link_np "const char *path_p"
+.Ft int
+.Fn acl_delete_fd_np "int filedes" "acl_type_t type"
+.Ft int
 .Fn acl_delete_file_np "const char *path_p" "acl_type_t type"
 .Ft int
-.Fn acl_delete_fd_np "int filedes" "acl_type_t type"
+.Fn acl_delete_link_np "const char *path_p" "acl_type_t type"
 .Sh DESCRIPTION
 The
 .Fn acl_delete_def_file ,
+.Fn acl_delete_def_link_np ,
+.Fn acl_delete_fd_np ,
 .Fn acl_delete_file_np ,
 and
-.Fn acl_delete_fd_np
+.Fn acl_delete_link_np
 each allow the deletion of an ACL from a file.
 .Fn acl_delete_def_file
 is a POSIX.1e call that deletes the default ACL from a file (normally a
-directory) by name; the other two calls are non-portable extensions that
-allow deleting of arbitrary ACL types from a file/directory by either path
-name, or by file descriptor.
+directory) by name; the remainder of the calls are non-portable extensions
+that permit the deletion of arbitrary ACL types from a file/directory
+either by path name or file descriptor.
+The
+.Fn _file
+variations follow a symlink if it occurs in the last segment of the
+path name; the
+.Fn _linke
+variations operate on the symlink itself.
 .Sh IMPLEMENTATION NOTES
 .Fx Ns 's
 support for POSIX.1e interfaces and features is still under
@@ -118,5 +134,3 @@
 and development continues.
 .Sh AUTHORS
 .An Robert N M Watson
-.Sh BUGS
-These features are not yet fully implemented.
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_delete.c	2002/04/16 06:36:52
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_delete.c	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 /*-
- * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
  * All rights reserved.
  *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -43,7 +45,13 @@
 	return (__acl_delete_file(path_p, ACL_TYPE_DEFAULT));
 }
 
+int
+acl_delete_def_link_np(const char *path_p)
+{
 
+	return (__acl_delete_link(path_p, ACL_TYPE_DEFAULT));
+}
+
 int
 acl_delete_file_np(const char *path_p, acl_type_t type)
 {
@@ -51,6 +59,13 @@
 	return (__acl_delete_file(path_p, type));
 }
 
+int
+acl_delete_link_np(const char *path_p, acl_type_t type)
+{
+
+	return (__acl_delete_link(path_p, type));
+}
+
 
 int
 acl_delete_fd_np(int filedes, acl_type_t type)
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_get.3	2001/11/08 13:33:34
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_get.3	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 .\"-
-.\" Copyright (c) 2000 Robert N. M. Watson
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
 .\" All rights reserved.
 .\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
@@ -31,7 +33,8 @@
 .Sh NAME
 .Nm acl_get_fd ,
 .Nm acl_get_fd_np ,
-.Nm acl_get_file
+.Nm acl_get_file ,
+.Nm acl_get_link_np
 .Nd get an ACL for a file
 .Sh LIBRARY
 .Lb libc
@@ -39,21 +42,20 @@
 .In sys/types.h
 .In sys/acl.h
 .Ft acl_t
-.Fn acl_get_file "const char *path_p" "acl_type_t type"
-.Ft acl_t
 .Fn acl_get_fd "int fd"
 .Ft acl_t
 .Fn acl_get_fd_np "int fd" "acl_type_t type"
+.Ft acl_t
+.Fn acl_get_file "const char *path_p" "acl_type_t type"
+.Ft acl_t
+.Fn acl_get_link_np "const char *path_p" "acl_type_t type"
 .Sh DESCRIPTION
 The
+.Fn acl_get_fd ,
 .Fn acl_get_file ,
-.Fn acl_get_fd ,
-and
+.Fn acl_get_link_np ,
 .Fn acl_get_fd_np
 each allow the retrieval of an ACL from a file.
-.Fn acl_get_file
-is a POSIX.1e call that allows the retrieval of a
-specified type of ACL from a file by name;
 .Fn acl_get_fd
 is a POSIX.1e call that allows the retrieval of an ACL of type
 ACL_TYPE_ACCESS
@@ -62,8 +64,16 @@
 is a non-portable form of
 .Fn acl_get_fd
 that allows the retrieval of any type of ACL from a file descriptor.
+.Fn acl_get_file
+is a POSIX.1e call that allows the retrieval of a
+specified type of ACL from a file by name;
+.Fn acl_get_link_np
+is a non-portable variation on
+.Fn acl_get_file
+which does not follow a symlink if the target of the call is a
+symlink.
 .Pp
-This function may cause memory to be allocated.  The caller should free
+These functions may cause memory to be allocated.  The caller should free
 any releasable memory, when the new ACL is no longer required, by calling
 .Xr acl_free 3
 with the
@@ -135,5 +145,3 @@
 and development continues.
 .Sh AUTHORS
 .An Robert N M Watson
-.Sh BUGS
-These features are not yet fully implemented.
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_get.c	2002/04/16 06:36:52
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_get.c	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 /*-
- * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
  * All rights reserved.
  *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -24,9 +26,11 @@
  * SUCH DAMAGE.
  */
 /*
- * acl_get_file - syscall wrapper for retrieving ACL by filename
  * acl_get_fd - syscall wrapper for retrieving access ACL by fd
  * acl_get_fd_np - syscall wrapper for retrieving ACL by fd (non-POSIX)
+ * acl_get_file - syscall wrapper for retrieving ACL by filename
+ * acl_get_link_np - syscall wrapper for retrieving ACL by filename (NOFOLLOW)
+ *                   (non-POSIX)
  * acl_get_perm_np() checks if a permission is in the specified
  *                   permset (non-POSIX)
  * acl_get_permset() returns the permission set in the ACL entry
@@ -66,6 +70,25 @@
 }
 
 acl_t
+acl_get_link_np(const char *path_p, acl_type_t type)
+{
+	acl_t	aclp;
+	int	error;
+
+	aclp = acl_init(ACL_MAX_ENTRIES);
+	if (aclp == NULL)
+		return (NULL);
+
+	error = __acl_get_link(path_p, type, &aclp->ats_acl);
+	if (error) {
+		acl_free(aclp);
+		return (NULL);
+	}
+
+	return (aclp);
+}
+
+acl_t
 acl_get_fd(int fd)
 {
 	acl_t	aclp;
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_set.3	2002/01/10 11:15:51
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_set.3	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 .\"-
-.\" Copyright (c) 2000 Robert N. M. Watson
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
 .\" All rights reserved.
 .\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
@@ -31,7 +33,8 @@
 .Sh NAME
 .Nm acl_set_fd ,
 .Nm acl_set_fd_np ,
-.Nm acl_set_file
+.Nm acl_set_file ,
+.Nm acl_set_link_np
 .Nd set an ACL for a file
 .Sh LIBRARY
 .Lb libc
@@ -39,29 +42,36 @@
 .In sys/types.h
 .In sys/acl.h
 .Ft int
-.Fn acl_set_file "const char *path_p" "acl_type_t type" "acl_t acl"
-.Ft int
 .Fn acl_set_fd "int fd" "acl_t acl"
 .Ft int
 .Fn acl_set_fd_np "int fd" "acl_t acl" "acl_type_t type"
+.Ft int
+.Fn acl_set_file "const char *path_p" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_set_link_np "const char *path_p" "acl_type_t type" "acl_t acl"
 .Sh DESCRIPTION
 The
+.Fn acl_set_fd ,
+.Fn acl_set_fd_np ,
 .Fn acl_set_file ,
-.Fn acl_set_fd ,
 and
-.Fn acl_set_fd_np
+.Fn acl_set_link_np ,
 each associate an ACL with an object referred to by
 .Va fd
 or
 .Va path_p .
-All except
 .Fn acl_set_fd_np
-are POSIX.1e calls--
+and
+.Fn acl_set_link_np
+are not POSIX.1e calls.
 .Fn acl_set_fd
 allows only the setting of ACLs of type ACL_TYPE_ACCESS
 where as
 .Fn acl_set_fd_np
 allows the setting of ACLs of any type.
+.Fn acl_set_link_np
+acts on a symlink rather than its target, if the target of the
+path is a symlink.
 .Sh IMPLEMENTATION NOTES
 .Fx Ns 's
 support for POSIX.1e interfaces and features is still under
@@ -125,5 +135,3 @@
 and development continues.
 .Sh AUTHORS
 .An Robert N M Watson
-.Sh BUGS
-These features are not yet fully implemented.
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_set.c	2002/04/16 06:36:52
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_set.c	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 /*-
- * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
  * All rights reserved.
  *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -70,6 +72,28 @@
 }
 
 int
+acl_set_link_np(const char *path_p, acl_type_t type, acl_t acl)
+{
+	int	error;
+
+	if (acl == NULL || path_p == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+	if (_posix1e_acl(acl, type)) {
+		error = _posix1e_acl_sort(acl);
+		if (error) {
+			errno = error;
+			return (-1);
+		}
+	}
+
+	acl->ats_cur_entry = 0;
+
+	return (__acl_set_link(path_p, type, &acl->ats_acl));
+}
+
+int
 acl_set_fd(int fd, acl_t acl)
 {
 	int	error;
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_valid.3	2001/11/08 13:33:34
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_valid.3	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 .\"-
-.\" Copyright (c) 2000 Robert N. M. Watson
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
 .\" All rights reserved.
 .\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
@@ -31,7 +33,8 @@
 .Sh NAME
 .Nm acl_valid ,
 .Nm acl_valid_fd_np ,
-.Nm acl_valid_file_np
+.Nm acl_valid_file_np ,
+.Nm acl_valid_link_np
 .Nd validate an ACL
 .Sh LIBRARY
 .Lb libc
@@ -44,6 +47,8 @@
 .Fn acl_valid_fd_np "int fd" "acl_type_t type" "acl_t acl"
 .Ft int
 .Fn acl_valid_file_np "const char *path_p" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_valid_link_np "const char *path_p" "acl_type_t type" "acl_t acl"
 .Sh DESCRIPTION
 These functions check that the ACL referred to by the argument
 .Va acl
@@ -51,13 +56,20 @@
 .Fn acl_valid ,
 checks this validity only with POSIX.1e ACL semantics, and irrespective
 of the context in which the ACL is to be used.  The non-portable forms,
-.Fn acl_valid_fd_np
+.Fn acl_valid_fd_np ,
+.Fn acl_valid_file_np ,
 and
-.Fn acl_valid_file_np ,
+.Fn acl_valid_link_np
 allow an ACL to be checked in the context of a specific acl type,
 .Va type ,
-and file system object.  In environments where additional ACL types are
+and file system object.
+In environments where additional ACL types are
 supported than just POSIX.1e, this makes more sense.
+Whereas
+.Fn acl_valid_file_np
+will follow the symlink if the specified path is to a symlink,
+.Fn acl_valid_link_np
+will not.
 .Pp
 For POSIX.1e semantics, the checks include:
 .Bd -literal -offset indent
@@ -140,5 +152,3 @@
 and development continues.
 .Sh AUTHORS
 .An Robert N M Watson
-.Sh BUGS
-These features are not yet fully implemented.
--- //depot/projects/trustedbsd/base/lib/libc/posix1e/acl_valid.c	2002/04/16 06:36:52
+++ //depot/projects/trustedbsd/acl/lib/libc/posix1e/acl_valid.c	2002/12/18 20:18:53
@@ -1,7 +1,9 @@
 /*-
- * Copyright (c) 1999, 2000, 20001 Robert N. M. Watson
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
  * All rights reserved.
  *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -70,7 +72,6 @@
 	}
 }
 
-
 int
 acl_valid_file_np(const char *pathp, acl_type_t type, acl_t acl)
 {
@@ -91,6 +92,25 @@
 	return (__acl_aclcheck_file(pathp, type, &acl->ats_acl));
 }
 
+int
+acl_valid_link_np(const char *pathp, acl_type_t type, acl_t acl)
+{
+	int	error;
+
+	if (pathp == NULL || acl == NULL) {
+		errno = EINVAL;
+		return (-1);
+	}
+	if (_posix1e_acl(acl, type)) {
+		error = _posix1e_acl_sort(acl);
+		if (error) {
+			errno = error;
+			return (-1);
+		}
+	}
+
+	return (__acl_aclcheck_link(pathp, type, &acl->ats_acl));
+}
 
 int
 acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
--- //depot/projects/trustedbsd/base/sys/kern/init_sysent.c	2002/12/17 19:59:54
+++ //depot/projects/trustedbsd/acl/sys/kern/init_sysent.c	2002/12/18 19:23:40
@@ -2,7 +2,7 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/init_sysent.c,v 1.144 2002/12/15 19:19:14 dillon Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.138 2002/12/15 19:17:56 dillon Exp 
  */
 
@@ -453,4 +453,8 @@
 	{ SYF_MPSAFE | AS(setcontext_args), (sy_call_t *)setcontext },	/* 422 = setcontext */
 	{ SYF_MPSAFE | AS(swapcontext_args), (sy_call_t *)swapcontext },	/* 423 = swapcontext */
 	{ SYF_MPSAFE | AS(swapoff_args), (sy_call_t *)swapoff },	/* 424 = swapoff */
+	{ SYF_MPSAFE | AS(__acl_get_link_args), (sy_call_t *)__acl_get_link },	/* 425 = __acl_get_link */
+	{ SYF_MPSAFE | AS(__acl_set_link_args), (sy_call_t *)__acl_set_link },	/* 426 = __acl_set_link */
+	{ SYF_MPSAFE | AS(__acl_delete_link_args), (sy_call_t *)__acl_delete_link },	/* 427 = __acl_delete_link */
+	{ SYF_MPSAFE | AS(__acl_aclcheck_link_args), (sy_call_t *)__acl_aclcheck_link },	/* 428 = __acl_aclcheck_link */
 };
--- //depot/projects/trustedbsd/base/sys/kern/kern_acl.c	2002/12/17 19:59:54
+++ //depot/projects/trustedbsd/acl/sys/kern/kern_acl.c	2002/12/18 19:27:58
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1999-2001 Robert N. M. Watson
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
  * All rights reserved.
  *
  * This software was developed by Robert Watson for the TrustedBSD Project.
@@ -700,6 +700,28 @@
 }
 
 /*
+ * Given a file path, get an ACL for it; don't follow links.
+ *
+ * MPSAFE
+ */
+int
+__acl_get_link(struct thread *td, struct __acl_get_link_args *uap)
+{
+	struct nameidata nd;
+	int error;
+
+	mtx_lock(&Giant);
+	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
+	error = namei(&nd);
+	if (error == 0) {
+		error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
+		NDFREE(&nd, 0);
+	}
+	mtx_unlock(&Giant);
+	return (error);
+}
+
+/*
  * Given a file path, set an ACL for it
  *
  * MPSAFE
@@ -722,6 +744,28 @@
 }
 
 /*
+ * Given a file path, set an ACL for it; don't follow links.
+ *
+ * MPSAFE
+ */
+int
+__acl_set_link(struct thread *td, struct __acl_set_link_args *uap)
+{
+	struct nameidata nd;
+	int error;
+
+	mtx_lock(&Giant);
+	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
+	error = namei(&nd);
+	if (error == 0) {
+		error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
+		NDFREE(&nd, 0);
+	}
+	mtx_unlock(&Giant);
+	return (error);
+}
+
+/*
  * Given a file descriptor, get an ACL for it
  *
  * MPSAFE
@@ -788,6 +832,28 @@
 }
 
 /*
+ * Given a file path, delete an ACL from it; don't follow links.
+ *
+ * MPSAFE
+ */
+int
+__acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap)
+{
+	struct nameidata nd;
+	int error;
+
+	mtx_lock(&Giant);
+	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
+	error = namei(&nd);
+	if (error == 0) {
+		error = vacl_delete(td, nd.ni_vp, uap->type);
+		NDFREE(&nd, 0);
+	}
+	mtx_unlock(&Giant);
+	return (error);
+}
+
+/*
  * Given a file path, delete an ACL from it.
  *
  * MPSAFE
@@ -832,6 +898,28 @@
 }
 
 /*
+ * Given a file path, check an ACL for it; don't follow links.
+ *
+ * MPSAFE
+ */
+int
+__acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap)
+{
+	struct nameidata	nd;
+	int	error;
+
+	mtx_lock(&Giant);
+	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
+	error = namei(&nd);
+	if (error == 0) {
+		error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
+		NDFREE(&nd, 0);
+	}
+	mtx_unlock(&Giant);
+	return (error);
+}
+
+/*
  * Given a file descriptor, check an ACL for it
  *
  * MPSAFE
--- //depot/projects/trustedbsd/base/sys/kern/syscalls.c	2002/12/17 19:59:54
+++ //depot/projects/trustedbsd/acl/sys/kern/syscalls.c	2002/12/18 19:23:40
@@ -2,7 +2,7 @@
  * System call names.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/syscalls.c,v 1.130 2002/12/15 19:19:14 dillon Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.138 2002/12/15 19:17:56 dillon Exp 
  */
 
@@ -432,4 +432,8 @@
 	"setcontext",			/* 422 = setcontext */
 	"swapcontext",			/* 423 = swapcontext */
 	"swapoff",			/* 424 = swapoff */
+	"__acl_get_link",			/* 425 = __acl_get_link */
+	"__acl_set_link",			/* 426 = __acl_set_link */
+	"__acl_delete_link",			/* 427 = __acl_delete_link */
+	"__acl_aclcheck_link",			/* 428 = __acl_aclcheck_link */
 };
--- //depot/projects/trustedbsd/base/sys/kern/syscalls.master	2002/12/17 19:59:54
+++ //depot/projects/trustedbsd/acl/sys/kern/syscalls.master	2002/12/18 19:23:40
@@ -613,6 +613,14 @@
 423	MSTD	BSD	{ int swapcontext(struct __ucontext *oucp, \
 			    const struct __ucontext *ucp); }
 424	MSTD	BSD	{ int swapoff(const char *name); }
+425	MSTD	BSD	{ int __acl_get_link(const char *path, \
+			    acl_type_t type, struct acl *aclp); }
+426	MSTD	BSD	{ int __acl_set_link(const char *path, \
+			    acl_type_t type, struct acl *aclp); }
+427	MSTD	BSD	{ int __acl_delete_link(const char *path, \
+			    acl_type_t type); }
+428	MSTD	BSD	{ int __acl_aclcheck_link(const char *path, \
+			    acl_type_t type, struct acl *aclp); }
 
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/ia64/ia32/syscalls.master  (take a best guess)
--- //depot/projects/trustedbsd/base/sys/sys/acl.h	2002/06/14 22:21:29
+++ //depot/projects/trustedbsd/acl/sys/sys/acl.h	2002/12/23 20:07:56
@@ -140,12 +140,17 @@
 int	__acl_aclcheck_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
 int	__acl_aclcheck_file(const char *_path, acl_type_t _type,
 	    struct acl *_aclp);
+int	__acl_aclcheck_link(const char *_path, acl_type_t _type,
+	    struct acl *_aclp);
 int	__acl_delete_fd(int _filedes, acl_type_t _type);
 int	__acl_delete_file(const char *_path_p, acl_type_t _type);
+int	__acl_delete_link(const char *_path_p, acl_type_t _type);
 int	__acl_get_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
 int	__acl_get_file(const char *_path, acl_type_t _type, struct acl *_aclp);
+int	__acl_get_link(const char *_path, acl_type_t _type, struct acl *_aclp);
 int	__acl_set_fd(int _filedes, acl_type_t _type, struct acl *_aclp);
 int	__acl_set_file(const char *_path, acl_type_t _type, struct acl *_aclp);
+int	__acl_set_link(const char *_path, acl_type_t _type, struct acl *_aclp);
 __END_DECLS
 
 /*
@@ -162,10 +167,12 @@
 ssize_t	acl_copy_ext(void *_buf_p, acl_t _acl, ssize_t _size);
 acl_t	acl_copy_int(const void *_buf_p);
 int	acl_create_entry(acl_t *_acl_p, acl_entry_t *_entry_p);
+int	acl_delete_entry(acl_t _acl, acl_entry_t _entry_d);
 int	acl_delete_fd_np(int _filedes, acl_type_t _type);
-int	acl_delete_entry(acl_t _acl, acl_entry_t _entry_d);
 int	acl_delete_file_np(const char *_path_p, acl_type_t _type);
+int	acl_delete_link_np(const char *_path_p, acl_type_t _type);
 int	acl_delete_def_file(const char *_path_p);
+int	acl_delete_def_link_np(const char *_path_p);
 int	acl_delete_perm(acl_permset_t _permset_d, acl_perm_t _perm);
 acl_t	acl_dup(acl_t _acl);
 int	acl_free(void *_obj_p);
@@ -174,6 +181,7 @@
 acl_t	acl_get_fd(int _fd);
 acl_t	acl_get_fd_np(int fd, acl_type_t _type);
 acl_t	acl_get_file(const char *_path_p, acl_type_t _type);
+acl_t	acl_get_link_np(const char *_path_p, acl_type_t _type);
 void	*acl_get_qualifier(acl_entry_t _entry_d);
 int	acl_get_perm_np(acl_permset_t _permset_d, acl_perm_t _perm);
 int	acl_get_permset(acl_entry_t _entry_d, acl_permset_t *_permset_p);
@@ -182,6 +190,7 @@
 int	acl_set_fd(int _fd, acl_t _acl);
 int	acl_set_fd_np(int _fd, acl_t _acl, acl_type_t _type);
 int	acl_set_file(const char *_path_p, acl_type_t _type, acl_t _acl);
+int	acl_set_link_np(const char *_path_p, acl_type_t _type, acl_t _acl);
 int	acl_set_permset(acl_entry_t _entry_d, acl_permset_t _permset_d);
 int	acl_set_qualifier(acl_entry_t _entry_d, const void *_tag_qualifier_p);
 int	acl_set_tag_type(acl_entry_t _entry_d, acl_tag_t _tag_type);
@@ -190,6 +199,7 @@
 int	acl_valid(acl_t _acl);
 int	acl_valid_fd_np(int _fd, acl_type_t _type, acl_t _acl);
 int	acl_valid_file_np(const char *_path_p, acl_type_t _type, acl_t _acl);
+int	acl_valid_link_np(const char *_path_p, acl_type_t _type, acl_t _acl);
 __END_DECLS
 
 #endif /* !_KERNEL */
--- //depot/projects/trustedbsd/base/sys/sys/mount.h	2002/11/08 20:01:36
+++ //depot/projects/trustedbsd/acl/sys/sys/mount.h	2002/12/18 19:22:34
@@ -210,7 +210,8 @@
 			MNT_SYNCHRONOUS	| MNT_UNION	| MNT_ASYNC	| \
 			MNT_NOATIME | \
 			MNT_NOSYMFOLLOW	| MNT_IGNORE	| MNT_JAILDEVFS	| \
-			MNT_NOCLUSTERR	| MNT_NOCLUSTERW | MNT_SUIDDIR)
+			MNT_NOCLUSTERR	| MNT_NOCLUSTERW | MNT_SUIDDIR	| \
+			MNT_ACLS)
   
 /*
  * External filesystem command modifier flags.
--- //depot/projects/trustedbsd/base/sys/sys/syscall.h	2002/12/17 19:59:54
+++ //depot/projects/trustedbsd/acl/sys/sys/syscall.h	2002/12/18 19:23:40
@@ -2,7 +2,7 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/syscall.h,v 1.128 2002/12/15 19:19:15 dillon Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.138 2002/12/15 19:17:56 dillon Exp 
  */
 
@@ -330,4 +330,8 @@
 #define	SYS_setcontext	422
 #define	SYS_swapcontext	423
 #define	SYS_swapoff	424
-#define	SYS_MAXSYSCALL	425
+#define	SYS___acl_get_link	425
+#define	SYS___acl_set_link	426
+#define	SYS___acl_delete_link	427
+#define	SYS___acl_aclcheck_link	428
+#define	SYS_MAXSYSCALL	429
--- //depot/projects/trustedbsd/base/sys/sys/syscall.mk	2002/12/17 19:59:54
+++ //depot/projects/trustedbsd/acl/sys/sys/syscall.mk	2002/12/18 19:23:40
@@ -1,6 +1,6 @@
 # FreeBSD system call names.
 # DO NOT EDIT-- this file is automatically generated.
-# $FreeBSD: src/sys/sys/syscall.mk,v 1.83 2002/12/15 19:19:15 dillon Exp $
+# $FreeBSD$
 # created from FreeBSD: src/sys/kern/syscalls.master,v 1.138 2002/12/15 19:17:56 dillon Exp 
 MIASM =  \
 	syscall.o \
@@ -275,4 +275,8 @@
 	getcontext.o \
 	setcontext.o \
 	swapcontext.o \
-	swapoff.o
+	swapoff.o \
+	__acl_get_link.o \
+	__acl_set_link.o \
+	__acl_delete_link.o \
+	__acl_aclcheck_link.o
--- //depot/projects/trustedbsd/base/sys/sys/sysproto.h	2002/12/17 19:59:54
+++ //depot/projects/trustedbsd/acl/sys/sys/sysproto.h	2002/12/18 19:23:40
@@ -2,7 +2,7 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/sysproto.h,v 1.121 2002/12/15 19:19:15 dillon Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.138 2002/12/15 19:17:56 dillon Exp 
  */
 
@@ -1204,6 +1204,25 @@
 struct swapoff_args {
 	char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)];
 };
+struct __acl_get_link_args {
+	char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
+	char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)];
+	char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)];
+};
+struct __acl_set_link_args {
+	char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
+	char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)];
+	char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)];
+};
+struct __acl_delete_link_args {
+	char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
+	char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)];
+};
+struct __acl_aclcheck_link_args {
+	char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
+	char type_l_[PADL_(acl_type_t)]; acl_type_t type; char type_r_[PADR_(acl_type_t)];
+	char aclp_l_[PADL_(struct acl *)]; struct acl * aclp; char aclp_r_[PADR_(struct acl *)];
+};
 int	nosys(struct thread *, struct nosys_args *);
 void	sys_exit(struct thread *, struct sys_exit_args *);
 int	fork(struct thread *, struct fork_args *);
@@ -1476,6 +1495,10 @@
 int	setcontext(struct thread *, struct setcontext_args *);
 int	swapcontext(struct thread *, struct swapcontext_args *);
 int	swapoff(struct thread *, struct swapoff_args *);
+int	__acl_get_link(struct thread *, struct __acl_get_link_args *);
+int	__acl_set_link(struct thread *, struct __acl_set_link_args *);
+int	__acl_delete_link(struct thread *, struct __acl_delete_link_args *);
+int	__acl_aclcheck_link(struct thread *, struct __acl_aclcheck_link_args *);
 
 #ifdef COMPAT_43
 
--- //depot/projects/trustedbsd/base/sys/ufs/ufs/ufs_acl.c	2002/10/18 12:15:19
+++ //depot/projects/trustedbsd/acl/sys/ufs/ufs/ufs_acl.c	2002/12/18 21:02:44
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 1999-2001 Robert N. M. Watson
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
  * All rights reserved.
  *
  * This software was developed by Robert Watson for the TrustedBSD Project.
