xref: /illumos-gate/usr/src/cmd/zlook/zlook.c (revision 6a634c9d)
1e802abbdSTim Haley /*
2e802abbdSTim Haley  * CDDL HEADER START
3e802abbdSTim Haley  *
4e802abbdSTim Haley  * The contents of this file are subject to the terms of the
5e802abbdSTim Haley  * Common Development and Distribution License (the "License").
6e802abbdSTim Haley  * You may not use this file except in compliance with the License.
7e802abbdSTim Haley  *
8e802abbdSTim Haley  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e802abbdSTim Haley  * or http://www.opensolaris.org/os/licensing.
10e802abbdSTim Haley  * See the License for the specific language governing permissions
11e802abbdSTim Haley  * and limitations under the License.
12e802abbdSTim Haley  *
13e802abbdSTim Haley  * When distributing Covered Code, include this CDDL HEADER in each
14e802abbdSTim Haley  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e802abbdSTim Haley  * If applicable, add the following below this CDDL HEADER, with the
16e802abbdSTim Haley  * fields enclosed by brackets "[]" replaced with your own identifying
17e802abbdSTim Haley  * information: Portions Copyright [yyyy] [name of copyright owner]
18e802abbdSTim Haley  *
19e802abbdSTim Haley  * CDDL HEADER END
20e802abbdSTim Haley  */
21e802abbdSTim Haley 
22e802abbdSTim Haley /*
23*6a45aeb4STim Haley  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24e802abbdSTim Haley  */
25e802abbdSTim Haley 
26e802abbdSTim Haley /*
27e802abbdSTim Haley  * This is a test program that uses ioctls to the ZFS Unit Test driver
28e802abbdSTim Haley  * to perform readdirs or lookups using flags not normally available
29e802abbdSTim Haley  * to user-land programs.  This allows testing of the flags'
30e802abbdSTim Haley  * behavior outside of a complicated consumer, such as the SMB driver.
31e802abbdSTim Haley  */
32e802abbdSTim Haley 
33e802abbdSTim Haley #include <stdio.h>
34e802abbdSTim Haley #include <stdlib.h>
35e802abbdSTim Haley #include <unistd.h>
36e802abbdSTim Haley #include <stropts.h>
37e802abbdSTim Haley #include <errno.h>
38e802abbdSTim Haley #include <sys/stat.h>
39e802abbdSTim Haley #include <sys/types.h>
40e802abbdSTim Haley #include <sys/dirent.h>
41e802abbdSTim Haley #include <sys/attr.h>
42e802abbdSTim Haley #include <stddef.h>
43e802abbdSTim Haley #include <fcntl.h>
44e802abbdSTim Haley #include <string.h>
45e802abbdSTim Haley #include <time.h>
46e802abbdSTim Haley 
47e802abbdSTim Haley #define	_KERNEL
48e802abbdSTim Haley 
49e802abbdSTim Haley #include <sys/fs/zut.h>
50e802abbdSTim Haley #include <sys/extdirent.h>
51e802abbdSTim Haley 
52e802abbdSTim Haley #undef	_KERNEL
53e802abbdSTim Haley 
54e802abbdSTim Haley #define	MAXBUF (64 * 1024)
55e802abbdSTim Haley #define	BIGBUF 4096
56*6a45aeb4STim Haley #define	LILBUF (sizeof (dirent_t))
57e802abbdSTim Haley 
58e802abbdSTim Haley #define	DIRENT_NAMELEN(reclen)	\
59e802abbdSTim Haley 	((reclen) - (offsetof(dirent_t, d_name[0])))
60e802abbdSTim Haley 
61e802abbdSTim Haley static void
usage(char * pnam)62e802abbdSTim Haley usage(char *pnam)
63e802abbdSTim Haley {
64e802abbdSTim Haley 	(void) fprintf(stderr, "Usage:\n    %s -l [-is] dir-to-look-in "
65e802abbdSTim Haley 	    "file-in-dir [xfile-on-file]\n", pnam);
66e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -i [-ls] dir-to-look-in "
67e802abbdSTim Haley 	    "file-in-dir [xfile-on-file]\n", pnam);
68e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -s [-il] dir-to-look-in "
69e802abbdSTim Haley 	    "file-in-dir [xfile-on-file]\n", pnam);
70e802abbdSTim Haley 	(void) fprintf(stderr, "\t    Perform a lookup\n");
71e802abbdSTim Haley 	(void) fprintf(stderr, "\t    -l == lookup\n");
72e802abbdSTim Haley 	(void) fprintf(stderr, "\t    -i == request FIGNORECASE\n");
73e802abbdSTim Haley 	(void) fprintf(stderr, "\t    -s == request stat(2) and xvattr info\n");
74e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -r [-ea] [-b buffer-size-in-bytes] "
75e802abbdSTim Haley 	    "dir-to-look-in [file-in-dir]\n", pnam);
76e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -e [-ra] [-b buffer-size-in-bytes] "
77e802abbdSTim Haley 	    "dir-to-look-in [file-in-dir]\n", pnam);
78e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -a [-re] [-b buffer-size-in-bytes] "
79e802abbdSTim Haley 	    "dir-to-look-in [file-in-dir]\n", pnam);
80e802abbdSTim Haley 	(void) fprintf(stderr, "\t    Perform a readdir\n");
81e802abbdSTim Haley 	(void) fprintf(stderr, "\t    -r == readdir\n");
82e802abbdSTim Haley 	(void) fprintf(stderr, "\t    -e == request extended entries\n");
83e802abbdSTim Haley 	(void) fprintf(stderr, "\t    -a == request access filtering\n");
84e802abbdSTim Haley 	(void) fprintf(stderr, "\t    -b == buffer size (default 4K)\n");
85e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -A path\n", pnam);
86e802abbdSTim Haley 	(void) fprintf(stderr, "\t    Look up _PC_ACCESS_FILTERING "
87e802abbdSTim Haley 	    "for path with pathconf(2)\n");
88e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -E path\n", pnam);
89e802abbdSTim Haley 	(void) fprintf(stderr, "\t    Look up _PC_SATTR_EXISTS "
90e802abbdSTim Haley 	    "for path with pathconf(2)\n");
91e802abbdSTim Haley 	(void) fprintf(stderr, "    %s -S path\n", pnam);
92e802abbdSTim Haley 	(void) fprintf(stderr, "\t    Look up _PC_SATTR_EXISTS "
93e802abbdSTim Haley 	    "for path with pathconf(2)\n");
94e802abbdSTim Haley 	exit(EINVAL);
95e802abbdSTim Haley }
96e802abbdSTim Haley 
97e802abbdSTim Haley static void
print_extd_entries(zut_readdir_t * r)98e802abbdSTim Haley print_extd_entries(zut_readdir_t *r)
99e802abbdSTim Haley {
100e802abbdSTim Haley 	struct edirent *eodp;
101e802abbdSTim Haley 	char *bufstart;
102e802abbdSTim Haley 
103e802abbdSTim Haley 	eodp = (edirent_t *)(uintptr_t)r->zr_buf;
104e802abbdSTim Haley 	bufstart = (char *)eodp;
105e802abbdSTim Haley 	while ((char *)eodp < bufstart + r->zr_bytes) {
106e802abbdSTim Haley 		char *blanks = "                ";
107e802abbdSTim Haley 		int i = 0;
108e802abbdSTim Haley 		while (i < EDIRENT_NAMELEN(eodp->ed_reclen)) {
109e802abbdSTim Haley 			if (!eodp->ed_name[i])
110e802abbdSTim Haley 				break;
111e802abbdSTim Haley 			(void) printf("%c", eodp->ed_name[i++]);
112e802abbdSTim Haley 		}
113e802abbdSTim Haley 		if (i < 16)
114e802abbdSTim Haley 			(void) printf("%.*s", 16 - i, blanks);
115e802abbdSTim Haley 		(void) printf("\t%x\n", eodp->ed_eflags);
116e802abbdSTim Haley 		eodp = (edirent_t *)((intptr_t)eodp + eodp->ed_reclen);
117e802abbdSTim Haley 	}
118e802abbdSTim Haley }
119e802abbdSTim Haley 
120e802abbdSTim Haley static void
print_entries(zut_readdir_t * r)121e802abbdSTim Haley print_entries(zut_readdir_t *r)
122e802abbdSTim Haley {
123e802abbdSTim Haley 	dirent64_t *dp;
124e802abbdSTim Haley 	char *bufstart;
125e802abbdSTim Haley 
126c5c8461eSTim Haley 	dp = (dirent64_t *)(intptr_t)r->zr_buf;
127e802abbdSTim Haley 	bufstart = (char *)dp;
128e802abbdSTim Haley 	while ((char *)dp < bufstart + r->zr_bytes) {
129e802abbdSTim Haley 		int i = 0;
130e802abbdSTim Haley 		while (i < DIRENT_NAMELEN(dp->d_reclen)) {
131e802abbdSTim Haley 			if (!dp->d_name[i])
132e802abbdSTim Haley 				break;
133e802abbdSTim Haley 			(void) printf("%c", dp->d_name[i++]);
134e802abbdSTim Haley 		}
135e802abbdSTim Haley 		(void) printf("\n");
136e802abbdSTim Haley 		dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen);
137e802abbdSTim Haley 	}
138e802abbdSTim Haley }
139e802abbdSTim Haley 
140e802abbdSTim Haley static void
print_stats(struct stat64 * sb)141e802abbdSTim Haley print_stats(struct stat64 *sb)
142e802abbdSTim Haley {
143e802abbdSTim Haley 	char timebuf[512];
144e802abbdSTim Haley 
145e802abbdSTim Haley 	(void) printf("st_mode\t\t\t%04lo\n", (unsigned long)sb->st_mode);
146e802abbdSTim Haley 	(void) printf("st_ino\t\t\t%llu\n", (unsigned long long)sb->st_ino);
147e802abbdSTim Haley 	(void) printf("st_nlink\t\t%lu\n", (unsigned long)sb->st_nlink);
148e802abbdSTim Haley 	(void) printf("st_uid\t\t\t%d\n", sb->st_uid);
149e802abbdSTim Haley 	(void) printf("st_gid\t\t\t%d\n", sb->st_gid);
150e802abbdSTim Haley 	(void) printf("st_size\t\t\t%lld\n", (long long)sb->st_size);
151e802abbdSTim Haley 	(void) printf("st_blksize\t\t%ld\n", (long)sb->st_blksize);
152e802abbdSTim Haley 	(void) printf("st_blocks\t\t%lld\n", (long long)sb->st_blocks);
153e802abbdSTim Haley 
154e802abbdSTim Haley 	timebuf[0] = 0;
155e802abbdSTim Haley 	if (ctime_r(&sb->st_atime, timebuf, 512)) {
156e802abbdSTim Haley 		(void) printf("st_atime\t\t");
157e802abbdSTim Haley 		(void) printf("%s", timebuf);
158e802abbdSTim Haley 	}
159e802abbdSTim Haley 	timebuf[0] = 0;
160e802abbdSTim Haley 	if (ctime_r(&sb->st_mtime, timebuf, 512)) {
161e802abbdSTim Haley 		(void) printf("st_mtime\t\t");
162e802abbdSTim Haley 		(void) printf("%s", timebuf);
163e802abbdSTim Haley 	}
164e802abbdSTim Haley 	timebuf[0] = 0;
165e802abbdSTim Haley 	if (ctime_r(&sb->st_ctime, timebuf, 512)) {
166e802abbdSTim Haley 		(void) printf("st_ctime\t\t");
167e802abbdSTim Haley 		(void) printf("%s", timebuf);
168e802abbdSTim Haley 	}
169e802abbdSTim Haley }
170e802abbdSTim Haley 
171e802abbdSTim Haley static void
print_xvs(uint64_t xvs)172e802abbdSTim Haley print_xvs(uint64_t xvs)
173e802abbdSTim Haley {
174e802abbdSTim Haley 	uint_t bits;
175e802abbdSTim Haley 	int idx = 0;
176e802abbdSTim Haley 
177e802abbdSTim Haley 	if (xvs == 0)
178e802abbdSTim Haley 		return;
179e802abbdSTim Haley 
180e802abbdSTim Haley 	(void) printf("-------------------\n");
181e802abbdSTim Haley 	(void) printf("Attribute bit(s) set:\n");
182e802abbdSTim Haley 	(void) printf("-------------------\n");
183e802abbdSTim Haley 
184e802abbdSTim Haley 	bits = xvs & ((1 << F_ATTR_ALL) - 1);
185e802abbdSTim Haley 	while (bits) {
186e802abbdSTim Haley 		uint_t rest = bits >> 1;
187e802abbdSTim Haley 		if (bits & 1) {
188e802abbdSTim Haley 			(void) printf("%s", attr_to_name((f_attr_t)idx));
189e802abbdSTim Haley 			if (rest)
190e802abbdSTim Haley 				(void) printf(", ");
191e802abbdSTim Haley 		}
192e802abbdSTim Haley 		idx++;
193e802abbdSTim Haley 		bits = rest;
194e802abbdSTim Haley 	}
195e802abbdSTim Haley 	(void) printf("\n");
196e802abbdSTim Haley }
197e802abbdSTim Haley 
198e802abbdSTim Haley int
main(int argc,char ** argv)199e802abbdSTim Haley main(int argc, char **argv)
200e802abbdSTim Haley {
201e802abbdSTim Haley 	zut_lookup_t lk = {0};
202e802abbdSTim Haley 	zut_readdir_t rd = {0};
203e802abbdSTim Haley 	boolean_t checking = B_FALSE;
204e802abbdSTim Haley 	boolean_t looking = B_FALSE;
205e802abbdSTim Haley 	boolean_t reading = B_FALSE;
206e802abbdSTim Haley 	boolean_t bflag = B_FALSE;
207e802abbdSTim Haley 	long rddir_bufsize = BIGBUF;
208e802abbdSTim Haley 	int error = 0;
209e802abbdSTim Haley 	int check;
210e802abbdSTim Haley 	int fd;
211e802abbdSTim Haley 	int c;
212e802abbdSTim Haley 
213e802abbdSTim Haley 	while ((c = getopt(argc, argv, "lisaerb:ASE")) != -1) {
214e802abbdSTim Haley 		switch (c) {
215e802abbdSTim Haley 		case 'l':
216e802abbdSTim Haley 			looking = B_TRUE;
217e802abbdSTim Haley 			break;
218e802abbdSTim Haley 		case 'i':
219e802abbdSTim Haley 			lk.zl_reqflags |= ZUT_IGNORECASE;
220e802abbdSTim Haley 			looking = B_TRUE;
221e802abbdSTim Haley 			break;
222e802abbdSTim Haley 		case 's':
223e802abbdSTim Haley 			lk.zl_reqflags |= ZUT_GETSTAT;
224e802abbdSTim Haley 			looking = B_TRUE;
225e802abbdSTim Haley 			break;
226e802abbdSTim Haley 		case 'a':
227e802abbdSTim Haley 			rd.zr_reqflags |= ZUT_ACCFILTER;
228e802abbdSTim Haley 			reading = B_TRUE;
229e802abbdSTim Haley 			break;
230e802abbdSTim Haley 		case 'e':
231e802abbdSTim Haley 			rd.zr_reqflags |= ZUT_EXTRDDIR;
232e802abbdSTim Haley 			reading = B_TRUE;
233e802abbdSTim Haley 			break;
234e802abbdSTim Haley 		case 'r':
235e802abbdSTim Haley 			reading = B_TRUE;
236e802abbdSTim Haley 			break;
237e802abbdSTim Haley 		case 'b':
238e802abbdSTim Haley 			reading = B_TRUE;
239e802abbdSTim Haley 			bflag = B_TRUE;
240e802abbdSTim Haley 			rddir_bufsize = strtol(optarg, NULL, 0);
241e802abbdSTim Haley 			break;
242e802abbdSTim Haley 		case 'A':
243e802abbdSTim Haley 			checking = B_TRUE;
244e802abbdSTim Haley 			check = _PC_ACCESS_FILTERING;
245e802abbdSTim Haley 			break;
246e802abbdSTim Haley 		case 'S':
247e802abbdSTim Haley 			checking = B_TRUE;
248e802abbdSTim Haley 			check = _PC_SATTR_ENABLED;
249e802abbdSTim Haley 			break;
250e802abbdSTim Haley 		case 'E':
251e802abbdSTim Haley 			checking = B_TRUE;
252e802abbdSTim Haley 			check = _PC_SATTR_EXISTS;
253e802abbdSTim Haley 			break;
254e802abbdSTim Haley 		case '?':
255e802abbdSTim Haley 		default:
256e802abbdSTim Haley 			usage(argv[0]);		/* no return */
257e802abbdSTim Haley 		}
258e802abbdSTim Haley 	}
259e802abbdSTim Haley 
260e802abbdSTim Haley 	if ((checking && looking) || (checking && reading) ||
261e802abbdSTim Haley 	    (looking && reading) || (!reading && bflag) ||
262e802abbdSTim Haley 	    (!checking && !reading && !looking))
263e802abbdSTim Haley 		usage(argv[0]);		/* no return */
264e802abbdSTim Haley 
265e802abbdSTim Haley 	if (rddir_bufsize < LILBUF || rddir_bufsize > MAXBUF) {
266e802abbdSTim Haley 		(void) fprintf(stderr, "Sorry, buffer size "
267e802abbdSTim Haley 		    "must be >= %d and less than or equal to %d bytes.\n",
268*6a45aeb4STim Haley 		    (int)LILBUF, MAXBUF);
269e802abbdSTim Haley 		exit(EINVAL);
270e802abbdSTim Haley 	}
271e802abbdSTim Haley 
272e802abbdSTim Haley 	if (checking) {
273e802abbdSTim Haley 		char pathbuf[MAXPATHLEN];
274e802abbdSTim Haley 		long result;
275e802abbdSTim Haley 
276e802abbdSTim Haley 		if (argc - optind < 1)
277e802abbdSTim Haley 			usage(argv[0]);		/* no return */
278e802abbdSTim Haley 		(void) strlcpy(pathbuf, argv[optind], MAXPATHLEN);
279e802abbdSTim Haley 		result = pathconf(pathbuf, check);
280e802abbdSTim Haley 		(void) printf("pathconf(2) check for %s\n", pathbuf);
281e802abbdSTim Haley 		switch (check) {
282e802abbdSTim Haley 		case _PC_SATTR_ENABLED:
283e802abbdSTim Haley 			(void) printf("System attributes ");
284e802abbdSTim Haley 			if (result != 0)
285e802abbdSTim Haley 				(void) printf("Enabled\n");
286e802abbdSTim Haley 			else
287e802abbdSTim Haley 				(void) printf("Not enabled\n");
288e802abbdSTim Haley 			break;
289e802abbdSTim Haley 		case _PC_SATTR_EXISTS:
290e802abbdSTim Haley 			(void) printf("System attributes ");
291e802abbdSTim Haley 			if (result != 0)
292e802abbdSTim Haley 				(void) printf("Exist\n");
293e802abbdSTim Haley 			else
294e802abbdSTim Haley 				(void) printf("Do not exist\n");
295e802abbdSTim Haley 			break;
296e802abbdSTim Haley 		case _PC_ACCESS_FILTERING:
297e802abbdSTim Haley 			(void) printf("Access filtering ");
298e802abbdSTim Haley 			if (result != 0)
299e802abbdSTim Haley 				(void) printf("Available\n");
300e802abbdSTim Haley 			else
301e802abbdSTim Haley 				(void) printf("Not available\n");
302e802abbdSTim Haley 			break;
303e802abbdSTim Haley 		}
304e802abbdSTim Haley 		return (result);
305e802abbdSTim Haley 	}
306e802abbdSTim Haley 
307e802abbdSTim Haley 	if ((fd = open(ZUT_DEV, O_RDONLY)) < 0) {
308e802abbdSTim Haley 		perror(ZUT_DEV);
309e802abbdSTim Haley 		return (ENXIO);
310e802abbdSTim Haley 	}
311e802abbdSTim Haley 
312e802abbdSTim Haley 	if (reading) {
313e802abbdSTim Haley 		char *buf;
314e802abbdSTim Haley 
315e802abbdSTim Haley 		if (argc - optind < 1)
316e802abbdSTim Haley 			usage(argv[0]);		/* no return */
317e802abbdSTim Haley 
318e802abbdSTim Haley 		(void) strlcpy(rd.zr_dir, argv[optind], MAXPATHLEN);
319e802abbdSTim Haley 		if (argc - optind > 1) {
320e802abbdSTim Haley 			(void) strlcpy(rd.zr_file, argv[optind + 1],
321e802abbdSTim Haley 			    MAXNAMELEN);
322e802abbdSTim Haley 			rd.zr_reqflags |= ZUT_XATTR;
323e802abbdSTim Haley 		}
324e802abbdSTim Haley 
325e802abbdSTim Haley 		if ((buf = malloc(rddir_bufsize)) == NULL) {
326e802abbdSTim Haley 			error = errno;
327e802abbdSTim Haley 			perror("malloc");
328e802abbdSTim Haley 			(void) close(fd);
329e802abbdSTim Haley 			return (error);
330e802abbdSTim Haley 		}
331e802abbdSTim Haley 
332e802abbdSTim Haley 		rd.zr_buf = (uint64_t)(uintptr_t)buf;
333e802abbdSTim Haley 		rd.zr_buflen = rddir_bufsize;
334e802abbdSTim Haley 
335e802abbdSTim Haley 		while (!rd.zr_eof) {
336e802abbdSTim Haley 			int ierr;
337e802abbdSTim Haley 
338e802abbdSTim Haley 			if ((ierr = ioctl(fd, ZUT_IOC_READDIR, &rd)) != 0) {
339e802abbdSTim Haley 				(void) fprintf(stderr,
340e802abbdSTim Haley 				    "IOCTL error: %s (%d)\n",
341e802abbdSTim Haley 				    strerror(ierr), ierr);
342e802abbdSTim Haley 				free(buf);
343e802abbdSTim Haley 				(void) close(fd);
344e802abbdSTim Haley 				return (ierr);
345e802abbdSTim Haley 			}
346e802abbdSTim Haley 			if (rd.zr_retcode) {
347e802abbdSTim Haley 				(void) fprintf(stderr,
348e802abbdSTim Haley 				    "readdir result: %s (%d)\n",
349e802abbdSTim Haley 				    strerror(rd.zr_retcode), rd.zr_retcode);
350e802abbdSTim Haley 				free(buf);
351e802abbdSTim Haley 				(void) close(fd);
352e802abbdSTim Haley 				return (rd.zr_retcode);
353e802abbdSTim Haley 			}
354e802abbdSTim Haley 			if (rd.zr_reqflags & ZUT_EXTRDDIR)
355e802abbdSTim Haley 				print_extd_entries(&rd);
356e802abbdSTim Haley 			else
357e802abbdSTim Haley 				print_entries(&rd);
358e802abbdSTim Haley 		}
359e802abbdSTim Haley 		free(buf);
360e802abbdSTim Haley 	} else {
361e802abbdSTim Haley 		int ierr;
362e802abbdSTim Haley 
363e802abbdSTim Haley 		if (argc - optind < 2)
364e802abbdSTim Haley 			usage(argv[0]);		/* no return */
365e802abbdSTim Haley 
366e802abbdSTim Haley 		(void) strlcpy(lk.zl_dir, argv[optind], MAXPATHLEN);
367e802abbdSTim Haley 		(void) strlcpy(lk.zl_file, argv[optind + 1], MAXNAMELEN);
368e802abbdSTim Haley 		if (argc - optind > 2) {
369e802abbdSTim Haley 			(void) strlcpy(lk.zl_xfile,
370e802abbdSTim Haley 			    argv[optind + 2], MAXNAMELEN);
371e802abbdSTim Haley 			lk.zl_reqflags |= ZUT_XATTR;
372e802abbdSTim Haley 		}
373e802abbdSTim Haley 
374e802abbdSTim Haley 		if ((ierr = ioctl(fd, ZUT_IOC_LOOKUP, &lk)) != 0) {
375e802abbdSTim Haley 			(void) fprintf(stderr,
376e802abbdSTim Haley 			    "IOCTL error: %s (%d)\n",
377e802abbdSTim Haley 			    strerror(ierr), ierr);
378e802abbdSTim Haley 			(void) close(fd);
379e802abbdSTim Haley 			return (ierr);
380e802abbdSTim Haley 		}
381e802abbdSTim Haley 
382e802abbdSTim Haley 		(void) printf("\nLookup of ");
383e802abbdSTim Haley 		if (lk.zl_reqflags & ZUT_XATTR) {
384e802abbdSTim Haley 			(void) printf("extended attribute \"%s\" of ",
385e802abbdSTim Haley 			    lk.zl_xfile);
386e802abbdSTim Haley 		}
387e802abbdSTim Haley 		(void) printf("file \"%s\" ", lk.zl_file);
388e802abbdSTim Haley 		(void) printf("in directory \"%s\" ", lk.zl_dir);
389e802abbdSTim Haley 		if (lk.zl_retcode) {
390e802abbdSTim Haley 			(void) printf("failed: %s (%d)\n",
391e802abbdSTim Haley 			    strerror(lk.zl_retcode), lk.zl_retcode);
392e802abbdSTim Haley 			(void) close(fd);
393e802abbdSTim Haley 			return (lk.zl_retcode);
394e802abbdSTim Haley 		}
395e802abbdSTim Haley 
396e802abbdSTim Haley 		(void) printf("succeeded.\n");
397e802abbdSTim Haley 		if (lk.zl_reqflags & ZUT_IGNORECASE) {
398e802abbdSTim Haley 			(void) printf("----------------------------\n");
399e802abbdSTim Haley 			(void) printf("dirent flags: 0x%0x\n", lk.zl_deflags);
400e802abbdSTim Haley 			(void) printf("real name: %s\n", lk.zl_real);
401e802abbdSTim Haley 		}
402e802abbdSTim Haley 		if (lk.zl_reqflags & ZUT_GETSTAT) {
403e802abbdSTim Haley 			(void) printf("----------------------------\n");
404e802abbdSTim Haley 			print_stats(&lk.zl_statbuf);
405e802abbdSTim Haley 			print_xvs(lk.zl_xvattrs);
406e802abbdSTim Haley 		}
407e802abbdSTim Haley 	}
408e802abbdSTim Haley 
409e802abbdSTim Haley 	(void) close(fd);
410e802abbdSTim Haley 	return (0);
411e802abbdSTim Haley }
412