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