1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)quotacheck.c	5.6 (Berkeley) 11/3/85";
  15: #endif not lint
  16: 
  17: /*
  18:  * Fix up / report on disc quotas & usage
  19:  */
  20: #include <stdio.h>
  21: #include <ctype.h>
  22: #include <signal.h>
  23: #include <errno.h>
  24: #include <sys/param.h>
  25: #include <sys/inode.h>
  26: #include <sys/fs.h>
  27: #include <sys/quota.h>
  28: #include <sys/stat.h>
  29: #include <sys/wait.h>
  30: #include <fstab.h>
  31: #include <pwd.h>
  32: 
  33: union {
  34:     struct  fs  sblk;
  35:     char    dummy[MAXBSIZE];
  36: } un;
  37: #define sblock  un.sblk
  38: 
  39: #define ITABSZ  256
  40: struct  dinode  itab[ITABSZ];
  41: struct  dinode  *dp;
  42: 
  43: #define LOGINNAMESIZE 8
  44: struct fileusage {
  45:     struct fileusage *fu_next;
  46:     struct dqusage fu_usage;
  47:     u_short fu_uid;
  48:     char fu_name[LOGINNAMESIZE + 1];
  49: };
  50: #define FUHASH 997
  51: struct fileusage *fuhead[FUHASH];
  52: struct fileusage *lookup();
  53: struct fileusage *adduid();
  54: int highuid;
  55: 
  56: int fi;
  57: ino_t ino;
  58: long done;
  59: struct  passwd  *getpwent();
  60: struct  dinode  *ginode();
  61: char *malloc(), *makerawname();
  62: 
  63: int vflag;      /* verbose */
  64: int aflag;      /* all file systems */
  65: int pflag;      /* fsck like parallel check */
  66: 
  67: char *qfname = "quotas";
  68: char quotafile[MAXPATHLEN + 1];
  69: struct dqblk zerodqbuf;
  70: struct fileusage zerofileusage;
  71: 
  72: main(argc, argv)
  73:     int argc;
  74:     char **argv;
  75: {
  76:     register struct fstab *fs;
  77:     register struct fileusage *fup;
  78:     register struct passwd *pw;
  79:     int i, errs = 0;
  80: 
  81: again:
  82:     argc--, argv++;
  83:     if (argc > 0 && strcmp(*argv, "-v") == 0) {
  84:         vflag++;
  85:         goto again;
  86:     }
  87:     if (argc > 0 && strcmp(*argv, "-a") == 0) {
  88:         aflag++;
  89:         goto again;
  90:     }
  91:     if (argc > 0 && strcmp(*argv, "-p") == 0) {
  92:         pflag++;
  93:         goto again;
  94:     }
  95:     if (argc <= 0 && !aflag) {
  96:         fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
  97:             "quotacheck [-v] [-p] -a",
  98:             "quotacheck [-v] [-p] filesys ...");
  99:         exit(1);
 100:     }
 101: 
 102:     setpwent();
 103:     while ((pw = getpwent()) != 0) {
 104:         fup = lookup(pw->pw_uid);
 105:         if (fup == 0) {
 106:             fup = adduid(pw->pw_uid);
 107:             strncpy(fup->fu_name, pw->pw_name,
 108:                 sizeof(fup->fu_name));
 109:         }
 110:     }
 111:     endpwent();
 112: 
 113:     if (pflag)
 114:         errs = preen(argc, argv);
 115:     else {
 116:         if (setfsent() == 0) {
 117:             fprintf(stderr, "Can't open ");
 118:             perror(FSTAB);
 119:             exit(8);
 120:         }
 121:         while ((fs = getfsent()) != NULL) {
 122:             if (aflag &&
 123:                 (fs->fs_type == 0 ||
 124:                  strcmp(fs->fs_type, FSTAB_RQ) != 0))
 125:                 continue;
 126:             if (!aflag &&
 127:                 !(oneof(fs->fs_file, argv, argc) ||
 128:                   oneof(fs->fs_spec, argv, argc)))
 129:                 continue;
 130:             (void) sprintf(quotafile, "%s/%s", fs->fs_file, qfname);
 131:             errs += chkquota(fs->fs_spec, fs->fs_file, quotafile);
 132:         }
 133:         endfsent();
 134:     }
 135: 
 136:     for (i = 0; i < argc; i++)
 137:         if ((done & (1 << i)) == 0)
 138:             fprintf(stderr, "%s not found in %s\n",
 139:                 argv[i], FSTAB);
 140:     exit(errs);
 141: }
 142: 
 143: preen(argc, argv)
 144:     int argc;
 145:     char **argv;
 146: {
 147:     register struct fstab *fs;
 148:     register int passno, anygtr;
 149:     register int errs;
 150:     union wait status;
 151: 
 152:     passno = 1;
 153:     errs = 0;
 154:     do {
 155:         anygtr = 0;
 156: 
 157:         if (setfsent() == 0) {
 158:             fprintf(stderr, "Can't open ");
 159:             perror(FSTAB);
 160:             exit(8);
 161:         }
 162: 
 163:         while ((fs = getfsent()) != NULL) {
 164:             if (fs->fs_passno > passno)
 165:                 anygtr = 1;
 166: 
 167:             if (aflag &&
 168:                 (fs->fs_type == 0 ||
 169:                  strcmp(fs->fs_type, FSTAB_RQ) != 0))
 170:                 continue;
 171: 
 172:             if (!aflag &&
 173:                 !(oneof(fs->fs_file, argv, argc) ||
 174:                   oneof(fs->fs_spec, argv, argc)))
 175:                 continue;
 176: 
 177:             if (fs->fs_passno != passno)
 178:                 continue;
 179: 
 180:             switch (fork()) {
 181:             case -1:
 182:                 perror("fork");
 183:                 exit(8);
 184:                 break;
 185: 
 186:             case 0:
 187:                 sprintf(quotafile, "%s/%s",
 188:                     fs->fs_file, qfname);
 189:                 exit(chkquota(fs->fs_spec,
 190:                     fs->fs_file, quotafile));
 191:             }
 192:         }
 193: 
 194:         while (wait(&status) != -1)
 195:             errs += status.w_retcode;
 196: 
 197:         passno++;
 198:     } while (anygtr);
 199: 
 200:     return (errs);
 201: }
 202: 
 203: chkquota(fsdev, fsfile, qffile)
 204:     char *fsdev;
 205:     char *fsfile;
 206:     char *qffile;
 207: {
 208:     register struct fileusage *fup;
 209:     dev_t quotadev;
 210:     register FILE *qfi, *qfo;
 211:     u_short uid;
 212:     int cg, i, fdo;
 213:     char *rawdisk;
 214:     struct stat statb;
 215:     struct dqblk dqbuf;
 216:     static int warned = 0;
 217:     extern int errno;
 218: 
 219:     rawdisk = makerawname(fsdev);
 220:     if (vflag)
 221:         fprintf(stdout, "*** Checking quotas for %s (%s)\n", rawdisk, fsfile);
 222:     fi = open(rawdisk, 0);
 223:     if (fi < 0) {
 224:         perror(rawdisk);
 225:         return (1);
 226:     }
 227:     qfi = fopen(qffile, "r");
 228:     if (qfi == NULL) {
 229:         perror(qffile);
 230:         close(fi);
 231:         return (1);
 232:     }
 233:     if (fstat(fileno(qfi), &statb) < 0) {
 234:         perror(qffile);
 235:         fclose(qfi);
 236:         close(fi);
 237:         return (1);
 238:     }
 239:     quotadev = statb.st_dev;
 240:     if (stat(fsdev, &statb) < 0) {
 241:         perror(fsdev);
 242:         fclose(qfi);
 243:         close(fi);
 244:         return (1);
 245:     }
 246:     if (quotadev != statb.st_rdev) {
 247:         fprintf(stderr, "%s dev (0x%x) mismatch %s dev (0x%x)\n",
 248:             qffile, quotadev, fsdev, statb.st_rdev);
 249:         fclose(qfi);
 250:         close(fi);
 251:         return (1);
 252:     }
 253:     /*
 254: 	 * Must do fdopen(open(qffile, 1), "w") instead of fopen(qffile, "w")
 255: 	 * because fopen(qffile, "w") would truncate the quota file.
 256: 	 */
 257:     fdo = open(qffile, 1);
 258:     if (fdo < 0 || (qfo = fdopen(fdo, "w")) == NULL) {
 259:         perror(qffile);
 260:         if (fdo >= 0)
 261:             close(fdo);
 262:         fclose(qfi);
 263:         close(fi);
 264:         return (1);
 265:     }
 266:     if (quota(Q_SYNC, 0, quotadev, (caddr_t)0) < 0 &&
 267:         errno == EINVAL && !warned && vflag) {
 268:         warned++;
 269:         fprintf(stdout,
 270:             "*** Warning: Quotas are not compiled into this kernel\n");
 271:     }
 272:     sync();
 273:     bread(SBLOCK, (char *)&sblock, SBSIZE);
 274:     ino = 0;
 275:     for (cg = 0; cg < sblock.fs_ncg; cg++) {
 276:         dp = NULL;
 277:         for (i = 0; i < sblock.fs_ipg; i++)
 278:             acct(ginode());
 279:     }
 280:     for (uid = 0; uid <= highuid; uid++) {
 281:         i = fread(&dqbuf, sizeof(struct dqblk), 1, qfi);
 282:         if (i == 0)
 283:             dqbuf = zerodqbuf;
 284:         fup = lookup(uid);
 285:         if (fup == 0)
 286:             fup = &zerofileusage;
 287:         if (dqbuf.dqb_curinodes == fup->fu_usage.du_curinodes &&
 288:             dqbuf.dqb_curblocks == fup->fu_usage.du_curblocks) {
 289:             fup->fu_usage.du_curinodes = 0;
 290:             fup->fu_usage.du_curblocks = 0;
 291:             fseek(qfo, (long)sizeof(struct dqblk), 1);
 292:             continue;
 293:         }
 294:         if (vflag) {
 295:             if (pflag)
 296:                 printf("%s: ", rawdisk);
 297:             if (fup->fu_name[0] != '\0')
 298:                 printf("%-8s fixed:", fup->fu_name);
 299:             else
 300:                 printf("#%-7d fixed:", uid);
 301:             if (dqbuf.dqb_curinodes != fup->fu_usage.du_curinodes)
 302:                 fprintf(stdout, "\tinodes %d -> %d",
 303:                     dqbuf.dqb_curinodes, fup->fu_usage.du_curinodes);
 304:             if (dqbuf.dqb_curblocks != fup->fu_usage.du_curblocks)
 305:                 fprintf(stdout, "\tblocks %d -> %d",
 306:                     dqbuf.dqb_curblocks, fup->fu_usage.du_curblocks);
 307:             fprintf(stdout, "\n");
 308:         }
 309:         dqbuf.dqb_curinodes = fup->fu_usage.du_curinodes;
 310:         dqbuf.dqb_curblocks = fup->fu_usage.du_curblocks;
 311:         fwrite(&dqbuf, sizeof(struct dqblk), 1, qfo);
 312:         quota(Q_SETDUSE, uid, quotadev, &fup->fu_usage);
 313:         fup->fu_usage.du_curinodes = 0;
 314:         fup->fu_usage.du_curblocks = 0;
 315:     }
 316:     fflush(qfo);
 317:     ftruncate(fileno(qfo), (off_t)((highuid + 1) * sizeof(struct dqblk)));
 318:     fclose(qfi);
 319:     fclose(qfo);
 320:     close(fi);
 321:     return (0);
 322: }
 323: 
 324: acct(ip)
 325:     register struct dinode *ip;
 326: {
 327:     register struct fileusage *fup;
 328: 
 329:     if (ip == NULL)
 330:         return;
 331:     if (ip->di_mode == 0)
 332:         return;
 333:     fup = adduid(ip->di_uid);
 334:     fup->fu_usage.du_curinodes++;
 335:     if ((ip->di_mode & IFMT) == IFCHR || (ip->di_mode & IFMT) == IFBLK)
 336:         return;
 337:     fup->fu_usage.du_curblocks += ip->di_blocks;
 338: }
 339: 
 340: oneof(target, list, n)
 341:     char *target, *list[];
 342:     register int n;
 343: {
 344:     register int i;
 345: 
 346:     for (i = 0; i < n; i++)
 347:         if (strcmp(target, list[i]) == 0) {
 348:             done |= 1 << i;
 349:             return (1);
 350:         }
 351:     return (0);
 352: }
 353: 
 354: struct dinode *
 355: ginode()
 356: {
 357:     register unsigned long iblk;
 358: 
 359:     if (dp == NULL || ++dp >= &itab[ITABSZ]) {
 360:         iblk = itod(&sblock, ino);
 361:         bread(fsbtodb(&sblock, iblk), (char *)itab, sizeof itab);
 362:         dp = &itab[ino % INOPB(&sblock)];
 363:     }
 364:     if (ino++ < ROOTINO)
 365:         return(NULL);
 366:     return(dp);
 367: }
 368: 
 369: bread(bno, buf, cnt)
 370:     long unsigned bno;
 371:     char *buf;
 372: {
 373:     extern  off_t lseek();
 374:     register off_t pos;
 375: 
 376:     pos = (off_t)dbtob(bno);
 377:     if (lseek(fi, pos, 0) != pos) {
 378:         perror("lseek");
 379:         exit(1);
 380:     }
 381: 
 382:     if (read(fi, buf, cnt) != cnt) {
 383:         perror("read");
 384:         exit(1);
 385:     }
 386: }
 387: 
 388: struct fileusage *
 389: lookup(uid)
 390:     u_short uid;
 391: {
 392:     register struct fileusage *fup;
 393: 
 394:     for (fup = fuhead[uid % FUHASH]; fup != 0; fup = fup->fu_next)
 395:         if (fup->fu_uid == uid)
 396:             return (fup);
 397:     return ((struct fileusage *)0);
 398: }
 399: 
 400: struct fileusage *
 401: adduid(uid)
 402:     u_short uid;
 403: {
 404:     struct fileusage *fup, **fhp;
 405:     extern char *calloc();
 406: 
 407:     fup = lookup(uid);
 408:     if (fup != 0)
 409:         return (fup);
 410:     fup = (struct fileusage *)calloc(1, sizeof(struct fileusage));
 411:     if (fup == 0) {
 412:         fprintf(stderr, "out of memory for fileusage structures\n");
 413:         exit(1);
 414:     }
 415:     fhp = &fuhead[uid % FUHASH];
 416:     fup->fu_next = *fhp;
 417:     *fhp = fup;
 418:     fup->fu_uid = uid;
 419:     if (uid > highuid)
 420:         highuid = uid;
 421:     return (fup);
 422: }
 423: 
 424: char *
 425: makerawname(name)
 426:     char *name;
 427: {
 428:     register char *cp;
 429:     char tmp, ch, *rindex();
 430:     static char rawname[MAXPATHLEN];
 431: 
 432:     strcpy(rawname, name);
 433:     cp = rindex(rawname, '/');
 434:     if (cp == NULL)
 435:         return (name);
 436:     else
 437:         cp++;
 438:     for (ch = 'r'; *cp != '\0'; ) {
 439:         tmp = *cp;
 440:         *cp++ = ch;
 441:         ch = tmp;
 442:     }
 443:     *cp++ = ch;
 444:     *cp = '\0';
 445:     return (rawname);
 446: }

Defined functions

acct defined in line 324; used 1 times
adduid defined in line 400; used 3 times
bread defined in line 369; used 2 times
chkquota defined in line 203; used 2 times
ginode defined in line 354; used 2 times
lookup defined in line 388; used 4 times
main defined in line 72; never used
makerawname defined in line 424; used 2 times
oneof defined in line 340; used 4 times
preen defined in line 143; used 1 times

Defined variables

aflag defined in line 64; used 6 times
copyright defined in line 8; never used
done defined in line 58; used 2 times
dp defined in line 41; used 5 times
fi defined in line 56; used 10 times
fuhead defined in line 51; used 2 times
highuid defined in line 54; used 4 times
itab defined in line 40; used 4 times
pflag defined in line 65; used 3 times
qfname defined in line 67; used 2 times
quotafile defined in line 68; used 4 times
sccsid defined in line 14; never used
vflag defined in line 63; used 4 times
zerodqbuf defined in line 69; used 1 times
zerofileusage defined in line 70; used 1 times

Defined struct's

fileusage defined in line 44; used 30 times

Defined macros

FUHASH defined in line 50; used 3 times
ITABSZ defined in line 39; used 2 times
LOGINNAMESIZE defined in line 43; used 1 times
  • in line 48
sblock defined in line 37; used 6 times
Last modified: 1985-11-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1711
Valid CSS Valid XHTML 1.0 Strict