quot: Clean up

* Fix numerous style violations.
* Modernize somewhat.
* Don't bother examining errno after calling get_inode(), as it always
  exits on error.
* Fix confusing wording in the manual page.

The code remains somewhat idiosyncratic, e.g. in its insistance on
counting down rather than up in simple for loops, but in the absence
of comprehensive automated tests, the risk of introducing bugs exceeds
the benefit of rewriting these into more idiomatic forms.

Reviewed by:	obiwac
Differential Revision:	https://reviews.freebsd.org/D53130
This commit is contained in:
Dag-Erling Smørgrav
2025-10-17 13:54:59 +02:00
parent 5854d1cbab
commit 195b00ec45
3 changed files with 106 additions and 130 deletions
-2
View File
@@ -2,6 +2,4 @@ PROG= quot
MAN= quot.8
LIBADD= ufs
WARNS?= 2
.include <bsd.prog.mk>
+3 -4
View File
@@ -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 February 8, 1994
.Dd October 15, 2025
.Dt QUOT 8
.Os
.Sh NAME
@@ -55,9 +55,8 @@ blocks in files with this or lower size.
For each user, display count of files and space occupied.
.It Fl h
Estimate the number of blocks in each file based on its size.
Despite that this does not give the correct results (it does not
account for the holes in files), this option is not any faster
and thus is discouraged.
Note that this does not account for sparse files and is no faster than
reporting the accurate block count.
.It Fl k
Force the numbers to be reported in kilobyte counts.
By default, all sizes are reported in 512-byte block counts.
+103 -124
View File
@@ -32,19 +32,20 @@
*/
#include <sys/param.h>
#include <sys/stdint.h>
#include <sys/mount.h>
#include <sys/disklabel.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <errno.h>
#include <libufs.h>
#include <paths.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -52,10 +53,11 @@
#include <unistd.h>
/* some flags of what to do: */
static char estimate;
static char count;
static char unused;
static void (*func)(int, struct fs *, char *);
static bool all;
static bool count;
static bool estimate;
static bool unused;
static void (*func)(int, struct fs *);
static long blocksize;
static char *header;
static int headerlen;
@@ -69,9 +71,9 @@ static struct user *user(uid_t);
static int cmpusers(const void *, const void *);
static void uses(uid_t, daddr_t, time_t);
static void initfsizes(void);
static void dofsizes(int, struct fs *, char *);
static void douser(int, struct fs *, char *);
static void donames(int, struct fs *, char *);
static void dofsizes(int, struct fs *);
static void douser(int, struct fs *);
static void donames(int, struct fs *);
static void usage(void);
static void quot(char *, char *);
@@ -89,7 +91,7 @@ static void quot(char *, char *);
#ifdef COMPAT
#define SIZE(n) (n)
#else
#define SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize))
#define SIZE(n) ((int)(((intmax_t)(n) * 512 + blocksize - 1) / blocksize))
#endif
#define INOCNT(fs) ((fs)->fs_ipg)
@@ -104,29 +106,26 @@ static void quot(char *, char *);
static union dinode *
get_inode(int fd, struct fs *super, ino_t ino)
{
static caddr_t ipbuf;
static union dinode *ipbuf;
static struct cg *cgp;
static ino_t last;
static int cg;
static unsigned long cg;
struct ufs2_dinode *di2;
off_t off;
if (fd < 0) { /* flush cache */
if (ipbuf) {
free(ipbuf);
ipbuf = 0;
if (super != NULL && super->fs_magic == FS_UFS2_MAGIC) {
free(cgp);
cgp = 0;
}
}
return 0;
free(ipbuf);
ipbuf = NULL;
free(cgp);
cgp = NULL;
return (NULL);
}
if (!ipbuf || ino < last || ino >= last + INOCNT(super)) {
if (ipbuf == NULL || ino < last || ino >= last + INOCNT(super)) {
if (super->fs_magic == FS_UFS2_MAGIC &&
(!cgp || cg != ino_to_cg(super, ino))) {
(cgp == NULL || cg != ino_to_cg(super, ino))) {
cg = ino_to_cg(super, ino);
if (!cgp && !(cgp = malloc(super->fs_cgsize)))
if (cgp == NULL && (cgp = malloc(super->fs_cgsize)) == NULL)
errx(1, "allocate cg");
if (lseek(fd, (off_t)cgtod(super, cg) << super->fs_fshift, 0) < 0)
err(1, "lseek cg");
@@ -135,12 +134,12 @@ get_inode(int fd, struct fs *super, ino_t ino)
if (!cg_chkmagic(cgp))
errx(1, "cg has bad magic");
}
if (!ipbuf
&& !(ipbuf = malloc(INOSZ(super))))
if (ipbuf == NULL && (ipbuf = malloc(INOSZ(super))) == NULL)
errx(1, "allocate inodes");
last = rounddown(ino, INOCNT(super));
if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
|| read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super))
off = (off_t)ino_to_fsba(super, last) << super->fs_fshift;
if (lseek(fd, off, SEEK_SET) != off ||
read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super))
err(1, "read inodes");
}
@@ -150,7 +149,7 @@ get_inode(int fd, struct fs *super, ino_t ino)
di2 = &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)];
/* If the inode is unused, it might be unallocated too, so zero it. */
if (isclr(cg_inosused(cgp), ino % super->fs_ipg))
bzero(di2, sizeof (*di2));
memset(di2, 0, sizeof(*di2));
return ((union dinode *)di2);
}
@@ -166,8 +165,8 @@ static int virtualblocks(struct fs *super, union dinode *dp)
sz = DIP(super, dp, di_size);
#ifdef COMPAT
if (lblkno(super,sz) >= UFS_NDADDR) {
nblk = blkroundup(super,sz);
if (lblkno(super, sz) >= UFS_NDADDR) {
nblk = blkroundup(super, sz);
if (sz == nblk)
nblk += super->fs_bsize;
}
@@ -176,9 +175,9 @@ static int virtualblocks(struct fs *super, union dinode *dp)
#else /* COMPAT */
if (lblkno(super,sz) >= UFS_NDADDR) {
nblk = blkroundup(super,sz);
sz = lblkno(super,nblk);
if (lblkno(super, sz) >= UFS_NDADDR) {
nblk = blkroundup(super, sz);
sz = lblkno(super, nblk);
sz = (sz - UFS_NDADDR + NINDIR(super) - 1) / NINDIR(super);
while (sz > 0) {
nblk += sz * super->fs_bsize;
@@ -186,7 +185,7 @@ static int virtualblocks(struct fs *super, union dinode *dp)
sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super);
}
} else
nblk = fragroundup(super,sz);
nblk = fragroundup(super, sz);
return nblk / 512;
#endif /* COMPAT */
@@ -234,10 +233,9 @@ inituser(void)
int i;
struct user *usr;
if (!nusers) {
if (nusers == 0) {
nusers = 8;
if (!(users =
(struct user *)calloc(nusers,sizeof(struct user))))
if ((users = calloc(nusers, sizeof(*users))) == NULL)
errx(1, "allocate users");
} else {
for (usr = users, i = nusers; --i >= 0; usr++) {
@@ -255,14 +253,13 @@ usrrehash(void)
struct user *svusr;
svusr = users;
nusers <<= 1;
if (!(users = (struct user *)calloc(nusers,sizeof(struct user))))
nusers *= 2;
if ((users = calloc(nusers, sizeof(*users))) == NULL)
errx(1, "allocate users");
for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) {
for (usrn = users + (usr->uid&(nusers - 1)); usrn->name;
usrn--) {
for (usr = svusr, i = nusers / 2; --i >= 0; usr++) {
for (usrn = users + usr->uid % nusers; usrn->name; usrn--) {
if (usrn <= users)
usrn = users + nusers;
usrn += nusers;
}
*usrn = *usr;
}
@@ -272,29 +269,24 @@ static struct user *
user(uid_t uid)
{
struct user *usr;
int i;
struct passwd *pwd;
int i;
while (1) {
for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0;
usr--) {
if (!usr->name) {
for (usr = users + uid % nusers, i = nusers; --i >= 0; usr--) {
if (usr->name == NULL) {
usr->uid = uid;
if (!(pwd = getpwuid(uid))) {
if ((pwd = getpwuid(uid)) == NULL)
asprintf(&usr->name, "#%u", uid);
} else {
else
usr->name = strdup(pwd->pw_name);
}
if (!usr->name)
if (usr->name == NULL)
errx(1, "allocate users");
return usr;
} else if (usr->uid == uid)
return usr;
}
if (usr->uid == uid)
return (usr);
if (usr <= users)
usr = users + nusers;
usr += nusers;
}
usrrehash();
}
@@ -303,15 +295,13 @@ user(uid_t uid)
static int
cmpusers(const void *v1, const void *v2)
{
const struct user *u1, *u2;
u1 = (const struct user *)v1;
u2 = (const struct user *)v2;
const struct user *u1 = v1, *u2 = v2;
return u2->space - u1->space;
return (u2->space - u1->space);
}
#define sortusers(users) (qsort((users),nusers,sizeof(struct user), \
cmpusers))
#define sortusers(users) \
qsort((users), nusers, sizeof(struct user), cmpusers)
static void
uses(uid_t uid, daddr_t blks, time_t act)
@@ -339,7 +329,7 @@ uses(uid_t uid, daddr_t blks, time_t act)
#else
#define FSZCNT 512
#endif
struct fsizes {
static struct fsizes {
struct fsizes *fsz_next;
daddr_t fsz_first, fsz_last;
ino_t fsz_count[FSZCNT];
@@ -361,7 +351,7 @@ initfsizes(void)
}
static void
dofsizes(int fd, struct fs *super, char *name)
dofsizes(int fd, struct fs *super)
{
ino_t inode, maxino;
union dinode *dp;
@@ -375,13 +365,12 @@ dofsizes(int fd, struct fs *super, char *name)
errx(1, "allocate fsize structure");
#endif /* COMPAT */
for (inode = 0; inode < maxino; inode++) {
errno = 0;
if ((dp = get_inode(fd,super,inode))
if ((dp = get_inode(fd, super, inode)) != NULL &&
#ifdef COMPAT
&& ((DIP(super, dp, di_mode) & IFMT) == IFREG
|| (DIP(super, dp, di_mode) & IFMT) == IFDIR)
((DIP(super, dp, di_mode) & IFMT) == IFREG ||
(DIP(super, dp, di_mode) & IFMT) == IFDIR)
#else /* COMPAT */
&& !isfree(super, dp)
!isfree(super, dp)
#endif /* COMPAT */
) {
sz = estimate ? virtualblocks(super, dp) :
@@ -400,9 +389,8 @@ dofsizes(int fd, struct fs *super, char *name)
if (ksz < fp->fsz_last)
break;
}
if (!fp || ksz < fp->fsz_first) {
if (!(fp = (struct fsizes *)
malloc(sizeof(struct fsizes))))
if (fp == NULL || ksz < fp->fsz_first) {
if ((fp = malloc(sizeof(*fp))) == NULL)
errx(1, "allocate fsize structure");
fp->fsz_next = *fsp;
*fsp = fp;
@@ -416,24 +404,23 @@ dofsizes(int fd, struct fs *super, char *name)
fp->fsz_count[ksz % FSZCNT]++;
fp->fsz_sz[ksz % FSZCNT] += sz;
#endif /* COMPAT */
} else if (errno) {
err(1, "%s", name);
}
}
sz = 0;
for (fp = fsizes; fp; fp = fp->fsz_next) {
for (fp = fsizes; fp != NULL; fp = fp->fsz_next) {
for (i = 0; i < FSZCNT; i++) {
if (fp->fsz_count[i])
if (fp->fsz_count[i] != 0) {
printf("%jd\t%jd\t%d\n",
(intmax_t)(fp->fsz_first + i),
(intmax_t)fp->fsz_count[i],
SIZE(sz += fp->fsz_sz[i]));
}
}
}
}
static void
douser(int fd, struct fs *super, char *name)
douser(int fd, struct fs *super)
{
ino_t inode, maxino;
struct user *usr, *usrs;
@@ -442,38 +429,36 @@ douser(int fd, struct fs *super, char *name)
maxino = super->fs_ncg * super->fs_ipg - 1;
for (inode = 0; inode < maxino; inode++) {
errno = 0;
if ((dp = get_inode(fd,super,inode))
&& !isfree(super, dp))
if ((dp = get_inode(fd, super, inode)) != NULL &&
!isfree(super, dp)) {
uses(DIP(super, dp, di_uid),
estimate ? virtualblocks(super, dp) :
actualblocks(super, dp),
DIP(super, dp, di_atime));
else if (errno) {
err(1, "%s", name);
}
}
if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user))))
if ((usrs = malloc(nusers * sizeof(*usrs))) == NULL)
errx(1, "allocate users");
bcopy(users,usrs,nusers * sizeof(struct user));
memcpy(usrs, users, nusers * sizeof(*usrs));
sortusers(usrs);
for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) {
printf("%5d",SIZE(usr->space));
printf("%5d", SIZE(usr->space));
if (count)
printf("\t%5ld",usr->count);
printf("\t%-8s",usr->name);
if (unused)
printf("\t%5ld", usr->count);
printf("\t%-8s", usr->name);
if (unused) {
printf("\t%5d\t%5d\t%5d",
SIZE(usr->spc30),
SIZE(usr->spc60),
SIZE(usr->spc90));
SIZE(usr->spc30),
SIZE(usr->spc60),
SIZE(usr->spc90));
}
printf("\n");
}
free(usrs);
}
static void
donames(int fd, struct fs *super, char *name)
donames(int fd, struct fs *super)
{
int c;
ino_t maxino;
@@ -484,18 +469,18 @@ donames(int fd, struct fs *super, char *name)
/* first skip the name of the filesystem */
while ((c = getchar()) != EOF && (c < '0' || c > '9'))
while ((c = getchar()) != EOF && c != '\n');
ungetc(c,stdin);
ungetc(c, stdin);
while (scanf("%ju", &inode) == 1) {
if (inode > maxino) {
warnx("illegal inode %ju", inode);
return;
}
errno = 0;
if ((dp = get_inode(fd,super,inode))
&& !isfree(super, dp)) {
printf("%s\t",user(DIP(super, dp, di_uid))->name);
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');
while ((c = getchar()) == ' ' || c == '\t')
/* nothing */;
/* and print out the remainder of the input line */
while (c != EOF && c != '\n') {
putchar(c);
@@ -503,11 +488,9 @@ donames(int fd, struct fs *super, char *name)
}
putchar('\n');
} else {
if (errno) {
err(1, "%s", name);
}
/* skip this line */
while ((c = getchar()) != EOF && c != '\n');
while ((c = getchar()) != EOF && c != '\n')
/* nothing */;
}
if (c == EOF)
break;
@@ -534,7 +517,7 @@ quot(char *name, char *mp)
get_inode(-1, NULL, 0); /* flush cache */
inituser();
initfsizes();
if ((fd = open(name,0)) < 0) {
if ((fd = open(name, 0)) < 0) {
warn("%s", name);
close(fd);
return;
@@ -551,11 +534,11 @@ quot(char *name, char *mp)
close(fd);
return;
}
printf("%s:",name);
printf("%s:", name);
if (mp)
printf(" (%s)",mp);
printf(" (%s)", mp);
putchar('\n');
(*func)(fd, fs, name);
(*func)(fd, fs);
free(fs);
close(fd);
}
@@ -563,29 +546,27 @@ quot(char *name, char *mp)
int
main(int argc, char *argv[])
{
char all = 0;
struct statfs *mp;
struct fstab *fs;
int cnt;
int ch;
int ch, cnt;
func = douser;
#ifndef COMPAT
header = getbsize(&headerlen,&blocksize);
header = getbsize(&headerlen, &blocksize);
#endif
while ((ch = getopt(argc, argv, "acfhknv")) != -1) {
switch (ch) {
case 'a':
all = 1;
all = true;
break;
case 'c':
func = dofsizes;
break;
case 'f':
count = 1;
count = true;
break;
case 'h':
estimate = 1;
estimate = true;
break;
#ifndef COMPAT
case 'k':
@@ -596,7 +577,7 @@ main(int argc, char *argv[])
func = donames;
break;
case 'v':
unused = 1;
unused = true;
break;
default:
usage();
@@ -609,18 +590,16 @@ main(int argc, char *argv[])
usage();
if (all) {
cnt = getmntinfo(&mp,MNT_NOWAIT);
for (; --cnt >= 0; mp++) {
if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN))
for (cnt = getmntinfo(&mp, MNT_NOWAIT); --cnt >= 0; mp++)
if (strncmp(mp->f_fstypename, "ufs", MFSNAMELEN) == 0)
quot(mp->f_mntfromname, mp->f_mntonname);
}
}
while (--argc >= 0) {
while (argc-- > 0) {
if ((fs = getfsfile(*argv)) != NULL)
quot(fs->fs_spec, 0);
else
quot(*argv,0);
quot(*argv, 0);
argv++;
}
return 0;
return (0);
}