|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980, 1990 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Robert Elz at The University of Melbourne. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted provided ! 9: * that: (1) source distributions retain this entire copyright notice and ! 10: * comment, and (2) distributions including binaries display the following ! 11: * acknowledgement: ``This product includes software developed by the ! 12: * University of California, Berkeley and its contributors'' in the ! 13: * documentation or other materials provided with the distribution and in ! 14: * all advertising materials mentioning features or use of this software. ! 15: * Neither the name of the University nor the names of its contributors may ! 16: * be used to endorse or promote products derived from this software without ! 17: * specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: char copyright[] = ! 25: "@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\ ! 26: All rights reserved.\n"; ! 27: #endif /* not lint */ ! 28: ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)repquota.c 5.10 (Berkeley) 6/1/90"; ! 31: #endif /* not lint */ ! 32: ! 33: /* ! 34: * Quota report ! 35: */ ! 36: #include <sys/param.h> ! 37: #include <sys/stat.h> ! 38: #include <ufs/quota.h> ! 39: #include <fstab.h> ! 40: #include <pwd.h> ! 41: #include <grp.h> ! 42: #include <stdio.h> ! 43: #include <errno.h> ! 44: ! 45: struct fileusage { ! 46: struct fileusage *fu_next; ! 47: struct dqblk fu_dqblk; ! 48: u_long fu_id; ! 49: char fu_name[1]; ! 50: /* actually bigger */ ! 51: }; ! 52: #define FUHASH 1024 /* must be power of two */ ! 53: struct fileusage *fuhead[MAXQUOTAS][FUHASH]; ! 54: struct fileusage *lookup(); ! 55: struct fileusage *addid(); ! 56: u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */ ! 57: ! 58: int vflag; /* verbose */ ! 59: int aflag; /* all file systems */ ! 60: ! 61: main(argc, argv) ! 62: int argc; ! 63: char **argv; ! 64: { ! 65: register struct fstab *fs; ! 66: register struct passwd *pw; ! 67: register struct group *gr; ! 68: int gflag = 0, uflag = 0, errs = 0; ! 69: long i, argnum, done = 0; ! 70: extern char *optarg; ! 71: extern int optind; ! 72: char ch, *qfnp; ! 73: ! 74: while ((ch = getopt(argc, argv, "aguv")) != EOF) { ! 75: switch(ch) { ! 76: case 'a': ! 77: aflag++; ! 78: break; ! 79: case 'g': ! 80: gflag++; ! 81: break; ! 82: case 'u': ! 83: uflag++; ! 84: break; ! 85: case 'v': ! 86: vflag++; ! 87: break; ! 88: default: ! 89: usage(); ! 90: } ! 91: } ! 92: argc -= optind; ! 93: argv += optind; ! 94: if (argc == 0 && !aflag) ! 95: usage(); ! 96: if (!gflag && !uflag) { ! 97: if (aflag) ! 98: gflag++; ! 99: uflag++; ! 100: } ! 101: if (gflag) { ! 102: setgrent(); ! 103: while ((gr = getgrent()) != 0) ! 104: (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name); ! 105: endgrent(); ! 106: } ! 107: if (uflag) { ! 108: setpwent(); ! 109: while ((pw = getpwent()) != 0) ! 110: (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name); ! 111: endpwent(); ! 112: } ! 113: setfsent(); ! 114: while ((fs = getfsent()) != NULL) { ! 115: if (strcmp(fs->fs_vfstype, "ufs")) ! 116: continue; ! 117: if (aflag) { ! 118: if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) ! 119: errs += repquota(fs, GRPQUOTA, qfnp); ! 120: if (uflag && hasquota(fs, USRQUOTA, &qfnp)) ! 121: errs += repquota(fs, USRQUOTA, qfnp); ! 122: continue; ! 123: } ! 124: if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || ! 125: (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { ! 126: done |= 1 << argnum; ! 127: if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) ! 128: errs += repquota(fs, GRPQUOTA, qfnp); ! 129: if (uflag && hasquota(fs, USRQUOTA, &qfnp)) ! 130: errs += repquota(fs, USRQUOTA, qfnp); ! 131: } ! 132: } ! 133: endfsent(); ! 134: for (i = 0; i < argc; i++) ! 135: if ((done & (1 << i)) == 0) ! 136: fprintf(stderr, "%s not found in fstab\n", argv[i]); ! 137: exit(errs); ! 138: } ! 139: ! 140: usage() ! 141: { ! 142: fprintf(stderr, "Usage:\n\t%s\n\t%s\n", ! 143: "repquota [-v] [-g] [-u] -a", ! 144: "repquota [-v] [-g] [-u] filesys ..."); ! 145: exit(1); ! 146: } ! 147: ! 148: repquota(fs, type, qfpathname) ! 149: register struct fstab *fs; ! 150: int type; ! 151: char *qfpathname; ! 152: { ! 153: register struct fileusage *fup; ! 154: FILE *qf; ! 155: u_long id; ! 156: struct dqblk dqbuf; ! 157: char *timeprt(); ! 158: static struct dqblk zerodqblk; ! 159: static int warned = 0; ! 160: static int multiple = 0; ! 161: extern int errno; ! 162: ! 163: if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 && ! 164: errno == EOPNOTSUPP && !warned && vflag) { ! 165: warned++; ! 166: fprintf(stdout, ! 167: "*** Warning: Quotas are not compiled into this kernel\n"); ! 168: } ! 169: if (multiple++) ! 170: printf("\n"); ! 171: if (vflag) ! 172: fprintf(stdout, "*** Report for %s quotas on %s (%s)\n", ! 173: qfextension[type], fs->fs_file, fs->fs_spec); ! 174: if ((qf = fopen(qfpathname, "r")) == NULL) { ! 175: perror(qfpathname); ! 176: return (1); ! 177: } ! 178: for (id = 0; ; id++) { ! 179: fread(&dqbuf, sizeof(struct dqblk), 1, qf); ! 180: if (feof(qf)) ! 181: break; ! 182: if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0) ! 183: continue; ! 184: if ((fup = lookup(id, type)) == 0) ! 185: fup = addid(id, type, (char *)0); ! 186: fup->fu_dqblk = dqbuf; ! 187: } ! 188: fclose(qf); ! 189: printf(" Block limits File limits\n"); ! 190: printf("User used soft hard grace used soft hard grace\n"); ! 191: for (id = 0; id <= highid[type]; id++) { ! 192: fup = lookup(id, type); ! 193: if (fup == 0) ! 194: continue; ! 195: if (fup->fu_dqblk.dqb_curinodes == 0 && ! 196: fup->fu_dqblk.dqb_curblocks == 0) ! 197: continue; ! 198: printf("%-10s", fup->fu_name); ! 199: printf("%c%c%8d%8d%8d%7s", ! 200: fup->fu_dqblk.dqb_bsoftlimit && ! 201: fup->fu_dqblk.dqb_curblocks >= ! 202: fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-', ! 203: fup->fu_dqblk.dqb_isoftlimit && ! 204: fup->fu_dqblk.dqb_curinodes >= ! 205: fup->fu_dqblk.dqb_isoftlimit ? '+' : '-', ! 206: dbtob(fup->fu_dqblk.dqb_curblocks) / 1024, ! 207: dbtob(fup->fu_dqblk.dqb_bsoftlimit) / 1024, ! 208: dbtob(fup->fu_dqblk.dqb_bhardlimit) / 1024, ! 209: fup->fu_dqblk.dqb_bsoftlimit && ! 210: fup->fu_dqblk.dqb_curblocks >= ! 211: fup->fu_dqblk.dqb_bsoftlimit ? ! 212: timeprt(fup->fu_dqblk.dqb_btime) : ""); ! 213: printf(" %6d%6d%6d%7s\n", ! 214: fup->fu_dqblk.dqb_curinodes, ! 215: fup->fu_dqblk.dqb_isoftlimit, ! 216: fup->fu_dqblk.dqb_ihardlimit, ! 217: fup->fu_dqblk.dqb_isoftlimit && ! 218: fup->fu_dqblk.dqb_curinodes >= ! 219: fup->fu_dqblk.dqb_isoftlimit ? ! 220: timeprt(fup->fu_dqblk.dqb_itime) : ""); ! 221: fup->fu_dqblk = zerodqblk; ! 222: } ! 223: return (0); ! 224: } ! 225: ! 226: /* ! 227: * Check to see if target appears in list of size cnt. ! 228: */ ! 229: oneof(target, list, cnt) ! 230: register char *target, *list[]; ! 231: int cnt; ! 232: { ! 233: register int i; ! 234: ! 235: for (i = 0; i < cnt; i++) ! 236: if (strcmp(target, list[i]) == 0) ! 237: return (i); ! 238: return (-1); ! 239: } ! 240: ! 241: /* ! 242: * Check to see if a particular quota is to be enabled. ! 243: */ ! 244: hasquota(fs, type, qfnamep) ! 245: register struct fstab *fs; ! 246: int type; ! 247: char **qfnamep; ! 248: { ! 249: register char *opt; ! 250: char *cp, *index(), *strtok(); ! 251: static char initname, usrname[100], grpname[100]; ! 252: static char buf[BUFSIZ]; ! 253: ! 254: if (!initname) { ! 255: sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); ! 256: sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); ! 257: initname = 1; ! 258: } ! 259: strcpy(buf, fs->fs_mntops); ! 260: for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { ! 261: if (cp = index(opt, '=')) ! 262: *cp++ = '\0'; ! 263: if (type == USRQUOTA && strcmp(opt, usrname) == 0) ! 264: break; ! 265: if (type == GRPQUOTA && strcmp(opt, grpname) == 0) ! 266: break; ! 267: } ! 268: if (!opt) ! 269: return (0); ! 270: if (cp) { ! 271: *qfnamep = cp; ! 272: return (1); ! 273: } ! 274: (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); ! 275: *qfnamep = buf; ! 276: return (1); ! 277: } ! 278: ! 279: /* ! 280: * Routines to manage the file usage table. ! 281: * ! 282: * Lookup an id of a specific type. ! 283: */ ! 284: struct fileusage * ! 285: lookup(id, type) ! 286: u_long id; ! 287: int type; ! 288: { ! 289: register struct fileusage *fup; ! 290: ! 291: for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next) ! 292: if (fup->fu_id == id) ! 293: return (fup); ! 294: return ((struct fileusage *)0); ! 295: } ! 296: ! 297: /* ! 298: * Add a new file usage id if it does not already exist. ! 299: */ ! 300: struct fileusage * ! 301: addid(id, type, name) ! 302: u_long id; ! 303: int type; ! 304: char *name; ! 305: { ! 306: struct fileusage *fup, **fhp; ! 307: int len; ! 308: extern char *calloc(); ! 309: ! 310: if (fup = lookup(id, type)) ! 311: return (fup); ! 312: if (name) ! 313: len = strlen(name); ! 314: else ! 315: len = 10; ! 316: if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) { ! 317: fprintf(stderr, "out of memory for fileusage structures\n"); ! 318: exit(1); ! 319: } ! 320: fhp = &fuhead[type][id & (FUHASH - 1)]; ! 321: fup->fu_next = *fhp; ! 322: *fhp = fup; ! 323: fup->fu_id = id; ! 324: if (id > highid[type]) ! 325: highid[type] = id; ! 326: if (name) { ! 327: bcopy(name, fup->fu_name, len + 1); ! 328: } else { ! 329: sprintf(fup->fu_name, "%u", id); ! 330: } ! 331: return (fup); ! 332: } ! 333: ! 334: /* ! 335: * Calculate the grace period and return a printable string for it. ! 336: */ ! 337: char * ! 338: timeprt(seconds) ! 339: time_t seconds; ! 340: { ! 341: time_t hours, minutes; ! 342: static char buf[20]; ! 343: static time_t now; ! 344: ! 345: if (now == 0) ! 346: time(&now); ! 347: if (now > seconds) ! 348: return ("none"); ! 349: seconds -= now; ! 350: minutes = (seconds + 30) / 60; ! 351: hours = (minutes + 30) / 60; ! 352: if (hours >= 36) { ! 353: sprintf(buf, "%ddays", (hours + 12) / 24); ! 354: return (buf); ! 355: } ! 356: if (minutes >= 60) { ! 357: sprintf(buf, "%2d:%d", minutes / 60, minutes % 60); ! 358: return (buf); ! 359: } ! 360: sprintf(buf, "%2d", minutes); ! 361: return (buf); ! 362: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.