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