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