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[] = "@(#)repquota.c 5.6 (Berkeley) 06/18/88"; 26 #endif /* not lint */ 27 28 /* 29 * Quota report 30 */ 31 #include <stdio.h> 32 #include <errno.h> 33 #include <sys/param.h> 34 #include <sys/quota.h> 35 #include <sys/stat.h> 36 #include <fstab.h> 37 #include <pwd.h> 38 39 #define LOGINNAMESIZE 8 40 struct fileusage { 41 struct fileusage *fu_next; 42 struct dqblk fu_dqblk; 43 u_short fu_uid; 44 char fu_name[LOGINNAMESIZE + 1]; 45 }; 46 #define FUHASH 997 47 struct fileusage *fuhead[FUHASH]; 48 struct fileusage *lookup(); 49 struct fileusage *adduid(); 50 int highuid; 51 52 long done; 53 struct passwd *getpwent(); 54 55 int vflag; /* verbose */ 56 int aflag; /* all file systems */ 57 58 char *qfname = "quotas"; 59 struct dqblk zerodqblk; 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 fileusage *fup; 68 char quotafile[MAXPATHLEN]; 69 int i, errs = 0; 70 71 again: 72 argc--, argv++; 73 if (argc > 0 && strcmp(*argv, "-v") == 0) { 74 vflag++; 75 goto again; 76 } 77 if (argc > 0 && strcmp(*argv, "-a") == 0) { 78 aflag++; 79 goto again; 80 } 81 if (argc <= 0 && !aflag) { 82 fprintf(stderr, "Usage:\n\t%s\n\t%s\n", 83 "repquota [-v] -a", 84 "repquota [-v] filesys ..."); 85 exit(1); 86 } 87 setpwent(); 88 while ((pw = getpwent()) != 0) { 89 fup = lookup(pw->pw_uid); 90 if (fup == 0) { 91 fup = adduid(pw->pw_uid); 92 strncpy(fup->fu_name, pw->pw_name, sizeof(fup->fu_name)); 93 } 94 } 95 endpwent(); 96 setfsent(); 97 while ((fs = getfsent()) != NULL) { 98 if (aflag && 99 (fs->fs_type == 0 || strcmp(fs->fs_type, "rq") != 0)) 100 continue; 101 if (!aflag && 102 !(oneof(fs->fs_file, argv, argc) || 103 oneof(fs->fs_spec, argv, argc))) 104 continue; 105 (void) sprintf(quotafile, "%s/%s", fs->fs_file, qfname); 106 errs += repquota(fs->fs_spec, fs->fs_file, quotafile); 107 } 108 endfsent(); 109 for (i = 0; i < argc; i++) 110 if ((done & (1 << i)) == 0) 111 fprintf(stderr, "%s not found in /etc/fstab\n", 112 argv[i]); 113 exit(errs); 114 } 115 116 repquota(fsdev, fsfile, qffile) 117 char *fsdev; 118 char *fsfile; 119 char *qffile; 120 { 121 register struct fileusage *fup; 122 FILE *qf; 123 u_short uid; 124 struct dqblk dqbuf; 125 struct stat statb; 126 static int warned = 0; 127 extern int errno; 128 129 if (vflag) 130 fprintf(stdout, "*** Quota report for %s (%s)\n", fsdev, fsfile); 131 qf = fopen(qffile, "r"); 132 if (qf == NULL) { 133 perror(qffile); 134 return (1); 135 } 136 if (fstat(fileno(qf), &statb) < 0) { 137 perror(qffile); 138 fclose(qf); 139 return (1); 140 } 141 if (quota(Q_SYNC, 0, statb.st_dev, 0) < 0 && 142 errno == EINVAL && !warned && vflag) { 143 warned++; 144 fprintf(stdout, 145 "*** Warning: Quotas are not compiled into this kernel\n"); 146 } 147 for (uid = 0; ; uid++) { 148 fread(&dqbuf, sizeof(struct dqblk), 1, qf); 149 if (feof(qf)) 150 break; 151 fup = lookup(uid); 152 if ((fup == 0 || fup->fu_name[0] == 0) && 153 dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0) 154 continue; 155 if (fup == 0) 156 fup = adduid(uid); 157 fup->fu_dqblk = dqbuf; 158 } 159 printf(" Block limits File limits\n"); 160 printf("User used soft hard warn used soft hard warn\n"); 161 for (uid = 0; uid <= highuid; uid++) { 162 fup = lookup(uid); 163 if (fup == 0) 164 continue; 165 if (fup->fu_dqblk.dqb_curinodes == 0 && 166 fup->fu_dqblk.dqb_curblocks == 0) 167 continue; 168 if (fup->fu_name[0] != '\0') 169 printf("%-10s", fup->fu_name); 170 else 171 printf("#%-9d", uid); 172 printf("%c%c%8d%8d%8d %5d %5d %5d %5d %5d\n", 173 fup->fu_dqblk.dqb_bsoftlimit && 174 fup->fu_dqblk.dqb_curblocks >= 175 fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-', 176 fup->fu_dqblk.dqb_isoftlimit && 177 fup->fu_dqblk.dqb_curinodes >= 178 fup->fu_dqblk.dqb_isoftlimit ? '+' : '-', 179 dbtob(fup->fu_dqblk.dqb_curblocks) / 1024, 180 dbtob(fup->fu_dqblk.dqb_bsoftlimit) / 1024, 181 dbtob(fup->fu_dqblk.dqb_bhardlimit) / 1024, 182 fup->fu_dqblk.dqb_bwarn, 183 fup->fu_dqblk.dqb_curinodes, 184 fup->fu_dqblk.dqb_isoftlimit, 185 fup->fu_dqblk.dqb_ihardlimit, 186 fup->fu_dqblk.dqb_iwarn); 187 fup->fu_dqblk = zerodqblk; 188 } 189 fclose(qf); 190 return (0); 191 } 192 193 oneof(target, list, n) 194 char *target, *list[]; 195 register int n; 196 { 197 register int i; 198 199 for (i = 0; i < n; i++) 200 if (strcmp(target, list[i]) == 0) { 201 done |= 1 << i; 202 return (1); 203 } 204 return (0); 205 } 206 207 struct fileusage * 208 lookup(uid) 209 u_short uid; 210 { 211 register struct fileusage *fup; 212 213 for (fup = fuhead[uid % FUHASH]; fup != 0; fup = fup->fu_next) 214 if (fup->fu_uid == uid) 215 return (fup); 216 return ((struct fileusage *)0); 217 } 218 219 struct fileusage * 220 adduid(uid) 221 u_short uid; 222 { 223 struct fileusage *fup, **fhp; 224 extern char *calloc(); 225 226 fup = lookup(uid); 227 if (fup != 0) 228 return (fup); 229 fup = (struct fileusage *)calloc(1, sizeof(struct fileusage)); 230 if (fup == 0) { 231 fprintf(stderr, "out of memory for fileusage structures\n"); 232 exit(1); 233 } 234 fhp = &fuhead[uid % FUHASH]; 235 fup->fu_next = *fhp; 236 *fhp = fup; 237 fup->fu_uid = uid; 238 if (uid > highuid) 239 highuid = uid; 240 return (fup); 241 } 242