diff options
Diffstat (limited to 'usr.sbin/quot')
| -rw-r--r-- | usr.sbin/quot/quot.8 | 24 | ||||
| -rw-r--r-- | usr.sbin/quot/quot.c | 47 | ||||
| -rw-r--r-- | usr.sbin/quot/tests/quot_test.sh | 19 |
3 files changed, 66 insertions, 24 deletions
diff --git a/usr.sbin/quot/quot.8 b/usr.sbin/quot/quot.8 index 32e666e2a863..b4b40bf395e9 100644 --- a/usr.sbin/quot/quot.8 +++ b/usr.sbin/quot/quot.8 @@ -27,7 +27,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 15, 2025 +.Dd November 13, 2025 .Dt QUOT 8 .Os .Sh NAME @@ -41,7 +41,9 @@ The .Nm utility -is used to gather statistics about the disk usage for each local user. +is used to gather per-user disk usage statistics from +.Xr ffs 7 +file systems. .Pp The following options are available: .Bl -tag -width indent @@ -51,8 +53,16 @@ Include statistics for all mounted file systems. Display three columns containing number of blocks per file, number of files in this category, and aggregate total of blocks in files with this or lower size. +This option is mutually exclusive with the +.Fl n +option. .It Fl f For each user, display count of files and space occupied. +This option has no effect if combined with the +.Fl c +or +.Fl n +options. .It Fl k Force the numbers to be reported in kilobyte counts. By default, all sizes are reported in 512-byte block counts. @@ -60,6 +70,7 @@ By default, all sizes are reported in 512-byte block counts. Given a list of inodes (plus some optional data on each line) in the standard input, for each file print out the owner (plus the remainder of the input line). +Lines that do not begin with a number are ignored. This is traditionally used in the pipe: .Bd -literal -offset indent @@ -68,9 +79,17 @@ ls -i | sed -e 's,^ *,,' | sort -k 1n | quot -n filesystem .Ed .Pp to get a report of files and their owners. +This option is mutually exclusive with the +.Fl c +option. .It Fl v In addition to the default output, display the number of files not accessed within 30, 60 and 90 days. +This option has no effect if combined with the +.Fl c +or +.Fl n +options. .El .Sh ENVIRONMENT .Bl -tag -width BLOCKSIZE @@ -87,6 +106,7 @@ size block. .Xr quota 1 , .Xr getmntinfo 3 , .Xr fstab 5 , +.Xr ffs 7 , .Xr mount 8 .Sh HISTORY This implementation of diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c index 5dda36ac8499..d2f7646f7041 100644 --- a/usr.sbin/quot/quot.c +++ b/usr.sbin/quot/quot.c @@ -41,6 +41,7 @@ #include <errno.h> #include <fcntl.h> #include <fstab.h> +#include <inttypes.h> #include <libufs.h> #include <mntopts.h> #include <paths.h> @@ -390,41 +391,43 @@ douser(int fd, struct fs *super) static void donames(int fd, struct fs *super) { - int c; - ino_t maxino; - uintmax_t inode; union dinode *dp; + char *end, *line; + size_t cap; + ssize_t len; + intmax_t inode, maxino; maxino = super->fs_ncg * super->fs_ipg - 1; - /* first skip the name of the filesystem */ - while ((c = getchar()) != EOF && (c < '0' || c > '9')) - while ((c = getchar()) != EOF && c != '\n'); - ungetc(c, stdin); - while (scanf("%ju", &inode) == 1) { - if (inode > maxino) { - warnx("illegal inode %ju", inode); - return; + line = NULL; + cap = 0; + while ((len = getline(&line, &cap, stdin)) > 0) { + if (len > 0 && line[len - 1] == '\n') + line[--len] = '\0'; + inode = strtoimax(line, &end, 10); + /* + * Silently ignore lines that do not begin with a number. + * For backward compatibility reasons, we do not require + * the optional comment to be preceded by whitespace. + */ + if (end == line) + continue; + if (inode <= 0 || inode > maxino) { + warnx("invalid inode %jd", inode); + continue; } if ((dp = get_inode(fd, super, inode)) != NULL && !isfree(super, dp)) { printf("%s\t", user(DIP(super, dp, di_uid))->name); /* now skip whitespace */ - while ((c = getchar()) == ' ' || c == '\t') - /* nothing */; + while (*end == ' ' || *end == '\t') + end++; /* and print out the remainder of the input line */ - while (c != EOF && c != '\n') { - putchar(c); - c = getchar(); - } - putchar('\n'); + printf("%s\n", end); } else { /* skip this line */ - while ((c = getchar()) != EOF && c != '\n') - /* nothing */; } - if (c == EOF) - break; } + free(line); } static void diff --git a/usr.sbin/quot/tests/quot_test.sh b/usr.sbin/quot/tests/quot_test.sh index 21088d162a53..c5e6717adca1 100644 --- a/usr.sbin/quot/tests/quot_test.sh +++ b/usr.sbin/quot/tests/quot_test.sh @@ -15,6 +15,8 @@ quot_setup() atf_check mount /dev/$dev "$mnt" echo "/dev/$dev: ($mnt)" >expect printf "%5d\t%5d\t%-8s\n" 8 2 "#0" >>expect + printf "%s\n" "/dev/$dev" >ninput + echo "/dev/$dev: ($mnt)" >nexpect } # Create a directory owned by a given UID @@ -23,12 +25,25 @@ quot_adduid() local uid=$1 atf_check install -d -o $uid -g 0 mnt/$uid printf "%5d\t%5d\t%-8s\n" 4 1 "#$uid" >>expect + ls -di mnt/$uid >>ninput + printf "%s\t%s\n" "#$uid" mnt/$uid >>nexpect } # Perform the tests quot_test() { local dev=$(cat dev) + # Deliberately add invalid lines to our -n input before the + # valid ones to verify that quot does not abort on first + # error. Note that quot deliberately ignores initial lines + # that don't start with a number, and that after encountering + # at least one line that does start with a number, quot would + # previously terminate on encountering one that doesn't (now + # it simply ignores them). This also tests that we don't + # require whitespace between the inode number and the comment. + echo "0zero" >>ninput + echo "invalid" >>ninput + echo "-1minusone" >>ninput # Create inodes owned by a large number of users to exercise # hash collisions and rehashing. The code uses an open hash # table that starts out with only 8 entries and doubles every @@ -50,6 +65,10 @@ quot_test() atf_check mount -ur /dev/$dev atf_check -o file:expect quot -fkN /dev/$dev atf_check -o file:expect quot -fkN $(realpath mnt) + # Test -n option + atf_check -o file:nexpect \ + -e inline:"quot: invalid inode 0\nquot: invalid inode -1\n" \ + quot -Nn /dev/$dev <ninput } # Unmount and release the memory disk |
