]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/report.c
xfs: fix maxicount division by zero error
[thirdparty/xfsprogs-dev.git] / quota / report.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6 #include <stdbool.h>
7 #include "command.h"
8 #include <sys/types.h>
9 #include <pwd.h>
10 #include <grp.h>
11 #include <utmp.h>
12 #include "init.h"
13 #include "quota.h"
14
15 static cmdinfo_t dump_cmd;
16 static cmdinfo_t report_cmd;
17
18 static void
19 dump_help(void)
20 {
21 dump_cmd.args = _("[-g|-p|-u] [-f file]");
22 dump_cmd.oneline = _("dump quota information for backup utilities");
23 printf(_(
24 "\n"
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"
30 "\n"));
31 }
32
33 static void
34 report_help(void)
35 {
36 report_cmd.args = _("[-bir] [-gpu] [-ahntlLNU] [-f file]");
37 report_cmd.oneline = _("report filesystem quota information");
38 printf(_(
39 "\n"
40 " report used space and inodes, and quota limits, for a filesystem\n"
41 " Example:\n"
42 " 'report -igh'\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"
61 "\n"));
62 }
63
64 static int
65 dump_file(
66 FILE *fp,
67 uint id,
68 uint *oid,
69 uint type,
70 char *dev,
71 int flags)
72 {
73 fs_disk_quota_t d;
74 int cmd;
75
76 if (flags & GETNEXTQUOTA_FLAG)
77 cmd = XFS_GETNEXTQUOTA;
78 else
79 cmd = XFS_GETQUOTA;
80
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 &&
84 cmd == XFS_GETQUOTA)
85 perror("XFS_GETQUOTA");
86 return 0;
87 }
88
89 if (oid) {
90 *oid = d.d_id;
91 /* Did kernelspace wrap? */
92 if (*oid < id)
93 return 0;
94 }
95
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)
99 return 1;
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",
104 d.d_id,
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);
111 else
112 fprintf(fp, "%-10d %7llu %7llu %7llu %7llu\n",
113 d.d_id,
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);
118
119 return 1;
120 }
121
122 static void
123 dump_limits_any_type(
124 FILE *fp,
125 uint type,
126 char *dir,
127 uint lower,
128 uint upper)
129 {
130 fs_path_t *mount;
131 uint id = 0, oid;
132
133 if ((mount = fs_table_lookup(dir, FS_MOUNT_POINT)) == NULL) {
134 exitcode = 1;
135 fprintf(stderr, "%s: cannot find mount point %s\n",
136 progname, dir);
137 return;
138 }
139
140 /* Range was specified; query everything in it */
141 if (upper) {
142 for (id = lower; id <= upper; id++)
143 dump_file(fp, id, NULL, type, mount->fs_name, 0);
144 return;
145 }
146
147 /* Use GETNEXTQUOTA if it's available */
148 if (dump_file(fp, id, &oid, type, mount->fs_name, GETNEXTQUOTA_FLAG)) {
149 id = oid + 1;
150 while (dump_file(fp, id, &oid, type, mount->fs_name,
151 GETNEXTQUOTA_FLAG))
152 id = oid + 1;
153 return;
154 }
155
156 /* Otherwise fall back to iterating over each uid/gid/prjid */
157 switch (type) {
158 case XFS_GROUP_QUOTA: {
159 struct group *g;
160 setgrent();
161 while ((g = getgrent()) != NULL)
162 dump_file(fp, g->gr_gid, NULL, type,
163 mount->fs_name, 0);
164 endgrent();
165 break;
166 }
167 case XFS_PROJ_QUOTA: {
168 struct fs_project *p;
169 setprent();
170 while ((p = getprent()) != NULL)
171 dump_file(fp, p->pr_prid, NULL, type,
172 mount->fs_name, 0);
173 endprent();
174 break;
175 }
176 case XFS_USER_QUOTA: {
177 struct passwd *u;
178 setpwent();
179 while ((u = getpwent()) != NULL)
180 dump_file(fp, u->pw_uid, NULL, type,
181 mount->fs_name, 0);
182 endpwent();
183 break;
184 }
185 }
186 }
187
188 static int
189 dump_f(
190 int argc,
191 char **argv)
192 {
193 FILE *fp;
194 char *fname = NULL;
195 uint lower = 0, upper = 0;
196 int c, type = 0;
197
198 while ((c = getopt(argc, argv, "f:gpuL:U:")) != EOF) {
199 switch(c) {
200 case 'f':
201 fname = optarg;
202 break;
203 case 'g':
204 type |= XFS_GROUP_QUOTA;
205 break;
206 case 'p':
207 type |= XFS_PROJ_QUOTA;
208 break;
209 case 'u':
210 type |= XFS_USER_QUOTA;
211 break;
212 case 'L':
213 lower = (uint)atoi(optarg);
214 break;
215 case 'U':
216 upper = (uint)atoi(optarg);
217 break;
218 default:
219 return command_usage(&dump_cmd);
220 }
221 }
222
223 if (argc != optind)
224 return command_usage(&dump_cmd);
225
226 if (!type) {
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);
232 }
233
234 if ((fp = fopen_write_secure(fname)) == NULL)
235 return 0;
236
237 dump_limits_any_type(fp, type, fs_path->fs_dir, lower, upper);
238
239 if (fname)
240 fclose(fp);
241
242 return 0;
243 }
244
245 static void
246 report_header(
247 FILE *fp,
248 uint form,
249 uint type,
250 fs_path_t *mount,
251 int flags)
252 {
253 char *typename = type_to_string(type);
254 char scratch[64];
255 uint i, count;
256
257 if (flags & NO_HEADER_FLAG)
258 return;
259
260 /* line 1 */
261 fprintf(fp, _("%s quota on %s (%s)\n"),
262 typename, mount->fs_dir, mount->fs_name);
263
264 /* line 2 */
265 for (i = 0; i < 10; i++)
266 fputc(' ', fp);
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), ' ');
279 fputc('\n', fp);
280
281 /* line 3 */
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 "));
296 fputc('\n', fp);
297
298 /* line 4 */
299 for (i = 0; i < 10; i++)
300 fputc('-', fp);
301 fputc(' ', fp);
302 count = (flags & HUMAN_FLAG) ? 33 : 50;
303 if (form & XFS_BLOCK_QUOTA) {
304 for (i = 0; i < count; i++)
305 fputc('-', fp);
306 fputc(' ', fp);
307 }
308 if (form & XFS_INODE_QUOTA) {
309 for (i = 0; i < count; i++)
310 fputc('-', fp);
311 fputc(' ', fp);
312 }
313 if (form & XFS_RTBLOCK_QUOTA) {
314 for (i = 0; i < count; i++)
315 fputc('-', fp);
316 fputc(' ', fp);
317 }
318 fputc('\n', fp);
319 }
320
321 static int
322 report_mount(
323 FILE *fp,
324 uint32_t id,
325 char *name,
326 uint32_t *oid,
327 uint form,
328 uint type,
329 fs_path_t *mount,
330 uint flags)
331 {
332 fs_disk_quota_t d;
333 char *dev = mount->fs_name;
334 char c[8], h[8], s[8];
335 uint qflags;
336 int count;
337 int cmd;
338
339 if (flags & GETNEXTQUOTA_FLAG)
340 cmd = XFS_GETNEXTQUOTA;
341 else
342 cmd = XFS_GETQUOTA;
343
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 &&
347 cmd == XFS_GETQUOTA)
348 perror("XFS_GETQUOTA");
349 return 0;
350 }
351
352 if (oid) {
353 *oid = d.d_id;
354 /* Did kernelspace wrap? */
355 if (* oid < id)
356 return 0;
357 }
358
359 if (flags & TERSE_FLAG) {
360 count = 0;
361 if ((form & XFS_BLOCK_QUOTA) && d.d_bcount)
362 count++;
363 if ((form & XFS_INODE_QUOTA) && d.d_icount)
364 count++;
365 if ((form & XFS_RTBLOCK_QUOTA) && d.d_rtbcount)
366 count++;
367 if (!count)
368 return 0;
369 }
370
371 if (!(flags & NO_HEADER_FLAG))
372 report_header(fp, form, type, mount, flags);
373
374 if (flags & NO_LOOKUP_FLAG) {
375 fprintf(fp, "#%-10u", d.d_id);
376 } else {
377 if (name == NULL) {
378 if (type == XFS_USER_QUOTA) {
379 struct passwd *u = getpwuid(d.d_id);
380 if (u)
381 name = u->pw_name;
382 } else if (type == XFS_GROUP_QUOTA) {
383 struct group *g = getgrgid(d.d_id);
384 if (g)
385 name = g->gr_name;
386 } else if (type == XFS_PROJ_QUOTA) {
387 fs_project_t *p = getprprid(d.d_id);
388 if (p)
389 name = p->pr_name;
390 }
391 }
392 /* If no name is found, print the id #num instead of (null) */
393 if (name != NULL)
394 fprintf(fp, "%-10s", name);
395 else
396 fprintf(fp, "#%-9u", d.d_id);
397 }
398
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)),
410 d.d_bwarns,
411 time_to_string(d.d_btimer, qflags));
412 else
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,
417 d.d_bwarns,
418 time_to_string(d.d_btimer, qflags));
419 }
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)),
431 d.d_iwarns,
432 time_to_string(d.d_itimer, qflags));
433 else
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,
438 d.d_iwarns,
439 time_to_string(d.d_itimer, qflags));
440 }
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)),
452 d.d_rtbwarns,
453 time_to_string(d.d_rtbtimer, qflags));
454 else
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,
459 d.d_rtbwarns,
460 time_to_string(d.d_rtbtimer, qflags));
461 }
462 fputc('\n', fp);
463 return 1;
464 }
465
466 static void
467 report_user_mount(
468 FILE *fp,
469 uint form,
470 fs_path_t *mount,
471 uint lower,
472 uint upper,
473 uint flags)
474 {
475 struct passwd *u;
476 uint id = 0, oid;
477
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;
483 }
484 } else if (report_mount(fp, id, NULL, &oid, form,
485 XFS_USER_QUOTA, mount,
486 flags|GETNEXTQUOTA_FLAG)) {
487 id = oid + 1;
488 flags |= GETNEXTQUOTA_FLAG;
489 flags |= NO_HEADER_FLAG;
490 while (report_mount(fp, id, NULL, &oid, form, XFS_USER_QUOTA,
491 mount, flags)) {
492 id = oid + 1;
493 }
494 } else {
495 setpwent();
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;
500 }
501 endpwent();
502 }
503
504 if (flags & NO_HEADER_FLAG)
505 fputc('\n', fp);
506 }
507
508 static void
509 report_group_mount(
510 FILE *fp,
511 uint form,
512 fs_path_t *mount,
513 uint lower,
514 uint upper,
515 uint flags)
516 {
517 struct group *g;
518 uint id = 0, oid;
519
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;
525 }
526 } else if (report_mount(fp, id, NULL, &oid, form,
527 XFS_GROUP_QUOTA, mount,
528 flags|GETNEXTQUOTA_FLAG)) {
529 id = oid + 1;
530 flags |= GETNEXTQUOTA_FLAG;
531 flags |= NO_HEADER_FLAG;
532 while (report_mount(fp, id, NULL, &oid, form, XFS_GROUP_QUOTA,
533 mount, flags)) {
534 id = oid + 1;
535 }
536 } else {
537 setgrent();
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;
542 }
543 }
544 if (flags & NO_HEADER_FLAG)
545 fputc('\n', fp);
546 endgrent();
547 }
548
549 static void
550 report_project_mount(
551 FILE *fp,
552 uint form,
553 fs_path_t *mount,
554 uint lower,
555 uint upper,
556 uint flags)
557 {
558 fs_project_t *p;
559 uint id = 0, oid;
560
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;
566 }
567 } else if (report_mount(fp, id, NULL, &oid, form,
568 XFS_PROJ_QUOTA, mount,
569 flags|GETNEXTQUOTA_FLAG)) {
570 id = oid + 1;
571 flags |= GETNEXTQUOTA_FLAG;
572 flags |= NO_HEADER_FLAG;
573 while (report_mount(fp, id, NULL, &oid, form, XFS_PROJ_QUOTA,
574 mount, flags)) {
575 id = oid + 1;
576 }
577 } else {
578 if (!getprprid(0)) {
579 /*
580 * Print default project quota, even if projid 0
581 * isn't defined
582 */
583 if (report_mount(fp, 0, NULL, NULL,
584 form, XFS_PROJ_QUOTA, mount, flags))
585 flags |= NO_HEADER_FLAG;
586 }
587
588 setprent();
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;
593 }
594 endprent();
595 }
596
597 if (flags & NO_HEADER_FLAG)
598 fputc('\n', fp);
599 }
600
601 static void
602 report_any_type(
603 FILE *fp,
604 uint form,
605 uint type,
606 char *dir,
607 uint lower,
608 uint upper,
609 uint flags)
610 {
611 fs_cursor_t cursor;
612 fs_path_t *mount;
613
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))
618 continue;
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);
625 }
626 }
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))
631 continue;
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);
638 }
639 }
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))
644 continue;
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);
651 }
652 }
653 }
654
655 static int
656 report_f(
657 int argc,
658 char **argv)
659 {
660 FILE *fp = NULL;
661 char *fname = NULL;
662 uint lower = 0, upper = 0;
663 bool lookup = false;
664 int c, flags = 0, type = 0, form = 0;
665
666 while ((c = getopt(argc, argv, "abdf:ghilL:NnprtuU:")) != EOF) {
667 switch (c) {
668 case 'f':
669 fname = optarg;
670 break;
671 case 'b':
672 form |= XFS_BLOCK_QUOTA;
673 break;
674 case 'i':
675 form |= XFS_INODE_QUOTA;
676 break;
677 case 'r':
678 form |= XFS_RTBLOCK_QUOTA;
679 break;
680 case 'g':
681 type |= XFS_GROUP_QUOTA;
682 break;
683 case 'p':
684 type |= XFS_PROJ_QUOTA;
685 break;
686 case 'u':
687 type |= XFS_USER_QUOTA;
688 break;
689 case 'a':
690 flags |= ALL_MOUNTS_FLAG;
691 break;
692 case 'h':
693 flags |= HUMAN_FLAG;
694 break;
695 case 'n':
696 flags |= NO_LOOKUP_FLAG;
697 break;
698 case 'N':
699 flags |= NO_HEADER_FLAG;
700 break;
701 case 't':
702 flags |= TERSE_FLAG;
703 break;
704 case 'L':
705 lower = (uint)atoi(optarg);
706 flags |= NO_LOOKUP_FLAG;
707 break;
708 case 'U':
709 upper = (uint)atoi(optarg);
710 flags |= NO_LOOKUP_FLAG;
711 break;
712 case 'l':
713 lookup = true;
714 break;
715 default:
716 return command_usage(&report_cmd);
717 }
718 }
719
720 if (!form)
721 form = XFS_BLOCK_QUOTA;
722
723 if (!type)
724 type = XFS_USER_QUOTA | XFS_GROUP_QUOTA | XFS_PROJ_QUOTA;
725
726 if (lookup)
727 flags &= ~NO_LOOKUP_FLAG;
728
729 if ((fp = fopen_write_secure(fname)) == NULL)
730 return 0;
731
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);
742 }
743
744 if (fname)
745 fclose(fp);
746 return 0;
747 }
748
749 void
750 report_init(void)
751 {
752 dump_cmd.name = "dump";
753 dump_cmd.cfunc = dump_f;
754 dump_cmd.argmin = 0;
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;
760
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;
770
771 if (expert) {
772 add_command(&dump_cmd);
773 add_command(&report_cmd);
774 }
775 }