]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Fix xfs_quota bugs found by QA tests, and add some options to assist testing.
authorNathan Scott <nathans@sgi.com>
Fri, 3 Jun 2005 06:10:38 +0000 (06:10 +0000)
committerNathan Scott <nathans@sgi.com>
Fri, 3 Jun 2005 06:10:38 +0000 (06:10 +0000)
Merge of master-melb:xfs-cmds:22798a by kenmcd.

quota/edit.c
quota/free.c
quota/quot.c
quota/quota.c
quota/quota.h
quota/report.c

index 5c52e354d8d864a38d54627992ac08387437cbeb..d2bc6019c2669ea11f28d541bb5732760c7b6075 100644 (file)
@@ -71,14 +71,15 @@ timer_help(void)
 {
        printf(_(
 "\n"
-" modify quota enforcement timeout for the specified user\n"
+" modify quota enforcement timeout for the current filesystem\n"
 "\n"
 " Example:\n"
-" 'timer -i 3days sam'\n"
-" (soft inode limit timer for user 'sam' is changed to 3 days)\n"
+" 'timer -i 3days'\n"
+" (soft inode limit timer is changed to 3 days)\n"
 "\n"
 " Changes the timeout value associated with the block limits, inode limits\n"
-" and/or realtime block limits for the specified user, group, or project.\n"
+" and/or realtime block limits for all users, groups, or projects on the\n"
+" current filesystem.\n"
 " As soon as a user consumes the amount of space or number of inodes set as\n"
 " the soft limit, a timer is started.  If the timer expires and the user is\n"
 " still over the soft limit, the soft limit is enforced as the hard limit.\n"
@@ -94,7 +95,6 @@ timer_help(void)
 " However, a suffix may be used to alternatively specify minutes (m),\n"
 " hours (h), days (d), or weeks (w) - either the full word or the first\n"
 " letter of the word can be used.\n"
-" The user/group/project can be specified either by name or by number.\n"
 "\n"));
 }
 
@@ -225,8 +225,9 @@ set_project_limits(
                                bsoft, bhard, isoft, ihard, rtbsoft, rtbhard);
 }
 
+/* extract number of blocks from an ascii string */
 static int
-extract(
+extractb(
        char            *string,
        const char      *prefix,
        int             length,
@@ -246,6 +247,24 @@ extract(
        return 0;
 }
 
+/* extract number of inodes from an ascii string */
+static int
+extracti(
+       char            *string,
+       const char      *prefix,
+       int             length,
+       __uint64_t      *value)
+{
+       char            *sp, *s = string;
+
+       if (strncmp(string, prefix, length) == 0) {
+               s = string + length + 1;
+               *value = strtoll(s, &sp, 0);
+               return 1;
+       }
+       return 0;
+}
+
 static int
 limit_f(
        int             argc,
@@ -297,17 +316,17 @@ limit_f(
         */
        while (argc > optind + endoptions - 1) {
                char *s = argv[optind++];
-               if (extract(s, "bsoft=", 5, bsize, ssize, &bsoft))
+               if (extractb(s, "bsoft=", 5, bsize, ssize, &bsoft))
                        mask |= FS_DQ_BSOFT;
-               else if (extract(s, "bhard=", 5, bsize, ssize, &bhard))
+               else if (extractb(s, "bhard=", 5, bsize, ssize, &bhard))
                        mask |= FS_DQ_BHARD;
-               else if (extract(s, "isoft=", 5, bsize, ssize, &isoft))
+               else if (extracti(s, "isoft=", 5, &isoft))
                        mask |= FS_DQ_ISOFT;
-               else if (extract(s, "ihard=", 5, bsize, ssize, &ihard))
+               else if (extracti(s, "ihard=", 5, &ihard))
                        mask |= FS_DQ_IHARD;
-               else if (extract(s, "rtbsoft=", 7, bsize, ssize, &rtbsoft))
+               else if (extractb(s, "rtbsoft=", 7, bsize, ssize, &rtbsoft))
                        mask |= FS_DQ_RTBSOFT;
-               else if (extract(s, "rtbhard=", 7, bsize, ssize, &rtbhard))
+               else if (extractb(s, "rtbhard=", 7, bsize, ssize, &rtbhard))
                        mask |= FS_DQ_RTBHARD;
                else {
                        fprintf(stderr, _("%s: unrecognised argument %s\n"),
@@ -435,7 +454,6 @@ restore_f(
 
 static void
 set_timer(
-       __uint32_t      id,
        uint            type,
        uint            mask,
        char            *dev,
@@ -445,80 +463,27 @@ set_timer(
 
        memset(&d, 0, sizeof(d));
        d.d_version = FS_DQUOT_VERSION;
-       d.d_id = id;
        d.d_flags = type;
        d.d_fieldmask = mask;
        d.d_itimer = value;
        d.d_btimer = value;
        d.d_rtbtimer = value;
 
-       if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0)
+       if (xfsquotactl(XFS_SETQLIM, dev, type, 0, (void *)&d) < 0)
                fprintf(stderr, _("%s: cannot set timer: %s\n"),
                                progname, strerror(errno));
 }
 
-static void
-set_user_timer(
-       char            *name,
-       uint            type,
-       uint            mask,
-       uint            value)
-{
-       uid_t           uid = uid_from_string(name);
-
-       if (uid == -1)
-               fprintf(stderr, _("%s: invalid user name: %s\n"),
-                               progname, name);
-       else
-               set_timer(uid, type, mask, fs_path->fs_name, value);
-}
-
-static void
-set_group_timer(
-       char            *name,
-       uint            type,
-       uint            mask,
-       uint            value)
-{
-       gid_t           gid = gid_from_string(name);
-
-       if (gid == -1)
-               fprintf(stderr, _("%s: invalid group name: %s\n"),
-                               progname, name);
-       else
-               set_timer(gid, type, mask, fs_path->fs_name, value);
-}
-
-static void
-set_project_timer(
-       char            *name,
-       uint            type,
-       uint            mask,
-       uint            value)
-{
-       prid_t          prid = prid_from_string(name);
-
-       if (prid == -1)
-               fprintf(stderr, _("%s: invalid project name: %s\n"),
-                               progname, name);
-       else
-               set_timer(prid, type, mask, fs_path->fs_name, value);
-}
-
 static int
 timer_f(
        int             argc,
        char            **argv)
 {
-       char            *name;
        uint            value;
-       int             c, flags = 0, type = 0, mask = 0;
+       int             c, type = 0, mask = 0;
 
-       while ((c = getopt(argc, argv, "bdgipru")) != EOF) {
+       while ((c = getopt(argc, argv, "bgipru")) != EOF) {
                switch (c) {
-               case 'd':
-                       flags |= DEFAULTS_FLAG;
-                       break;
                case 'b':
                        mask |= FS_DQ_BTIMER;
                        break;
@@ -542,20 +507,10 @@ timer_f(
                }
        }
 
-       /*
-        * In the usual case, we need at least 2 more arguments -
-        * one (or more) value and a user name/id.
-        * For setting defaults (-d) we don't want a user name/id.
-        */
-       if (flags & DEFAULTS_FLAG) {
-               if (argc != optind + 1)
-                       return command_usage(&timer_cmd);
-       } else if (argc != optind + 2) {
+       if (argc != optind + 1)
                return command_usage(&timer_cmd);
-       }
 
        value = cvttime(argv[optind++]);
-       name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++];
 
        if (!mask)
                mask = FS_DQ_TIMER_MASK;
@@ -563,17 +518,7 @@ timer_f(
        if (!type)
                type = XFS_USER_QUOTA;
 
-       switch (type) {
-       case XFS_USER_QUOTA:
-               set_user_timer(name, type, mask, value);
-               break;
-       case XFS_GROUP_QUOTA:
-               set_group_timer(name, type, mask, value);
-               break;
-       case XFS_PROJ_QUOTA:
-               set_project_timer(name, type, mask, value);
-               break;
-       }
+       set_timer(type, mask, fs_path->fs_name, value);
        return 0;
 }
 
index 63b1fb4b16e2ff8245f3701d82510bf575f468a2..717bffc7bb779a32a435a07c3a0e8770200e8b6c 100644 (file)
@@ -51,7 +51,7 @@ free_help(void)
 " -i -- report the inode count values\n"
 " -r -- report the realtime block count values\n"
 " -h -- report in a human-readable format\n"
-" -n -- suppress the header from the output\n"
+" -N -- suppress the header from the output\n"
 "\n"));
 }
 
@@ -318,7 +318,7 @@ free_f(
        char            *fname = NULL;
        int             c, flags = 0, form = 0, type = 0;
 
-       while ((c = getopt(argc, argv, "bf:hnir")) != EOF) {
+       while ((c = getopt(argc, argv, "bf:hNir")) != EOF) {
                switch (c) {
                case 'f':
                        fname = optarg;
@@ -335,7 +335,7 @@ free_f(
                case 'h':
                        flags |= HUMAN_FLAG;
                        break;
-               case 'n':
+               case 'N':
                        flags |= NO_HEADER_FLAG;
                        break;
                default:
index 068c409707aa9d27df6132adc6321c69817eeb1f..751cb286b2babc8e7409bcd5b6368e0ac930ba2a 100644 (file)
@@ -82,7 +82,8 @@ quot_help(void)
 " -b -- display number of blocks used\n"
 " -i -- display number of inodes used\n"
 " -r -- display number of realtime blocks used\n"
-" -n -- suppress the initial header\n"
+" -n -- skip identifier-to-name translations, just report IDs\n"
+" -N -- suppress the initial header\n"
 " -f -- send output to a file\n"
 " The (optional) user/group/project can be specified either by name or by\n"
 " number (i.e. uid/gid/projid).\n"
@@ -240,7 +241,8 @@ quot_report_mount_any_type(
                if (form & XFS_INODE_QUOTA)
                        fprintf(fp, "%8llu    ",
                                (unsigned long long) dp->nfiles);
-               if ((cp = (names)(dp->id)) != NULL)
+               if (!(flags & NO_LOOKUP_FLAG) &&
+                   ((cp = (names)(dp->id)) != NULL))
                        fprintf(fp, "%-8.8s", cp);
                else
                        fprintf(fp, "#%-7d", dp->id);
@@ -357,7 +359,7 @@ quot_f(
        char            *fname = NULL;
        int             c, flags = 0, type = 0, form = 0;
 
-       while ((c = getopt(argc, argv, "abcf:hgipruv")) != EOF) {
+       while ((c = getopt(argc, argv, "abcf:ghinpruv")) != EOF) {
                switch (c) {
                case 'f':
                        fname = optarg;
@@ -386,6 +388,9 @@ quot_f(
                case 'c':
                        flags |= HISTOGRAM_FLAG;
                        break;
+               case 'n':
+                       flags |= NO_LOOKUP_FLAG;
+                       break;
                case 'v':
                        flags |= VERBOSE_FLAG;
                        break;
index 8af5facc9ae7c56d2299dab88a2207025e008e77..8da04def599837fb409e40cce0a1d3b39d21d58d 100644 (file)
@@ -53,7 +53,8 @@ quota_help(void)
 " -i -- display number of inodes used\n"
 " -r -- display number of realtime blocks used\n"
 " -h -- report in a human-readable format\n"
-" -n -- suppress the initial header\n"
+" -n -- skip identifier-to-name translations, just report IDs\n"
+" -N -- suppress the initial header\n"
 " -v -- increase verbosity in reporting (also dumps zero values)\n"
 " -f -- send output to a file\n"
 " The (optional) user/group/project can be specified either by name or by\n"
@@ -210,12 +211,13 @@ quota(
 
 static char *
 getusername(
-       uid_t           uid)
+       uid_t           uid,
+       int             numeric)
 {
        static char     buffer[32];
        struct passwd   *u;
 
-       if ((u = getpwuid(uid)))
+       if (!numeric && (u = getpwuid(uid)))
                return u->pw_name;
        snprintf(buffer, sizeof(buffer), "#%u", uid);
        return &buffer[0];
@@ -235,7 +237,7 @@ quota_user_type(
        if (name) {
                if (isdigit(name[0])) {
                        id = atoi(name);
-                       name = getusername(id);
+                       name = getusername(id, flags & NO_LOOKUP_FLAG);
                } else if ((u = getpwnam(name))) {
                        id = u->pw_uid;
                        name = u->pw_name;
@@ -246,7 +248,7 @@ quota_user_type(
                }
        } else {
                id = getuid();
-               name = getusername(id);
+               name = getusername(id, flags & NO_LOOKUP_FLAG);
        }
 
        quota(fp, id, name, form, type, flags);
@@ -254,12 +256,13 @@ quota_user_type(
 
 static char *
 getgroupname(
-       gid_t           gid)
+       gid_t           gid,
+       int             numeric)
 {
        static char     buffer[32];
        struct group    *g;
 
-       if ((g = getgrgid(gid)))
+       if (!numeric && (g = getgrgid(gid)))
                return g->gr_name;
        snprintf(buffer, sizeof(buffer), "#%u", gid);
        return &buffer[0];
@@ -280,7 +283,7 @@ quota_group_type(
        if (name) {
                if (isdigit(name[0])) {
                        gid = atoi(name);
-                       name = getgroupname(gid);
+                       name = getgroupname(gid, flags & NO_LOOKUP_FLAG);
                } else {
                        if ((g = getgrnam(name))) {
                                gid = g->gr_gid;
@@ -306,7 +309,7 @@ quota_group_type(
 
        for (i = 0; i < ngroups; i++, name = NULL) {
                if (!name)
-                       name = getgroupname(gids[i]);
+                       name = getgroupname(gids[i], flags & NO_LOOKUP_FLAG);
                quota(fp, gids[i], name, form, type, flags);
        }
 
@@ -316,7 +319,8 @@ quota_group_type(
 
 static char *
 getprojectname(
-       prid_t          prid)
+       prid_t          prid,
+       int             numeric)
 {
        static char     buffer[32];
        fs_project_t    *p;
@@ -346,7 +350,7 @@ quota_proj_type(
 
        if (isdigit(name[0])) {
                id = atoi(name);
-               name = getprojectname(id);
+               name = getprojectname(id, flags & NO_LOOKUP_FLAG);
        } else if ((p = getprnam(name))) {
                id = p->pr_prid;
                name = p->pr_name;
@@ -389,7 +393,7 @@ quota_f(
        char            *fname = NULL;
        int             c, flags = 0, type = 0, form = 0;
 
-       while ((c = getopt(argc, argv, "bf:hgnipruv")) != EOF) {
+       while ((c = getopt(argc, argv, "bf:ghnNipruv")) != EOF) {
                switch (c) {
                case 'f':
                        fname = optarg;
@@ -416,6 +420,9 @@ quota_f(
                        flags |= HUMAN_FLAG;
                        break;
                case 'n':
+                       flags |= NO_LOOKUP_FLAG;
+                       break;
+               case 'N':
                        flags |= NO_HEADER_FLAG;
                        break;
                case 'v':
index 818427e3534457d365e75e7ed88f7595963b420b..f84f116a691a72036789603a7ce04154d7c46194 100644 (file)
@@ -83,6 +83,7 @@ enum {
        HISTOGRAM_FLAG =        0x0080, /* histogram format output */
        DEFAULTS_FLAG =         0x0100, /* use value as a default */
        ABSOLUTE_FLAG =         0x0200, /* absolute time, not related to now */
+       NO_LOOKUP_FLAG =        0x0400, /* skip name lookups, just report ID */
 };
 
 /*
index 0d297e9ee6431d839fff95c44dce5c11543a57cc..a32e016d71d1aaebd3e145dc78fb06e352f573fb 100644 (file)
@@ -70,7 +70,8 @@ report_help(void)
 " or all filesystems.\n"
 " -a -- report for all mounted filesystems with quota enabled\n"
 " -h -- report in a human-readable format\n"
-" -n -- suppress the header from the output\n"
+" -n -- skip identifier-to-name translations, just report IDs\n"
+" -N -- suppress the header from the output\n"
 " -t -- terse output format, hides rows which are all zero\n"
 " -g -- report group usage and quota information\n"
 " -p -- report project usage and quota information\n"
@@ -92,23 +93,38 @@ dump_file(
 
        if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0)
                return;
+       if (!d.d_blk_softlimit && !d.d_blk_hardlimit &&
+           !d.d_ino_softlimit && !d.d_ino_hardlimit &&
+           !d.d_rtb_softlimit && !d.d_rtb_hardlimit)
+               return;
        fprintf(fp, "fs = %s\n", dev);
-       fprintf(fp, "%-10d %7llu %7llu %7llu %7llu %7llu %7llu\n", id,
-               (unsigned long long)d.d_blk_softlimit,
-               (unsigned long long)d.d_blk_hardlimit,
-               (unsigned long long)d.d_ino_softlimit,
-               (unsigned long long)d.d_ino_hardlimit,
-               (unsigned long long)d.d_rtb_softlimit,
-               (unsigned long long)d.d_rtb_hardlimit);
+       /* this branch is for backward compatibility reasons */
+       if (d.d_rtb_softlimit || d.d_rtb_hardlimit)
+               fprintf(fp, "%-10d %7llu %7llu %7llu %7llu %7llu %7llu\n", id,
+                       (unsigned long long)d.d_blk_softlimit,
+                       (unsigned long long)d.d_blk_hardlimit,
+                       (unsigned long long)d.d_ino_softlimit,
+                       (unsigned long long)d.d_ino_hardlimit,
+                       (unsigned long long)d.d_rtb_softlimit,
+                       (unsigned long long)d.d_rtb_hardlimit);
+       else
+               fprintf(fp, "%-10d %7llu %7llu %7llu %7llu\n", id,
+                       (unsigned long long)d.d_blk_softlimit,
+                       (unsigned long long)d.d_blk_hardlimit,
+                       (unsigned long long)d.d_ino_softlimit,
+                       (unsigned long long)d.d_ino_hardlimit);
 }
 
 static void
 dump_limits_any_type(
        FILE            *fp,
        uint            type,
-       char            *dir)
+       char            *dir,
+       uint            lower,
+       uint            upper)
 {
        fs_path_t       *mount;
+       uint            id;
 
        if ((mount = fs_table_lookup(dir, FS_MOUNT_POINT)) == NULL) {
                fprintf(stderr, "%s: cannot find mount point %s\n",
@@ -116,6 +132,12 @@ dump_limits_any_type(
                return;
        }
 
+       if (upper) {
+               for (id = lower; id < upper; id++)
+                       dump_file(fp, id, type, mount->fs_name);
+               return;
+       }
+
        switch (type) {
        case XFS_GROUP_QUOTA: {
                        struct group *g;
@@ -151,9 +173,10 @@ dump_f(
 {
        FILE            *fp;
        char            *fname = NULL;
+       uint            lower = 0, upper = 0;
        int             c, type = XFS_USER_QUOTA;
 
-       while ((c = getopt(argc, argv, "f:gpu")) != EOF) {
+       while ((c = getopt(argc, argv, "f:gpuL:U:")) != EOF) {
                switch(c) {
                case 'f':
                        fname = optarg;
@@ -167,6 +190,12 @@ dump_f(
                case 'u':
                        type = XFS_USER_QUOTA;
                        break;
+               case 'L':
+                       lower = (uint)atoi(optarg);
+                       break;
+               case 'U':
+                       upper = (uint)atoi(optarg);
+                       break;
                default:
                        return command_usage(&dump_cmd);
                }
@@ -178,7 +207,7 @@ dump_f(
        if ((fp = fopen_write_secure(fname)) == NULL)
                return 0;
 
-       dump_limits_any_type(fp, type, fs_path->fs_dir);
+       dump_limits_any_type(fp, type, fs_path->fs_dir, lower, upper);
 
        if (fname)
                fclose(fp);
@@ -369,18 +398,37 @@ report_user_mount(
        FILE            *fp,
        uint            form,
        fs_path_t       *mount,
+       uint            lower,
+       uint            upper,
        uint            flags)
 {
-       struct passwd *u;
+       struct passwd   *u;
+       char            n[MAXNAMELEN];
+       uint            id;
+
+       if (upper) {    /* identifier range specified */
+               for (id = lower; id < upper; id++) {
+                       snprintf(n, sizeof(n)-1, "#%u", id);
+                       if (report_mount(fp, id, n,
+                                       form, XFS_USER_QUOTA, mount, flags))
+                               flags |= NO_HEADER_FLAG;
+               }
+       } else {
+               setpwent();
+               while ((u = getpwent()) != NULL) {
+                       if (flags & NO_LOOKUP_FLAG)
+                               snprintf(n, sizeof(n)-1, "#%u", u->pw_uid);
+                       else
+                               strncpy(n, u->pw_name, sizeof(n)-1);
+                       if (report_mount(fp, u->pw_uid, n,
+                                       form, XFS_USER_QUOTA, mount, flags))
+                               flags |= NO_HEADER_FLAG;
+               }
+               endpwent();
+       }
 
-       setpwent();
-       while ((u = getpwent()) != NULL)
-               if (report_mount(fp, u->pw_uid, u->pw_name,
-                               form, XFS_USER_QUOTA, mount, flags))
-                       flags |= NO_HEADER_FLAG;
        if (flags & NO_HEADER_FLAG)
                fputc('\n', fp);
-       endpwent();
 }
 
 static void
@@ -388,15 +436,33 @@ report_group_mount(
        FILE            *fp,
        uint            form,
        fs_path_t       *mount,
+       uint            lower,
+       uint            upper,
        uint            flags)
 {
-       struct group *g;
-
-       setgrent();
-       while ((g = getgrent()) != NULL)
-               if (report_mount(fp, g->gr_gid, g->gr_name,
-                               form, XFS_GROUP_QUOTA, mount, flags))
-                       flags |= NO_HEADER_FLAG;
+       struct group    *g;
+       char            n[MAXNAMELEN];
+       uint            id;
+
+       if (upper) {    /* identifier range specified */
+               for (id = lower; id < upper; id++) {
+                       snprintf(n, sizeof(n)-1, "#%u", id);
+                       if (report_mount(fp, id, n,
+                                       form, XFS_GROUP_QUOTA, mount, flags))
+                               flags |= NO_HEADER_FLAG;
+               }
+       } else {
+               setgrent();
+               while ((g = getgrent()) != NULL) {
+                       if (flags & NO_LOOKUP_FLAG)
+                               snprintf(n, sizeof(n)-1, "#%u", g->gr_gid);
+               else
+                       strncpy(n, g->gr_name, sizeof(n)-1);
+                       if (report_mount(fp, g->gr_gid, n,
+                                       form, XFS_GROUP_QUOTA, mount, flags))
+                               flags |= NO_HEADER_FLAG;
+               }
+       }
        if (flags & NO_HEADER_FLAG)
                fputc('\n', fp);
        endgrent();
@@ -407,18 +473,37 @@ report_project_mount(
        FILE            *fp,
        uint            form,
        fs_path_t       *mount,
+       uint            lower,
+       uint            upper,
        uint            flags)
 {
        fs_project_t    *p;
+       char            n[MAXNAMELEN];
+       uint            id;
+
+       if (upper) {    /* identifier range specified */
+               for (id = lower; id < upper; id++) {
+                       snprintf(n, sizeof(n)-1, "#%u", id);
+                       if (report_mount(fp, id, n,
+                                       form, XFS_PROJ_QUOTA, mount, flags))
+                               flags |= NO_HEADER_FLAG;
+               }
+       } else {
+               setprent();
+               while ((p = getprent()) != NULL) {
+                       if (flags & NO_LOOKUP_FLAG)
+                               snprintf(n, sizeof(n)-1, "#%u", p->pr_prid);
+                       else
+                               strncpy(n, p->pr_name, sizeof(n)-1);
+                       if (report_mount(fp, p->pr_prid, n,
+                                       form, XFS_PROJ_QUOTA, mount, flags))
+                               flags |= NO_HEADER_FLAG;
+               }
+               endprent();
+       }
 
-       setprent();
-       while ((p = getprent()) != NULL)
-               if (report_mount(fp, p->pr_prid, p->pr_name,
-                               form, XFS_PROJ_QUOTA, mount, flags))
-                       flags |= NO_HEADER_FLAG;
        if (flags & NO_HEADER_FLAG)
                fputc('\n', fp);
-       endprent();
 }
 
 static void
@@ -427,6 +512,8 @@ report_any_type(
        uint            form,
        uint            type,
        char            *dir,
+       uint            lower,
+       uint            upper,
        uint            flags)
 {
        fs_cursor_t     cursor;
@@ -435,17 +522,20 @@ report_any_type(
        if (type & XFS_USER_QUOTA) {
                fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor);
                while ((mount = fs_cursor_next_entry(&cursor)))
-                       report_user_mount(fp, form, mount, flags);
+                       report_user_mount(fp, form, mount,
+                                               lower, upper, flags);
        }
        if (type & XFS_GROUP_QUOTA) {
                fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor);
                while ((mount = fs_cursor_next_entry(&cursor)))
-                       report_group_mount(fp, form, mount, flags);
+                       report_group_mount(fp, form, mount,
+                                               lower, upper, flags);
        }
        if (type & XFS_PROJ_QUOTA) {
                fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor);
                while ((mount = fs_cursor_next_entry(&cursor)))
-                       report_project_mount(fp, form, mount, flags);
+                       report_project_mount(fp, form, mount,
+                                               lower, upper, flags);
        }
 }
 
@@ -455,10 +545,11 @@ report_f(
        char            **argv)
 {
        FILE            *fp = NULL;
-       char            *fname = NULL;
+       char            *dir, *fname = NULL;
+       uint            lower = 0, upper = 0;
        int             c, flags = 0, type = 0, form = 0;
 
-       while ((c = getopt(argc, argv, "abf:hgniprtu")) != EOF) {
+       while ((c = getopt(argc, argv, "abf:ghiL:NnprtuU:")) != EOF) {
                switch (c) {
                case 'f':
                        fname = optarg;
@@ -488,11 +579,20 @@ report_f(
                        flags |= HUMAN_FLAG;
                        break;
                case 'n':
+                       flags |= NO_LOOKUP_FLAG;
+                       break;
+               case 'N':
                        flags |= NO_HEADER_FLAG;
                        break;
                case 't':
                        flags |= TERSE_FLAG;
                        break;
+               case 'L':
+                       lower = (uint)atoi(optarg);
+                       break;
+               case 'U':
+                       upper = (uint)atoi(optarg);
+                       break;
                default:
                        return command_usage(&report_cmd);
                }
@@ -509,9 +609,11 @@ report_f(
 
        if (argc == optind)
                report_any_type(fp, form, type, (flags & ALL_MOUNTS_FLAG) ?
-                               NULL : fs_path->fs_dir, flags);
-       else while (argc > optind)
-               report_any_type(fp, form, type, argv[optind++], flags);
+                               NULL : fs_path->fs_dir, lower, upper, flags);
+       else while (argc > optind) {
+               dir = argv[optind++];
+               report_any_type(fp, form, type, dir, lower, upper, flags);
+       }
 
        if (fname)
                fclose(fp);