|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.