summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/Makefile.lint1
-rw-r--r--usr/src/cmd/Makefile1
-rw-r--r--usr/src/cmd/devfsadm/Makefile.com7
-rw-r--r--usr/src/cmd/devfsadm/zut_link.c60
-rw-r--r--usr/src/cmd/truss/codes.c2
-rw-r--r--usr/src/cmd/zlook/Makefile52
-rw-r--r--usr/src/cmd/zlook/Makefile.com49
-rw-r--r--usr/src/cmd/zlook/amd64/Makefile30
-rw-r--r--usr/src/cmd/zlook/i386/Makefile29
-rw-r--r--usr/src/cmd/zlook/sparc/Makefile29
-rw-r--r--usr/src/cmd/zlook/sparcv9/Makefile30
-rw-r--r--usr/src/cmd/zlook/zlook.c412
-rw-r--r--usr/src/pkgdefs/SUNWonzfs/Makefile5
-rw-r--r--usr/src/pkgdefs/SUNWonzfs/postinstall.tmpl28
-rw-r--r--usr/src/pkgdefs/SUNWonzfs/preremove.tmpl28
-rw-r--r--usr/src/pkgdefs/SUNWonzfs/prototype_com22
-rw-r--r--usr/src/pkgdefs/SUNWonzfs/prototype_i3869
-rw-r--r--usr/src/pkgdefs/SUNWonzfs/prototype_sparc6
-rw-r--r--usr/src/uts/common/Makefile.files3
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/fs/fs_subr.c6
-rw-r--r--usr/src/uts/common/fs/xattr.c5
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_acl.h1
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_acl.c187
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c1
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c21
-rw-r--r--usr/src/uts/common/fs/zut/zut.c550
-rw-r--r--usr/src/uts/common/fs/zut/zut.conf25
-rw-r--r--usr/src/uts/common/sys/Makefile3
-rw-r--r--usr/src/uts/common/sys/fs/zut.h93
-rw-r--r--usr/src/uts/common/sys/unistd.h1
-rw-r--r--usr/src/uts/common/sys/vfs.h3
-rw-r--r--usr/src/uts/common/sys/vnode.h1
-rw-r--r--usr/src/uts/intel/Makefile.intel.shared2
-rw-r--r--usr/src/uts/intel/zut/Makefile100
-rw-r--r--usr/src/uts/sparc/Makefile.sparc.shared2
-rw-r--r--usr/src/uts/sparc/zut/Makefile100
37 files changed, 1835 insertions, 76 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index 2d4c742123..3698d152b0 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -321,6 +321,7 @@ COMMON_SUBDIRS = \
cmd/zonecfg \
cmd/zonename \
cmd/zpool \
+ cmd/zlook \
cmd/ztest \
lib/abi \
lib/auditd_plugins \
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index 9cdec8af4d..92bde29d42 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -460,6 +460,7 @@ COMMON_SUBDIRS= \
zonecfg \
zonename \
zpool \
+ zlook \
ztest
$(CLOSED_BUILD)COMMON_SUBDIRS += \
diff --git a/usr/src/cmd/devfsadm/Makefile.com b/usr/src/cmd/devfsadm/Makefile.com
index dab5217c6f..13114e60ce 100644
--- a/usr/src/cmd/devfsadm/Makefile.com
+++ b/usr/src/cmd/devfsadm/Makefile.com
@@ -18,11 +18,9 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
include ../../Makefile.cmd
@@ -66,7 +64,8 @@ LINK_OBJS_CMN = \
md_link.o \
dtrace_link.o \
vscan_link.o \
- zfs_link.o
+ zfs_link.o \
+ zut_link.o
LINK_OBJS = $(LINK_OBJS_CMN) \
$(LINK_OBJS_$(MACH))
diff --git a/usr/src/cmd/devfsadm/zut_link.c b/usr/src/cmd/devfsadm/zut_link.c
new file mode 100644
index 0000000000..b34668200a
--- /dev/null
+++ b/usr/src/cmd/devfsadm/zut_link.c
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <regex.h>
+#include <devfsadm.h>
+#include <stdio.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/mkdev.h>
+#include <sys/fs/zut.h>
+
+/* zfs unit test driver */
+
+static int zut(di_minor_t minor, di_node_t node);
+
+/*
+ * devfs create callback register
+ */
+static devfsadm_create_t zut_create_cbt[] = {
+ { "pseudo", "ddi_pseudo", ZUT_DRIVER,
+ TYPE_EXACT | DRV_EXACT, ILEVEL_0, zut,
+ },
+};
+DEVFSADM_CREATE_INIT_V0(zut_create_cbt);
+
+/*
+ * For the zut control node:
+ * /dev/zut -> /devices/pseudo/zut@0:zut
+ */
+static int
+zut(di_minor_t minor, di_node_t node)
+{
+ if (strcmp(di_minor_name(minor), ZUT_DRIVER) == 0)
+ (void) devfsadm_mklink(ZUT_DRIVER, node, minor, 0);
+
+ return (DEVFSADM_CONTINUE);
+}
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
index aa9b9ed7bd..b81844b9b5 100644
--- a/usr/src/cmd/truss/codes.c
+++ b/usr/src/cmd/truss/codes.c
@@ -247,7 +247,7 @@ const char *const PATHCONFname[] = {
"_PC_CASE_BEHAVIOR", /* 22 */
"_PC_SATTR_ENABLED", /* 23 */
"_PC_SATTR_EXISTS", /* 24 */
- NULL, /* 25 */
+ "_PC_ACCESS_FILTERING", /* 25 */
NULL, /* 26 */
NULL, /* 27 */
NULL, /* 28 */
diff --git a/usr/src/cmd/zlook/Makefile b/usr/src/cmd/zlook/Makefile
new file mode 100644
index 0000000000..fb2ee0ede2
--- /dev/null
+++ b/usr/src/cmd/zlook/Makefile
@@ -0,0 +1,52 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PROG:sh= basename `pwd`
+
+include ../Makefile.cmd
+
+$(INTEL_BLD)SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all clean clobber lint: $(SUBDIRS)
+
+install: $(SUBDIRS)
+ -$(RM) $(ROOTPROG)
+ -$(LN) $(ISAEXEC) $(ROOTPROG)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/zlook/Makefile.com b/usr/src/cmd/zlook/Makefile.com
new file mode 100644
index 0000000000..9afe89f00f
--- /dev/null
+++ b/usr/src/cmd/zlook/Makefile.com
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PROG= zlook
+SRCS= ../$(PROG).c
+
+include ../../Makefile.cmd
+
+C99MODE= -xc99=%all
+C99LMODE= -Xc99=%all
+CFLAGS += -g $(CCVERBOSE)
+CFLAGS64 += -g $(CCVERBOSE)
+CPPFLAGS += -D_LARGEFILE64_SOURCE=1 -D_REENTRANT $(INCS)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(SRCS)
+ $(LINK.c) -o $(PROG) $(SRCS) $(LDLIBS)
+ $(POST_PROCESS)
+
+clean:
+
+lint: lint_SRCS
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/zlook/amd64/Makefile b/usr/src/cmd/zlook/amd64/Makefile
new file mode 100644
index 0000000000..64da121d75
--- /dev/null
+++ b/usr/src/cmd/zlook/amd64/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+include ../../Makefile.cmd.64
+
+install: all $(ROOTPROG64)
diff --git a/usr/src/cmd/zlook/i386/Makefile b/usr/src/cmd/zlook/i386/Makefile
new file mode 100644
index 0000000000..1bd7915dff
--- /dev/null
+++ b/usr/src/cmd/zlook/i386/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTPROG32)
diff --git a/usr/src/cmd/zlook/sparc/Makefile b/usr/src/cmd/zlook/sparc/Makefile
new file mode 100644
index 0000000000..1bd7915dff
--- /dev/null
+++ b/usr/src/cmd/zlook/sparc/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTPROG32)
diff --git a/usr/src/cmd/zlook/sparcv9/Makefile b/usr/src/cmd/zlook/sparcv9/Makefile
new file mode 100644
index 0000000000..64da121d75
--- /dev/null
+++ b/usr/src/cmd/zlook/sparcv9/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+include ../../Makefile.cmd.64
+
+install: all $(ROOTPROG64)
diff --git a/usr/src/cmd/zlook/zlook.c b/usr/src/cmd/zlook/zlook.c
new file mode 100644
index 0000000000..36394f4973
--- /dev/null
+++ b/usr/src/cmd/zlook/zlook.c
@@ -0,0 +1,412 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This is a test program that uses ioctls to the ZFS Unit Test driver
+ * to perform readdirs or lookups using flags not normally available
+ * to user-land programs. This allows testing of the flags'
+ * behavior outside of a complicated consumer, such as the SMB driver.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stropts.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <sys/attr.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+
+#define _KERNEL
+
+#include <sys/fs/zut.h>
+#include <sys/extdirent.h>
+
+#undef _KERNEL
+
+#define MAXBUF (64 * 1024)
+#define BIGBUF 4096
+#define LILBUF 64
+
+#define DIRENT_NAMELEN(reclen) \
+ ((reclen) - (offsetof(dirent_t, d_name[0])))
+
+static void
+usage(char *pnam)
+{
+ (void) fprintf(stderr, "Usage:\n %s -l [-is] dir-to-look-in "
+ "file-in-dir [xfile-on-file]\n", pnam);
+ (void) fprintf(stderr, " %s -i [-ls] dir-to-look-in "
+ "file-in-dir [xfile-on-file]\n", pnam);
+ (void) fprintf(stderr, " %s -s [-il] dir-to-look-in "
+ "file-in-dir [xfile-on-file]\n", pnam);
+ (void) fprintf(stderr, "\t Perform a lookup\n");
+ (void) fprintf(stderr, "\t -l == lookup\n");
+ (void) fprintf(stderr, "\t -i == request FIGNORECASE\n");
+ (void) fprintf(stderr, "\t -s == request stat(2) and xvattr info\n");
+ (void) fprintf(stderr, " %s -r [-ea] [-b buffer-size-in-bytes] "
+ "dir-to-look-in [file-in-dir]\n", pnam);
+ (void) fprintf(stderr, " %s -e [-ra] [-b buffer-size-in-bytes] "
+ "dir-to-look-in [file-in-dir]\n", pnam);
+ (void) fprintf(stderr, " %s -a [-re] [-b buffer-size-in-bytes] "
+ "dir-to-look-in [file-in-dir]\n", pnam);
+ (void) fprintf(stderr, "\t Perform a readdir\n");
+ (void) fprintf(stderr, "\t -r == readdir\n");
+ (void) fprintf(stderr, "\t -e == request extended entries\n");
+ (void) fprintf(stderr, "\t -a == request access filtering\n");
+ (void) fprintf(stderr, "\t -b == buffer size (default 4K)\n");
+ (void) fprintf(stderr, " %s -A path\n", pnam);
+ (void) fprintf(stderr, "\t Look up _PC_ACCESS_FILTERING "
+ "for path with pathconf(2)\n");
+ (void) fprintf(stderr, " %s -E path\n", pnam);
+ (void) fprintf(stderr, "\t Look up _PC_SATTR_EXISTS "
+ "for path with pathconf(2)\n");
+ (void) fprintf(stderr, " %s -S path\n", pnam);
+ (void) fprintf(stderr, "\t Look up _PC_SATTR_EXISTS "
+ "for path with pathconf(2)\n");
+ exit(EINVAL);
+}
+
+static void
+print_extd_entries(zut_readdir_t *r)
+{
+ struct edirent *eodp;
+ char *bufstart;
+
+ eodp = (edirent_t *)(uintptr_t)r->zr_buf;
+ bufstart = (char *)eodp;
+ while ((char *)eodp < bufstart + r->zr_bytes) {
+ char *blanks = " ";
+ int i = 0;
+ while (i < EDIRENT_NAMELEN(eodp->ed_reclen)) {
+ if (!eodp->ed_name[i])
+ break;
+ (void) printf("%c", eodp->ed_name[i++]);
+ }
+ if (i < 16)
+ (void) printf("%.*s", 16 - i, blanks);
+ (void) printf("\t%x\n", eodp->ed_eflags);
+ eodp = (edirent_t *)((intptr_t)eodp + eodp->ed_reclen);
+ }
+}
+
+static void
+print_entries(zut_readdir_t *r)
+{
+ dirent64_t *dp;
+ char *bufstart;
+
+ dp = (dirent64_t *)r->zr_buf;
+ bufstart = (char *)dp;
+ while ((char *)dp < bufstart + r->zr_bytes) {
+ int i = 0;
+ while (i < DIRENT_NAMELEN(dp->d_reclen)) {
+ if (!dp->d_name[i])
+ break;
+ (void) printf("%c", dp->d_name[i++]);
+ }
+ (void) printf("\n");
+ dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen);
+ }
+}
+
+static void
+print_stats(struct stat64 *sb)
+{
+ char timebuf[512];
+
+ (void) printf("st_mode\t\t\t%04lo\n", (unsigned long)sb->st_mode);
+ (void) printf("st_ino\t\t\t%llu\n", (unsigned long long)sb->st_ino);
+ (void) printf("st_nlink\t\t%lu\n", (unsigned long)sb->st_nlink);
+ (void) printf("st_uid\t\t\t%d\n", sb->st_uid);
+ (void) printf("st_gid\t\t\t%d\n", sb->st_gid);
+ (void) printf("st_size\t\t\t%lld\n", (long long)sb->st_size);
+ (void) printf("st_blksize\t\t%ld\n", (long)sb->st_blksize);
+ (void) printf("st_blocks\t\t%lld\n", (long long)sb->st_blocks);
+
+ timebuf[0] = 0;
+ if (ctime_r(&sb->st_atime, timebuf, 512)) {
+ (void) printf("st_atime\t\t");
+ (void) printf("%s", timebuf);
+ }
+ timebuf[0] = 0;
+ if (ctime_r(&sb->st_mtime, timebuf, 512)) {
+ (void) printf("st_mtime\t\t");
+ (void) printf("%s", timebuf);
+ }
+ timebuf[0] = 0;
+ if (ctime_r(&sb->st_ctime, timebuf, 512)) {
+ (void) printf("st_ctime\t\t");
+ (void) printf("%s", timebuf);
+ }
+}
+
+static void
+print_xvs(uint64_t xvs)
+{
+ uint_t bits;
+ int idx = 0;
+
+ if (xvs == 0)
+ return;
+
+ (void) printf("-------------------\n");
+ (void) printf("Attribute bit(s) set:\n");
+ (void) printf("-------------------\n");
+
+ bits = xvs & ((1 << F_ATTR_ALL) - 1);
+ while (bits) {
+ uint_t rest = bits >> 1;
+ if (bits & 1) {
+ (void) printf("%s", attr_to_name((f_attr_t)idx));
+ if (rest)
+ (void) printf(", ");
+ }
+ idx++;
+ bits = rest;
+ }
+ (void) printf("\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ zut_lookup_t lk = {0};
+ zut_readdir_t rd = {0};
+ boolean_t checking = B_FALSE;
+ boolean_t looking = B_FALSE;
+ boolean_t reading = B_FALSE;
+ boolean_t bflag = B_FALSE;
+ long rddir_bufsize = BIGBUF;
+ int error = 0;
+ int check;
+ int fd;
+ int c;
+
+ while ((c = getopt(argc, argv, "lisaerb:ASE")) != -1) {
+ switch (c) {
+ case 'l':
+ looking = B_TRUE;
+ break;
+ case 'i':
+ lk.zl_reqflags |= ZUT_IGNORECASE;
+ looking = B_TRUE;
+ break;
+ case 's':
+ lk.zl_reqflags |= ZUT_GETSTAT;
+ looking = B_TRUE;
+ break;
+ case 'a':
+ rd.zr_reqflags |= ZUT_ACCFILTER;
+ reading = B_TRUE;
+ break;
+ case 'e':
+ rd.zr_reqflags |= ZUT_EXTRDDIR;
+ reading = B_TRUE;
+ break;
+ case 'r':
+ reading = B_TRUE;
+ break;
+ case 'b':
+ reading = B_TRUE;
+ bflag = B_TRUE;
+ rddir_bufsize = strtol(optarg, NULL, 0);
+ break;
+ case 'A':
+ checking = B_TRUE;
+ check = _PC_ACCESS_FILTERING;
+ break;
+ case 'S':
+ checking = B_TRUE;
+ check = _PC_SATTR_ENABLED;
+ break;
+ case 'E':
+ checking = B_TRUE;
+ check = _PC_SATTR_EXISTS;
+ break;
+ case '?':
+ default:
+ usage(argv[0]); /* no return */
+ }
+ }
+
+ if ((checking && looking) || (checking && reading) ||
+ (looking && reading) || (!reading && bflag) ||
+ (!checking && !reading && !looking))
+ usage(argv[0]); /* no return */
+
+ if (rddir_bufsize < LILBUF || rddir_bufsize > MAXBUF) {
+ (void) fprintf(stderr, "Sorry, buffer size "
+ "must be >= %d and less than or equal to %d bytes.\n",
+ LILBUF, MAXBUF);
+ exit(EINVAL);
+ }
+
+ if (checking) {
+ char pathbuf[MAXPATHLEN];
+ long result;
+
+ if (argc - optind < 1)
+ usage(argv[0]); /* no return */
+ (void) strlcpy(pathbuf, argv[optind], MAXPATHLEN);
+ result = pathconf(pathbuf, check);
+ (void) printf("pathconf(2) check for %s\n", pathbuf);
+ switch (check) {
+ case _PC_SATTR_ENABLED:
+ (void) printf("System attributes ");
+ if (result != 0)
+ (void) printf("Enabled\n");
+ else
+ (void) printf("Not enabled\n");
+ break;
+ case _PC_SATTR_EXISTS:
+ (void) printf("System attributes ");
+ if (result != 0)
+ (void) printf("Exist\n");
+ else
+ (void) printf("Do not exist\n");
+ break;
+ case _PC_ACCESS_FILTERING:
+ (void) printf("Access filtering ");
+ if (result != 0)
+ (void) printf("Available\n");
+ else
+ (void) printf("Not available\n");
+ break;
+ }
+ return (result);
+ }
+
+ if ((fd = open(ZUT_DEV, O_RDONLY)) < 0) {
+ perror(ZUT_DEV);
+ return (ENXIO);
+ }
+
+ if (reading) {
+ char *buf;
+
+ if (argc - optind < 1)
+ usage(argv[0]); /* no return */
+
+ (void) strlcpy(rd.zr_dir, argv[optind], MAXPATHLEN);
+ if (argc - optind > 1) {
+ (void) strlcpy(rd.zr_file, argv[optind + 1],
+ MAXNAMELEN);
+ rd.zr_reqflags |= ZUT_XATTR;
+ }
+
+ if ((buf = malloc(rddir_bufsize)) == NULL) {
+ error = errno;
+ perror("malloc");
+ (void) close(fd);
+ return (error);
+ }
+
+ rd.zr_buf = (uint64_t)(uintptr_t)buf;
+ rd.zr_buflen = rddir_bufsize;
+
+ while (!rd.zr_eof) {
+ int ierr;
+
+ if ((ierr = ioctl(fd, ZUT_IOC_READDIR, &rd)) != 0) {
+ (void) fprintf(stderr,
+ "IOCTL error: %s (%d)\n",
+ strerror(ierr), ierr);
+ free(buf);
+ (void) close(fd);
+ return (ierr);
+ }
+ if (rd.zr_retcode) {
+ (void) fprintf(stderr,
+ "readdir result: %s (%d)\n",
+ strerror(rd.zr_retcode), rd.zr_retcode);
+ free(buf);
+ (void) close(fd);
+ return (rd.zr_retcode);
+ }
+ if (rd.zr_reqflags & ZUT_EXTRDDIR)
+ print_extd_entries(&rd);
+ else
+ print_entries(&rd);
+ }
+ free(buf);
+ } else {
+ int ierr;
+
+ if (argc - optind < 2)
+ usage(argv[0]); /* no return */
+
+ (void) strlcpy(lk.zl_dir, argv[optind], MAXPATHLEN);
+ (void) strlcpy(lk.zl_file, argv[optind + 1], MAXNAMELEN);
+ if (argc - optind > 2) {
+ (void) strlcpy(lk.zl_xfile,
+ argv[optind + 2], MAXNAMELEN);
+ lk.zl_reqflags |= ZUT_XATTR;
+ }
+
+ if ((ierr = ioctl(fd, ZUT_IOC_LOOKUP, &lk)) != 0) {
+ (void) fprintf(stderr,
+ "IOCTL error: %s (%d)\n",
+ strerror(ierr), ierr);
+ (void) close(fd);
+ return (ierr);
+ }
+
+ (void) printf("\nLookup of ");
+ if (lk.zl_reqflags & ZUT_XATTR) {
+ (void) printf("extended attribute \"%s\" of ",
+ lk.zl_xfile);
+ }
+ (void) printf("file \"%s\" ", lk.zl_file);
+ (void) printf("in directory \"%s\" ", lk.zl_dir);
+ if (lk.zl_retcode) {
+ (void) printf("failed: %s (%d)\n",
+ strerror(lk.zl_retcode), lk.zl_retcode);
+ (void) close(fd);
+ return (lk.zl_retcode);
+ }
+
+ (void) printf("succeeded.\n");
+ if (lk.zl_reqflags & ZUT_IGNORECASE) {
+ (void) printf("----------------------------\n");
+ (void) printf("dirent flags: 0x%0x\n", lk.zl_deflags);
+ (void) printf("real name: %s\n", lk.zl_real);
+ }
+ if (lk.zl_reqflags & ZUT_GETSTAT) {
+ (void) printf("----------------------------\n");
+ print_stats(&lk.zl_statbuf);
+ print_xvs(lk.zl_xvattrs);
+ }
+ }
+
+ (void) close(fd);
+ return (0);
+}
diff --git a/usr/src/pkgdefs/SUNWonzfs/Makefile b/usr/src/pkgdefs/SUNWonzfs/Makefile
index 193c83ef69..ec31009fd4 100644
--- a/usr/src/pkgdefs/SUNWonzfs/Makefile
+++ b/usr/src/pkgdefs/SUNWonzfs/Makefile
@@ -19,13 +19,13 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
include ../Makefile.com
+TMPLFILES += postinstall preremove
DATAFILES += depend
.KEEP_STATE:
@@ -35,3 +35,4 @@ all: $(FILES)
install: all pkg
include ../Makefile.targ
+include ../Makefile.prtarg
diff --git a/usr/src/pkgdefs/SUNWonzfs/postinstall.tmpl b/usr/src/pkgdefs/SUNWonzfs/postinstall.tmpl
new file mode 100644
index 0000000000..ea3fcb6cf1
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWonzfs/postinstall.tmpl
@@ -0,0 +1,28 @@
+#!/sbin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include drv_utils
+
+pkg_drvadd -m '* 0666 root sys' zut || exit 1
diff --git a/usr/src/pkgdefs/SUNWonzfs/preremove.tmpl b/usr/src/pkgdefs/SUNWonzfs/preremove.tmpl
new file mode 100644
index 0000000000..33cdae3e8a
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWonzfs/preremove.tmpl
@@ -0,0 +1,28 @@
+#!/sbin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include drv_utils
+
+pkg_drvrem zut || exit 1
diff --git a/usr/src/pkgdefs/SUNWonzfs/prototype_com b/usr/src/pkgdefs/SUNWonzfs/prototype_com
index 7a4bf243e9..f3c1613ff5 100644
--- a/usr/src/pkgdefs/SUNWonzfs/prototype_com
+++ b/usr/src/pkgdefs/SUNWonzfs/prototype_com
@@ -18,19 +18,31 @@
#
# CDDL HEADER END
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-#
i pkginfo
i copyright
i depend
+i postinstall
+i preremove
#
# SUNWonzfs
#
+d none kernel 755 root sys
+d none kernel/drv 0755 root sys
+f none kernel/drv/zut.conf 644 root sys
d none usr 755 root sys
-d none usr/sbin 755 root bin
-l none usr/sbin/zinject=../../usr/lib/isaexec
d none usr/bin 755 root bin
l none usr/bin/ztest=../../usr/lib/isaexec
+l none usr/bin/zlook=../../usr/lib/isaexec
+d none usr/include 755 root bin
+d none usr/include/sys 755 root bin
+d none usr/include/sys/fs 755 root bin
+f none usr/include/sys/fs/zut.h 644 root bin
+d none usr/lib 755 root bin
+d none usr/lib/devfsadm 755 root sys
+d none usr/lib/devfsadm/linkmod 755 root sys
+f none usr/lib/devfsadm/linkmod/SUNW_zut_link.so 755 root sys
+d none usr/sbin 755 root bin
+l none usr/sbin/zinject=../../usr/lib/isaexec
diff --git a/usr/src/pkgdefs/SUNWonzfs/prototype_i386 b/usr/src/pkgdefs/SUNWonzfs/prototype_i386
index d81f259bdd..e5354be554 100644
--- a/usr/src/pkgdefs/SUNWonzfs/prototype_i386
+++ b/usr/src/pkgdefs/SUNWonzfs/prototype_i386
@@ -18,18 +18,21 @@
#
# CDDL HEADER END
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-#
!include prototype_com
#
+f none kernel/drv/zut 755 root sys
+d none kernel/drv/amd64 755 root sys
+f none kernel/drv/amd64/zut 755 root sys
d none usr/sbin/amd64 755 root bin
f none usr/sbin/amd64/zinject 555 root bin
d none usr/sbin/i86 755 root bin
f none usr/sbin/i86/zinject 555 root bin
d none usr/bin/amd64 755 root bin
+f none usr/bin/amd64/zlook 555 root bin
f none usr/bin/amd64/ztest 555 root bin
d none usr/bin/i86 755 root bin
+f none usr/bin/i86/zlook 555 root bin
f none usr/bin/i86/ztest 555 root bin
diff --git a/usr/src/pkgdefs/SUNWonzfs/prototype_sparc b/usr/src/pkgdefs/SUNWonzfs/prototype_sparc
index dfef30ce02..1965ad8b12 100644
--- a/usr/src/pkgdefs/SUNWonzfs/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWonzfs/prototype_sparc
@@ -18,14 +18,16 @@
#
# CDDL HEADER END
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
#
!include prototype_com
#
+d none kernel/drv/sparcv9 755 root sys
+f none kernel/drv/sparcv9/zut 755 root sys
d none usr/sbin/sparcv9 755 root bin
f none usr/sbin/sparcv9/zinject 555 root bin
d none usr/bin/sparcv9 755 root bin
+f none usr/bin/sparcv9/zlook 555 root bin
f none usr/bin/sparcv9/ztest 555 root bin
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index b4462e3118..ac17b4f78f 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1340,6 +1340,9 @@ ZFS_OBJS += \
zfs_vnops.o \
zvol.o
+ZUT_OBJS += \
+ zut.o
+
#
# streams modules
#
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index 5158c543b7..63793d9d9f 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -316,6 +316,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/zfs/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/zut/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(COMMONBASE)/xattr/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1609,6 +1613,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/vscan/%.c
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/zfs/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/zut/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(COMMONBASE)/xattr/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/common/fs/fs_subr.c b/usr/src/uts/common/fs/fs_subr.c
index abf5a2db30..5187ecf327 100644
--- a/usr/src/uts/common/fs/fs_subr.c
+++ b/usr/src/uts/common/fs/fs_subr.c
@@ -23,7 +23,7 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -512,6 +512,10 @@ fs_pathconf(
val = 0;
break;
+ case _PC_ACCESS_FILTERING:
+ val = 0;
+ break;
+
default:
error = EINVAL;
break;
diff --git a/usr/src/uts/common/fs/xattr.c b/usr/src/uts/common/fs/xattr.c
index 2926a82483..ed5cc8217c 100644
--- a/usr/src/uts/common/fs/xattr.c
+++ b/usr/src/uts/common/fs/xattr.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1210,7 +1210,8 @@ xattr_dir_readdir(vnode_t *dvp, uio_t *uiop, cred_t *cr, int *eofp,
* subsequent call refers to the static entries or to those
* in an underlying fs.
*/
- ASSERT(*eofp);
+ if (*eofp == 0)
+ return (EINVAL);
reset_off = 1;
}
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
index e123aa1882..f5e5aa7f4a 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h
@@ -201,6 +201,7 @@ int zfs_setacl(struct znode *, vsecattr_t *, boolean_t, cred_t *);
void zfs_acl_rele(void *);
void zfs_oldace_byteswap(ace_t *, int);
void zfs_ace_byteswap(void *, size_t, boolean_t);
+extern boolean_t zfs_has_access(struct znode *zp, cred_t *cr);
extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *);
extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *);
extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *);
diff --git a/usr/src/uts/common/fs/zfs/zfs_acl.c b/usr/src/uts/common/fs/zfs/zfs_acl.c
index 2dab3a8edb..734bd83958 100644
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_acl.c
@@ -2164,46 +2164,17 @@ done:
}
/*
- * working_mode returns the permissions that were not granted
+ * Check accesses of interest (AoI) against attributes of the dataset
+ * such as read-only. Returns zero if no AoI conflict with dataset
+ * attributes, otherwise an appropriate errno is returned.
*/
static int
-zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
- boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr)
+zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
{
- zfs_acl_t *aclp;
- zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- int error;
- uid_t uid = crgetuid(cr);
- uint64_t who;
- uint16_t type, iflags;
- uint16_t entry_type;
- uint32_t access_mask;
- uint32_t deny_mask = 0;
- zfs_ace_hdr_t *acep = NULL;
- boolean_t checkit;
- uid_t fowner;
- uid_t gowner;
-
- /*
- * Short circuit empty requests
- */
- if (v4_mode == 0)
- return (0);
-
- *check_privs = B_TRUE;
-
- if (zfsvfs->z_replay) {
- *working_mode = 0;
- return (0);
- }
-
- *working_mode = v4_mode;
-
if ((v4_mode & WRITE_MASK) &&
(zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) &&
(!IS_DEVVP(ZTOV(zp)) ||
(IS_DEVVP(ZTOV(zp)) && (v4_mode & WRITE_MASK_ATTRS)))) {
- *check_privs = B_FALSE;
return (EROFS);
}
@@ -2215,31 +2186,64 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
(zp->z_phys->zp_flags & (ZFS_READONLY | ZFS_IMMUTABLE))) ||
(ZTOV(zp)->v_type == VDIR &&
(zp->z_phys->zp_flags & ZFS_IMMUTABLE)))) {
- *check_privs = B_FALSE;
return (EPERM);
}
if ((v4_mode & (ACE_DELETE | ACE_DELETE_CHILD)) &&
(zp->z_phys->zp_flags & ZFS_NOUNLINK)) {
- *check_privs = B_FALSE;
return (EPERM);
}
if (((v4_mode & (ACE_READ_DATA|ACE_EXECUTE)) &&
(zp->z_phys->zp_flags & ZFS_AV_QUARANTINED))) {
- *check_privs = B_FALSE;
return (EACCES);
}
- /*
- * The caller requested that the ACL check be skipped. This
- * would only happen if the caller checked VOP_ACCESS() with a
- * 32 bit ACE mask and already had the appropriate permissions.
- */
- if (skipaclchk) {
- *working_mode = 0;
- return (0);
- }
+ return (0);
+}
+
+/*
+ * The primary usage of this function is to loop through all of the
+ * ACEs in the znode, determining what accesses of interest (AoI) to
+ * the caller are allowed or denied. The AoI are expressed as bits in
+ * the working_mode parameter. As each ACE is processed, bits covered
+ * by that ACE are removed from the working_mode. This removal
+ * facilitates two things. The first is that when the working mode is
+ * empty (= 0), we know we've looked at all the AoI. The second is
+ * that the ACE interpretation rules don't allow a later ACE to undo
+ * something granted or denied by an earlier ACE. Removing the
+ * discovered access or denial enforces this rule. At the end of
+ * processing the ACEs, all AoI that were found to be denied are
+ * placed into the working_mode, giving the caller a mask of denied
+ * accesses. Returns:
+ * 0 if all AoI granted
+ * EACCESS if the denied mask is non-zero
+ * other error if abnormal failure (e.g., IO error)
+ *
+ * A secondary usage of the function is to determine if any of the
+ * AoI are granted. If an ACE grants any access in
+ * the working_mode, we immediately short circuit out of the function.
+ * This mode is chosen by setting anyaccess to B_TRUE. The
+ * working_mode is not a denied access mask upon exit if the function
+ * is used in this manner.
+ */
+static int
+zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
+ boolean_t anyaccess, cred_t *cr)
+{
+ zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ zfs_acl_t *aclp;
+ int error;
+ uid_t uid = crgetuid(cr);
+ uint64_t who;
+ uint16_t type, iflags;
+ uint16_t entry_type;
+ uint32_t access_mask;
+ uint32_t deny_mask = 0;
+ zfs_ace_hdr_t *acep = NULL;
+ boolean_t checkit;
+ uid_t fowner;
+ uid_t gowner;
zfs_fuid_map_ids(zp, cr, &fowner, &gowner);
@@ -2253,6 +2257,7 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,
&iflags, &type)) {
+ uint32_t mask_matched;
if (!zfs_acl_valid_ace_type(type, iflags))
continue;
@@ -2260,6 +2265,11 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
if (ZTOV(zp)->v_type == VDIR && (iflags & ACE_INHERIT_ONLY_ACE))
continue;
+ /* Skip ACE if it does not affect any AoI */
+ mask_matched = (access_mask & *working_mode);
+ if (!mask_matched)
+ continue;
+
entry_type = (iflags & ACE_TYPE_FLAGS);
checkit = B_FALSE;
@@ -2298,14 +2308,24 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
}
if (checkit) {
- uint32_t mask_matched = (access_mask & *working_mode);
-
- if (mask_matched) {
- if (type == DENY)
- deny_mask |= mask_matched;
-
- *working_mode &= ~mask_matched;
+ if (type == DENY) {
+ DTRACE_PROBE3(zfs__ace__denies,
+ znode_t *, zp,
+ zfs_ace_hdr_t *, acep,
+ uint32_t, mask_matched);
+ deny_mask |= mask_matched;
+ } else {
+ DTRACE_PROBE3(zfs__ace__allows,
+ znode_t *, zp,
+ zfs_ace_hdr_t *, acep,
+ uint32_t, mask_matched);
+ if (anyaccess) {
+ mutex_exit(&zp->z_acl_lock);
+ zfs_acl_free(aclp);
+ return (0);
+ }
}
+ *working_mode &= ~mask_matched;
}
/* Are we done? */
@@ -2327,6 +2347,69 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
return (0);
}
+/*
+ * Return true if any access whatsoever granted, we don't actually
+ * care what access is granted.
+ */
+boolean_t
+zfs_has_access(znode_t *zp, cred_t *cr)
+{
+ uint32_t have = ACE_ALL_PERMS;
+
+ if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr) != 0) {
+ uid_t owner;
+
+ owner = zfs_fuid_map_id(zp->z_zfsvfs,
+ zp->z_phys->zp_uid, cr, ZFS_OWNER);
+
+ return (
+ secpolicy_vnode_access(cr, ZTOV(zp), owner, VREAD) == 0 ||
+ secpolicy_vnode_access(cr, ZTOV(zp), owner, VWRITE) == 0 ||
+ secpolicy_vnode_access(cr, ZTOV(zp), owner, VEXEC) == 0 ||
+ secpolicy_vnode_chown(cr, B_TRUE) == 0 ||
+ secpolicy_vnode_chown(cr, B_FALSE) == 0 ||
+ secpolicy_vnode_setdac(cr, owner) == 0 ||
+ secpolicy_vnode_remove(cr) == 0);
+ }
+ return (B_TRUE);
+}
+
+static int
+zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
+ boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr)
+{
+ zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+ int err;
+
+ *working_mode = v4_mode;
+ *check_privs = B_TRUE;
+
+ /*
+ * Short circuit empty requests
+ */
+ if (v4_mode == 0 || zfsvfs->z_replay) {
+ *working_mode = 0;
+ return (0);
+ }
+
+ if ((err = zfs_zaccess_dataset_check(zp, v4_mode)) != 0) {
+ *check_privs = B_FALSE;
+ return (err);
+ }
+
+ /*
+ * The caller requested that the ACL check be skipped. This
+ * would only happen if the caller checked VOP_ACCESS() with a
+ * 32 bit ACE mask and already had the appropriate permissions.
+ */
+ if (skipaclchk) {
+ *working_mode = 0;
+ return (0);
+ }
+
+ return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr));
+}
+
static int
zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs,
cred_t *cr)
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index 1e6f8aae72..9a14eb7d7f 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -1061,6 +1061,7 @@ zfs_set_fuid_feature(zfsvfs_t *zfsvfs)
vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
+ vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
}
}
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index bc43bf98a0..55a3d1acef 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -2013,6 +2013,21 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
}
}
+ if (flags & V_RDDIR_ACCFILTER) {
+ /*
+ * If we have no access at all, don't include
+ * this entry in the returned information
+ */
+ znode_t *ezp;
+ if (zfs_zget(zp->z_zfsvfs, objnum, &ezp) != 0)
+ goto skip_entry;
+ if (!zfs_has_access(ezp, cr)) {
+ VN_RELE(ZTOV(ezp));
+ goto skip_entry;
+ }
+ VN_RELE(ZTOV(ezp));
+ }
+
if (flags & V_RDDIR_ENTFLAGS)
reclen = EDIRENT_RECLEN(strlen(zap.za_name));
else
@@ -2064,6 +2079,7 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
if (prefetch)
dmu_prefetch(os, objnum, 0, 0);
+ skip_entry:
/*
* Move to the next entry, fill in the previous offset.
*/
@@ -4405,6 +4421,11 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
(vp->v_type == VREG || vp->v_type == VDIR);
return (0);
+ case _PC_ACCESS_FILTERING:
+ *valp = vfs_has_feature(vp->v_vfsp, VFSFT_ACCESS_FILTER) &&
+ vp->v_type == VDIR;
+ return (0);
+
case _PC_ACL_ENABLED:
*valp = _ACL_ACE_ENABLED;
return (0);
diff --git a/usr/src/uts/common/fs/zut/zut.c b/usr/src/uts/common/fs/zut/zut.c
new file mode 100644
index 0000000000..9381b69aea
--- /dev/null
+++ b/usr/src/uts/common/fs/zut/zut.c
@@ -0,0 +1,550 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/conf.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/pathname.h>
+#include <sys/proc.h>
+#include <sys/mode.h>
+#include <sys/vnode.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sunldi.h>
+#include <sys/uio.h>
+#include <sys/attr.h>
+#include <sys/acl.h>
+#include <sys/fs/zut.h>
+
+ldi_ident_t zut_li = NULL;
+dev_info_t *zut_dip;
+
+static int
+zut_open_dir(char *path, vnode_t *startvp, cred_t *cr, int flags,
+ pathname_t *realpn, vnode_t **dvn)
+{
+ pathname_t pn;
+ vnode_t *vp;
+ vnode_t *rootvp;
+ proc_t *p = curproc;
+ int error;
+
+ pn_alloc(&pn);
+ (void) strlcpy(pn.pn_buf, path, MAXPATHLEN);
+ pn.pn_pathlen = strlen(path);
+
+ mutex_enter(&p->p_lock); /* for u_rdir and u_cdir */
+ if ((rootvp = PTOU(p)->u_rdir) == NULL)
+ rootvp = rootdir;
+ else if (rootvp != rootdir) /* no need to VN_HOLD rootdir */
+ VN_HOLD(rootvp);
+
+ if (pn.pn_path[0] == '/') {
+ vp = rootvp;
+ } else {
+ vp = (startvp == NULL) ? PTOU(p)->u_cdir : startvp;
+ }
+ VN_HOLD(vp);
+ mutex_exit(&p->p_lock);
+
+ /*
+ * Skip over leading slashes
+ */
+ while (pn.pn_path[0] == '/') {
+ pn.pn_path++;
+ pn.pn_pathlen--;
+ }
+
+ error = lookuppnvp(&pn, realpn, flags | FOLLOW, NULL,
+ dvn, rootvp, vp, cr);
+
+ /*
+ * If we lack read access to the directory, we should error out.
+ */
+ if (!error) {
+ if (vfs_has_feature((*dvn)->v_vfsp, VFSFT_ACEMASKONACCESS)) {
+ error = VOP_ACCESS(*dvn, ACE_LIST_DIRECTORY,
+ V_ACE_MASK, cr, NULL);
+ } else {
+ error = VOP_ACCESS(*dvn, VREAD, 0, cr, NULL);
+ }
+ }
+
+ pn_free(&pn);
+
+ return (error);
+}
+
+static int
+zut_readdir(intptr_t arg, cred_t *cr, int iflag, int *rvalp)
+{
+ zut_readdir_t *zr;
+ struct iovec aiov;
+ struct uio auio;
+ vnode_t *dvn = NULL;
+ vnode_t *fvn = NULL;
+ char *kbuf;
+ int flags = 0;
+ int error, rc;
+
+ zr = kmem_zalloc(sizeof (zut_readdir_t), KM_SLEEP);
+ error = ddi_copyin((void *)arg, zr, sizeof (zut_readdir_t), iflag);
+ if (error)
+ goto zutr_bail;
+
+ kbuf = kmem_zalloc(zr->zr_buflen, KM_SLEEP);
+
+ zr->zr_retcode = zut_open_dir(zr->zr_dir, NULL, cr, flags, NULL, &dvn);
+ if (zr->zr_retcode)
+ goto zutr_done;
+
+ if (zr->zr_reqflags & ZUT_XATTR) {
+ vattr_t vattr;
+
+ zr->zr_retcode = VOP_LOOKUP(dvn, zr->zr_file, &fvn,
+ NULL, flags, NULL, cr, NULL, NULL, NULL);
+ VN_RELE(dvn);
+ dvn = NULL;
+ if (zr->zr_retcode)
+ goto zutr_done;
+
+ /*
+ * In order to access hidden attribute directory the
+ * user must have appropriate read access and be able
+ * to stat() the file
+ */
+ if (vfs_has_feature(fvn->v_vfsp, VFSFT_ACEMASKONACCESS)) {
+ zr->zr_retcode = VOP_ACCESS(fvn, ACE_READ_NAMED_ATTRS,
+ V_ACE_MASK, cr, NULL);
+ } else {
+ zr->zr_retcode = VOP_ACCESS(fvn, VREAD, 0, cr, NULL);
+ }
+ if (zr->zr_retcode)
+ goto zutr_done;
+
+ vattr.va_mask = AT_ALL;
+ zr->zr_retcode = VOP_GETATTR(fvn, &vattr, 0, cr, NULL);
+ if (zr->zr_retcode)
+ goto zutr_done;
+
+ zr->zr_retcode = VOP_LOOKUP(fvn, "", &dvn, NULL,
+ flags | LOOKUP_XATTR, NULL, cr, NULL, NULL, NULL);
+ VN_RELE(fvn);
+ if (zr->zr_retcode)
+ goto zutr_done;
+ }
+
+ aiov.iov_base = kbuf;
+ aiov.iov_len = zr->zr_buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_loffset = zr->zr_loffset;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_resid = zr->zr_buflen;
+ auio.uio_fmode = 0;
+ auio.uio_extflg = UIO_COPY_CACHED;
+
+ if (zr->zr_reqflags & ZUT_EXTRDDIR)
+ flags |= V_RDDIR_ENTFLAGS;
+ if (zr->zr_reqflags & ZUT_ACCFILTER)
+ flags |= V_RDDIR_ACCFILTER;
+
+ (void) VOP_RWLOCK(dvn, V_WRITELOCK_FALSE, NULL);
+ zr->zr_retcode = VOP_READDIR(dvn, &auio, cr, &zr->zr_eof,
+ NULL, flags);
+ VOP_RWUNLOCK(dvn, V_WRITELOCK_FALSE, NULL);
+ VN_RELE(dvn);
+
+ zr->zr_bytes = aiov.iov_base - kbuf;
+ zr->zr_loffset = auio.uio_loffset;
+
+ error = ddi_copyout(kbuf, (void *)(uintptr_t)zr->zr_buf,
+ zr->zr_buflen, iflag);
+
+zutr_done:
+ kmem_free(kbuf, zr->zr_buflen);
+ rc = ddi_copyout(zr, (void *)arg, sizeof (zut_readdir_t), iflag);
+ if (error == 0)
+ error = rc;
+
+zutr_bail:
+ kmem_free(zr, sizeof (zut_readdir_t));
+ if (rvalp)
+ *rvalp = error;
+ return (error);
+}
+
+static int
+zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr)
+{
+ xoptattr_t *xoap = NULL;
+ xvattr_t xv = { 0 };
+ int error;
+
+ xva_init(&xv);
+
+ XVA_SET_REQ(&xv, XAT_ARCHIVE);
+ XVA_SET_REQ(&xv, XAT_SYSTEM);
+ XVA_SET_REQ(&xv, XAT_READONLY);
+ XVA_SET_REQ(&xv, XAT_HIDDEN);
+ XVA_SET_REQ(&xv, XAT_NOUNLINK);
+ XVA_SET_REQ(&xv, XAT_IMMUTABLE);
+ XVA_SET_REQ(&xv, XAT_APPENDONLY);
+ XVA_SET_REQ(&xv, XAT_NODUMP);
+ XVA_SET_REQ(&xv, XAT_OPAQUE);
+ XVA_SET_REQ(&xv, XAT_AV_QUARANTINED);
+ XVA_SET_REQ(&xv, XAT_AV_MODIFIED);
+
+ xv.xva_vattr.va_mask |= AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
+ if (error = VOP_GETATTR(vp, &xv.xva_vattr, flag, cr, NULL))
+ return (error);
+
+ bzero(sb, sizeof (sb));
+ sb->st_dev = xv.xva_vattr.va_fsid;
+ sb->st_ino = xv.xva_vattr.va_nodeid;
+ sb->st_mode = VTTOIF(xv.xva_vattr.va_type) | xv.xva_vattr.va_mode;
+ sb->st_nlink = xv.xva_vattr.va_nlink;
+ sb->st_uid = xv.xva_vattr.va_uid;
+ sb->st_gid = xv.xva_vattr.va_gid;
+ sb->st_rdev = xv.xva_vattr.va_rdev;
+ sb->st_size = xv.xva_vattr.va_size;
+ sb->st_atim = xv.xva_vattr.va_atime;
+ sb->st_mtim = xv.xva_vattr.va_mtime;
+ sb->st_ctim = xv.xva_vattr.va_ctime;
+ sb->st_blksize = xv.xva_vattr.va_blksize;
+ sb->st_blocks = xv.xva_vattr.va_nblocks;
+ sb->st_fstype[0] = 0;
+
+ if ((xoap = xva_getxoptattr(&xv)) == NULL)
+ return (0);
+
+ if (XVA_ISSET_RTN(&xv, XAT_ARCHIVE) && xoap->xoa_archive)
+ *xvs |= (1 << F_ARCHIVE);
+ if (XVA_ISSET_RTN(&xv, XAT_SYSTEM) && xoap->xoa_system)
+ *xvs |= (1 << F_SYSTEM);
+ if (XVA_ISSET_RTN(&xv, XAT_READONLY) && xoap->xoa_readonly)
+ *xvs |= (1 << F_READONLY);
+ if (XVA_ISSET_RTN(&xv, XAT_HIDDEN) && xoap->xoa_hidden)
+ *xvs |= (1 << F_HIDDEN);
+ if (XVA_ISSET_RTN(&xv, XAT_NOUNLINK) && xoap->xoa_nounlink)
+ *xvs |= (1 << F_NOUNLINK);
+ if (XVA_ISSET_RTN(&xv, XAT_IMMUTABLE) && xoap->xoa_immutable)
+ *xvs |= (1 << F_IMMUTABLE);
+ if (XVA_ISSET_RTN(&xv, XAT_APPENDONLY) && xoap->xoa_appendonly)
+ *xvs |= (1 << F_APPENDONLY);
+ if (XVA_ISSET_RTN(&xv, XAT_NODUMP) && xoap->xoa_nodump)
+ *xvs |= (1 << F_NODUMP);
+ if (XVA_ISSET_RTN(&xv, XAT_OPAQUE) && xoap->xoa_opaque)
+ *xvs |= (1 << F_OPAQUE);
+ if (XVA_ISSET_RTN(&xv, XAT_AV_QUARANTINED) && xoap->xoa_av_quarantined)
+ *xvs |= (1 << F_AV_QUARANTINED);
+ if (XVA_ISSET_RTN(&xv, XAT_AV_MODIFIED) && xoap->xoa_av_modified)
+ *xvs |= (1 << F_AV_MODIFIED);
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
+zut_lookup(intptr_t arg, cred_t *cr, int iflag, int *rvalp)
+{
+ zut_lookup_t *zl;
+ pathname_t rpn;
+ vnode_t *dvn = NULL;
+ vnode_t *fvn = NULL;
+ vnode_t *xdvn = NULL;
+ vnode_t *xfvn = NULL;
+ vnode_t *release = NULL;
+ int flags = 0;
+ int error, rc;
+
+ zl = kmem_zalloc(sizeof (zut_lookup_t), KM_SLEEP);
+
+ error = ddi_copyin((void *)arg, zl, sizeof (zut_lookup_t), iflag);
+ if (error)
+ goto zutl_bail;
+
+ pn_alloc(&rpn);
+ bzero(rpn.pn_buf, MAXPATHLEN);
+
+ zl->zl_retcode = zut_open_dir(zl->zl_dir, NULL, cr, flags, &rpn, &dvn);
+ if (zl->zl_retcode)
+ goto zutl_done;
+
+ if (zl->zl_reqflags & ZUT_IGNORECASE)
+ flags |= FIGNORECASE;
+
+ zl->zl_retcode = VOP_LOOKUP(dvn, zl->zl_file, &fvn, NULL, flags, NULL,
+ cr, NULL, &zl->zl_deflags, &rpn);
+ if (zl->zl_retcode)
+ goto zutl_done;
+
+ release = fvn;
+
+ if (zl->zl_reqflags & ZUT_XATTR) {
+ vattr_t vattr;
+
+ /*
+ * In order to access hidden attribute directory the
+ * user must have appropriate read access and be able
+ * to stat() the file
+ */
+ if (vfs_has_feature(fvn->v_vfsp, VFSFT_ACEMASKONACCESS)) {
+ zl->zl_retcode = VOP_ACCESS(fvn, ACE_READ_NAMED_ATTRS,
+ V_ACE_MASK, cr, NULL);
+ } else {
+ zl->zl_retcode = VOP_ACCESS(fvn, VREAD, 0, cr, NULL);
+ }
+ if (zl->zl_retcode)
+ goto zutl_done;
+
+ vattr.va_mask = AT_ALL;
+ zl->zl_retcode = VOP_GETATTR(fvn, &vattr, 0, cr, NULL);
+ if (zl->zl_retcode)
+ goto zutl_done;
+
+ zl->zl_retcode = VOP_LOOKUP(fvn, "", &xdvn, NULL,
+ flags | LOOKUP_XATTR, NULL, cr, NULL, NULL, NULL);
+ if (zl->zl_retcode)
+ goto zutl_done;
+ VN_RELE(fvn);
+ release = xdvn;
+
+ zl->zl_retcode = VOP_LOOKUP(xdvn, zl->zl_xfile, &xfvn,
+ NULL, flags, NULL, cr, NULL, &zl->zl_deflags, &rpn);
+ if (zl->zl_retcode)
+ goto zutl_done;
+ VN_RELE(xdvn);
+ release = xfvn;
+ }
+
+ if (zl->zl_reqflags & ZUT_GETSTAT) {
+ zl->zl_retcode = zut_stat64(release,
+ &zl->zl_statbuf, &zl->zl_xvattrs, 0, cr);
+ }
+
+zutl_done:
+ (void) strlcpy(zl->zl_real, rpn.pn_path, MAXPATHLEN);
+
+ rc = ddi_copyout(zl, (void *)arg, sizeof (zut_lookup_t), iflag);
+ if (error == 0)
+ error = rc;
+
+ if (release)
+ VN_RELE(release);
+ if (dvn)
+ VN_RELE(dvn);
+ pn_free(&rpn);
+
+zutl_bail:
+ kmem_free(zl, sizeof (zut_lookup_t));
+ if (rvalp)
+ *rvalp = error;
+ return (error);
+}
+
+/*ARGSUSED*/
+static int
+zut_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
+{
+ int error;
+
+ if (getminor(dev) != 0)
+ return (ENXIO);
+
+ if (cmd <= ZUT_IOC_MIN_CMD || cmd >= ZUT_IOC_MAX_CMD)
+ return (EINVAL);
+
+ switch (cmd) {
+ case ZUT_IOC_LOOKUP:
+ error = zut_lookup(arg, cr, flag, rvalp);
+ break;
+ case ZUT_IOC_READDIR:
+ error = zut_readdir(arg, cr, flag, rvalp);
+ default:
+ break;
+ }
+
+ return (error);
+}
+
+static int
+zut_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+ if (cmd != DDI_ATTACH)
+ return (DDI_FAILURE);
+
+ if (ddi_create_minor_node(dip, "zut", S_IFCHR, 0,
+ DDI_PSEUDO, 0) == DDI_FAILURE)
+ return (DDI_FAILURE);
+
+ zut_dip = dip;
+
+ ddi_report_dev(dip);
+
+ return (DDI_SUCCESS);
+}
+
+static int
+zut_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+ if (cmd != DDI_DETACH)
+ return (DDI_FAILURE);
+
+ zut_dip = NULL;
+
+ ddi_prop_remove_all(dip);
+ ddi_remove_minor_node(dip, NULL);
+
+ return (DDI_SUCCESS);
+}
+
+/*ARGSUSED*/
+static int
+zut_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
+{
+ switch (infocmd) {
+ case DDI_INFO_DEVT2DEVINFO:
+ *result = zut_dip;
+ return (DDI_SUCCESS);
+
+ case DDI_INFO_DEVT2INSTANCE:
+ *result = (void *)0;
+ return (DDI_SUCCESS);
+ }
+
+ return (DDI_FAILURE);
+}
+
+/*ARGSUSED*/
+int
+zut_open(dev_t *devp, int flag, int otyp, cred_t *cr)
+{
+ minor_t minor = getminor(*devp);
+
+ if (minor == 0) /* This is the control device */
+ return (0);
+
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+int
+zut_close(dev_t dev, int flag, int otyp, cred_t *cr)
+{
+ minor_t minor = getminor(dev);
+
+ if (minor == 0) /* This is the control device */
+ return (0);
+
+ return (ENXIO);
+}
+
+/*
+ * /dev/zut is the control node, i.e. minor 0.
+ *
+ * There are no other minor nodes, and /dev/zut basically does nothing
+ * other than serve up ioctls.
+ */
+static struct cb_ops zut_cb_ops = {
+ zut_open, /* open */
+ zut_close, /* close */
+ nodev, /* strategy */
+ nodev, /* print */
+ nodev, /* dump */
+ nodev, /* read */
+ nodev, /* write */
+ zut_ioctl, /* ioctl */
+ nodev, /* devmap */
+ nodev, /* mmap */
+ nodev, /* segmap */
+ nochpoll, /* poll */
+ ddi_prop_op, /* prop_op */
+ NULL, /* streamtab */
+ D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */
+ CB_REV, /* version */
+ nodev, /* async read */
+ nodev, /* async write */
+};
+
+static struct dev_ops zut_dev_ops = {
+ DEVO_REV, /* version */
+ 0, /* refcnt */
+ zut_info, /* info */
+ nulldev, /* identify */
+ nulldev, /* probe */
+ zut_attach, /* attach */
+ zut_detach, /* detach */
+ nodev, /* reset */
+ &zut_cb_ops, /* driver operations */
+ NULL /* no bus operations */
+};
+
+static struct modldrv zut_modldrv = {
+ &mod_driverops, "ZFS unit test " ZUT_VERSION_STRING,
+ &zut_dev_ops
+};
+
+static struct modlinkage modlinkage = {
+ MODREV_1,
+ (void *)&zut_modldrv,
+ NULL
+};
+
+int
+_init(void)
+{
+ int error;
+
+ if ((error = mod_install(&modlinkage)) != 0) {
+ return (error);
+ }
+
+ error = ldi_ident_from_mod(&modlinkage, &zut_li);
+ ASSERT(error == 0);
+
+ return (0);
+}
+
+int
+_fini(void)
+{
+ int error;
+
+ if ((error = mod_remove(&modlinkage)) != 0)
+ return (error);
+
+ ldi_ident_release(zut_li);
+ zut_li = NULL;
+
+ return (error);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&modlinkage, modinfop));
+}
diff --git a/usr/src/uts/common/fs/zut/zut.conf b/usr/src/uts/common/fs/zut/zut.conf
new file mode 100644
index 0000000000..ae79cc4074
--- /dev/null
+++ b/usr/src/uts/common/fs/zut/zut.conf
@@ -0,0 +1,25 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+name="zut" parent="pseudo";
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index aff3d8e74c..75eab6b302 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -835,7 +835,8 @@ FSHDRS= \
ufs_quota.h \
ufs_snap.h \
ufs_trans.h \
- zfs.h
+ zfs.h \
+ zut.h
PCMCIAHDRS= \
pcata.h \
diff --git a/usr/src/uts/common/sys/fs/zut.h b/usr/src/uts/common/sys/fs/zut.h
new file mode 100644
index 0000000000..36c9eaa7f1
--- /dev/null
+++ b/usr/src/uts/common/sys/fs/zut.h
@@ -0,0 +1,93 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ZUT_H
+#define _ZUT_H
+
+/*
+ * IOCTLs for the zfs unit test driver
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define ZUT_DRIVER "zut"
+#define ZUT_DEV "/dev/zut"
+
+#define ZUT_VERSION_STRING "1"
+
+/*
+ * /dev/zut ioctl numbers.
+ */
+#define ZUT_IOC ('U' << 8)
+
+/* Request flags */
+#define ZUT_IGNORECASE 0x01
+#define ZUT_ACCFILTER 0x02
+#define ZUT_XATTR 0x04
+#define ZUT_EXTRDDIR 0x08
+#define ZUT_GETSTAT 0x10
+
+typedef struct zut_lookup {
+ int zl_reqflags;
+ int zl_deflags; /* output */
+ int zl_retcode; /* output */
+ char zl_dir[MAXPATHLEN];
+ char zl_file[MAXNAMELEN];
+ char zl_xfile[MAXNAMELEN];
+ char zl_real[MAXPATHLEN]; /* output */
+ uint64_t zl_xvattrs; /* output */
+ struct stat64 zl_statbuf; /* output */
+} zut_lookup_t;
+
+typedef struct zut_readdir {
+ uint64_t zr_buf; /* pointer to output buffer */
+ uint64_t zr_loffset; /* output */
+ char zr_dir[MAXPATHLEN];
+ char zr_file[MAXNAMELEN];
+ int zr_reqflags;
+ int zr_retcode; /* output */
+ int zr_eof; /* output */
+ uint_t zr_bytes; /* output */
+ uint_t zr_buflen;
+} zut_readdir_t;
+
+typedef enum zut_ioc {
+ ZUT_IOC_MIN_CMD = ZUT_IOC - 1,
+ ZUT_IOC_LOOKUP = ZUT_IOC,
+ ZUT_IOC_READDIR,
+ ZUT_IOC_MAX_CMD
+} zut_ioc_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZUT_H */
diff --git a/usr/src/uts/common/sys/unistd.h b/usr/src/uts/common/sys/unistd.h
index 4547187b37..bc0c6be828 100644
--- a/usr/src/uts/common/sys/unistd.h
+++ b/usr/src/uts/common/sys/unistd.h
@@ -311,6 +311,7 @@ extern "C" {
#define _PC_CASE_BEHAVIOR 22
#define _PC_SATTR_ENABLED 23
#define _PC_SATTR_EXISTS 24
+#define _PC_ACCESS_FILTERING 25
/*
* Large File Summit names
diff --git a/usr/src/uts/common/sys/vfs.h b/usr/src/uts/common/sys/vfs.h
index 5d2d43e804..17ee536024 100644
--- a/usr/src/uts/common/sys/vfs.h
+++ b/usr/src/uts/common/sys/vfs.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -296,6 +296,7 @@ typedef uint64_t vfs_feature_t;
#define VFSFT_ACLONCREATE 0x100000010 /* Supports ACL on create */
#define VFSFT_ACEMASKONACCESS 0x100000020 /* Can use ACEMASK for access */
#define VFSFT_SYSATTR_VIEWS 0x100000040 /* Supports sysattr view i/f */
+#define VFSFT_ACCESS_FILTER 0x100000080 /* dirents filtered by access */
/*
* Argument structure for mount(2).
diff --git a/usr/src/uts/common/sys/vnode.h b/usr/src/uts/common/sys/vnode.h
index 947144b841..2bbf0ae843 100644
--- a/usr/src/uts/common/sys/vnode.h
+++ b/usr/src/uts/common/sys/vnode.h
@@ -1139,6 +1139,7 @@ extern int fop_vnevent(vnode_t *, vnevent_t, vnode_t *, char *,
* Flags for VOP_READDIR
*/
#define V_RDDIR_ENTFLAGS 0x01 /* request dirent flags */
+#define V_RDDIR_ACCFILTER 0x02 /* filter out inaccessible dirents */
/*
* Flags for VOP_RWLOCK/VOP_RWUNLOCK
diff --git a/usr/src/uts/intel/Makefile.intel.shared b/usr/src/uts/intel/Makefile.intel.shared
index 180e3efd00..b899836da5 100644
--- a/usr/src/uts/intel/Makefile.intel.shared
+++ b/usr/src/uts/intel/Makefile.intel.shared
@@ -510,7 +510,7 @@ SCHED_KMODS += IA RT TS RT_DPTBL TS_DPTBL FSS FX FX_DPTBL
# File System Modules (/kernel/fs):
#
FS_KMODS += autofs cachefs ctfs dcfs dev devfs fdfs fifofs hsfs lofs
-FS_KMODS += lx_afs lx_proc mntfs namefs nfs objfs zfs
+FS_KMODS += lx_afs lx_proc mntfs namefs nfs objfs zfs zut
FS_KMODS += pcfs procfs sockfs specfs tmpfs udfs ufs sharefs
FS_KMODS += smbfs
diff --git a/usr/src/uts/intel/zut/Makefile b/usr/src/uts/intel/zut/Makefile
new file mode 100644
index 0000000000..09c58e7756
--- /dev/null
+++ b/usr/src/uts/intel/zut/Makefile
@@ -0,0 +1,100 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# This makefile drives the production of the zut file system
+# kernel module.
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+ARCHDIR:sh = cd ..; basename `pwd`
+
+#
+# Define the module and object file sets.
+#
+MODULE = zut
+OBJECTS = $(ZUT_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(ZUT_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
+CONF_SRCDIR = $(UTSBASE)/common/fs/zut
+
+#
+# Include common rules.
+#
+include ../Makefile.$(ARCHDIR)
+
+#
+# Define targets
+#
+ALL_TARGET = $(BINARY) $(SRC_CONFILE)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
+
+#
+# Overrides and depends_on
+#
+MODSTUBS_DIR = $(OBJS_DIR)
+LDFLAGS += -dy -Ndrv/smbsrv
+
+INC_PATH += -I$(UTSBASE)/common/fs/zut
+INC_PATH += -I$(SRC)/common
+INC_PATH += -I$(COMMONBASE)/zut
+
+C99MODE= -xc99=%all
+C99LMODE= -Xc99=%all
+
+#
+# For now, disable these lint checks; maintainers should endeavor
+# to investigate and remove these for maximum lint coverage.
+# Please do not carry these forward to new Makefiles.
+#
+LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW
+
+#
+# Default build targets.
+#
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+lint: $(LINT_DEPS)
+
+modlintlib: $(MODLINTLIB_DEPS)
+
+clean.lint: $(CLEAN_LINT_DEPS)
+
+install: $(INSTALL_DEPS)
+
+#
+# Include common targets.
+#
+include ../Makefile.targ
diff --git a/usr/src/uts/sparc/Makefile.sparc.shared b/usr/src/uts/sparc/Makefile.sparc.shared
index f60bad2e77..c0c134ad3e 100644
--- a/usr/src/uts/sparc/Makefile.sparc.shared
+++ b/usr/src/uts/sparc/Makefile.sparc.shared
@@ -352,7 +352,7 @@ SCHED_KMODS += RT TS RT_DPTBL TS_DPTBL IA FSS FX FX_DPTBL
# File System Modules (/kernel/fs):
#
FS_KMODS += dev devfs fdfs fifofs hsfs lofs namefs nfs pcfs tmpfs zfs
-FS_KMODS += specfs udfs ufs autofs cachefs procfs sockfs mntfs
+FS_KMODS += zut specfs udfs ufs autofs cachefs procfs sockfs mntfs
FS_KMODS += ctfs objfs sharefs dcfs smbfs
#
diff --git a/usr/src/uts/sparc/zut/Makefile b/usr/src/uts/sparc/zut/Makefile
new file mode 100644
index 0000000000..09c58e7756
--- /dev/null
+++ b/usr/src/uts/sparc/zut/Makefile
@@ -0,0 +1,100 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# This makefile drives the production of the zut file system
+# kernel module.
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+ARCHDIR:sh = cd ..; basename `pwd`
+
+#
+# Define the module and object file sets.
+#
+MODULE = zut
+OBJECTS = $(ZUT_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(ZUT_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
+CONF_SRCDIR = $(UTSBASE)/common/fs/zut
+
+#
+# Include common rules.
+#
+include ../Makefile.$(ARCHDIR)
+
+#
+# Define targets
+#
+ALL_TARGET = $(BINARY) $(SRC_CONFILE)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
+
+#
+# Overrides and depends_on
+#
+MODSTUBS_DIR = $(OBJS_DIR)
+LDFLAGS += -dy -Ndrv/smbsrv
+
+INC_PATH += -I$(UTSBASE)/common/fs/zut
+INC_PATH += -I$(SRC)/common
+INC_PATH += -I$(COMMONBASE)/zut
+
+C99MODE= -xc99=%all
+C99LMODE= -Xc99=%all
+
+#
+# For now, disable these lint checks; maintainers should endeavor
+# to investigate and remove these for maximum lint coverage.
+# Please do not carry these forward to new Makefiles.
+#
+LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW
+
+#
+# Default build targets.
+#
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+lint: $(LINT_DEPS)
+
+modlintlib: $(MODLINTLIB_DEPS)
+
+clean.lint: $(CLEAN_LINT_DEPS)
+
+install: $(INSTALL_DEPS)
+
+#
+# Include common targets.
+#
+include ../Makefile.targ