4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * This is a test program that uses ioctls to the ZFS Unit Test driver
28 * to perform readdirs or lookups using flags not normally available
29 * to user-land programs. This allows testing of the flags'
30 * behavior outside of a complicated consumer, such as the SMB driver.
39 #include <sys/types.h>
40 #include <sys/dirent.h>
49 #include <sys/fs/zut.h>
50 #include <sys/extdirent.h>
54 #define MAXBUF (64 * 1024)
56 #define LILBUF (sizeof (dirent_t))
58 #define DIRENT_NAMELEN(reclen) \
59 ((reclen) - (offsetof(dirent_t, d_name[0])))
64 (void) fprintf(stderr, "Usage:\n %s -l [-is] dir-to-look-in "
65 "file-in-dir [xfile-on-file]\n", pnam);
66 (void) fprintf(stderr, " %s -i [-ls] dir-to-look-in "
67 "file-in-dir [xfile-on-file]\n", pnam);
68 (void) fprintf(stderr, " %s -s [-il] dir-to-look-in "
69 "file-in-dir [xfile-on-file]\n", pnam);
70 (void) fprintf(stderr, "\t Perform a lookup\n");
71 (void) fprintf(stderr, "\t -l == lookup\n");
72 (void) fprintf(stderr, "\t -i == request FIGNORECASE\n");
73 (void) fprintf(stderr, "\t -s == request stat(2) and xvattr info\n");
74 (void) fprintf(stderr, " %s -r [-ea] [-b buffer-size-in-bytes] "
75 "dir-to-look-in [file-in-dir]\n", pnam);
76 (void) fprintf(stderr, " %s -e [-ra] [-b buffer-size-in-bytes] "
77 "dir-to-look-in [file-in-dir]\n", pnam);
78 (void) fprintf(stderr, " %s -a [-re] [-b buffer-size-in-bytes] "
79 "dir-to-look-in [file-in-dir]\n", pnam);
80 (void) fprintf(stderr, "\t Perform a readdir\n");
81 (void) fprintf(stderr, "\t -r == readdir\n");
82 (void) fprintf(stderr, "\t -e == request extended entries\n");
83 (void) fprintf(stderr, "\t -a == request access filtering\n");
84 (void) fprintf(stderr, "\t -b == buffer size (default 4K)\n");
85 (void) fprintf(stderr, " %s -A path\n", pnam);
86 (void) fprintf(stderr, "\t Look up _PC_ACCESS_FILTERING "
87 "for path with pathconf(2)\n");
88 (void) fprintf(stderr, " %s -E path\n", pnam);
89 (void) fprintf(stderr, "\t Look up _PC_SATTR_EXISTS "
90 "for path with pathconf(2)\n");
91 (void) fprintf(stderr, " %s -S path\n", pnam);
92 (void) fprintf(stderr, "\t Look up _PC_SATTR_EXISTS "
93 "for path with pathconf(2)\n");
98 print_extd_entries(zut_readdir_t *r)
100 struct edirent *eodp;
103 eodp = (edirent_t *)(uintptr_t)r->zr_buf;
104 bufstart = (char *)eodp;
105 while ((char *)eodp < bufstart + r->zr_bytes) {
108 while (i < EDIRENT_NAMELEN(eodp->ed_reclen)) {
109 if (!eodp->ed_name[i])
111 (void) printf("%c", eodp->ed_name[i++]);
114 (void) printf("%.*s", 16 - i, blanks);
115 (void) printf("\t%x\n", eodp->ed_eflags);
116 eodp = (edirent_t *)((intptr_t)eodp + eodp->ed_reclen);
121 print_entries(zut_readdir_t *r)
126 dp = (dirent64_t *)(intptr_t)r->zr_buf;
127 bufstart = (char *)dp;
128 while ((char *)dp < bufstart + r->zr_bytes) {
130 while (i < DIRENT_NAMELEN(dp->d_reclen)) {
133 (void) printf("%c", dp->d_name[i++]);
136 dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen);
141 print_stats(struct stat64 *sb)
145 (void) printf("st_mode\t\t\t%04lo\n", (unsigned long)sb->st_mode);
146 (void) printf("st_ino\t\t\t%llu\n", (unsigned long long)sb->st_ino);
147 (void) printf("st_nlink\t\t%lu\n", (unsigned long)sb->st_nlink);
148 (void) printf("st_uid\t\t\t%d\n", sb->st_uid);
149 (void) printf("st_gid\t\t\t%d\n", sb->st_gid);
150 (void) printf("st_size\t\t\t%lld\n", (long long)sb->st_size);
151 (void) printf("st_blksize\t\t%ld\n", (long)sb->st_blksize);
152 (void) printf("st_blocks\t\t%lld\n", (long long)sb->st_blocks);
155 if (ctime_r(&sb->st_atime, timebuf, 512)) {
156 (void) printf("st_atime\t\t");
157 (void) printf("%s", timebuf);
160 if (ctime_r(&sb->st_mtime, timebuf, 512)) {
161 (void) printf("st_mtime\t\t");
162 (void) printf("%s", timebuf);
165 if (ctime_r(&sb->st_ctime, timebuf, 512)) {
166 (void) printf("st_ctime\t\t");
167 (void) printf("%s", timebuf);
172 print_xvs(uint64_t xvs)
180 (void) printf("-------------------\n");
181 (void) printf("Attribute bit(s) set:\n");
182 (void) printf("-------------------\n");
184 bits = xvs & ((1 << F_ATTR_ALL) - 1);
186 uint_t rest = bits >> 1;
188 (void) printf("%s", attr_to_name((f_attr_t)idx));
199 main(int argc, char **argv)
201 zut_lookup_t lk = {0};
202 zut_readdir_t rd = {0};
203 boolean_t checking = B_FALSE;
204 boolean_t looking = B_FALSE;
205 boolean_t reading = B_FALSE;
206 boolean_t bflag = B_FALSE;
207 long rddir_bufsize = BIGBUF;
213 while ((c = getopt(argc, argv, "lisaerb:ASE")) != -1) {
219 lk.zl_reqflags |= ZUT_IGNORECASE;
223 lk.zl_reqflags |= ZUT_GETSTAT;
227 rd.zr_reqflags |= ZUT_ACCFILTER;
231 rd.zr_reqflags |= ZUT_EXTRDDIR;
240 rddir_bufsize = strtol(optarg, NULL, 0);
244 check = _PC_ACCESS_FILTERING;
248 check = _PC_SATTR_ENABLED;
252 check = _PC_SATTR_EXISTS;
256 usage(argv[0]); /* no return */
260 if ((checking && looking) || (checking && reading) ||
261 (looking && reading) || (!reading && bflag) ||
262 (!checking && !reading && !looking))
263 usage(argv[0]); /* no return */
265 if (rddir_bufsize < LILBUF || rddir_bufsize > MAXBUF) {
266 (void) fprintf(stderr, "Sorry, buffer size "
267 "must be >= %d and less than or equal to %d bytes.\n",
268 (int)LILBUF, MAXBUF);
273 char pathbuf[MAXPATHLEN];
276 if (argc - optind < 1)
277 usage(argv[0]); /* no return */
278 (void) strlcpy(pathbuf, argv[optind], MAXPATHLEN);
279 result = pathconf(pathbuf, check);
280 (void) printf("pathconf(2) check for %s\n", pathbuf);
282 case _PC_SATTR_ENABLED:
283 (void) printf("System attributes ");
285 (void) printf("Enabled\n");
287 (void) printf("Not enabled\n");
289 case _PC_SATTR_EXISTS:
290 (void) printf("System attributes ");
292 (void) printf("Exist\n");
294 (void) printf("Do not exist\n");
296 case _PC_ACCESS_FILTERING:
297 (void) printf("Access filtering ");
299 (void) printf("Available\n");
301 (void) printf("Not available\n");
307 if ((fd = open(ZUT_DEV, O_RDONLY)) < 0) {
315 if (argc - optind < 1)
316 usage(argv[0]); /* no return */
318 (void) strlcpy(rd.zr_dir, argv[optind], MAXPATHLEN);
319 if (argc - optind > 1) {
320 (void) strlcpy(rd.zr_file, argv[optind + 1],
322 rd.zr_reqflags |= ZUT_XATTR;
325 if ((buf = malloc(rddir_bufsize)) == NULL) {
332 rd.zr_buf = (uint64_t)(uintptr_t)buf;
333 rd.zr_buflen = rddir_bufsize;
338 if ((ierr = ioctl(fd, ZUT_IOC_READDIR, &rd)) != 0) {
339 (void) fprintf(stderr,
340 "IOCTL error: %s (%d)\n",
341 strerror(ierr), ierr);
347 (void) fprintf(stderr,
348 "readdir result: %s (%d)\n",
349 strerror(rd.zr_retcode), rd.zr_retcode);
352 return (rd.zr_retcode);
354 if (rd.zr_reqflags & ZUT_EXTRDDIR)
355 print_extd_entries(&rd);
363 if (argc - optind < 2)
364 usage(argv[0]); /* no return */
366 (void) strlcpy(lk.zl_dir, argv[optind], MAXPATHLEN);
367 (void) strlcpy(lk.zl_file, argv[optind + 1], MAXNAMELEN);
368 if (argc - optind > 2) {
369 (void) strlcpy(lk.zl_xfile,
370 argv[optind + 2], MAXNAMELEN);
371 lk.zl_reqflags |= ZUT_XATTR;
374 if ((ierr = ioctl(fd, ZUT_IOC_LOOKUP, &lk)) != 0) {
375 (void) fprintf(stderr,
376 "IOCTL error: %s (%d)\n",
377 strerror(ierr), ierr);
382 (void) printf("\nLookup of ");
383 if (lk.zl_reqflags & ZUT_XATTR) {
384 (void) printf("extended attribute \"%s\" of ",
387 (void) printf("file \"%s\" ", lk.zl_file);
388 (void) printf("in directory \"%s\" ", lk.zl_dir);
390 (void) printf("failed: %s (%d)\n",
391 strerror(lk.zl_retcode), lk.zl_retcode);
393 return (lk.zl_retcode);
396 (void) printf("succeeded.\n");
397 if (lk.zl_reqflags & ZUT_IGNORECASE) {
398 (void) printf("----------------------------\n");
399 (void) printf("dirent flags: 0x%0x\n", lk.zl_deflags);
400 (void) printf("real name: %s\n", lk.zl_real);
402 if (lk.zl_reqflags & ZUT_GETSTAT) {
403 (void) printf("----------------------------\n");
404 print_stats(&lk.zl_statbuf);
405 print_xvs(lk.zl_xvattrs);