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