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