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[] = "@(#)quota.c 5.6 (Berkeley) 06/29/88"; 26 #endif /* not lint */ 27 28 /* 29 * Disk quota reporting program. 30 */ 31 #include <stdio.h> 32 #include <fstab.h> 33 #include <ctype.h> 34 #include <pwd.h> 35 #include <errno.h> 36 37 #include <sys/param.h> 38 #include <sys/quota.h> 39 #include <sys/file.h> 40 #include <sys/stat.h> 41 42 int qflag; 43 int vflag; 44 int done; 45 int morethanone; 46 char *qfname = "quotas"; 47 48 main(argc, argv) 49 char *argv[]; 50 { 51 register char *cp; 52 extern int errno; 53 54 if (quota(Q_SYNC, 0, 0, (caddr_t)0) < 0 && errno == EINVAL) { 55 fprintf(stderr, "There are no quotas on this system\n"); 56 exit(0); 57 } 58 argc--,argv++; 59 while (argc > 0) { 60 if (argv[0][0] == '-') 61 for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 62 63 case 'v': 64 vflag++; 65 break; 66 67 case 'q': 68 qflag++; 69 break; 70 71 default: 72 fprintf(stderr, "quota: %c: unknown option\n", 73 *cp); 74 exit(1); 75 } 76 else 77 break; 78 argc--, argv++; 79 } 80 morethanone = argc > 1; 81 if (argc == 0) { 82 showuid(getuid()); 83 exit(0); 84 } 85 for (; argc > 0; argc--, argv++) { 86 if (alldigits(*argv)) 87 showuid(atoi(*argv)); 88 else 89 showname(*argv); 90 } 91 } 92 93 showuid(uid) 94 int uid; 95 { 96 struct passwd *pwd = getpwuid(uid); 97 98 if (pwd == NULL) 99 showquotas(uid, "(no account)"); 100 else 101 showquotas(uid, pwd->pw_name); 102 } 103 104 showname(name) 105 char *name; 106 { 107 struct passwd *pwd = getpwnam(name); 108 109 if (pwd == NULL) { 110 fprintf(stderr, "quota: %s: unknown user\n", name); 111 return; 112 } 113 showquotas(pwd->pw_uid, name); 114 } 115 116 showquotas(uid, name) 117 int uid; 118 char *name; 119 { 120 register struct fstab *fs; 121 register char *msgi, *msgb; 122 register enab = 1; 123 dev_t fsdev; 124 struct stat statb; 125 struct dqblk dqblk; 126 int myuid, fd; 127 char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; 128 129 myuid = getuid(); 130 if (uid != myuid && myuid != 0) { 131 printf("quota: %s (uid %d): permission denied\n", name, uid); 132 return; 133 } 134 done = 0; 135 (void) setfsent(); 136 while (fs = getfsent()) { 137 if (stat(fs->fs_spec, &statb) < 0) 138 continue; 139 msgi = msgb = (char *) 0; 140 fsdev = statb.st_rdev; 141 (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); 142 if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) 143 continue; 144 if (quota(Q_GETDLIM, uid, fsdev, (caddr_t)&dqblk) != 0) { 145 fd = open(qfilename, O_RDONLY); 146 if (fd < 0) 147 continue; 148 (void) lseek(fd, (off_t)(uid * sizeof (dqblk)), L_SET); 149 switch (read(fd, (char *)&dqblk, sizeof dqblk)) { 150 case 0: /* EOF */ 151 /* 152 * Convert implicit 0 quota (EOF) 153 * into an explicit one (zero'ed dqblk). 154 */ 155 bzero((caddr_t)&dqblk, sizeof dqblk); 156 break; 157 158 case sizeof dqblk: /* OK */ 159 break; 160 161 default: /* ERROR */ 162 fprintf(stderr, "quota: read error in "); 163 perror(qfilename); 164 (void) close(fd); 165 continue; 166 } 167 (void) close(fd); 168 if (!vflag && dqblk.dqb_isoftlimit == 0 && 169 dqblk.dqb_bsoftlimit == 0) 170 continue; 171 enab = 0; 172 } 173 if (dqblk.dqb_ihardlimit && 174 dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) 175 msgi = "File count limit reached on %s"; 176 else if (enab && dqblk.dqb_iwarn == 0) 177 msgi = "Out of inode warnings on %s"; 178 else if (dqblk.dqb_isoftlimit && 179 dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) 180 msgi = "Too many files on %s"; 181 if (dqblk.dqb_bhardlimit && 182 dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) 183 msgb = "Block limit reached on %s"; 184 else if (enab && dqblk.dqb_bwarn == 0) 185 msgb = "Out of block warnings on %s"; 186 else if (dqblk.dqb_bsoftlimit && 187 dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) 188 msgb = "Over disc quota on %s"; 189 if (dqblk.dqb_iwarn < MAX_IQ_WARN) 190 (void) sprintf(iwarn, "%d", dqblk.dqb_iwarn); 191 else 192 iwarn[0] = '\0'; 193 if (dqblk.dqb_bwarn < MAX_DQ_WARN) 194 (void) sprintf(dwarn, "%d", dqblk.dqb_bwarn); 195 else 196 dwarn[0] = '\0'; 197 if (qflag) { 198 if (msgi != (char *)0 || msgb != (char *)0) 199 heading(uid, name); 200 if (msgi != (char *)0) 201 xprintf(msgi, fs->fs_file); 202 if (msgb != (char *)0) 203 xprintf(msgb, fs->fs_file); 204 continue; 205 } 206 if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { 207 heading(uid, name); 208 printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" 209 , fs->fs_file 210 , dbtob(dqblk.dqb_curblocks) / 1024 211 , (msgb == (char *)0) ? ' ' : '*' 212 , dbtob(dqblk.dqb_bsoftlimit) / 1024 213 , dbtob(dqblk.dqb_bhardlimit) / 1024 214 , dwarn 215 , dqblk.dqb_curinodes 216 , (msgi == (char *)0) ? ' ' : '*' 217 , dqblk.dqb_isoftlimit 218 , dqblk.dqb_ihardlimit 219 , iwarn 220 ); 221 } 222 } 223 (void) endfsent(); 224 if (!done && !qflag) { 225 if (morethanone) 226 (void) putchar('\n'); 227 xprintf("Disc quotas for %s (uid %d):", name, uid); 228 xprintf("none."); 229 } 230 xprintf((char *)0); 231 } 232 233 heading(uid, name) 234 int uid; 235 char *name; 236 { 237 238 if (done++) 239 return; 240 xprintf((char *)0); 241 if (qflag) { 242 if (!morethanone) 243 return; 244 xprintf("User %s (uid %d):", name, uid); 245 xprintf((char *)0); 246 return; 247 } 248 (void) putchar('\n'); 249 xprintf("Disc quotas for %s (uid %d):", name, uid); 250 xprintf((char *)0); 251 printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" 252 , "Filsys" 253 , "current" 254 , "quota" 255 , "limit" 256 , "#warns" 257 , "files" 258 , "quota" 259 , "limit" 260 , "#warns" 261 ); 262 } 263 264 /*VARARGS1*/ 265 xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) 266 char *fmt; 267 { 268 char buf[100]; 269 static int column; 270 271 if (fmt == 0 && column || column >= 40) { 272 (void) putchar('\n'); 273 column = 0; 274 } 275 if (fmt == 0) 276 return; 277 (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); 278 if (column != 0 && strlen(buf) < 39) 279 while (column++ < 40) 280 (void) putchar(' '); 281 else if (column) { 282 (void) putchar('\n'); 283 column = 0; 284 } 285 printf("%s", buf); 286 column += strlen(buf); 287 } 288 289 alldigits(s) 290 register char *s; 291 { 292 register c; 293 294 c = *s++; 295 do { 296 if (!isdigit(c)) 297 return (0); 298 } while (c = *s++); 299 return (1); 300 } 301