121520Smckusick /* 221520Smckusick * Copyright (c) 1980 Regents of the University of California. 334372Sbostic * All rights reserved. 434372Sbostic * 534372Sbostic * Redistribution and use in source and binary forms are permitted 634911Sbostic * provided that the above copyright notice and this paragraph are 734911Sbostic * duplicated in all such forms and that any documentation, 834911Sbostic * advertising materials, and other materials related to such 934911Sbostic * distribution and use acknowledge that the software was developed 1034911Sbostic * by the University of California, Berkeley. The name of the 1134911Sbostic * University may not be used to endorse or promote products derived 1234911Sbostic * from this software without specific prior written permission. 1334911Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434911Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534911Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621520Smckusick */ 1721520Smckusick 1812710Smckusick #ifndef lint 1921520Smckusick char copyright[] = 2021520Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 2121520Smckusick All rights reserved.\n"; 2234372Sbostic #endif /* not lint */ 2312710Smckusick 2421520Smckusick #ifndef lint 25*37078Sbostic static char sccsid[] = "@(#)quota.c 5.7 (Berkeley) 03/06/89"; 2634372Sbostic #endif /* not lint */ 2721520Smckusick 2812710Smckusick /* 2912710Smckusick * Disk quota reporting program. 3012710Smckusick */ 31*37078Sbostic #include <sys/param.h> 32*37078Sbostic #include <sys/quota.h> 33*37078Sbostic #include <sys/file.h> 34*37078Sbostic #include <sys/stat.h> 3512710Smckusick #include <stdio.h> 3612710Smckusick #include <fstab.h> 3712710Smckusick #include <ctype.h> 3812710Smckusick #include <pwd.h> 3921392Smckusick #include <errno.h> 4012710Smckusick 4112710Smckusick 4212710Smckusick int qflag; 4312710Smckusick int vflag; 4412710Smckusick int done; 4512710Smckusick int morethanone; 4612711Smckusick char *qfname = "quotas"; 4712710Smckusick 4812710Smckusick main(argc, argv) 4912710Smckusick char *argv[]; 5012710Smckusick { 5112710Smckusick register char *cp; 5221392Smckusick extern int errno; 5312710Smckusick 5426401Slepreau if (quota(Q_SYNC, 0, 0, (caddr_t)0) < 0 && errno == EINVAL) { 5521392Smckusick fprintf(stderr, "There are no quotas on this system\n"); 5621392Smckusick exit(0); 5721392Smckusick } 5812710Smckusick argc--,argv++; 5912710Smckusick while (argc > 0) { 6012710Smckusick if (argv[0][0] == '-') 6112710Smckusick for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 6212710Smckusick 6312710Smckusick case 'v': 6412710Smckusick vflag++; 6512710Smckusick break; 6612710Smckusick 6712710Smckusick case 'q': 6812710Smckusick qflag++; 6912710Smckusick break; 7012710Smckusick 7112710Smckusick default: 7212710Smckusick fprintf(stderr, "quota: %c: unknown option\n", 7312710Smckusick *cp); 7412710Smckusick exit(1); 7512710Smckusick } 7612710Smckusick else 7712710Smckusick break; 7812710Smckusick argc--, argv++; 7912710Smckusick } 8012710Smckusick morethanone = argc > 1; 8112710Smckusick if (argc == 0) { 8212710Smckusick showuid(getuid()); 8312710Smckusick exit(0); 8412710Smckusick } 8512710Smckusick for (; argc > 0; argc--, argv++) { 8612710Smckusick if (alldigits(*argv)) 8712710Smckusick showuid(atoi(*argv)); 8812710Smckusick else 8912710Smckusick showname(*argv); 9012710Smckusick } 9112710Smckusick } 9212710Smckusick 9312710Smckusick showuid(uid) 9412710Smckusick int uid; 9512710Smckusick { 9612710Smckusick struct passwd *pwd = getpwuid(uid); 9712710Smckusick 9812710Smckusick if (pwd == NULL) 9912710Smckusick showquotas(uid, "(no account)"); 10012710Smckusick else 10112710Smckusick showquotas(uid, pwd->pw_name); 10212710Smckusick } 10312710Smckusick 10412710Smckusick showname(name) 10512710Smckusick char *name; 10612710Smckusick { 10712710Smckusick struct passwd *pwd = getpwnam(name); 10812710Smckusick 10912710Smckusick if (pwd == NULL) { 11012710Smckusick fprintf(stderr, "quota: %s: unknown user\n", name); 11112710Smckusick return; 11212710Smckusick } 11312710Smckusick showquotas(pwd->pw_uid, name); 11412710Smckusick } 11512710Smckusick 11612710Smckusick showquotas(uid, name) 11712710Smckusick int uid; 11812710Smckusick char *name; 11912710Smckusick { 12012710Smckusick register struct fstab *fs; 12126401Slepreau register char *msgi, *msgb; 12221392Smckusick register enab = 1; 12321392Smckusick dev_t fsdev; 12421392Smckusick struct stat statb; 12521392Smckusick struct dqblk dqblk; 12621392Smckusick int myuid, fd; 12721392Smckusick char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; 12812710Smckusick 12912710Smckusick myuid = getuid(); 13012710Smckusick if (uid != myuid && myuid != 0) { 13112710Smckusick printf("quota: %s (uid %d): permission denied\n", name, uid); 13212710Smckusick return; 13312710Smckusick } 13412710Smckusick done = 0; 13526401Slepreau (void) setfsent(); 13612710Smckusick while (fs = getfsent()) { 13712710Smckusick if (stat(fs->fs_spec, &statb) < 0) 13812710Smckusick continue; 13926401Slepreau msgi = msgb = (char *) 0; 14012710Smckusick fsdev = statb.st_rdev; 14112711Smckusick (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); 14212711Smckusick if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) 14312710Smckusick continue; 14426401Slepreau if (quota(Q_GETDLIM, uid, fsdev, (caddr_t)&dqblk) != 0) { 14521392Smckusick fd = open(qfilename, O_RDONLY); 14612710Smckusick if (fd < 0) 14712710Smckusick continue; 14826401Slepreau (void) lseek(fd, (off_t)(uid * sizeof (dqblk)), L_SET); 14926401Slepreau switch (read(fd, (char *)&dqblk, sizeof dqblk)) { 15024684Sserge case 0: /* EOF */ 15124684Sserge /* 15224684Sserge * Convert implicit 0 quota (EOF) 15324684Sserge * into an explicit one (zero'ed dqblk). 15424684Sserge */ 15524684Sserge bzero((caddr_t)&dqblk, sizeof dqblk); 15624684Sserge break; 15724684Sserge 15824684Sserge case sizeof dqblk: /* OK */ 15924684Sserge break; 16024684Sserge 16124684Sserge default: /* ERROR */ 16224684Sserge fprintf(stderr, "quota: read error in "); 16324684Sserge perror(qfilename); 16426401Slepreau (void) close(fd); 16512710Smckusick continue; 16612710Smckusick } 16726401Slepreau (void) close(fd); 16824684Sserge if (!vflag && dqblk.dqb_isoftlimit == 0 && 16912710Smckusick dqblk.dqb_bsoftlimit == 0) 17012710Smckusick continue; 17112710Smckusick enab = 0; 17212710Smckusick } 17312710Smckusick if (dqblk.dqb_ihardlimit && 17412710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) 17512710Smckusick msgi = "File count limit reached on %s"; 17612710Smckusick else if (enab && dqblk.dqb_iwarn == 0) 17712710Smckusick msgi = "Out of inode warnings on %s"; 17812710Smckusick else if (dqblk.dqb_isoftlimit && 17912710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) 18012710Smckusick msgi = "Too many files on %s"; 18112710Smckusick if (dqblk.dqb_bhardlimit && 18212710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) 18312710Smckusick msgb = "Block limit reached on %s"; 18412710Smckusick else if (enab && dqblk.dqb_bwarn == 0) 18512710Smckusick msgb = "Out of block warnings on %s"; 18612710Smckusick else if (dqblk.dqb_bsoftlimit && 18712710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) 18812710Smckusick msgb = "Over disc quota on %s"; 18912710Smckusick if (dqblk.dqb_iwarn < MAX_IQ_WARN) 19026401Slepreau (void) sprintf(iwarn, "%d", dqblk.dqb_iwarn); 19112710Smckusick else 19212710Smckusick iwarn[0] = '\0'; 19312710Smckusick if (dqblk.dqb_bwarn < MAX_DQ_WARN) 19426401Slepreau (void) sprintf(dwarn, "%d", dqblk.dqb_bwarn); 19512710Smckusick else 19612710Smckusick dwarn[0] = '\0'; 19712710Smckusick if (qflag) { 19812710Smckusick if (msgi != (char *)0 || msgb != (char *)0) 19912710Smckusick heading(uid, name); 20012710Smckusick if (msgi != (char *)0) 20112710Smckusick xprintf(msgi, fs->fs_file); 20212710Smckusick if (msgb != (char *)0) 20312710Smckusick xprintf(msgb, fs->fs_file); 20412710Smckusick continue; 20512710Smckusick } 20612710Smckusick if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { 20712710Smckusick heading(uid, name); 20813222Ssam printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" 20912710Smckusick , fs->fs_file 21025400Sbloom , dbtob(dqblk.dqb_curblocks) / 1024 21112710Smckusick , (msgb == (char *)0) ? ' ' : '*' 21225400Sbloom , dbtob(dqblk.dqb_bsoftlimit) / 1024 21325400Sbloom , dbtob(dqblk.dqb_bhardlimit) / 1024 21412710Smckusick , dwarn 21512710Smckusick , dqblk.dqb_curinodes 21612710Smckusick , (msgi == (char *)0) ? ' ' : '*' 21712710Smckusick , dqblk.dqb_isoftlimit 21812721Smckusick , dqblk.dqb_ihardlimit 21912710Smckusick , iwarn 22012710Smckusick ); 22112710Smckusick } 22212710Smckusick } 22326401Slepreau (void) endfsent(); 22412710Smckusick if (!done && !qflag) { 22512710Smckusick if (morethanone) 22626401Slepreau (void) putchar('\n'); 22712710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 22812710Smckusick xprintf("none."); 22912710Smckusick } 23024684Sserge xprintf((char *)0); 23112710Smckusick } 23212710Smckusick 23312710Smckusick heading(uid, name) 23412710Smckusick int uid; 23512710Smckusick char *name; 23612710Smckusick { 23712710Smckusick 23812710Smckusick if (done++) 23912710Smckusick return; 24024684Sserge xprintf((char *)0); 24112710Smckusick if (qflag) { 24212710Smckusick if (!morethanone) 24312710Smckusick return; 24412710Smckusick xprintf("User %s (uid %d):", name, uid); 24524684Sserge xprintf((char *)0); 24612710Smckusick return; 24712710Smckusick } 24826401Slepreau (void) putchar('\n'); 24912710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 25024684Sserge xprintf((char *)0); 25113222Ssam printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" 25212710Smckusick , "Filsys" 25312710Smckusick , "current" 25412710Smckusick , "quota" 25512710Smckusick , "limit" 25612710Smckusick , "#warns" 25712710Smckusick , "files" 25812710Smckusick , "quota" 25912710Smckusick , "limit" 26012710Smckusick , "#warns" 26112710Smckusick ); 26212710Smckusick } 26312710Smckusick 26424684Sserge /*VARARGS1*/ 26512710Smckusick xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) 26612710Smckusick char *fmt; 26712710Smckusick { 26812710Smckusick char buf[100]; 26912710Smckusick static int column; 27012710Smckusick 27112710Smckusick if (fmt == 0 && column || column >= 40) { 27226401Slepreau (void) putchar('\n'); 27312710Smckusick column = 0; 27412710Smckusick } 27512710Smckusick if (fmt == 0) 27612710Smckusick return; 27726401Slepreau (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); 27812710Smckusick if (column != 0 && strlen(buf) < 39) 27912710Smckusick while (column++ < 40) 28026401Slepreau (void) putchar(' '); 28112710Smckusick else if (column) { 28226401Slepreau (void) putchar('\n'); 28312710Smckusick column = 0; 28412710Smckusick } 28512710Smckusick printf("%s", buf); 28612710Smckusick column += strlen(buf); 28712710Smckusick } 28812710Smckusick 28912710Smckusick alldigits(s) 29012710Smckusick register char *s; 29112710Smckusick { 29212710Smckusick register c; 29312710Smckusick 29412710Smckusick c = *s++; 29512710Smckusick do { 29612710Smckusick if (!isdigit(c)) 29712710Smckusick return (0); 29812710Smckusick } while (c = *s++); 29912710Smckusick return (1); 30012710Smckusick } 301