file reorg, pathnames.h
[unix-history] / usr / src / usr.sbin / quot / quot.c
index 8079605..c172e77 100644 (file)
@@ -1,30 +1,42 @@
-static char *sccsid = "@(#)quot.c      4.2 (Berkeley) 82/03/29";
+#ifndef lint
+static char *sccsid = "@(#)quot.c      4.16 (Berkeley) 89/05/15";
+#endif
 
 /*
  * quot
  */
 
 
 /*
  * quot
  */
 
-#include <stdio.h>
-#include <ctype.h>
-#include <pwd.h>
 #include <sys/param.h>
 #include <sys/param.h>
-#include <sys/ino.h>
 #include <sys/inode.h>
 #include <sys/inode.h>
-#include <sys/filsys.h>
-
-#define        ITABSZ  256
-#define        ISIZ    (BSIZE/sizeof(struct dinode))
-#define        NUID    1000
-struct filsys  sblock;
-struct dinode  itab[ITABSZ];
-struct du
-{
+#include <sys/fs.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <paths.h>
+
+#define        ISIZ    (MAXBSIZE/sizeof(struct dinode))
+union {
+       struct fs u_sblock;
+       char dummy[SBSIZE];
+} sb_un;
+#define sblock sb_un.u_sblock
+struct dinode itab[MAXBSIZE/sizeof(struct dinode)];
+
+struct du {
+       struct  du *next;
        long    blocks;
        long    blocks;
-       long    blocks30,blocks60,blocks90;
+       long    blocks30;
+       long    blocks60;
+       long    blocks90;
        long    nfiles;
        int     uid;
        long    nfiles;
        int     uid;
-       char    *name;
-} du[NUID];
+#define        NDU     2048
+} du[NDU];
+int    ndu;
+#define        DUHASH  8209    /* smallest prime >= 4 * NDU */
+#define        HASH(u) ((u) % DUHASH)
+struct du *duhash[DUHASH];
+
 #define        TSIZE   500
 int    sizes[TSIZE];
 long   overflow;
 #define        TSIZE   500
 int    sizes[TSIZE];
 long   overflow;
@@ -33,214 +45,329 @@ int       nflg;
 int    fflg;
 int    cflg;
 int    vflg;
 int    fflg;
 int    cflg;
 int    vflg;
+int    hflg;
 long   now;
 
 long   now;
 
-int    fi;
 unsigned       ino;
 unsigned       ino;
-unsigned       nfiles;
 
 
-struct passwd  *getpwent();
 char   *malloc();
 char   *malloc();
-char   *copy();
+char   *getname();
 
 main(argc, argv)
 
 main(argc, argv)
-char **argv;
+       int argc;
+       char *argv[];
 {
 {
-       register int n;
-       register struct passwd *lp;
-       register char **p;
-
-       now = time(0);
-       for(n=0; n<NUID; n++)
-               du[n].uid = n;
-       while((lp=getpwent()) != 0) {
-               n = lp->pw_uid;
-               if (n>NUID)
+       extern char *optarg;
+       extern int optind;
+       int ch;
+       time_t time();
+
+       while ((ch = getopt(argc, argv, "cfhnv")) != EOF)
+               switch((char)ch) {
+               case 'c':
+                       cflg++; break;
+               case 'f':
+                       fflg++; break;
+               case 'h':               /* undocumented */
+                       hflg++; break;
+               case 'n':
+                       nflg++; break;
+               case 'v':               /* undocumented */
+                       vflg++; break;
+               case '?':
+               default:
+                       fputs("usage: quot [-cfn] [filesystem ...]\n", stderr);
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+
+       (void)time(&now);
+       setpassent(1);
+       if (argc)
+               for (; *argv; ++argv) {
+                       if (check(*argv, (char *)NULL) == 0)
+                               report();
+               }
+       else
+               quotall();
+       exit(0);
+}
+
+#include <sys/dir.h>
+#include <fstab.h>
+
+quotall()
+{
+       register struct fstab *fs;
+       register char *cp;
+       char dev[MAXNAMLEN + 10], *rindex();
+
+       while (fs = getfsent()) {
+               if (strcmp(fs->fs_type, FSTAB_RO) &&
+                   strcmp(fs->fs_type, FSTAB_RW) &&
+                   strcmp(fs->fs_type, FSTAB_RQ))
                        continue;
                        continue;
-               if(du[n].name)
+               cp = rindex(fs->fs_spec, '/');
+               if (cp == 0)
                        continue;
                        continue;
-               du[n].name = copy(lp->pw_name);
-       }
-       if (argc == 1) {
-               fprintf(stderr, "usage: df device ...\n");
-               exit(1);
-       }
-       while (--argc) {
-               argv++;
-               if (argv[0][0]=='-') {
-                       if (argv[0][1]=='n')
-                               nflg++;
-                       else if (argv[0][1]=='f')
-                               fflg++;
-                       else if (argv[0][1]=='c')
-                               cflg++;
-                       else if (argv[0][1]=='v')
-                               vflg++;
-               } else {
-                       check(*argv);
+               (void)sprintf(dev, "%s/r%s", _PATH_DEV, cp + 1);
+               if (check(dev, fs->fs_file) == 0)
                        report();
                        report();
-               }
        }
        }
-       return(0);
 }
 
 }
 
-check(file)
-char *file;
+check(file, fsdir)
+       char *file;
+       char *fsdir;
 {
 {
-       register unsigned i, j;
-       register c;
+       register int i, j, nfiles;
+       register struct du **dp;
+       daddr_t iblk;
+       long dev_bsize;
+       int c, fd;
 
 
-       fi = open(file, 0);
-       if (fi < 0) {
-               printf("cannot open %s\n", file);
-               return;
+       /*
+        * Initialize tables between checks;
+        * because of the qsort done in report()
+        * the hash tables must be rebuilt each time.
+        */
+       for (i = 0; i < TSIZE; i++)
+               sizes[i] = 0;
+       overflow = 0;
+       for (dp = duhash; dp < &duhash[DUHASH]; dp++)
+               *dp = 0;
+       ndu = 0;
+       fd = open(file, O_RDONLY);
+       if (fd < 0) {
+               fprintf(stderr, "quot: ");
+               perror(file);
+               return (-1);
+       }
+       printf("%s", file);
+       if (fsdir == NULL) {
+               register struct fstab *fs = getfsspec(file);
+               if (fs != NULL)
+                       fsdir = fs->fs_file;
        }
        }
-       printf("%s:\n", file);
+       if (fsdir != NULL && *fsdir != '\0')
+               printf(" (%s)", fsdir);
+       printf(":\n");
        sync();
        sync();
-       bread(1, (char *)&sblock, sizeof sblock);
-       nfiles = (sblock.s_isize-2)*(BSIZE/sizeof(struct dinode));
-       ino = 0;
+       bread(fd, (long)SBOFF, (char *)&sblock, SBSIZE);
+       dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
        if (nflg) {
                if (isdigit(c = getchar()))
        if (nflg) {
                if (isdigit(c = getchar()))
-                       ungetc(c, stdin);
-               else while (c!='\n' && c != EOF)
+                       (void)ungetc(c, stdin);
+               else while (c != '\n' && c != EOF)
                        c = getchar();
        }
                        c = getchar();
        }
-       for(i=2; ino<nfiles; i += ITABSZ/ISIZ) {
-               bread(i, (char *)itab, sizeof itab);
-               for (j=0; j<ITABSZ && ino<nfiles; j++) {
-                       ino++;
+       nfiles = sblock.fs_ipg * sblock.fs_ncg;
+       for (ino = 0; ino < nfiles; ) {
+               iblk = fsbtodb(&sblock, itod(&sblock, ino));
+               bread(fd, iblk * dev_bsize, (char *)itab, (int)sblock.fs_bsize);
+               for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) {
+                       if (ino < ROOTINO)
+                               continue;
                        acct(&itab[j]);
                }
        }
                        acct(&itab[j]);
                }
        }
+       close(fd);
+       return (0);
 }
 
 acct(ip)
 }
 
 acct(ip)
-register struct dinode *ip;
+       register struct dinode *ip;
 {
 {
-       register n;
-       register char *np;
+       register struct du *dp;
+       struct du **hp;
+       long blks, frags, size;
+       int n;
        static fino;
 
        static fino;
 
-       if ((ip->di_mode&IFMT) == 0)
+       if ((ip->di_mode & IFMT) == 0)
                return;
                return;
+       /*
+        * By default, take block count in inode.  Otherwise (-h),
+        * take the size field and estimate the blocks allocated.
+        * The latter does not account for holes in files.
+        */
+       if (!hflg)
+               size = ip->di_blocks / 2;
+       else {
+               blks = lblkno(&sblock, ip->di_size);
+               frags = blks * sblock.fs_frag +
+                       numfrags(&sblock, dblksize(&sblock, ip, blks));
+               size = frags * sblock.fs_fsize / 1024;
+       }
        if (cflg) {
        if (cflg) {
-               if ((ip->di_mode&IFMT)!=IFDIR && (ip->di_mode&IFMT)!=IFREG)
+               if ((ip->di_mode&IFMT) != IFDIR && (ip->di_mode&IFMT) != IFREG)
                        return;
                        return;
-               n = (ip->di_size+BSIZE-1)/BSIZE;
-               if (n >= TSIZE) {
-                       overflow += n;
-                       n = TSIZE-1;
+               if (size >= TSIZE) {
+                       overflow += size;
+                       size = TSIZE-1;
                }
                }
-               sizes[n]++;
+               sizes[size]++;
                return;
        }
                return;
        }
-       if (ip->di_uid >= NUID)
-               return;
-       du[ip->di_uid].blocks += (ip->di_size+BSIZE-1)/BSIZE;
+       hp = &duhash[HASH(ip->di_uid)];
+       for (dp = *hp; dp; dp = dp->next)
+               if (dp->uid == ip->di_uid)
+                       break;
+       if (dp == 0) {
+               if (ndu >= NDU)
+                       return;
+               dp = &du[ndu++];
+               dp->next = *hp;
+               *hp = dp;
+               dp->uid = ip->di_uid;
+               dp->nfiles = 0;
+               dp->blocks = 0;
+               dp->blocks30 = 0;
+               dp->blocks60 = 0;
+               dp->blocks90 = 0;
+       }
+       dp->blocks += size;
 #define        DAY (60 * 60 * 24)      /* seconds per day */
        if (now - ip->di_atime > 30 * DAY)
 #define        DAY (60 * 60 * 24)      /* seconds per day */
        if (now - ip->di_atime > 30 * DAY)
-               du[ip->di_uid].blocks30 += (ip->di_size+BSIZE-1)/BSIZE;
+               dp->blocks30 += size;
        if (now - ip->di_atime > 60 * DAY)
        if (now - ip->di_atime > 60 * DAY)
-               du[ip->di_uid].blocks60 += (ip->di_size+BSIZE-1)/BSIZE;
+               dp->blocks60 += size;
        if (now - ip->di_atime > 90 * DAY)
        if (now - ip->di_atime > 90 * DAY)
-               du[ip->di_uid].blocks90 += (ip->di_size+BSIZE-1)/BSIZE;
-       du[ip->di_uid].nfiles++;
-       if (nflg) {
-       tryagain:
-               if (fino==0)
-                       if (scanf("%d", &fino)<=0)
+               dp->blocks90 += size;
+       dp->nfiles++;
+       while (nflg) {
+               register char *np;
+
+               if (fino == 0)
+                       if (scanf("%d", &fino) <= 0)
                                return;
                if (fino > ino)
                        return;
                                return;
                if (fino > ino)
                        return;
-               if (fino<ino) {
-                       while ((n=getchar())!='\n' && n!=EOF)
+               if (fino < ino) {
+                       while ((n = getchar()) != '\n' && n != EOF)
                                ;
                        fino = 0;
                                ;
                        fino = 0;
-                       goto tryagain;
+                       continue;
                }
                }
-               if (np = du[ip->di_uid].name)
-                       printf("%.7s    ", np);
+               if (np = getname(dp->uid))
+                       printf("%.7s\t", np);
                else
                else
-                       printf("%d      ", ip->di_uid);
-               while ((n = getchar())==' ' || n=='\t')
+                       printf("%u\t", ip->di_uid);
+               while ((n = getchar()) == ' ' || n == '\t')
                        ;
                putchar(n);
                        ;
                putchar(n);
-               while (n!=EOF && n!='\n') {
+               while (n != EOF && n != '\n') {
                        n = getchar();
                        putchar(n);
                }
                fino = 0;
                        n = getchar();
                        putchar(n);
                }
                fino = 0;
+               break;
        }
 }
 
        }
 }
 
-bread(bno, buf, cnt)
-unsigned bno;
-char *buf;
+bread(fd, bno, buf, cnt)
+       long bno;
+       char *buf;
 {
 {
+       off_t lseek();
 
 
-       lseek(fi, (long)bno*BSIZE, 0);
-       if (read(fi, buf, cnt) != cnt) {
-               printf("read error %u\n", bno);
+       (void)lseek(fd, bno, L_SET);
+       if (read(fd, buf, cnt) != cnt) {
+               fprintf(stderr, "quot: read error at block %ld\n", bno);
                exit(1);
        }
 }
 
 qcmp(p1, p2)
                exit(1);
        }
 }
 
 qcmp(p1, p2)
-register struct du *p1, *p2;
+       register struct du *p1, *p2;
 {
 {
+       char *s1, *s2;
+
        if (p1->blocks > p2->blocks)
        if (p1->blocks > p2->blocks)
-               return(-1);
+               return (-1);
        if (p1->blocks < p2->blocks)
        if (p1->blocks < p2->blocks)
-               return(1);
-       return(strcmp(p1->name, p2->name));
+               return (1);
+       s1 = getname(p1->uid);
+       if (s1 == 0)
+               return (0);
+       s2 = getname(p2->uid);
+       if (s2 == 0)
+               return (0);
+       return (strcmp(s1, s2));
 }
 
 report()
 {
        register i;
 }
 
 report()
 {
        register i;
+       register struct du *dp;
 
        if (nflg)
                return;
        if (cflg) {
 
        if (nflg)
                return;
        if (cflg) {
-               long t = 0;
-               for (i=0; i<TSIZE-1; i++)
+               register long t = 0;
+
+               for (i = 0; i < TSIZE - 1; i++)
                        if (sizes[i]) {
                                t += i*sizes[i];
                        if (sizes[i]) {
                                t += i*sizes[i];
-                               printf("%d      %d      %D\n", i, sizes[i], t);
+                               printf("%d\t%d\t%ld\n", i, sizes[i], t);
                        }
                        }
-               printf("%d      %d      %D\n", TSIZE-1, sizes[TSIZE-1], overflow+t);
+               printf("%d\t%d\t%ld\n",
+                   TSIZE - 1, sizes[TSIZE - 1], overflow + t);
                return;
        }
                return;
        }
-       qsort(du, NUID, sizeof(du[0]), qcmp);
-       for (i=0; i<NUID; i++) {
-               if (du[i].blocks==0)
+       qsort(du, ndu, sizeof (du[0]), qcmp);
+       for (dp = du; dp < &du[ndu]; dp++) {
+               register char *cp;
+
+               if (dp->blocks == 0)
                        return;
                        return;
-               printf("%5D\t", du[i].blocks);
+               printf("%5D\t", dp->blocks);
                if (fflg)
                if (fflg)
-                       printf("%5D\t", du[i].nfiles);
-               if (du[i].name)
-                       printf("%-8.8s", du[i].name);
+                       printf("%5D\t", dp->nfiles);
+               if (cp = getname(dp->uid))
+                       printf("%-8.8s", cp);
                else
                else
-                       printf("#%-8d", du[i].uid);
+                       printf("#%-8d", dp->uid);
                if (vflg)
                        printf("\t%5D\t%5D\t%5D",
                if (vflg)
                        printf("\t%5D\t%5D\t%5D",
-                           du[i].blocks30, du[i].blocks60, du[i].blocks90);
+                           dp->blocks30, dp->blocks60, dp->blocks90);
                printf("\n");
        }
 }
 
                printf("\n");
        }
 }
 
+/* rest should be done with nameserver or database */
+
+#include <pwd.h>
+#include <grp.h>
+#include <utmp.h>
+
+struct utmp utmp;
+#define        NMAX    (sizeof (utmp.ut_name))
+#define SCPYN(a, b)    strncpy(a, b, NMAX)
+
+#define NUID   64      /* power of 2 */
+#define UIDMASK        0x3f
+
+struct ncache {
+       int     uid;
+       char    name[NMAX+1];
+} nc[NUID];
+
 char *
 char *
-copy(s)
-char *s;
+getname(uid)
 {
 {
-       register char *p;
-       register n;
-
-       for(n=0; s[n]; n++)
-               ;
-       p = malloc((unsigned)n+1);
-       for(n=0; p[n] = s[n]; n++)
-               ;
-       return(p);
+       register struct passwd *pw;
+       struct passwd *getpwent();
+       register int cp;
+
+       cp = uid & UIDMASK;
+       if (uid >= 0 && nc[cp].uid == uid && nc[cp].name[0])
+               return (nc[cp].name);
+       pw = getpwuid(uid);
+       if (!pw)
+               return (0);
+       nc[cp].uid = uid;
+       SCPYN(nc[cp].name, pw->pw_name);
+       return (nc[cp].name);
 }
 }