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
);