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