QA source updates and some associated test changes
[xfstests-dev.git] / src / bstat.c
1 /*
2  * Copyright (c) 2000-2003 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 <xfs/libxfs.h>
34 #include <xfs/jdm.h>
35
36 void
37 dotime(void *ti, char *s)
38 {
39         char    *c;
40         xfs_bstime_t *t;
41
42         t = (xfs_bstime_t *)ti;
43
44         c = ctime(&t->tv_sec);
45         printf("\t%s %19.19s.%09d %s", s, c, t->tv_nsec, c + 20);
46 }
47
48 void
49 printbstat(xfs_bstat_t *sp)
50 {
51         printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
52                 sp->bs_ino, sp->bs_mode, sp->bs_nlink,
53                 sp->bs_uid, sp->bs_gid, sp->bs_rdev);
54         printf("\tblksize %d size %lld blocks %lld xflags %#x extsize %d\n",
55                 sp->bs_blksize, sp->bs_size, sp->bs_blocks,
56                 sp->bs_xflags, sp->bs_extsize);
57         dotime(&sp->bs_atime, "atime");
58         dotime(&sp->bs_mtime, "mtime");
59         dotime(&sp->bs_ctime, "ctime");
60         printf( "\textents %d %d gen %d\n",
61                 sp->bs_extents, sp->bs_aextents, sp->bs_gen);
62         printf( "\tDMI: event mask 0x%08x state 0x%04x\n",
63                 sp->bs_dmevmask, sp->bs_dmstate);
64 }
65
66 void
67 printstat(struct stat64 *sp)
68 {
69         printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
70                 (xfs_ino_t)sp->st_ino, sp->st_mode, sp->st_nlink,
71                 sp->st_uid, sp->st_gid, (unsigned int)sp->st_rdev);
72         printf("\tblksize %llu size %lld blocks %lld\n",
73                 (__uint64_t)sp->st_blksize, sp->st_size, sp->st_blocks);
74         dotime(&sp->st_atime, "atime");
75         dotime(&sp->st_mtime, "mtime");
76         dotime(&sp->st_ctime, "ctime");
77 }
78
79 int
80 main(int argc, char **argv)
81 {
82         __s32           count;
83         int             total = 0;
84         int             fsfd;
85         int             i;
86         __s64           last = 0;
87         char            *name;
88         int             nent;
89         int             debug = 0;
90         int             quiet = 0;
91         int             statit = 0;
92         int             verbose = 0;
93         xfs_bstat_t     *t;
94         int             ret;
95         jdm_fshandle_t  *fshandlep = NULL;
96         int             fd;
97         struct stat64   sb;
98         int nread;
99         char *cc_readlinkbufp;
100         int cc_readlinkbufsz;
101         int             c;
102         xfs_fsop_bulkreq_t bulkreq;
103
104         while ((c = getopt(argc, argv, "cdl:qv")) != -1) {
105                 switch (c) {
106                 case 'q':
107                         quiet = 1;
108                         break;
109                 case 'v':
110                         verbose = 1;
111                         break;
112                 case 'c':
113                         statit = 1;
114                         break;
115                 case 'd':
116                         debug = 1;
117                         break;
118                 case 'l':
119                         last = atoi(optarg);
120                         break;
121                 case '?':
122                 printf("usage: xfs_bstat [-c] [-q] [-v] [ dir [ batch_size ]]\n");
123                 printf("   -c   Check the results against stat(3) output\n");
124                 printf("   -q   Quiet\n");
125                 printf("   -l _num_  Inode to start with\n");
126                 printf("   -v   Verbose output\n");
127                         exit(1);
128                 }
129         }
130         argc -= optind;
131         argv += optind;
132
133         if (argc < 1)
134                 name = ".";
135         else
136                 name = *argv;
137
138         fsfd = open(name, O_RDONLY);
139         if (fsfd < 0) {
140                 perror(name);
141                 exit(1);
142         }
143         if (argc < 2)
144                 nent = 4096;
145         else
146                 nent = atoi(*++argv);
147
148         if (verbose)
149                 printf("Bulkstat test on %s, batch size=%d statcheck=%d\n", 
150                         name, nent, statit);
151
152         if (statit) {
153                 fshandlep = jdm_getfshandle( name );
154                 if (! fshandlep) {
155                         printf("unable to construct sys handle for %s: %s\n",
156                           name, strerror(errno));
157                         return -1;
158                 }
159         }
160
161         t = malloc(nent * sizeof(*t));
162
163         if (verbose)
164                 printf(
165                   "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d\n", last, nent);
166
167         bulkreq.lastip  = &last;
168         bulkreq.icount  = nent;
169         bulkreq.ubuffer = t;
170         bulkreq.ocount  = &count;
171
172         while ((ret = xfsctl(name, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
173                 total += count;
174
175                 if (verbose)
176                         printf(
177             "XFS_IOC_FSBULKSTAT test: last=%lld ret=%d count=%d total=%d\n", 
178                                                 last, ret, count, total);
179                 if (count == 0)
180                         exit(0);
181
182                 if ( quiet && ! statit )
183                         continue;
184
185                 for (i = 0; i < count; i++) {
186                         if (! quiet) {
187                                 printbstat(&t[i]);
188                         }
189         
190                         if (statit) {
191                                 switch(t[i].bs_mode & S_IFMT) {
192                                 case S_IFLNK:
193                                         cc_readlinkbufsz = MAXPATHLEN;
194                                         cc_readlinkbufp = (char *)calloc( 
195                                                               1, 
196                                                               cc_readlinkbufsz);
197                                         nread = jdm_readlink( 
198                                                    fshandlep,
199                                                    &t[i],
200                                                    cc_readlinkbufp,
201                                                    cc_readlinkbufsz);
202                                         if (verbose && nread > 0)
203                                                 printf(
204                                                  "readlink: ino %lld: <%*s>\n",
205                                                             t[i].bs_ino,
206                                                             nread,
207                                                             cc_readlinkbufp);
208                                         free(cc_readlinkbufp);
209                                         if ( nread < 0 ) {
210                                                 printf(
211                                               "could not read symlink ino %llu\n",
212                                                       t[i].bs_ino );
213                                                 printbstat(&t[i]);
214                                         }
215                                         break;
216
217                                 case S_IFCHR:
218                                 case S_IFBLK:
219                                 case S_IFIFO:
220                                 case S_IFSOCK:
221                                         break;
222
223                                 case S_IFREG:
224                                 case S_IFDIR:
225                                         fd = jdm_open( fshandlep, &t[i], O_RDONLY);
226                                         if (fd < 0) {
227                                                 printf(
228                                         "unable to open handle ino %lld: %s\n",
229                                                   t[i].bs_ino, strerror(errno));
230                                                 continue;
231                                         }
232                                         if (fstat64(fd, &sb) < 0) {
233                                                 printf(
234                                         "unable to stat ino %lld: %s\n",
235                                                   t[i].bs_ino, strerror(errno));
236                                         }
237                                         close(fd);
238
239                                         /*
240                                          * Don't compare blksize or blocks, 
241                                          * they are used differently by stat
242                                          * and bstat.
243                                          */
244                                         if ( (t[i].bs_ino != sb.st_ino) ||
245                                              (t[i].bs_mode != sb.st_mode) ||
246                                              (t[i].bs_nlink != sb.st_nlink) ||
247                                              (t[i].bs_uid != sb.st_uid) ||
248                                              (t[i].bs_gid != sb.st_gid) ||
249                                              (t[i].bs_rdev != sb.st_rdev) ||
250                                              (t[i].bs_size != sb.st_size) ||
251                                              /* (t[i].bs_blksize != sb.st_blksize) || */
252                                              (t[i].bs_mtime.tv_sec != sb.st_mtime) ||
253                                              (t[i].bs_ctime.tv_sec != sb.st_ctime) ) {
254                                                 printf("\nstat/bstat missmatch\n");
255                                                 printbstat(&t[i]);
256                                                 printstat(&sb);
257                                         }
258                                 }
259                         }
260                 }
261
262                 if (debug)
263                         break;
264         }
265
266         if (fsfd)
267                 close(fsfd);
268
269         if (ret < 0 )
270                 perror("xfsctl(XFS_IOC_FSBULKSTAT)");
271
272         if (verbose)
273                 printf(
274             "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d ret=%d count=%d\n", 
275                                                last, nent, ret, count);
276
277         return 1;
278 }