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