Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144616610
D53133.1775801520.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D53133.1775801520.diff
View Options
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -1285,6 +1285,8 @@
..
pw
..
+ quot
+ ..
rpcbind
..
sa
diff --git a/usr.sbin/quot/Makefile b/usr.sbin/quot/Makefile
--- a/usr.sbin/quot/Makefile
+++ b/usr.sbin/quot/Makefile
@@ -1,5 +1,9 @@
+.include <src.opts.mk>
+
PROG= quot
MAN= quot.8
-LIBADD= ufs
+LIBADD= ufs util
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
.include <bsd.prog.mk>
diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c
--- a/usr.sbin/quot/quot.c
+++ b/usr.sbin/quot/quot.c
@@ -42,6 +42,7 @@
#include <fcntl.h>
#include <fstab.h>
#include <libufs.h>
+#include <mntopts.h>
#include <paths.h>
#include <pwd.h>
#include <stdbool.h>
@@ -55,6 +56,7 @@
/* some flags of what to do: */
static bool all;
static bool count;
+static bool noname;
static bool unused;
static void (*func)(int, struct fs *);
static long blocksize;
@@ -227,7 +229,7 @@
for (usr = users + uid % nusers, i = nusers; --i >= 0; usr--) {
if (usr->name == NULL) {
usr->uid = uid;
- if ((pwd = getpwuid(uid)) == NULL)
+ if (noname || (pwd = getpwuid(uid)) == NULL)
asprintf(&usr->name, "#%u", uid);
else
usr->name = strdup(pwd->pw_name);
@@ -248,7 +250,10 @@
{
const struct user *u1 = v1, *u2 = v2;
- return (u2->space - u1->space);
+ return (u2->space > u1->space ? 1 :
+ u2->space < u1->space ? -1 :
+ u1->uid > u2->uid ? 1 :
+ u1->uid < u2->uid ? -1 : 0);
}
#define sortusers(users) \
@@ -469,12 +474,11 @@
main(int argc, char *argv[])
{
struct statfs *mp;
- struct fstab *fs;
int ch, cnt;
func = douser;
header = getbsize(&headerlen, &blocksize);
- while ((ch = getopt(argc, argv, "acfhknv")) != -1) {
+ while ((ch = getopt(argc, argv, "acfhkNnv")) != -1) {
switch (ch) {
case 'a':
all = true;
@@ -491,6 +495,9 @@
case 'k':
blocksize = 1024;
break;
+ case 'N':
+ noname = true;
+ break;
case 'n':
func = donames;
break;
@@ -513,8 +520,8 @@
quot(mp->f_mntfromname, mp->f_mntonname);
}
while (argc-- > 0) {
- if ((fs = getfsfile(*argv)) != NULL)
- quot(fs->fs_spec, 0);
+ if ((mp = getmntpoint(*argv)) != NULL)
+ quot(mp->f_mntfromname, mp->f_mntonname);
else
quot(*argv, 0);
argv++;
diff --git a/usr.sbin/quot/tests/Makefile b/usr.sbin/quot/tests/Makefile
new file mode 100644
--- /dev/null
+++ b/usr.sbin/quot/tests/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= tests
+ATF_TESTS_SH= quot_test
+
+.include <bsd.test.mk>
diff --git a/usr.sbin/quot/tests/quot_test.sh b/usr.sbin/quot/tests/quot_test.sh
new file mode 100644
--- /dev/null
+++ b/usr.sbin/quot/tests/quot_test.sh
@@ -0,0 +1,102 @@
+#
+# Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+# Create and mount a UFS filesystem on a small memory disk
+quot_setup()
+{
+ atf_check -o save:dev mdconfig -t malloc -s 16M
+ local dev=$(cat dev)
+ atf_check -o ignore newfs "$@" /dev/$dev
+ atf_check mkdir mnt
+ local mnt=$(realpath mnt)
+ atf_check mount /dev/$dev "$mnt"
+ echo "/dev/$dev: ($mnt)" >expect
+ printf "%5d\t%5d\t%-8s\n" 8 2 "#0" >>expect
+}
+
+# Create a directory owned by a given UID
+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
+}
+
+# Perform the tests
+quot_test()
+{
+ local dev=$(cat dev)
+ # 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
+ # time it fills up.
+ local uid
+ for uid in $(seq 1 32); do
+ quot_adduid $uid
+ done
+ # Also create inodes owned by users with long UIDs, up to the
+ # highest possible value (2^32 - 2, because chown(2) and
+ # friends interpret 2^32 - 1 as “leave unchanged”).
+ local shift
+ for shift in $(seq 6 32); do
+ quot_adduid $(((1 << shift) - 2))
+ done
+ # Since quot operates directly on the underlying device, not
+ # on the mounted filesystem, we remount read-only to ensure
+ # that everything gets flushed to the memory disk.
+ atf_check mount -ur /dev/$dev
+ atf_check -o file:expect quot -fkN /dev/$dev
+ atf_check -o file:expect quot -fkN $(realpath mnt)
+}
+
+# Unmount and release the memory disk
+quot_cleanup()
+{
+ if [ -d mnt ]; then
+ umount mnt || true
+ fi
+ if [ -f dev ]; then
+ mdconfig -d -u $(cat dev) || true
+ fi
+}
+
+atf_test_case ufs1 cleanup
+ufs1_head()
+{
+ atf_set descr "Test quot on UFS1"
+ atf_set require.user root
+}
+ufs1_body()
+{
+ quot_setup -O1
+ quot_test
+}
+ufs1_cleanup()
+{
+ quot_cleanup
+}
+
+atf_test_case ufs2 cleanup
+ufs2_head()
+{
+ atf_set descr "Test quot on UFS2"
+ atf_set require.user root
+}
+ufs2_body()
+{
+ quot_setup -O2
+ quot_test
+}
+ufs2_cleanup()
+{
+ quot_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case ufs1
+ atf_add_test_case ufs2
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 10, 6:12 AM (2 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28313438
Default Alt Text
D53133.1775801520.diff (4 KB)
Attached To
Mode
D53133: quot: Add tests
Attached
Detach File
Event Timeline
Log In to Comment