]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/report.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2005 Silicon Graphics, Inc.
15 static cmdinfo_t dump_cmd
;
16 static cmdinfo_t report_cmd
;
21 dump_cmd
.args
= _("[-g|-p|-u] [-f file]");
22 dump_cmd
.oneline
= _("dump quota information for backup utilities");
25 " create a backup file which contains quota limits information\n"
26 " -g -- dump out group quota limits\n"
27 " -p -- dump out project quota limits\n"
28 " -u -- dump out user quota limits (default)\n"
29 " -f -- write the dump out to the specified file\n"
36 report_cmd
.args
= _("[-bir] [-gpu] [-ahntlLNU] [-f file]");
37 report_cmd
.oneline
= _("report filesystem quota information");
40 " report used space and inodes, and quota limits, for a filesystem\n"
43 " (reports inode usage for all groups, in an easy-to-read format)\n"
44 " This command is the equivalent of the traditional repquota command, which\n"
45 " prints a summary of the disk usage and quotas for the current filesystem,\n"
46 " or all filesystems.\n"
47 " -a -- report for all mounted filesystems with quota enabled\n"
48 " -h -- report in a human-readable format\n"
49 " -n -- skip identifier-to-name translations, just report IDs\n"
50 " -N -- suppress the header from the output\n"
51 " -t -- terse output format, hides rows which are all zero\n"
52 " -L -- lower ID bound to report on\n"
53 " -U -- upper ID bound to report on\n"
54 " -l -- look up names for IDs in lower-upper range\n"
55 " -g -- report group usage and quota information\n"
56 " -p -- report project usage and quota information\n"
57 " -u -- report user usage and quota information\n"
58 " -b -- report blocks-used information only\n"
59 " -i -- report inodes-used information only\n"
60 " -r -- report realtime-blocks-used information only\n"
76 if (flags
& GETNEXTQUOTA_FLAG
)
77 cmd
= XFS_GETNEXTQUOTA
;
81 /* Fall back silently if XFS_GETNEXTQUOTA fails, warn on XFS_GETQUOTA */
82 if (xfsquotactl(cmd
, dev
, type
, id
, (void *)&d
) < 0) {
83 if (errno
!= ENOENT
&& errno
!= ENOSYS
&& errno
!= ESRCH
&&
85 perror("XFS_GETQUOTA");
91 /* Did kernelspace wrap? */
96 if (!d
.d_blk_softlimit
&& !d
.d_blk_hardlimit
&&
97 !d
.d_ino_softlimit
&& !d
.d_ino_hardlimit
&&
98 !d
.d_rtb_softlimit
&& !d
.d_rtb_hardlimit
)
100 fprintf(fp
, "fs = %s\n", dev
);
101 /* this branch is for backward compatibility reasons */
102 if (d
.d_rtb_softlimit
|| d
.d_rtb_hardlimit
)
103 fprintf(fp
, "%-10d %7llu %7llu %7llu %7llu %7llu %7llu\n",
105 (unsigned long long)d
.d_blk_softlimit
,
106 (unsigned long long)d
.d_blk_hardlimit
,
107 (unsigned long long)d
.d_ino_softlimit
,
108 (unsigned long long)d
.d_ino_hardlimit
,
109 (unsigned long long)d
.d_rtb_softlimit
,
110 (unsigned long long)d
.d_rtb_hardlimit
);
112 fprintf(fp
, "%-10d %7llu %7llu %7llu %7llu\n",
114 (unsigned long long)d
.d_blk_softlimit
,
115 (unsigned long long)d
.d_blk_hardlimit
,
116 (unsigned long long)d
.d_ino_softlimit
,
117 (unsigned long long)d
.d_ino_hardlimit
);
123 dump_limits_any_type(
133 if ((mount
= fs_table_lookup(dir
, FS_MOUNT_POINT
)) == NULL
) {
135 fprintf(stderr
, "%s: cannot find mount point %s\n",
140 /* Range was specified; query everything in it */
142 for (id
= lower
; id
<= upper
; id
++)
143 dump_file(fp
, id
, NULL
, type
, mount
->fs_name
, 0);
147 /* Use GETNEXTQUOTA if it's available */
148 if (dump_file(fp
, id
, &oid
, type
, mount
->fs_name
, GETNEXTQUOTA_FLAG
)) {
150 while (dump_file(fp
, id
, &oid
, type
, mount
->fs_name
,
156 /* Otherwise fall back to iterating over each uid/gid/prjid */
158 case XFS_GROUP_QUOTA
: {
161 while ((g
= getgrent()) != NULL
)
162 dump_file(fp
, g
->gr_gid
, NULL
, type
,
167 case XFS_PROJ_QUOTA
: {
168 struct fs_project
*p
;
170 while ((p
= getprent()) != NULL
)
171 dump_file(fp
, p
->pr_prid
, NULL
, type
,
176 case XFS_USER_QUOTA
: {
179 while ((u
= getpwent()) != NULL
)
180 dump_file(fp
, u
->pw_uid
, NULL
, type
,
195 uint lower
= 0, upper
= 0;
198 while ((c
= getopt(argc
, argv
, "f:gpuL:U:")) != EOF
) {
204 type
|= XFS_GROUP_QUOTA
;
207 type
|= XFS_PROJ_QUOTA
;
210 type
|= XFS_USER_QUOTA
;
213 lower
= (uint
)atoi(optarg
);
216 upper
= (uint
)atoi(optarg
);
219 return command_usage(&dump_cmd
);
224 return command_usage(&dump_cmd
);
227 type
= XFS_USER_QUOTA
;
228 } else if (type
!= XFS_GROUP_QUOTA
&&
229 type
!= XFS_PROJ_QUOTA
&&
230 type
!= XFS_USER_QUOTA
) {
231 return command_usage(&dump_cmd
);
234 if ((fp
= fopen_write_secure(fname
)) == NULL
)
237 dump_limits_any_type(fp
, type
, fs_path
->fs_dir
, lower
, upper
);
253 char *typename
= type_to_string(type
);
257 if (flags
& NO_HEADER_FLAG
)
261 fprintf(fp
, _("%s quota on %s (%s)\n"),
262 typename
, mount
->fs_dir
, mount
->fs_name
);
265 for (i
= 0; i
< 10; i
++)
267 if (form
& XFS_BLOCK_QUOTA
)
268 fprintf(fp
, (flags
& HUMAN_FLAG
) ?
269 "%13c %s %13c" : "%20c %s %20c",
270 ' ', form_to_string(XFS_BLOCK_QUOTA
), ' ');
271 if (form
& XFS_INODE_QUOTA
)
272 fprintf(fp
, (flags
& HUMAN_FLAG
) ?
273 "%13c %s %13c" : "%20c %s %20c",
274 ' ', form_to_string(XFS_INODE_QUOTA
), ' ');
275 if (form
& XFS_RTBLOCK_QUOTA
)
276 fprintf(fp
, (flags
& HUMAN_FLAG
) ?
277 "%9c %s %9c" : "%15c %s %15c",
278 ' ', form_to_string(XFS_RTBLOCK_QUOTA
), ' ');
282 snprintf(scratch
, sizeof(scratch
), "%s ID", typename
);
283 fprintf(fp
, "%-10s ", scratch
);
284 if (form
& XFS_BLOCK_QUOTA
)
285 fprintf(fp
, (flags
& HUMAN_FLAG
) ?
286 _(" Used Soft Hard Warn/Grace ") :
287 _(" Used Soft Hard Warn/Grace "));
288 if (form
& XFS_INODE_QUOTA
)
289 fprintf(fp
, (flags
& HUMAN_FLAG
) ?
290 _(" Used Soft Hard Warn/Grace ") :
291 _(" Used Soft Hard Warn/ Grace "));
292 if (form
& XFS_RTBLOCK_QUOTA
)
293 fprintf(fp
, (flags
& HUMAN_FLAG
) ?
294 _(" Used Soft Hard Warn/Grace ") :
295 _(" Used Soft Hard Warn/Grace "));
299 for (i
= 0; i
< 10; i
++)
302 count
= (flags
& HUMAN_FLAG
) ? 33 : 50;
303 if (form
& XFS_BLOCK_QUOTA
) {
304 for (i
= 0; i
< count
; i
++)
308 if (form
& XFS_INODE_QUOTA
) {
309 for (i
= 0; i
< count
; i
++)
313 if (form
& XFS_RTBLOCK_QUOTA
) {
314 for (i
= 0; i
< count
; i
++)
333 char *dev
= mount
->fs_name
;
334 char c
[8], h
[8], s
[8];
339 if (flags
& GETNEXTQUOTA_FLAG
)
340 cmd
= XFS_GETNEXTQUOTA
;
344 /* Fall back silently if XFS_GETNEXTQUOTA fails, warn on XFS_GETQUOTA*/
345 if (xfsquotactl(cmd
, dev
, type
, id
, (void *)&d
) < 0) {
346 if (errno
!= ENOENT
&& errno
!= ENOSYS
&& errno
!= ESRCH
&&
348 perror("XFS_GETQUOTA");
354 /* Did kernelspace wrap? */
359 if (flags
& TERSE_FLAG
) {
361 if ((form
& XFS_BLOCK_QUOTA
) && d
.d_bcount
)
363 if ((form
& XFS_INODE_QUOTA
) && d
.d_icount
)
365 if ((form
& XFS_RTBLOCK_QUOTA
) && d
.d_rtbcount
)
371 if (!(flags
& NO_HEADER_FLAG
))
372 report_header(fp
, form
, type
, mount
, flags
);
374 if (flags
& NO_LOOKUP_FLAG
) {
375 fprintf(fp
, "#%-10u", d
.d_id
);
378 if (type
== XFS_USER_QUOTA
) {
379 struct passwd
*u
= getpwuid(d
.d_id
);
382 } else if (type
== XFS_GROUP_QUOTA
) {
383 struct group
*g
= getgrgid(d
.d_id
);
386 } else if (type
== XFS_PROJ_QUOTA
) {
387 fs_project_t
*p
= getprprid(d
.d_id
);
392 /* If no name is found, print the id #num instead of (null) */
394 fprintf(fp
, "%-10s", name
);
396 fprintf(fp
, "#%-9u", d
.d_id
);
399 if (form
& XFS_BLOCK_QUOTA
) {
400 qflags
= (flags
& HUMAN_FLAG
);
401 if (d
.d_blk_hardlimit
&& d
.d_bcount
> d
.d_blk_hardlimit
)
402 qflags
|= LIMIT_FLAG
;
403 if (d
.d_blk_softlimit
&& d
.d_bcount
> d
.d_blk_softlimit
)
404 qflags
|= QUOTA_FLAG
;
405 if (flags
& HUMAN_FLAG
)
406 fprintf(fp
, " %6s %6s %6s %02d %8s",
407 bbs_to_string(d
.d_bcount
, c
, sizeof(c
)),
408 bbs_to_string(d
.d_blk_softlimit
, s
, sizeof(s
)),
409 bbs_to_string(d
.d_blk_hardlimit
, h
, sizeof(h
)),
411 time_to_string(d
.d_btimer
, qflags
));
413 fprintf(fp
, " %10llu %10llu %10llu %02d %9s",
414 (unsigned long long)d
.d_bcount
>> 1,
415 (unsigned long long)d
.d_blk_softlimit
>> 1,
416 (unsigned long long)d
.d_blk_hardlimit
>> 1,
418 time_to_string(d
.d_btimer
, qflags
));
420 if (form
& XFS_INODE_QUOTA
) {
421 qflags
= (flags
& HUMAN_FLAG
);
422 if (d
.d_ino_hardlimit
&& d
.d_icount
> d
.d_ino_hardlimit
)
423 qflags
|= LIMIT_FLAG
;
424 if (d
.d_ino_softlimit
&& d
.d_icount
> d
.d_ino_softlimit
)
425 qflags
|= QUOTA_FLAG
;
426 if (flags
& HUMAN_FLAG
)
427 fprintf(fp
, " %6s %6s %6s %02d %8s",
428 num_to_string(d
.d_icount
, c
, sizeof(c
)),
429 num_to_string(d
.d_ino_softlimit
, s
, sizeof(s
)),
430 num_to_string(d
.d_ino_hardlimit
, h
, sizeof(h
)),
432 time_to_string(d
.d_itimer
, qflags
));
434 fprintf(fp
, " %10llu %10llu %10llu %02d %9s",
435 (unsigned long long)d
.d_icount
,
436 (unsigned long long)d
.d_ino_softlimit
,
437 (unsigned long long)d
.d_ino_hardlimit
,
439 time_to_string(d
.d_itimer
, qflags
));
441 if (form
& XFS_RTBLOCK_QUOTA
) {
442 qflags
= (flags
& HUMAN_FLAG
);
443 if (d
.d_rtb_hardlimit
&& d
.d_rtbcount
> d
.d_rtb_hardlimit
)
444 qflags
|= LIMIT_FLAG
;
445 if (d
.d_rtb_softlimit
&& d
.d_rtbcount
> d
.d_rtb_softlimit
)
446 qflags
|= QUOTA_FLAG
;
447 if (flags
& HUMAN_FLAG
)
448 fprintf(fp
, " %6s %6s %6s %02d %8s",
449 bbs_to_string(d
.d_rtbcount
, c
, sizeof(c
)),
450 bbs_to_string(d
.d_rtb_softlimit
, s
, sizeof(s
)),
451 bbs_to_string(d
.d_rtb_hardlimit
, h
, sizeof(h
)),
453 time_to_string(d
.d_rtbtimer
, qflags
));
455 fprintf(fp
, " %10llu %10llu %10llu %02d %9s",
456 (unsigned long long)d
.d_rtbcount
>> 1,
457 (unsigned long long)d
.d_rtb_softlimit
>> 1,
458 (unsigned long long)d
.d_rtb_hardlimit
>> 1,
460 time_to_string(d
.d_rtbtimer
, qflags
));
478 if (upper
) { /* identifier range specified */
479 for (id
= lower
; id
<= upper
; id
++) {
480 if (report_mount(fp
, id
, NULL
, NULL
,
481 form
, XFS_USER_QUOTA
, mount
, flags
))
482 flags
|= NO_HEADER_FLAG
;
484 } else if (report_mount(fp
, id
, NULL
, &oid
, form
,
485 XFS_USER_QUOTA
, mount
,
486 flags
|GETNEXTQUOTA_FLAG
)) {
488 flags
|= GETNEXTQUOTA_FLAG
;
489 flags
|= NO_HEADER_FLAG
;
490 while (report_mount(fp
, id
, NULL
, &oid
, form
, XFS_USER_QUOTA
,
496 while ((u
= getpwent()) != NULL
) {
497 if (report_mount(fp
, u
->pw_uid
, u
->pw_name
, NULL
,
498 form
, XFS_USER_QUOTA
, mount
, flags
))
499 flags
|= NO_HEADER_FLAG
;
504 if (flags
& NO_HEADER_FLAG
)
520 if (upper
) { /* identifier range specified */
521 for (id
= lower
; id
<= upper
; id
++) {
522 if (report_mount(fp
, id
, NULL
, NULL
,
523 form
, XFS_GROUP_QUOTA
, mount
, flags
))
524 flags
|= NO_HEADER_FLAG
;
526 } else if (report_mount(fp
, id
, NULL
, &oid
, form
,
527 XFS_GROUP_QUOTA
, mount
,
528 flags
|GETNEXTQUOTA_FLAG
)) {
530 flags
|= GETNEXTQUOTA_FLAG
;
531 flags
|= NO_HEADER_FLAG
;
532 while (report_mount(fp
, id
, NULL
, &oid
, form
, XFS_GROUP_QUOTA
,
538 while ((g
= getgrent()) != NULL
) {
539 if (report_mount(fp
, g
->gr_gid
, g
->gr_name
, NULL
,
540 form
, XFS_GROUP_QUOTA
, mount
, flags
))
541 flags
|= NO_HEADER_FLAG
;
544 if (flags
& NO_HEADER_FLAG
)
550 report_project_mount(
561 if (upper
) { /* identifier range specified */
562 for (id
= lower
; id
<= upper
; id
++) {
563 if (report_mount(fp
, id
, NULL
, NULL
,
564 form
, XFS_PROJ_QUOTA
, mount
, flags
))
565 flags
|= NO_HEADER_FLAG
;
567 } else if (report_mount(fp
, id
, NULL
, &oid
, form
,
568 XFS_PROJ_QUOTA
, mount
,
569 flags
|GETNEXTQUOTA_FLAG
)) {
571 flags
|= GETNEXTQUOTA_FLAG
;
572 flags
|= NO_HEADER_FLAG
;
573 while (report_mount(fp
, id
, NULL
, &oid
, form
, XFS_PROJ_QUOTA
,
580 * Print default project quota, even if projid 0
583 if (report_mount(fp
, 0, NULL
, NULL
,
584 form
, XFS_PROJ_QUOTA
, mount
, flags
))
585 flags
|= NO_HEADER_FLAG
;
589 while ((p
= getprent()) != NULL
) {
590 if (report_mount(fp
, p
->pr_prid
, p
->pr_name
, NULL
,
591 form
, XFS_PROJ_QUOTA
, mount
, flags
))
592 flags
|= NO_HEADER_FLAG
;
597 if (flags
& NO_HEADER_FLAG
)
614 if (type
& XFS_USER_QUOTA
) {
615 fs_cursor_initialise(dir
, FS_MOUNT_POINT
, &cursor
);
616 while ((mount
= fs_cursor_next_entry(&cursor
))) {
617 if (!foreign_allowed
&& (mount
->fs_flags
& FS_FOREIGN
))
619 if (xfsquotactl(XFS_QSYNC
, mount
->fs_name
,
620 XFS_USER_QUOTA
, 0, NULL
) < 0
621 && errno
!= ENOENT
&& errno
!= ENOSYS
)
622 perror("XFS_QSYNC user quota");
623 report_user_mount(fp
, form
, mount
,
624 lower
, upper
, flags
);
627 if (type
& XFS_GROUP_QUOTA
) {
628 fs_cursor_initialise(dir
, FS_MOUNT_POINT
, &cursor
);
629 while ((mount
= fs_cursor_next_entry(&cursor
))) {
630 if (!foreign_allowed
&& (mount
->fs_flags
& FS_FOREIGN
))
632 if (xfsquotactl(XFS_QSYNC
, mount
->fs_name
,
633 XFS_GROUP_QUOTA
, 0, NULL
) < 0
634 && errno
!= ENOENT
&& errno
!= ENOSYS
)
635 perror("XFS_QSYNC group quota");
636 report_group_mount(fp
, form
, mount
,
637 lower
, upper
, flags
);
640 if (type
& XFS_PROJ_QUOTA
) {
641 fs_cursor_initialise(dir
, FS_MOUNT_POINT
, &cursor
);
642 while ((mount
= fs_cursor_next_entry(&cursor
))) {
643 if (!foreign_allowed
&& (mount
->fs_flags
& FS_FOREIGN
))
645 if (xfsquotactl(XFS_QSYNC
, mount
->fs_name
,
646 XFS_PROJ_QUOTA
, 0, NULL
) < 0
647 && errno
!= ENOENT
&& errno
!= ENOSYS
)
648 perror("XFS_QSYNC proj quota");
649 report_project_mount(fp
, form
, mount
,
650 lower
, upper
, flags
);
662 uint lower
= 0, upper
= 0;
664 int c
, flags
= 0, type
= 0, form
= 0;
666 while ((c
= getopt(argc
, argv
, "abdf:ghilL:NnprtuU:")) != EOF
) {
672 form
|= XFS_BLOCK_QUOTA
;
675 form
|= XFS_INODE_QUOTA
;
678 form
|= XFS_RTBLOCK_QUOTA
;
681 type
|= XFS_GROUP_QUOTA
;
684 type
|= XFS_PROJ_QUOTA
;
687 type
|= XFS_USER_QUOTA
;
690 flags
|= ALL_MOUNTS_FLAG
;
696 flags
|= NO_LOOKUP_FLAG
;
699 flags
|= NO_HEADER_FLAG
;
705 lower
= (uint
)atoi(optarg
);
706 flags
|= NO_LOOKUP_FLAG
;
709 upper
= (uint
)atoi(optarg
);
710 flags
|= NO_LOOKUP_FLAG
;
716 return command_usage(&report_cmd
);
721 form
= XFS_BLOCK_QUOTA
;
724 type
= XFS_USER_QUOTA
| XFS_GROUP_QUOTA
| XFS_PROJ_QUOTA
;
727 flags
&= ~NO_LOOKUP_FLAG
;
729 if ((fp
= fopen_write_secure(fname
)) == NULL
)
732 if (argc
== optind
) {
733 if (flags
& ALL_MOUNTS_FLAG
)
734 report_any_type(fp
, form
, type
, NULL
,
735 lower
, upper
, flags
);
736 else if (fs_path
&& (fs_path
->fs_flags
& FS_MOUNT_POINT
))
737 report_any_type(fp
, form
, type
, fs_path
->fs_dir
,
738 lower
, upper
, flags
);
739 } else while (argc
> optind
) {
740 report_any_type(fp
, form
, type
, argv
[optind
++],
741 lower
, upper
, flags
);
752 dump_cmd
.name
= "dump";
753 dump_cmd
.cfunc
= dump_f
;
755 dump_cmd
.argmax
= -1;
756 dump_cmd
.args
= _("[-g|-p|-u] [-f file]");
757 dump_cmd
.oneline
= _("dump quota information for backup utilities");
758 dump_cmd
.help
= dump_help
;
759 dump_cmd
.flags
= CMD_FLAG_FOREIGN_OK
;
761 report_cmd
.name
= "report";
762 report_cmd
.altname
= "repquota";
763 report_cmd
.cfunc
= report_f
;
764 report_cmd
.argmin
= 0;
765 report_cmd
.argmax
= -1;
766 report_cmd
.args
= _("[-bir] [-gpu] [-ahnt] [-f file]");
767 report_cmd
.oneline
= _("report filesystem quota information");
768 report_cmd
.help
= report_help
;
769 report_cmd
.flags
= CMD_FLAG_ONESHOT
| CMD_FLAG_FOREIGN_OK
;
772 add_command(&dump_cmd
);
773 add_command(&report_cmd
);