jfh@rpp386.Dallas.TX.US (John F. Haugh II) (11/03/88)
This has been posted to pubnet.sources before. pubnet does not receive a wide distribution, so I am reposting it here. This is liable to need much twiddling, so please hack first and write me second. Better still, hack several times before writing ;-) - John. -- #include <sys/param.h> #include <sys/sysmacros.h> #include <sys/types.h> #include <sys/ino.h> #include <sys/inode.h> #include <sys/filsys.h> #include <pwd.h> #include <grp.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #undef MAXUID #define MAXUID 400 #ifndef DEF_FS #define DEF_FS "/dev/root" #endif #define DIR_BLKS 10 #define FILSYS (sizeof (struct filsys)) static char sccsid[] = "@(#)quot.c 1.0"; struct passwd *getpwuid (); struct group *getgrgid (); struct ublks { int u_uid; /* uid of person/group */ long int u_blks; /* total blocks used */ } ublks[MAXUID]; int tflg, /* print totals only */ gflg; /* print groups, not users */ struct dinode *iget (fd, ino) register int fd, ino; { static long int lastblk = -1; static struct dinode iblk[4*INOPB]; if ((lastblk >> 2) != (itod (ino) >> 2)) { lastblk = itod (ino); lastblk &= ~03; if (lseek (fd, lastblk << BSHIFT, 0) < 0) return (0); if (read (fd, iblk, BSIZE*4) != BSIZE*4) return (0); } return (&iblk[((itod (ino) & 03) * INOPB) + itoo (ino)]); } int fsopen (fs, superb) char *fs; register struct filsys *superb; { register int file; if (((file = open (fs, O_RDONLY)) < 0) || (lseek (file, (long) (SUPERB << BSHIFT), 0) < 0) || (read (file, superb, BSIZE) != BSIZE)) return (-1); else return (file); } int blkcmp (a, b) struct ublks *a, *b; { return (b->u_blks - a->u_blks); } usage () { write (2, "usage: quot [ -tug ] [ filesystem ]\n", 36); exit (1); } printtotals (device) char *device; { int user; struct passwd *pwent; struct group *grent; printf ("%s:\n", device); qsort (ublks, MAXUID, sizeof (struct ublks), blkcmp); for (user = 0;user < MAXUID;user++) if (ublks[user].u_blks) { if (! gflg) if (pwent = getpwuid (ublks[user].u_uid)) printf ("%8.8s %d\n", pwent->pw_name, ublks[user].u_blks * 2); else printf ("%8.8d %d\n", ublks[user].u_uid, ublks[user].u_blks * 2); else if (grent = getgrgid (ublks[user].u_uid)) printf ("%8.8s %d\n", grent->gr_name, ublks[user].u_blks * 2); else printf ("%8.8d %d\n", ublks[user].u_uid, ublks[user].u_blks * 2); } } blocks (fsize) long int fsize; { long int extra = fsize; /* indirect blocks */ if (fsize <= NINDIR) /* single indirect */ return (fsize + 1); fsize -= NINDIR; extra++; if (fsize <= NINDIR*NINDIR) return (extra + ((fsize + NINDIR - 1) / NINDIR + 1)); extra += NINDIR + 1; fsize -= NINDIR*NINDIR; extra += (fsize + NINDIR - 1) / NINDIR; /* indirect blocks to point to direct blocks */ fsize = (fsize + NINDIR - 1) / NINDIR; /* fsize is now just the indirect block count */ extra += (fsize + NINDIR - 1) / NINDIR; /* double indirects to point to single indirects */ fsize = (fsize + NINDIR - 1) / NINDIR; /* fsize is now just the double indirect count */ extra += (fsize + NINDIR - 1) / NINDIR; /* triple indirect(s) to point to double indirects */ fsize = (fsize + NINDIR - 1) / NINDIR; /* had better just be 1 ... */ return (extra); } main (argc, argv) int argc; char **argv; { struct dinode *dino; char buf[BSIZE]; struct filsys *superb = (struct filsys *) buf; register int fd, ino, user; long fsize; long foobar; int arg, c, maxino; char *uid; struct passwd *pwent; for (user = 0;user < MAXUID;user++) { ublks[user].u_blks = 0; ublks[user].u_uid = user; } for (arg = 1;arg < argc;arg++) { if (argv[arg][0] != '-') break; for (c = 1;argv[arg][c];c++) switch (argv[arg][c]) { case 't': tflg++; break; case 'g': gflg++; break; case 'u': gflg = 0; break; default: usage (); } } if (argc == arg) { argv[arg] = DEF_FS; argc = arg + 1; } for (;arg < argc;arg++) { if ((fd = fsopen (argv[arg], superb)) < 0) { perror (argv[arg]); continue; } if (! tflg) for (user = 0;user < MAXUID;user++) { ublks[user].u_blks = 0; ublks[user].u_uid = user; } maxino = (superb->s_isize) * INOPB; for (ino = 2;ino < maxino;ino++) { if (! (dino = iget (fd, ino))) continue; if (! dino->di_mode || ! dino->di_nlink) continue; if ((dino->di_mode & IFMT) != IFDIR && (dino->di_mode & IFMT) != IFREG) continue; if (dino->di_size == 0) continue; if (gflg) dino->di_uid = dino->di_gid; if (dino->di_uid < 0 || dino->di_uid >= MAXUID) continue; fsize = (dino->di_size + BSIZE - 1) >> (BSHIFT); if (fsize <= DIR_BLKS) { ublks[dino->di_uid].u_blks += fsize; } else { ublks[dino->di_uid].u_blks += blocks (fsize - DIR_BLKS) + DIR_BLKS; } } close (fd); if (! tflg) printtotals (argv[arg]); } if (tflg) printtotals ("totals"); } -- John F. Haugh II +----Make believe quote of the week---- VoiceNet: (214) 250-3311 Data: -6272 | Nancy Reagan on Richard Stallman: InterNet: jfh@rpp386.Dallas.TX.US | "Just say `Gno'" UucpNet : <backbone>!killer!rpp386!jfh +--------------------------------------