121520Smckusick /* 221520Smckusick * Copyright (c) 1980 Regents of the University of California. 3*34372Sbostic * All rights reserved. 4*34372Sbostic * 5*34372Sbostic * Redistribution and use in source and binary forms are permitted 6*34372Sbostic * provided that this notice is preserved and that due credit is given 7*34372Sbostic * to the University of California at Berkeley. The name of the University 8*34372Sbostic * may not be used to endorse or promote products derived from this 9*34372Sbostic * software without specific prior written permission. This software 10*34372Sbostic * is provided ``as is'' without express or implied warranty. 1121520Smckusick */ 1221520Smckusick 1312710Smckusick #ifndef lint 1421520Smckusick char copyright[] = 1521520Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1621520Smckusick All rights reserved.\n"; 17*34372Sbostic #endif /* not lint */ 1812710Smckusick 1921520Smckusick #ifndef lint 20*34372Sbostic static char sccsid[] = "@(#)quota.c 5.5 (Berkeley) 05/20/88"; 21*34372Sbostic #endif /* not lint */ 2221520Smckusick 2312710Smckusick /* 2412710Smckusick * Disk quota reporting program. 2512710Smckusick */ 2612710Smckusick #include <stdio.h> 2712710Smckusick #include <fstab.h> 2812710Smckusick #include <ctype.h> 2912710Smckusick #include <pwd.h> 3021392Smckusick #include <errno.h> 3112710Smckusick 3212710Smckusick #include <sys/param.h> 3312710Smckusick #include <sys/quota.h> 3412710Smckusick #include <sys/file.h> 3512710Smckusick #include <sys/stat.h> 3612710Smckusick 3712710Smckusick int qflag; 3812710Smckusick int vflag; 3912710Smckusick int done; 4012710Smckusick int morethanone; 4112711Smckusick char *qfname = "quotas"; 4212710Smckusick 4312710Smckusick main(argc, argv) 4412710Smckusick char *argv[]; 4512710Smckusick { 4612710Smckusick register char *cp; 4721392Smckusick extern int errno; 4812710Smckusick 4926401Slepreau if (quota(Q_SYNC, 0, 0, (caddr_t)0) < 0 && errno == EINVAL) { 5021392Smckusick fprintf(stderr, "There are no quotas on this system\n"); 5121392Smckusick exit(0); 5221392Smckusick } 5312710Smckusick argc--,argv++; 5412710Smckusick while (argc > 0) { 5512710Smckusick if (argv[0][0] == '-') 5612710Smckusick for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 5712710Smckusick 5812710Smckusick case 'v': 5912710Smckusick vflag++; 6012710Smckusick break; 6112710Smckusick 6212710Smckusick case 'q': 6312710Smckusick qflag++; 6412710Smckusick break; 6512710Smckusick 6612710Smckusick default: 6712710Smckusick fprintf(stderr, "quota: %c: unknown option\n", 6812710Smckusick *cp); 6912710Smckusick exit(1); 7012710Smckusick } 7112710Smckusick else 7212710Smckusick break; 7312710Smckusick argc--, argv++; 7412710Smckusick } 7512710Smckusick morethanone = argc > 1; 7612710Smckusick if (argc == 0) { 7712710Smckusick showuid(getuid()); 7812710Smckusick exit(0); 7912710Smckusick } 8012710Smckusick for (; argc > 0; argc--, argv++) { 8112710Smckusick if (alldigits(*argv)) 8212710Smckusick showuid(atoi(*argv)); 8312710Smckusick else 8412710Smckusick showname(*argv); 8512710Smckusick } 8612710Smckusick } 8712710Smckusick 8812710Smckusick showuid(uid) 8912710Smckusick int uid; 9012710Smckusick { 9112710Smckusick struct passwd *pwd = getpwuid(uid); 9212710Smckusick 9312710Smckusick if (pwd == NULL) 9412710Smckusick showquotas(uid, "(no account)"); 9512710Smckusick else 9612710Smckusick showquotas(uid, pwd->pw_name); 9712710Smckusick } 9812710Smckusick 9912710Smckusick showname(name) 10012710Smckusick char *name; 10112710Smckusick { 10212710Smckusick struct passwd *pwd = getpwnam(name); 10312710Smckusick 10412710Smckusick if (pwd == NULL) { 10512710Smckusick fprintf(stderr, "quota: %s: unknown user\n", name); 10612710Smckusick return; 10712710Smckusick } 10812710Smckusick showquotas(pwd->pw_uid, name); 10912710Smckusick } 11012710Smckusick 11112710Smckusick showquotas(uid, name) 11212710Smckusick int uid; 11312710Smckusick char *name; 11412710Smckusick { 11512710Smckusick register struct fstab *fs; 11626401Slepreau register char *msgi, *msgb; 11721392Smckusick register enab = 1; 11821392Smckusick dev_t fsdev; 11921392Smckusick struct stat statb; 12021392Smckusick struct dqblk dqblk; 12121392Smckusick int myuid, fd; 12221392Smckusick char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; 12312710Smckusick 12412710Smckusick myuid = getuid(); 12512710Smckusick if (uid != myuid && myuid != 0) { 12612710Smckusick printf("quota: %s (uid %d): permission denied\n", name, uid); 12712710Smckusick return; 12812710Smckusick } 12912710Smckusick done = 0; 13026401Slepreau (void) setfsent(); 13112710Smckusick while (fs = getfsent()) { 13212710Smckusick if (stat(fs->fs_spec, &statb) < 0) 13312710Smckusick continue; 13426401Slepreau msgi = msgb = (char *) 0; 13512710Smckusick fsdev = statb.st_rdev; 13612711Smckusick (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); 13712711Smckusick if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) 13812710Smckusick continue; 13926401Slepreau if (quota(Q_GETDLIM, uid, fsdev, (caddr_t)&dqblk) != 0) { 14021392Smckusick fd = open(qfilename, O_RDONLY); 14112710Smckusick if (fd < 0) 14212710Smckusick continue; 14326401Slepreau (void) lseek(fd, (off_t)(uid * sizeof (dqblk)), L_SET); 14426401Slepreau switch (read(fd, (char *)&dqblk, sizeof dqblk)) { 14524684Sserge case 0: /* EOF */ 14624684Sserge /* 14724684Sserge * Convert implicit 0 quota (EOF) 14824684Sserge * into an explicit one (zero'ed dqblk). 14924684Sserge */ 15024684Sserge bzero((caddr_t)&dqblk, sizeof dqblk); 15124684Sserge break; 15224684Sserge 15324684Sserge case sizeof dqblk: /* OK */ 15424684Sserge break; 15524684Sserge 15624684Sserge default: /* ERROR */ 15724684Sserge fprintf(stderr, "quota: read error in "); 15824684Sserge perror(qfilename); 15926401Slepreau (void) close(fd); 16012710Smckusick continue; 16112710Smckusick } 16226401Slepreau (void) close(fd); 16324684Sserge if (!vflag && dqblk.dqb_isoftlimit == 0 && 16412710Smckusick dqblk.dqb_bsoftlimit == 0) 16512710Smckusick continue; 16612710Smckusick enab = 0; 16712710Smckusick } 16812710Smckusick if (dqblk.dqb_ihardlimit && 16912710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) 17012710Smckusick msgi = "File count limit reached on %s"; 17112710Smckusick else if (enab && dqblk.dqb_iwarn == 0) 17212710Smckusick msgi = "Out of inode warnings on %s"; 17312710Smckusick else if (dqblk.dqb_isoftlimit && 17412710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) 17512710Smckusick msgi = "Too many files on %s"; 17612710Smckusick if (dqblk.dqb_bhardlimit && 17712710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) 17812710Smckusick msgb = "Block limit reached on %s"; 17912710Smckusick else if (enab && dqblk.dqb_bwarn == 0) 18012710Smckusick msgb = "Out of block warnings on %s"; 18112710Smckusick else if (dqblk.dqb_bsoftlimit && 18212710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) 18312710Smckusick msgb = "Over disc quota on %s"; 18412710Smckusick if (dqblk.dqb_iwarn < MAX_IQ_WARN) 18526401Slepreau (void) sprintf(iwarn, "%d", dqblk.dqb_iwarn); 18612710Smckusick else 18712710Smckusick iwarn[0] = '\0'; 18812710Smckusick if (dqblk.dqb_bwarn < MAX_DQ_WARN) 18926401Slepreau (void) sprintf(dwarn, "%d", dqblk.dqb_bwarn); 19012710Smckusick else 19112710Smckusick dwarn[0] = '\0'; 19212710Smckusick if (qflag) { 19312710Smckusick if (msgi != (char *)0 || msgb != (char *)0) 19412710Smckusick heading(uid, name); 19512710Smckusick if (msgi != (char *)0) 19612710Smckusick xprintf(msgi, fs->fs_file); 19712710Smckusick if (msgb != (char *)0) 19812710Smckusick xprintf(msgb, fs->fs_file); 19912710Smckusick continue; 20012710Smckusick } 20112710Smckusick if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { 20212710Smckusick heading(uid, name); 20313222Ssam printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" 20412710Smckusick , fs->fs_file 20525400Sbloom , dbtob(dqblk.dqb_curblocks) / 1024 20612710Smckusick , (msgb == (char *)0) ? ' ' : '*' 20725400Sbloom , dbtob(dqblk.dqb_bsoftlimit) / 1024 20825400Sbloom , dbtob(dqblk.dqb_bhardlimit) / 1024 20912710Smckusick , dwarn 21012710Smckusick , dqblk.dqb_curinodes 21112710Smckusick , (msgi == (char *)0) ? ' ' : '*' 21212710Smckusick , dqblk.dqb_isoftlimit 21312721Smckusick , dqblk.dqb_ihardlimit 21412710Smckusick , iwarn 21512710Smckusick ); 21612710Smckusick } 21712710Smckusick } 21826401Slepreau (void) endfsent(); 21912710Smckusick if (!done && !qflag) { 22012710Smckusick if (morethanone) 22126401Slepreau (void) putchar('\n'); 22212710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 22312710Smckusick xprintf("none."); 22412710Smckusick } 22524684Sserge xprintf((char *)0); 22612710Smckusick } 22712710Smckusick 22812710Smckusick heading(uid, name) 22912710Smckusick int uid; 23012710Smckusick char *name; 23112710Smckusick { 23212710Smckusick 23312710Smckusick if (done++) 23412710Smckusick return; 23524684Sserge xprintf((char *)0); 23612710Smckusick if (qflag) { 23712710Smckusick if (!morethanone) 23812710Smckusick return; 23912710Smckusick xprintf("User %s (uid %d):", name, uid); 24024684Sserge xprintf((char *)0); 24112710Smckusick return; 24212710Smckusick } 24326401Slepreau (void) putchar('\n'); 24412710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 24524684Sserge xprintf((char *)0); 24613222Ssam printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" 24712710Smckusick , "Filsys" 24812710Smckusick , "current" 24912710Smckusick , "quota" 25012710Smckusick , "limit" 25112710Smckusick , "#warns" 25212710Smckusick , "files" 25312710Smckusick , "quota" 25412710Smckusick , "limit" 25512710Smckusick , "#warns" 25612710Smckusick ); 25712710Smckusick } 25812710Smckusick 25924684Sserge /*VARARGS1*/ 26012710Smckusick xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) 26112710Smckusick char *fmt; 26212710Smckusick { 26312710Smckusick char buf[100]; 26412710Smckusick static int column; 26512710Smckusick 26612710Smckusick if (fmt == 0 && column || column >= 40) { 26726401Slepreau (void) putchar('\n'); 26812710Smckusick column = 0; 26912710Smckusick } 27012710Smckusick if (fmt == 0) 27112710Smckusick return; 27226401Slepreau (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); 27312710Smckusick if (column != 0 && strlen(buf) < 39) 27412710Smckusick while (column++ < 40) 27526401Slepreau (void) putchar(' '); 27612710Smckusick else if (column) { 27726401Slepreau (void) putchar('\n'); 27812710Smckusick column = 0; 27912710Smckusick } 28012710Smckusick printf("%s", buf); 28112710Smckusick column += strlen(buf); 28212710Smckusick } 28312710Smckusick 28412710Smckusick alldigits(s) 28512710Smckusick register char *s; 28612710Smckusick { 28712710Smckusick register c; 28812710Smckusick 28912710Smckusick c = *s++; 29012710Smckusick do { 29112710Smckusick if (!isdigit(c)) 29212710Smckusick return (0); 29312710Smckusick } while (c = *s++); 29412710Smckusick return (1); 29512710Smckusick } 296