]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - cddl/contrib/opensolaris/cmd/zlook/zlook.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / cddl / contrib / opensolaris / cmd / zlook / zlook.c
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25
26 /*
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.
31  */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <stropts.h>
37 #include <errno.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <sys/dirent.h>
41 #include <sys/attr.h>
42 #include <stddef.h>
43 #include <fcntl.h>
44 #include <string.h>
45 #include <time.h>
46
47 #define _KERNEL
48
49 #include <sys/fs/zut.h>
50 #include <sys/extdirent.h>
51
52 #undef  _KERNEL
53
54 #define MAXBUF (64 * 1024)
55 #define BIGBUF 4096
56 #define LILBUF (sizeof (dirent_t))
57
58 #define DIRENT_NAMELEN(reclen)  \
59         ((reclen) - (offsetof(dirent_t, d_name[0])))
60
61 static void
62 usage(char *pnam)
63 {
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");
94         exit(EINVAL);
95 }
96
97 static void
98 print_extd_entries(zut_readdir_t *r)
99 {
100         struct edirent *eodp;
101         char *bufstart;
102
103         eodp = (edirent_t *)(uintptr_t)r->zr_buf;
104         bufstart = (char *)eodp;
105         while ((char *)eodp < bufstart + r->zr_bytes) {
106                 char *blanks = "                ";
107                 int i = 0;
108                 while (i < EDIRENT_NAMELEN(eodp->ed_reclen)) {
109                         if (!eodp->ed_name[i])
110                                 break;
111                         (void) printf("%c", eodp->ed_name[i++]);
112                 }
113                 if (i < 16)
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);
117         }
118 }
119
120 static void
121 print_entries(zut_readdir_t *r)
122 {
123         dirent64_t *dp;
124         char *bufstart;
125
126         dp = (dirent64_t *)(intptr_t)r->zr_buf;
127         bufstart = (char *)dp;
128         while ((char *)dp < bufstart + r->zr_bytes) {
129                 int i = 0;
130                 while (i < DIRENT_NAMELEN(dp->d_reclen)) {
131                         if (!dp->d_name[i])
132                                 break;
133                         (void) printf("%c", dp->d_name[i++]);
134                 }
135                 (void) printf("\n");
136                 dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen);
137         }
138 }
139
140 static void
141 print_stats(struct stat64 *sb)
142 {
143         char timebuf[512];
144
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);
153
154         timebuf[0] = 0;
155         if (ctime_r(&sb->st_atime, timebuf, 512)) {
156                 (void) printf("st_atime\t\t");
157                 (void) printf("%s", timebuf);
158         }
159         timebuf[0] = 0;
160         if (ctime_r(&sb->st_mtime, timebuf, 512)) {
161                 (void) printf("st_mtime\t\t");
162                 (void) printf("%s", timebuf);
163         }
164         timebuf[0] = 0;
165         if (ctime_r(&sb->st_ctime, timebuf, 512)) {
166                 (void) printf("st_ctime\t\t");
167                 (void) printf("%s", timebuf);
168         }
169 }
170
171 static void
172 print_xvs(uint64_t xvs)
173 {
174         uint_t bits;
175         int idx = 0;
176
177         if (xvs == 0)
178                 return;
179
180         (void) printf("-------------------\n");
181         (void) printf("Attribute bit(s) set:\n");
182         (void) printf("-------------------\n");
183
184         bits = xvs & ((1 << F_ATTR_ALL) - 1);
185         while (bits) {
186                 uint_t rest = bits >> 1;
187                 if (bits & 1) {
188                         (void) printf("%s", attr_to_name((f_attr_t)idx));
189                         if (rest)
190                                 (void) printf(", ");
191                 }
192                 idx++;
193                 bits = rest;
194         }
195         (void) printf("\n");
196 }
197
198 int
199 main(int argc, char **argv)
200 {
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;
208         int error = 0;
209         int check;
210         int fd;
211         int c;
212
213         while ((c = getopt(argc, argv, "lisaerb:ASE")) != -1) {
214                 switch (c) {
215                 case 'l':
216                         looking = B_TRUE;
217                         break;
218                 case 'i':
219                         lk.zl_reqflags |= ZUT_IGNORECASE;
220                         looking = B_TRUE;
221                         break;
222                 case 's':
223                         lk.zl_reqflags |= ZUT_GETSTAT;
224                         looking = B_TRUE;
225                         break;
226                 case 'a':
227                         rd.zr_reqflags |= ZUT_ACCFILTER;
228                         reading = B_TRUE;
229                         break;
230                 case 'e':
231                         rd.zr_reqflags |= ZUT_EXTRDDIR;
232                         reading = B_TRUE;
233                         break;
234                 case 'r':
235                         reading = B_TRUE;
236                         break;
237                 case 'b':
238                         reading = B_TRUE;
239                         bflag = B_TRUE;
240                         rddir_bufsize = strtol(optarg, NULL, 0);
241                         break;
242                 case 'A':
243                         checking = B_TRUE;
244                         check = _PC_ACCESS_FILTERING;
245                         break;
246                 case 'S':
247                         checking = B_TRUE;
248                         check = _PC_SATTR_ENABLED;
249                         break;
250                 case 'E':
251                         checking = B_TRUE;
252                         check = _PC_SATTR_EXISTS;
253                         break;
254                 case '?':
255                 default:
256                         usage(argv[0]);         /* no return */
257                 }
258         }
259
260         if ((checking && looking) || (checking && reading) ||
261             (looking && reading) || (!reading && bflag) ||
262             (!checking && !reading && !looking))
263                 usage(argv[0]);         /* no return */
264
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);
269                 exit(EINVAL);
270         }
271
272         if (checking) {
273                 char pathbuf[MAXPATHLEN];
274                 long result;
275
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);
281                 switch (check) {
282                 case _PC_SATTR_ENABLED:
283                         (void) printf("System attributes ");
284                         if (result != 0)
285                                 (void) printf("Enabled\n");
286                         else
287                                 (void) printf("Not enabled\n");
288                         break;
289                 case _PC_SATTR_EXISTS:
290                         (void) printf("System attributes ");
291                         if (result != 0)
292                                 (void) printf("Exist\n");
293                         else
294                                 (void) printf("Do not exist\n");
295                         break;
296                 case _PC_ACCESS_FILTERING:
297                         (void) printf("Access filtering ");
298                         if (result != 0)
299                                 (void) printf("Available\n");
300                         else
301                                 (void) printf("Not available\n");
302                         break;
303                 }
304                 return (result);
305         }
306
307         if ((fd = open(ZUT_DEV, O_RDONLY)) < 0) {
308                 perror(ZUT_DEV);
309                 return (ENXIO);
310         }
311
312         if (reading) {
313                 char *buf;
314
315                 if (argc - optind < 1)
316                         usage(argv[0]);         /* no return */
317
318                 (void) strlcpy(rd.zr_dir, argv[optind], MAXPATHLEN);
319                 if (argc - optind > 1) {
320                         (void) strlcpy(rd.zr_file, argv[optind + 1],
321                             MAXNAMELEN);
322                         rd.zr_reqflags |= ZUT_XATTR;
323                 }
324
325                 if ((buf = malloc(rddir_bufsize)) == NULL) {
326                         error = errno;
327                         perror("malloc");
328                         (void) close(fd);
329                         return (error);
330                 }
331
332                 rd.zr_buf = (uint64_t)(uintptr_t)buf;
333                 rd.zr_buflen = rddir_bufsize;
334
335                 while (!rd.zr_eof) {
336                         int ierr;
337
338                         if ((ierr = ioctl(fd, ZUT_IOC_READDIR, &rd)) != 0) {
339                                 (void) fprintf(stderr,
340                                     "IOCTL error: %s (%d)\n",
341                                     strerror(ierr), ierr);
342                                 free(buf);
343                                 (void) close(fd);
344                                 return (ierr);
345                         }
346                         if (rd.zr_retcode) {
347                                 (void) fprintf(stderr,
348                                     "readdir result: %s (%d)\n",
349                                     strerror(rd.zr_retcode), rd.zr_retcode);
350                                 free(buf);
351                                 (void) close(fd);
352                                 return (rd.zr_retcode);
353                         }
354                         if (rd.zr_reqflags & ZUT_EXTRDDIR)
355                                 print_extd_entries(&rd);
356                         else
357                                 print_entries(&rd);
358                 }
359                 free(buf);
360         } else {
361                 int ierr;
362
363                 if (argc - optind < 2)
364                         usage(argv[0]);         /* no return */
365
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;
372                 }
373
374                 if ((ierr = ioctl(fd, ZUT_IOC_LOOKUP, &lk)) != 0) {
375                         (void) fprintf(stderr,
376                             "IOCTL error: %s (%d)\n",
377                             strerror(ierr), ierr);
378                         (void) close(fd);
379                         return (ierr);
380                 }
381
382                 (void) printf("\nLookup of ");
383                 if (lk.zl_reqflags & ZUT_XATTR) {
384                         (void) printf("extended attribute \"%s\" of ",
385                             lk.zl_xfile);
386                 }
387                 (void) printf("file \"%s\" ", lk.zl_file);
388                 (void) printf("in directory \"%s\" ", lk.zl_dir);
389                 if (lk.zl_retcode) {
390                         (void) printf("failed: %s (%d)\n",
391                             strerror(lk.zl_retcode), lk.zl_retcode);
392                         (void) close(fd);
393                         return (lk.zl_retcode);
394                 }
395
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);
401                 }
402                 if (lk.zl_reqflags & ZUT_GETSTAT) {
403                         (void) printf("----------------------------\n");
404                         print_stats(&lk.zl_statbuf);
405                         print_xvs(lk.zl_xvattrs);
406                 }
407         }
408
409         (void) close(fd);
410         return (0);
411 }