cmd/xfs/stress/001 1.6 Renamed to cmd/xfstests/001
[xfstests-dev.git] / src / bstat.c
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  * 
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * 
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  * 
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  * 
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  * 
26  * http://www.sgi.com 
27  * 
28  * For further information regarding this notice, see: 
29  * 
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32
33 #include <libxfs.h>
34 #include <jdm.h>
35
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <sys/stat.h>
39 #include <sys/ioctl.h>
40
41 void
42 dotime(void *ti, char *s)
43 {
44         char    *c;
45         xfs_bstime_t *t;
46
47         t = (xfs_bstime_t *)ti;
48
49         c = ctime(&t->tv_sec);
50         printf("\t%s %19.19s.%09d %s", s, c, t->tv_nsec, c + 20);
51 }
52
53 void
54 printbstat(xfs_bstat_t *sp)
55 {
56         printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
57                 sp->bs_ino, sp->bs_mode, sp->bs_nlink,
58                 sp->bs_uid, sp->bs_gid, sp->bs_rdev);
59         printf("\tblksize %d size %lld blocks %lld xflags %#x extsize %d\n",
60                 sp->bs_blksize, sp->bs_size, sp->bs_blocks,
61                 sp->bs_xflags, sp->bs_extsize);
62         dotime(&sp->bs_atime, "atime");
63         dotime(&sp->bs_mtime, "mtime");
64         dotime(&sp->bs_ctime, "ctime");
65         printf( "\textents %d %d gen %d\n",
66                 sp->bs_extents, sp->bs_aextents, sp->bs_gen);
67         printf( "\tDMI: event mask 0x%08x state 0x%04x\n",
68                 sp->bs_dmevmask, sp->bs_dmstate);
69 }
70
71 void
72 printstat(struct stat64 *sp)
73 {
74         printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
75                 (xfs_ino_t)sp->st_ino, sp->st_mode, sp->st_nlink,
76                 sp->st_uid, sp->st_gid, (unsigned int)sp->st_rdev);
77         printf("\tblksize %llu size %lld blocks %lld\n",
78                 (__uint64_t)sp->st_blksize, sp->st_size, sp->st_blocks);
79         dotime(&sp->st_atime, "atime");
80         dotime(&sp->st_mtime, "mtime");
81         dotime(&sp->st_ctime, "ctime");
82 }
83
84 int
85 main(int argc, char **argv)
86 {
87         __s32           count;
88         int             total = 0;
89         int             fsfd;
90         int             i;
91         __s64           last = 0;
92         char            *name;
93         int             nent;
94         int             debug = 0;
95         int             quiet = 0;
96         int             statit = 0;
97         int             verbose = 0;
98         xfs_bstat_t     *t;
99         int             ret;
100         jdm_fshandle_t  *fshandlep;
101         int             fd;
102         struct stat64   sb;
103         int nread;
104         char *cc_readlinkbufp;
105         int cc_readlinkbufsz;
106         int             c;
107         xfs_fsop_bulkreq_t bulkreq;
108
109         while ((c = getopt(argc, argv, "cdl:qv")) != -1) {
110                 switch (c) {
111                 case 'q':
112                         quiet = 1;
113                         break;
114                 case 'v':
115                         verbose = 1;
116                         break;
117                 case 'c':
118                         statit = 1;
119                         break;
120                 case 'd':
121                         debug = 1;
122                         break;
123                 case 'l':
124                         last = atoi(optarg);
125                         break;
126                 case '?':
127                 printf("usage: xfs_bstat [-c] [-q] [-v] [ dir [ batch_size ]]\n");
128                 printf("   -c   Check the results against stat(3) output\n");
129                 printf("   -q   Quiet\n");
130                 printf("   -l _num_  Inode to start with\n");
131                 printf("   -v   Verbose output\n");
132                         exit(1);
133                 }
134         }
135         argc -= optind;
136         argv += optind;
137
138         if (argc < 1)
139                 name = ".";
140         else
141                 name = *argv;
142
143         fsfd = open(name, O_RDONLY);
144         if (fsfd < 0) {
145                 perror(name);
146                 exit(1);
147         }
148         if (argc < 2)
149                 nent = 4096;
150         else
151                 nent = atoi(*++argv);
152
153         if (verbose)
154                 printf("Bulkstat test on %s, batch size=%d statcheck=%d\n", 
155                         name, nent, statit);
156
157         if (statit) {
158                 fshandlep = jdm_getfshandle( name );
159                 if (! fshandlep) {
160                         printf("unable to construct sys handle for %s: %s\n",
161                           name, strerror(errno));
162                         return -1;
163                 }
164         }
165
166         t = malloc(nent * sizeof(*t));
167
168         if (verbose)
169                 printf(
170                   "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d\n", last, nent);
171
172         bulkreq.lastip  = &last;
173         bulkreq.icount  = nent;
174         bulkreq.ubuffer = t;
175         bulkreq.ocount  = &count;
176
177         while ((ret = ioctl(fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
178                 total += count;
179
180                 if (verbose)
181                         printf(
182             "XFS_IOC_FSBULKSTAT test: last=%lld ret=%d count=%d total=%d\n", 
183                                                 last, ret, count, total);
184                 if (count == 0)
185                         exit(0);
186
187                 if ( quiet && ! statit )
188                         continue;
189
190                 for (i = 0; i < count; i++) {
191                         if (! quiet) {
192                                 printbstat(&t[i]);
193                         }
194         
195                         if (statit) {
196                                 switch(t[i].bs_mode & S_IFMT) {
197                                 case S_IFLNK:
198                                         cc_readlinkbufsz = MAXPATHLEN;
199                                         cc_readlinkbufp = (char *)calloc( 
200                                                               1, 
201                                                               cc_readlinkbufsz);
202                                         nread = jdm_readlink( 
203                                                    fshandlep,
204                                                    &t[i],
205                                                    cc_readlinkbufp,
206                                                    cc_readlinkbufsz);
207                                         if (verbose && nread > 0)
208                                                 printf(
209                                                  "readlink: ino %lld: <%*s>\n",
210                                                             t[i].bs_ino,
211                                                             nread,
212                                                             cc_readlinkbufp);
213                                         free(cc_readlinkbufp);
214                                         if ( nread < 0 ) {
215                                                 printf(
216                                               "could not read symlink ino %llu\n",
217                                                       t[i].bs_ino );
218                                                 printbstat(&t[i]);
219                                         }
220                                         break;
221
222                                 case S_IFCHR:
223                                 case S_IFBLK:
224                                 case S_IFIFO:
225                                 case S_IFSOCK:
226                                         break;
227
228                                 case S_IFREG:
229                                 case S_IFDIR:
230                                         fd = jdm_open( fshandlep, &t[i], O_RDONLY);
231                                         if (fd < 0) {
232                                                 printf(
233                                         "unable to open handle ino %lld: %s\n",
234                                                   t[i].bs_ino, strerror(errno));
235                                                 continue;
236                                         }
237                                         if (fstat64(fd, &sb) < 0) {
238                                                 printf(
239                                         "unable to stat ino %lld: %s\n",
240                                                   t[i].bs_ino, strerror(errno));
241                                         }
242                                         close(fd);
243
244                                         /*
245                                          * Don't compare blksize or blocks, 
246                                          * they are used differently by stat
247                                          * and bstat.
248                                          */
249                                         if ( (t[i].bs_ino != sb.st_ino) ||
250                                              (t[i].bs_mode != sb.st_mode) ||
251                                              (t[i].bs_nlink != sb.st_nlink) ||
252                                              (t[i].bs_uid != sb.st_uid) ||
253                                              (t[i].bs_gid != sb.st_gid) ||
254                                              (t[i].bs_rdev != sb.st_rdev) ||
255                                              (t[i].bs_size != sb.st_size) ||
256                                              /* (t[i].bs_blksize != sb.st_blksize) || */
257                                              (t[i].bs_mtime.tv_sec != sb.st_mtime) ||
258                                              (t[i].bs_ctime.tv_sec != sb.st_ctime) ) {
259                                                 printf("\nstat/bstat missmatch\n");
260                                                 printbstat(&t[i]);
261                                                 printstat(&sb);
262                                         }
263                                 }
264                         }
265                 }
266
267                 if (debug)
268                         break;
269         }
270
271         if (fsfd)
272                 close(fsfd);
273
274         if (ret < 0 )
275                 perror("ioctl(XFS_IOC_FSBULKSTAT)");
276
277         if (verbose)
278                 printf(
279             "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d ret=%d count=%d\n", 
280                                                last, nent, ret, count);
281
282         return 1;
283 }