]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/stat.c
xfs_io: fix statx call for changed UAPI
[thirdparty/xfsprogs-dev.git] / io / stat.c
1 /*
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * Copyright (C) 2015, 2017 Red Hat, Inc.
6 * Portions of statx support written by David Howells (dhowells@redhat.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "command.h"
23 #include "input.h"
24 #include "init.h"
25 #include "io.h"
26 #include "statx.h"
27 #include "libxfs.h"
28
29 #include <fcntl.h>
30
31 static cmdinfo_t stat_cmd;
32 static cmdinfo_t statfs_cmd;
33 static cmdinfo_t statx_cmd;
34
35 off64_t
36 filesize(void)
37 {
38 struct stat st;
39
40 if (fstat(file->fd, &st) < 0) {
41 perror("fstat");
42 return -1;
43 }
44 return st.st_size;
45 }
46
47 static char *
48 filetype(mode_t mode)
49 {
50 switch (mode & S_IFMT) {
51 case S_IFSOCK:
52 return _("socket");
53 case S_IFDIR:
54 return _("directory");
55 case S_IFCHR:
56 return _("char device");
57 case S_IFBLK:
58 return _("block device");
59 case S_IFREG:
60 return _("regular file");
61 case S_IFLNK:
62 return _("symbolic link");
63 case S_IFIFO:
64 return _("fifo");
65 }
66 return NULL;
67 }
68
69 static int
70 dump_raw_stat(struct stat *st)
71 {
72 printf("stat.blksize = %lu\n", st->st_blksize);
73 printf("stat.nlink = %lu\n", st->st_nlink);
74 printf("stat.uid = %u\n", st->st_uid);
75 printf("stat.gid = %u\n", st->st_gid);
76 printf("stat.mode: 0%o\n", st->st_mode);
77 printf("stat.ino = %lu\n", st->st_ino);
78 printf("stat.size = %lu\n", st->st_size);
79 printf("stat.blocks = %lu\n", st->st_blocks);
80 printf("stat.atime.tv_sec = %ld\n", st->st_atim.tv_sec);
81 printf("stat.atime.tv_nsec = %ld\n", st->st_atim.tv_nsec);
82 printf("stat.ctime.tv_sec = %ld\n", st->st_ctim.tv_sec);
83 printf("stat.ctime.tv_nsec = %ld\n", st->st_ctim.tv_nsec);
84 printf("stat.mtime.tv_sec = %ld\n", st->st_mtim.tv_sec);
85 printf("stat.mtime.tv_nsec = %ld\n", st->st_mtim.tv_nsec);
86 printf("stat.rdev_major = %u\n", major(st->st_rdev));
87 printf("stat.rdev_minor = %u\n", minor(st->st_rdev));
88 printf("stat.dev_major = %u\n", major(st->st_dev));
89 printf("stat.dev_minor = %u\n", minor(st->st_dev));
90 return 0;
91 }
92
93 void print_file_info(void)
94 {
95 printf(_("fd.path = \"%s\"\n"), file->name);
96 printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
97 file->flags & IO_OSYNC ? _("sync") : _("non-sync"),
98 file->flags & IO_DIRECT ? _("direct") : _("non-direct"),
99 file->flags & IO_READONLY ? _("read-only") : _("read-write"),
100 file->flags & IO_REALTIME ? _(",real-time") : "",
101 file->flags & IO_APPEND ? _(",append-only") : "",
102 file->flags & IO_NONBLOCK ? _(",non-block") : "",
103 file->flags & IO_TMPFILE ? _(",tmpfile") : "");
104 }
105
106 void print_xfs_info(int verbose)
107 {
108 struct dioattr dio;
109 struct fsxattr fsx, fsxa;
110
111 if ((xfsctl(file->name, file->fd, FS_IOC_FSGETXATTR, &fsx)) < 0 ||
112 (xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTRA, &fsxa)) < 0) {
113 perror("FS_IOC_FSGETXATTR");
114 } else {
115 printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags);
116 printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
117 printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid);
118 printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize);
119 printf(_("fsxattr.cowextsize = %u\n"), fsx.fsx_cowextsize);
120 printf(_("fsxattr.nextents = %u\n"), fsx.fsx_nextents);
121 printf(_("fsxattr.naextents = %u\n"), fsxa.fsx_nextents);
122 }
123 if ((xfsctl(file->name, file->fd, XFS_IOC_DIOINFO, &dio)) < 0) {
124 perror("XFS_IOC_DIOINFO");
125 } else {
126 printf(_("dioattr.mem = 0x%x\n"), dio.d_mem);
127 printf(_("dioattr.miniosz = %u\n"), dio.d_miniosz);
128 printf(_("dioattr.maxiosz = %u\n"), dio.d_maxiosz);
129 }
130 }
131
132 int
133 stat_f(
134 int argc,
135 char **argv)
136 {
137 struct stat st;
138 int c, verbose = 0, raw = 0;
139
140 while ((c = getopt(argc, argv, "rv")) != EOF) {
141 switch (c) {
142 case 'r':
143 raw = 1;
144 break;
145 case 'v':
146 verbose = 1;
147 break;
148 default:
149 return command_usage(&stat_cmd);
150 }
151 }
152
153 if (raw && verbose)
154 return command_usage(&stat_cmd);
155
156 if (fstat(file->fd, &st) < 0) {
157 perror("fstat");
158 return 0;
159 }
160
161 if (raw)
162 return dump_raw_stat(&st);
163
164 print_file_info();
165
166 printf(_("stat.ino = %lld\n"), (long long)st.st_ino);
167 printf(_("stat.type = %s\n"), filetype(st.st_mode));
168 printf(_("stat.size = %lld\n"), (long long)st.st_size);
169 printf(_("stat.blocks = %lld\n"), (long long)st.st_blocks);
170 if (verbose) {
171 printf(_("stat.atime = %s"), ctime(&st.st_atime));
172 printf(_("stat.mtime = %s"), ctime(&st.st_mtime));
173 printf(_("stat.ctime = %s"), ctime(&st.st_ctime));
174 }
175
176 if (file->flags & IO_FOREIGN)
177 return 0;
178
179 print_xfs_info(verbose);
180
181 return 0;
182 }
183
184 static int
185 statfs_f(
186 int argc,
187 char **argv)
188 {
189 struct xfs_fsop_counts fscounts;
190 struct xfs_fsop_geom fsgeo;
191 struct statfs st;
192
193 printf(_("fd.path = \"%s\"\n"), file->name);
194 if (platform_fstatfs(file->fd, &st) < 0) {
195 perror("fstatfs");
196 } else {
197 printf(_("statfs.f_bsize = %lld\n"), (long long) st.f_bsize);
198 printf(_("statfs.f_blocks = %lld\n"), (long long) st.f_blocks);
199 printf(_("statfs.f_bavail = %lld\n"), (long long) st.f_bavail);
200 printf(_("statfs.f_files = %lld\n"), (long long) st.f_files);
201 printf(_("statfs.f_ffree = %lld\n"), (long long) st.f_ffree);
202 }
203 if (file->flags & IO_FOREIGN)
204 return 0;
205 if ((xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) {
206 perror("XFS_IOC_FSGEOMETRY_V1");
207 } else {
208 printf(_("geom.bsize = %u\n"), fsgeo.blocksize);
209 printf(_("geom.agcount = %u\n"), fsgeo.agcount);
210 printf(_("geom.agblocks = %u\n"), fsgeo.agblocks);
211 printf(_("geom.datablocks = %llu\n"),
212 (unsigned long long) fsgeo.datablocks);
213 printf(_("geom.rtblocks = %llu\n"),
214 (unsigned long long) fsgeo.rtblocks);
215 printf(_("geom.rtextents = %llu\n"),
216 (unsigned long long) fsgeo.rtextents);
217 printf(_("geom.rtextsize = %u\n"), fsgeo.rtextsize);
218 printf(_("geom.sunit = %u\n"), fsgeo.sunit);
219 printf(_("geom.swidth = %u\n"), fsgeo.swidth);
220 }
221 if ((xfsctl(file->name, file->fd, XFS_IOC_FSCOUNTS, &fscounts)) < 0) {
222 perror("XFS_IOC_FSCOUNTS");
223 } else {
224 printf(_("counts.freedata = %llu\n"),
225 (unsigned long long) fscounts.freedata);
226 printf(_("counts.freertx = %llu\n"),
227 (unsigned long long) fscounts.freertx);
228 printf(_("counts.freeino = %llu\n"),
229 (unsigned long long) fscounts.freeino);
230 printf(_("counts.allocino = %llu\n"),
231 (unsigned long long) fscounts.allocino);
232 }
233 return 0;
234 }
235
236 static ssize_t
237 _statx(
238 int dfd,
239 const char *filename,
240 unsigned int flags,
241 unsigned int mask,
242 struct statx *buffer)
243 {
244 #ifdef __NR_statx
245 return syscall(__NR_statx, dfd, filename, flags, mask, buffer);
246 #else
247 errno = ENOSYS;
248 return -1;
249 #endif
250 }
251
252 static void
253 statx_help(void)
254 {
255 printf(_(
256 "\n"
257 " Display extended file status.\n"
258 "\n"
259 " Options:\n"
260 " -v -- More verbose output\n"
261 " -r -- Print raw statx structure fields\n"
262 " -m mask -- Specify the field mask for the statx call\n"
263 " (can also be 'basic' or 'all'; default STATX_ALL)\n"
264 " -D -- Don't sync attributes with the server\n"
265 " -F -- Force the attributes to be sync'd with the server\n"
266 "\n"));
267 }
268
269 /* statx helper */
270 static int
271 dump_raw_statx(struct statx *stx)
272 {
273 printf("stat.mask = 0x%x\n", stx->stx_mask);
274 printf("stat.blksize = %u\n", stx->stx_blksize);
275 printf("stat.attributes = 0x%llx\n", stx->stx_attributes);
276 printf("stat.nlink = %u\n", stx->stx_nlink);
277 printf("stat.uid = %u\n", stx->stx_uid);
278 printf("stat.gid = %u\n", stx->stx_gid);
279 printf("stat.mode: 0%o\n", stx->stx_mode);
280 printf("stat.ino = %llu\n", stx->stx_ino);
281 printf("stat.size = %llu\n", stx->stx_size);
282 printf("stat.blocks = %llu\n", stx->stx_blocks);
283 printf("stat.atime.tv_sec = %lld\n", stx->stx_atime.tv_sec);
284 printf("stat.atime.tv_nsec = %d\n", stx->stx_atime.tv_nsec);
285 printf("stat.btime.tv_sec = %lld\n", stx->stx_btime.tv_sec);
286 printf("stat.btime.tv_nsec = %d\n", stx->stx_btime.tv_nsec);
287 printf("stat.ctime.tv_sec = %lld\n", stx->stx_ctime.tv_sec);
288 printf("stat.ctime.tv_nsec = %d\n", stx->stx_ctime.tv_nsec);
289 printf("stat.mtime.tv_sec = %lld\n", stx->stx_mtime.tv_sec);
290 printf("stat.mtime.tv_nsec = %d\n", stx->stx_mtime.tv_nsec);
291 printf("stat.rdev_major = %u\n", stx->stx_rdev_major);
292 printf("stat.rdev_minor = %u\n", stx->stx_rdev_minor);
293 printf("stat.dev_major = %u\n", stx->stx_dev_major);
294 printf("stat.dev_minor = %u\n", stx->stx_dev_minor);
295 return 0;
296 }
297
298 /*
299 * options:
300 * - input flags - query type
301 * - output style for flags (and all else?) (chars vs. hex?)
302 * - output - mask out incidental flag or not?
303 */
304 int
305 statx_f(
306 int argc,
307 char **argv)
308 {
309 int c, verbose = 0, raw = 0;
310 char *p;
311 struct statx stx;
312 int atflag = 0;
313 unsigned int mask = STATX_ALL;
314
315 while ((c = getopt(argc, argv, "m:rvFD")) != EOF) {
316 switch (c) {
317 case 'm':
318 if (strcmp(optarg, "basic") == 0)
319 mask = STATX_BASIC_STATS;
320 else if (strcmp(optarg, "all") == 0)
321 mask = STATX_ALL;
322 else {
323 mask = strtoul(optarg, &p, 0);
324 if (!p || p == optarg) {
325 printf(
326 _("non-numeric mask -- %s\n"), optarg);
327 return 0;
328 }
329 }
330 break;
331 case 'r':
332 raw = 1;
333 break;
334 case 'v':
335 verbose = 1;
336 break;
337 case 'F':
338 atflag &= ~AT_STATX_SYNC_TYPE;
339 atflag |= AT_STATX_FORCE_SYNC;
340 break;
341 case 'D':
342 atflag &= ~AT_STATX_SYNC_TYPE;
343 atflag |= AT_STATX_DONT_SYNC;
344 break;
345 default:
346 return command_usage(&statx_cmd);
347 }
348 }
349
350 if (raw && verbose)
351 return command_usage(&statx_cmd);
352
353 memset(&stx, 0xbf, sizeof(stx));
354 if (_statx(file->fd, "", atflag | AT_EMPTY_PATH, mask, &stx) < 0) {
355 perror("statx");
356 return 0;
357 }
358
359 if (raw)
360 return dump_raw_statx(&stx);
361
362 print_file_info();
363
364 printf(_("stat.ino = %lld\n"), (long long)stx.stx_ino);
365 printf(_("stat.type = %s\n"), filetype(stx.stx_mode));
366 printf(_("stat.size = %lld\n"), (long long)stx.stx_size);
367 printf(_("stat.blocks = %lld\n"), (long long)stx.stx_blocks);
368 if (verbose) {
369 printf(_("stat.atime = %s"), ctime((time_t *)&stx.stx_atime.tv_sec));
370 printf(_("stat.mtime = %s"), ctime((time_t *)&stx.stx_mtime.tv_sec));
371 printf(_("stat.ctime = %s"), ctime((time_t *)&stx.stx_ctime.tv_sec));
372 if (stx.stx_mask & STATX_BTIME)
373 printf(_("stat.btime = %s"),
374 ctime((time_t *)&stx.stx_btime.tv_sec));
375 }
376
377 if (file->flags & IO_FOREIGN)
378 return 0;
379
380 print_xfs_info(verbose);
381
382 return 0;
383 }
384
385 void
386 stat_init(void)
387 {
388 stat_cmd.name = "stat";
389 stat_cmd.cfunc = stat_f;
390 stat_cmd.argmin = 0;
391 stat_cmd.argmax = 1;
392 stat_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
393 stat_cmd.args = _("[-v|-r]");
394 stat_cmd.oneline = _("statistics on the currently open file");
395
396 statx_cmd.name = "statx";
397 statx_cmd.cfunc = statx_f;
398 statx_cmd.argmin = 0;
399 statx_cmd.argmax = -1;
400 statx_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
401 statx_cmd.args = _("[-v|-r][-m basic | -m all | -m <mask>][-FD]");
402 statx_cmd.oneline = _("extended statistics on the currently open file");
403 statx_cmd.help = statx_help;
404
405 statfs_cmd.name = "statfs";
406 statfs_cmd.cfunc = statfs_f;
407 statfs_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
408 statfs_cmd.oneline =
409 _("statistics on the filesystem of the currently open file");
410
411 add_command(&stat_cmd);
412 add_command(&statx_cmd);
413 add_command(&statfs_cmd);
414 }