summaryrefslogtreecommitdiffstats
path: root/sbin/quotacheck/quotacheck.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/quotacheck/quotacheck.c')
-rw-r--r--sbin/quotacheck/quotacheck.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c
index 54339e7..8407676 100644
--- a/sbin/quotacheck/quotacheck.c
+++ b/sbin/quotacheck/quotacheck.c
@@ -82,6 +82,14 @@ union {
long dev_bsize = 1;
ino_t maxino;
+union dinode {
+ struct ufs1_dinode dp1;
+ struct ufs2_dinode dp2;
+};
+#define DIP(dp, field) \
+ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \
+ (dp)->dp1.field : (dp)->dp2.field)
+
struct quotaname {
long flags;
char grpqfname[MAXPATHLEN + 1];
@@ -116,7 +124,7 @@ extern int checkfstab(int, int, void * (*)(struct fstab *),
int (*)(char *, char *, struct quotaname *));
int chkquota(char *, char *, struct quotaname *);
void freeinodebuf(void);
-struct dinode *
+union dinode *
getnextinode(ino_t);
int getquotagid(void);
int hasquota(struct fstab *, int, char **);
@@ -241,6 +249,11 @@ needchk(fs)
}
/*
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
+/*
* Scan the specified filesystem to check quota(s) present on it.
*/
int
@@ -249,7 +262,7 @@ chkquota(fsname, mntpt, qnp)
struct quotaname *qnp;
{
struct fileusage *fup;
- struct dinode *dp;
+ union dinode *dp;
int cg, i, mode, errs = 0;
ino_t ino;
@@ -268,7 +281,20 @@ chkquota(fsname, mntpt, qnp)
}
sync();
dev_bsize = 1;
- bread(SBOFF, (char *)&sblock, (long)SBSIZE);
+ for (i = 0; sblock_try[i] != -1; i++) {
+ bread(sblock_try[i], (char *)&sblock, (long)SBLOCKSIZE);
+ if ((sblock.fs_magic == FS_UFS1_MAGIC ||
+ (sblock.fs_magic == FS_UFS2_MAGIC &&
+ sblock.fs_sblockloc ==
+ numfrags(&sblock, sblock_try[i]))) &&
+ sblock.fs_bsize <= MAXBSIZE &&
+ sblock.fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
+ warn("Cannot find filesystem superblock");
+ return (1);
+ }
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
maxino = sblock.fs_ncg * sblock.fs_ipg;
resetinodebuf();
@@ -278,23 +304,23 @@ chkquota(fsname, mntpt, qnp)
continue;
if ((dp = getnextinode(ino)) == NULL)
continue;
- if ((mode = dp->di_mode & IFMT) == 0)
+ if ((mode = DIP(dp, di_mode) & IFMT) == 0)
continue;
if (qnp->flags & HASGRP) {
- fup = addid((u_long)dp->di_gid, GRPQUOTA,
+ fup = addid((u_long)DIP(dp, di_gid), GRPQUOTA,
(char *)0);
fup->fu_curinodes++;
if (mode == IFREG || mode == IFDIR ||
mode == IFLNK)
- fup->fu_curblocks += dp->di_blocks;
+ fup->fu_curblocks += DIP(dp, di_blocks);
}
if (qnp->flags & HASUSR) {
- fup = addid((u_long)dp->di_uid, USRQUOTA,
+ fup = addid((u_long)DIP(dp, di_uid), USRQUOTA,
(char *)0);
fup->fu_curinodes++;
if (mode == IFREG || mode == IFDIR ||
mode == IFLNK)
- fup->fu_curblocks += dp->di_blocks;
+ fup->fu_curblocks += DIP(dp, di_blocks);
}
}
}
@@ -536,20 +562,21 @@ addid(id, type, name)
* Special purpose version of ginode used to optimize pass
* over all the inodes in numerical order.
*/
-ino_t nextino, lastinum;
-long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
-struct dinode *inodebuf;
-#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */
+static ino_t nextino, lastinum, lastvalidinum;
+static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
+static caddr_t inodebuf;
+#define INOBUFSIZE 56*1024 /* size of buffer to read inodes */
-struct dinode *
+union dinode *
getnextinode(inumber)
ino_t inumber;
{
long size;
- daddr_t dblk;
- static struct dinode *dp;
+ ufs2_daddr_t dblk;
+ union dinode *dp;
+ static caddr_t nextinop;
- if (inumber != nextino++ || inumber > maxino)
+ if (inumber != nextino++ || inumber > lastvalidinum)
errx(1, "bad inode number %d to nextinode", inumber);
if (inumber >= lastinum) {
readcnt++;
@@ -561,10 +588,19 @@ getnextinode(inumber)
size = inobufsize;
lastinum += fullcnt;
}
- bread(dblk, (char *)inodebuf, size);
- dp = inodebuf;
+ /*
+ * If bread returns an error, it will already have zeroed
+ * out the buffer, so we do not need to do so here.
+ */
+ bread(dblk, inodebuf, size);
+ nextinop = inodebuf;
}
- return (dp++);
+ dp = (union dinode *)nextinop;
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ nextinop += sizeof(struct ufs1_dinode);
+ else
+ nextinop += sizeof(struct ufs2_dinode);
+ return (dp);
}
/*
@@ -578,10 +614,12 @@ resetinodebuf()
lastinum = 0;
readcnt = 0;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
- fullcnt = inobufsize / sizeof(struct dinode);
+ fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ?
+ sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
readpercg = sblock.fs_ipg / fullcnt;
partialcnt = sblock.fs_ipg % fullcnt;
- partialsize = partialcnt * sizeof(struct dinode);
+ partialsize = partialcnt * ((sblock.fs_magic == FS_UFS1_MAGIC) ?
+ sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode));
if (partialcnt != 0) {
readpercg++;
} else {
OpenPOWER on IntegriCloud