Page MenuHomeFreeBSD

D53133.1775801520.diff
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

D53133.1775801520.diff

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

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)

Event Timeline