|
|
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[] = "@(#)quota.c 5.11 (Berkeley) 6/1/90"; ! 31: #endif /* not lint */ ! 32: ! 33: /* ! 34: * Disk quota reporting program. ! 35: */ ! 36: #include <sys/param.h> ! 37: #include <sys/file.h> ! 38: #include <sys/stat.h> ! 39: #include <ufs/quota.h> ! 40: #include <stdio.h> ! 41: #include <fstab.h> ! 42: #include <ctype.h> ! 43: #include <pwd.h> ! 44: #include <grp.h> ! 45: #include <errno.h> ! 46: ! 47: struct quotause { ! 48: struct quotause *next; ! 49: long flags; ! 50: struct dqblk dqblk; ! 51: char fsname[MAXPATHLEN + 1]; ! 52: } *getprivs(); ! 53: #define FOUND 0x01 ! 54: ! 55: int qflag; ! 56: int vflag; ! 57: ! 58: main(argc, argv) ! 59: char *argv[]; ! 60: { ! 61: int ngroups, gidset[NGROUPS]; ! 62: int i, gflag = 0, uflag = 0; ! 63: char ch; ! 64: extern char *optarg; ! 65: extern int optind, errno; ! 66: ! 67: if (quotactl("/", 0, 0, (caddr_t)0) < 0 && errno == EOPNOTSUPP) { ! 68: fprintf(stderr, "There are no quotas on this system\n"); ! 69: exit(0); ! 70: } ! 71: while ((ch = getopt(argc, argv, "ugvq")) != EOF) { ! 72: switch(ch) { ! 73: case 'g': ! 74: gflag++; ! 75: break; ! 76: case 'u': ! 77: uflag++; ! 78: break; ! 79: case 'v': ! 80: vflag++; ! 81: break; ! 82: case 'q': ! 83: qflag++; ! 84: break; ! 85: default: ! 86: usage(); ! 87: } ! 88: } ! 89: argc -= optind; ! 90: argv += optind; ! 91: if (!uflag && !gflag) ! 92: uflag++; ! 93: if (argc == 0) { ! 94: if (uflag) ! 95: showuid(getuid()); ! 96: if (gflag) { ! 97: ngroups = getgroups(NGROUPS, gidset); ! 98: if (ngroups < 0) { ! 99: perror("quota: getgroups"); ! 100: exit(1); ! 101: } ! 102: for (i = 1; i < ngroups; i++) ! 103: showgid(gidset[i]); ! 104: } ! 105: exit(0); ! 106: } ! 107: if (uflag && gflag) ! 108: usage(); ! 109: if (uflag) { ! 110: for (; argc > 0; argc--, argv++) { ! 111: if (alldigits(*argv)) ! 112: showuid(atoi(*argv)); ! 113: else ! 114: showusrname(*argv); ! 115: } ! 116: exit(0); ! 117: } ! 118: if (gflag) { ! 119: for (; argc > 0; argc--, argv++) { ! 120: if (alldigits(*argv)) ! 121: showgid(atoi(*argv)); ! 122: else ! 123: showgrpname(*argv); ! 124: } ! 125: exit(0); ! 126: } ! 127: } ! 128: ! 129: usage() ! 130: { ! 131: ! 132: fprintf(stderr, "%s\n%s\n%s\n", ! 133: "Usage: quota [-guqv]", ! 134: "\tquota [-qv] -u username ...", ! 135: "\tquota [-qv] -g groupname ..."); ! 136: exit(1); ! 137: } ! 138: ! 139: /* ! 140: * Print out quotas for a specified user identifier. ! 141: */ ! 142: showuid(uid) ! 143: u_long uid; ! 144: { ! 145: struct passwd *pwd = getpwuid(uid); ! 146: u_long myuid; ! 147: char *name; ! 148: ! 149: if (pwd == NULL) ! 150: name = "(no account)"; ! 151: else ! 152: name = pwd->pw_name; ! 153: myuid = getuid(); ! 154: if (uid != myuid && myuid != 0) { ! 155: printf("quota: %s (uid %d): permission denied\n", name, uid); ! 156: return; ! 157: } ! 158: showquotas(USRQUOTA, uid, name); ! 159: } ! 160: ! 161: /* ! 162: * Print out quotas for a specifed user name. ! 163: */ ! 164: showusrname(name) ! 165: char *name; ! 166: { ! 167: struct passwd *pwd = getpwnam(name); ! 168: u_long myuid; ! 169: ! 170: if (pwd == NULL) { ! 171: fprintf(stderr, "quota: %s: unknown user\n", name); ! 172: return; ! 173: } ! 174: myuid = getuid(); ! 175: if (pwd->pw_uid != myuid && myuid != 0) { ! 176: fprintf(stderr, "quota: %s (uid %d): permission denied\n", ! 177: name, pwd->pw_uid); ! 178: return; ! 179: } ! 180: showquotas(USRQUOTA, pwd->pw_uid, name); ! 181: } ! 182: ! 183: /* ! 184: * Print out quotas for a specified group identifier. ! 185: */ ! 186: showgid(gid) ! 187: u_long gid; ! 188: { ! 189: struct group *grp = getgrgid(gid); ! 190: int ngroups, gidset[NGROUPS]; ! 191: register int i; ! 192: char *name; ! 193: ! 194: if (grp == NULL) ! 195: name = "(no entry)"; ! 196: else ! 197: name = grp->gr_name; ! 198: ngroups = getgroups(NGROUPS, gidset); ! 199: if (ngroups < 0) { ! 200: perror("quota: getgroups"); ! 201: return; ! 202: } ! 203: for (i = 1; i < ngroups; i++) ! 204: if (gid == gidset[i]) ! 205: break; ! 206: if (i >= ngroups && getuid() != 0) { ! 207: fprintf(stderr, "quota: %s (gid %d): permission denied\n", ! 208: name, gid); ! 209: return; ! 210: } ! 211: showquotas(GRPQUOTA, gid, name); ! 212: } ! 213: ! 214: /* ! 215: * Print out quotas for a specifed group name. ! 216: */ ! 217: showgrpname(name) ! 218: char *name; ! 219: { ! 220: struct group *grp = getgrnam(name); ! 221: int ngroups, gidset[NGROUPS]; ! 222: register int i; ! 223: ! 224: if (grp == NULL) { ! 225: fprintf(stderr, "quota: %s: unknown group\n", name); ! 226: return; ! 227: } ! 228: ngroups = getgroups(NGROUPS, gidset); ! 229: if (ngroups < 0) { ! 230: perror("quota: getgroups"); ! 231: return; ! 232: } ! 233: for (i = 1; i < ngroups; i++) ! 234: if (grp->gr_gid == gidset[i]) ! 235: break; ! 236: if (i >= ngroups && getuid() != 0) { ! 237: fprintf(stderr, "quota: %s (gid %d): permission denied\n", ! 238: name, grp->gr_gid); ! 239: return; ! 240: } ! 241: showquotas(GRPQUOTA, grp->gr_gid, name); ! 242: } ! 243: ! 244: showquotas(type, id, name) ! 245: int type; ! 246: u_long id; ! 247: char *name; ! 248: { ! 249: register struct quotause *qup; ! 250: struct quotause *quplist, *getprivs(); ! 251: char *msgi, *msgb, *timeprt(); ! 252: int myuid, fd, lines = 0; ! 253: static int first; ! 254: static time_t now; ! 255: ! 256: if (now == 0) ! 257: time(&now); ! 258: quplist = getprivs(id, type); ! 259: for (qup = quplist; qup; qup = qup->next) { ! 260: if (!vflag && ! 261: qup->dqblk.dqb_isoftlimit == 0 && ! 262: qup->dqblk.dqb_ihardlimit == 0 && ! 263: qup->dqblk.dqb_bsoftlimit == 0 && ! 264: qup->dqblk.dqb_bhardlimit == 0) ! 265: continue; ! 266: msgi = (char *)0; ! 267: if (qup->dqblk.dqb_ihardlimit && ! 268: qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit) ! 269: msgi = "File limit reached on"; ! 270: else if (qup->dqblk.dqb_isoftlimit && ! 271: qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit) ! 272: if (qup->dqblk.dqb_itime > now) ! 273: msgi = "In file grace period on"; ! 274: else ! 275: msgi = "Over file quota on"; ! 276: msgb = (char *)0; ! 277: if (qup->dqblk.dqb_bhardlimit && ! 278: qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit) ! 279: msgb = "Block limit reached on"; ! 280: else if (qup->dqblk.dqb_bsoftlimit && ! 281: qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit) ! 282: if (qup->dqblk.dqb_btime > now) ! 283: msgb = "In block grace period on"; ! 284: else ! 285: msgb = "Over block quota on"; ! 286: if (qflag) { ! 287: if ((msgi != (char *)0 || msgb != (char *)0) && ! 288: lines++ == 0) ! 289: heading(type, id, name, ""); ! 290: if (msgi != (char *)0) ! 291: printf("\t%s %s\n", msgi, qup->fsname); ! 292: if (msgb != (char *)0) ! 293: printf("\t%s %s\n", msgb, qup->fsname); ! 294: continue; ! 295: } ! 296: if (vflag || ! 297: qup->dqblk.dqb_curblocks || ! 298: qup->dqblk.dqb_curinodes) { ! 299: if (lines++ == 0) ! 300: heading(type, id, name, ""); ! 301: printf("%15s%8d%c%7d%8d%8s" ! 302: , qup->fsname ! 303: , dbtob(qup->dqblk.dqb_curblocks) / 1024 ! 304: , (msgb == (char *)0) ? ' ' : '*' ! 305: , dbtob(qup->dqblk.dqb_bsoftlimit) / 1024 ! 306: , dbtob(qup->dqblk.dqb_bhardlimit) / 1024 ! 307: , (msgb == (char *)0) ? "" ! 308: : timeprt(qup->dqblk.dqb_btime)); ! 309: printf("%8d%c%7d%8d%8s\n" ! 310: , qup->dqblk.dqb_curinodes ! 311: , (msgi == (char *)0) ? ' ' : '*' ! 312: , qup->dqblk.dqb_isoftlimit ! 313: , qup->dqblk.dqb_ihardlimit ! 314: , (msgi == (char *)0) ? "" ! 315: : timeprt(qup->dqblk.dqb_itime) ! 316: ); ! 317: continue; ! 318: } ! 319: } ! 320: if (!qflag && lines == 0) ! 321: heading(type, id, name, "none"); ! 322: } ! 323: ! 324: heading(type, id, name, tag) ! 325: int type; ! 326: u_long id; ! 327: char *name, *tag; ! 328: { ! 329: ! 330: printf("Disk quotas for %s %s (%cid %d): %s\n", qfextension[type], ! 331: name, *qfextension[type], id, tag); ! 332: if (!qflag && tag[0] == '\0') { ! 333: printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n" ! 334: , "Filesystem" ! 335: , "blocks" ! 336: , "quota" ! 337: , "limit" ! 338: , "grace" ! 339: , "files" ! 340: , "quota" ! 341: , "limit" ! 342: , "grace" ! 343: ); ! 344: } ! 345: } ! 346: ! 347: /* ! 348: * Calculate the grace period and return a printable string for it. ! 349: */ ! 350: char * ! 351: timeprt(seconds) ! 352: time_t seconds; ! 353: { ! 354: time_t hours, minutes; ! 355: static char buf[20]; ! 356: static time_t now; ! 357: ! 358: if (now == 0) ! 359: time(&now); ! 360: if (now > seconds) ! 361: return ("none"); ! 362: seconds -= now; ! 363: minutes = (seconds + 30) / 60; ! 364: hours = (minutes + 30) / 60; ! 365: if (hours >= 36) { ! 366: sprintf(buf, "%ddays", (hours + 12) / 24); ! 367: return (buf); ! 368: } ! 369: if (minutes >= 60) { ! 370: sprintf(buf, "%2d:%d", minutes / 60, minutes % 60); ! 371: return (buf); ! 372: } ! 373: sprintf(buf, "%2d", minutes); ! 374: return (buf); ! 375: } ! 376: ! 377: /* ! 378: * Collect the requested quota information. ! 379: */ ! 380: struct quotause * ! 381: getprivs(id, quotatype) ! 382: register long id; ! 383: int quotatype; ! 384: { ! 385: register struct fstab *fs; ! 386: register struct quotause *qup, *quptail; ! 387: struct quotause *quphead; ! 388: char *qfpathname; ! 389: int qcmd, fd; ! 390: ! 391: setfsent(); ! 392: quphead = (struct quotause *)0; ! 393: qcmd = QCMD(Q_GETQUOTA, quotatype); ! 394: while (fs = getfsent()) { ! 395: if (strcmp(fs->fs_vfstype, "ufs")) ! 396: continue; ! 397: if (!hasquota(fs, quotatype, &qfpathname)) ! 398: continue; ! 399: if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) { ! 400: fprintf(stderr, "quota: out of memory\n"); ! 401: exit(2); ! 402: } ! 403: if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { ! 404: if ((fd = open(qfpathname, O_RDONLY)) < 0) { ! 405: perror(qfpathname); ! 406: free(qup); ! 407: continue; ! 408: } ! 409: lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET); ! 410: switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { ! 411: case 0: /* EOF */ ! 412: /* ! 413: * Convert implicit 0 quota (EOF) ! 414: * into an explicit one (zero'ed dqblk) ! 415: */ ! 416: bzero((caddr_t)&qup->dqblk, ! 417: sizeof(struct dqblk)); ! 418: break; ! 419: ! 420: case sizeof(struct dqblk): /* OK */ ! 421: break; ! 422: ! 423: default: /* ERROR */ ! 424: fprintf(stderr, "quota: read error"); ! 425: perror(qfpathname); ! 426: close(fd); ! 427: free(qup); ! 428: continue; ! 429: } ! 430: close(fd); ! 431: } ! 432: strcpy(qup->fsname, fs->fs_file); ! 433: if (quphead == NULL) ! 434: quphead = qup; ! 435: else ! 436: quptail->next = qup; ! 437: quptail = qup; ! 438: qup->next = 0; ! 439: } ! 440: endfsent(); ! 441: return (quphead); ! 442: } ! 443: ! 444: /* ! 445: * Check to see if a particular quota is to be enabled. ! 446: */ ! 447: hasquota(fs, type, qfnamep) ! 448: register struct fstab *fs; ! 449: int type; ! 450: char **qfnamep; ! 451: { ! 452: register char *opt; ! 453: char *cp, *index(), *strtok(); ! 454: static char initname, usrname[100], grpname[100]; ! 455: static char buf[BUFSIZ]; ! 456: ! 457: if (!initname) { ! 458: sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); ! 459: sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); ! 460: initname = 1; ! 461: } ! 462: strcpy(buf, fs->fs_mntops); ! 463: for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { ! 464: if (cp = index(opt, '=')) ! 465: *cp++ = '\0'; ! 466: if (type == USRQUOTA && strcmp(opt, usrname) == 0) ! 467: break; ! 468: if (type == GRPQUOTA && strcmp(opt, grpname) == 0) ! 469: break; ! 470: } ! 471: if (!opt) ! 472: return (0); ! 473: if (cp) { ! 474: *qfnamep = cp; ! 475: return (1); ! 476: } ! 477: (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); ! 478: *qfnamep = buf; ! 479: return (1); ! 480: } ! 481: ! 482: alldigits(s) ! 483: register char *s; ! 484: { ! 485: register c; ! 486: ! 487: c = *s++; ! 488: do { ! 489: if (!isdigit(c)) ! 490: return (0); ! 491: } while (c = *s++); ! 492: return (1); ! 493: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.