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