quotaon.c revision 1553
140239Sken/*
246733Sken * Copyright (c) 1980, 1990, 1993
340239Sken *	The Regents of the University of California.  All rights reserved.
440239Sken *
540239Sken * This code is derived from software contributed to Berkeley by
640239Sken * Robert Elz at The University of Melbourne.
740239Sken *
840239Sken * Redistribution and use in source and binary forms, with or without
940239Sken * modification, are permitted provided that the following conditions
1040239Sken * are met:
1140239Sken * 1. Redistributions of source code must retain the above copyright
1240239Sken *    notice, this list of conditions and the following disclaimer.
1340239Sken * 2. Redistributions in binary form must reproduce the above copyright
1440239Sken *    notice, this list of conditions and the following disclaimer in the
1540239Sken *    documentation and/or other materials provided with the distribution.
1640239Sken * 3. All advertising materials mentioning features or use of this software
1740239Sken *    must display the following acknowledgement:
1840239Sken *	This product includes software developed by the University of
1940239Sken *	California, Berkeley and its contributors.
2040239Sken * 4. Neither the name of the University nor the names of its contributors
2140239Sken *    may be used to endorse or promote products derived from this software
2240239Sken *    without specific prior written permission.
2340239Sken *
2440239Sken * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2540239Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2640239Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2740239Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2850476Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2940239Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30318139Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3140239Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3279538Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3340239Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3440239Sken * SUCH DAMAGE.
3540239Sken */
3640239Sken
3756460Sasmodai#ifndef lint
3840239Skenstatic char copyright[] =
3940239Sken"@(#) Copyright (c) 1980, 1990, 1993\n\
4068962Sru	The Regents of the University of California.  All rights reserved.\n";
4140239Sken#endif /* not lint */
4279727Sschweikh
4340239Sken#ifndef lint
4440239Skenstatic char sccsid[] = "@(#)quotaon.c	8.1 (Berkeley) 6/6/93";
4568962Sru#endif /* not lint */
4640239Sken
47117011Sru/*
48117011Sru * Turn quota on/off for a filesystem.
4940239Sken */
5040239Sken#include <sys/param.h>
5140239Sken#include <sys/file.h>
5240239Sken#include <sys/mount.h>
5368962Sru#include <ufs/ufs/quota.h>
5440239Sken#include <stdio.h>
5540239Sken#include <fstab.h>
56291716Sken
57291716Skenchar *qfname = QUOTAFILENAME;
5840239Skenchar *qfextension[] = INITQFNAMES;
5940239Sken
6040239Skenint	aflag;		/* all file systems */
61291716Skenint	gflag;		/* operate on group quotas */
62291716Skenint	uflag;		/* operate on user quotas */
6340239Skenint	vflag;		/* verbose */
6440239Sken
6540239Skenmain(argc, argv)
6640239Sken	int argc;
6768962Sru	char **argv;
6840239Sken{
6968962Sru	register struct fstab *fs;
7040239Sken	char ch, *qfnp, *whoami, *rindex();
7140239Sken	long argnum, done = 0;
72291716Sken	int i, offmode = 0, errs = 0;
73291716Sken	extern char *optarg;
7440239Sken	extern int optind;
7540239Sken
76291716Sken	whoami = rindex(*argv, '/') + 1;
77291716Sken	if (whoami == (char *)1)
7846733Sken		whoami = *argv;
79117011Sru	if (strcmp(whoami, "quotaoff") == 0)
80117011Sru		offmode++;
8146733Sken	else if (strcmp(whoami, "quotaon") != 0) {
8246733Sken		fprintf(stderr, "Name must be quotaon or quotaoff not %s\n",
83117011Sru			whoami);
84117011Sru		exit(1);
8546733Sken	}
8646733Sken	while ((ch = getopt(argc, argv, "avug")) != EOF) {
8746733Sken		switch(ch) {
88318139Sken		case 'a':
89318139Sken			aflag++;
90318139Sken			break;
91318139Sken		case 'g':
92318139Sken			gflag++;
93291716Sken			break;
9440239Sken		case 'u':
95117011Sru			uflag++;
96117011Sru			break;
9768962Sru		case 'v':
9840239Sken			vflag++;
99141946Sru			break;
100117011Sru		default:
101117011Sru			usage(whoami);
10240239Sken		}
10340239Sken	}
104291716Sken	argc -= optind;
105291716Sken	argv += optind;
106301719Strasz	if (argc <= 0 && !aflag)
107291716Sken		usage(whoami);
108291716Sken	if (!gflag && !uflag) {
109291716Sken		gflag++;
110292205Sbrueffer		uflag++;
111291716Sken	}
112291716Sken	setfsent();
113291716Sken	while ((fs = getfsent()) != NULL) {
114291716Sken		if (strcmp(fs->fs_vfstype, "ufs") ||
115291716Sken		    strcmp(fs->fs_type, FSTAB_RW))
116291716Sken			continue;
117291716Sken		if (aflag) {
118291716Sken			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
119291716Sken				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
120291716Sken			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
121291716Sken				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
122291716Sken			continue;
123291716Sken		}
124291716Sken		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
125291716Sken		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
126291716Sken			done |= 1 << argnum;
127291716Sken			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
128292205Sbrueffer				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
129292205Sbrueffer			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
130291716Sken				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
131291716Sken		}
132292205Sbrueffer	}
133291716Sken	endfsent();
134291716Sken	for (i = 0; i < argc; i++)
135291716Sken		if ((done & (1 << i)) == 0)
136291716Sken			fprintf(stderr, "%s not found in fstab\n",
137291716Sken				argv[i]);
138291716Sken	exit(errs);
139291716Sken}
140291716Sken
141291716Skenusage(whoami)
142291716Sken	char *whoami;
143291716Sken{
144291716Sken
145291716Sken	fprintf(stderr, "Usage:\n\t%s [-g] [-u] [-v] -a\n", whoami);
146291716Sken	fprintf(stderr, "\t%s [-g] [-u] [-v] filesys ...\n", whoami);
147291716Sken	exit(1);
148291716Sken}
149291716Sken
150291716Skenquotaonoff(fs, offmode, type, qfpathname)
151291716Sken	register struct fstab *fs;
152291716Sken	int offmode, type;
153291716Sken	char *qfpathname;
154291716Sken{
155291716Sken
156291716Sken	if (strcmp(fs->fs_file, "/") && readonly(fs))
157291716Sken		return (1);
158291716Sken	if (offmode) {
159291716Sken		if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
160291716Sken			fprintf(stderr, "quotaoff: ");
161291716Sken			perror(fs->fs_file);
162291716Sken			return (1);
163291716Sken		}
164291716Sken		if (vflag)
165291716Sken			printf("%s: quotas turned off\n", fs->fs_file);
166291716Sken		return (0);
167291716Sken	}
168318139Sken	if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
169318139Sken		fprintf(stderr, "quotaon: using %s on", qfpathname);
170318139Sken		perror(fs->fs_file);
171318139Sken		return (1);
172318139Sken	}
173291716Sken	if (vflag)
174291716Sken		printf("%s: %s quotas turned on\n", fs->fs_file,
175291716Sken		    qfextension[type]);
176291716Sken	return (0);
177291716Sken}
178291716Sken
179291716Sken/*
180301719Strasz * Check to see if target appears in list of size cnt.
181291716Sken */
182291716Skenoneof(target, list, cnt)
183291716Sken	register char *target, *list[];
184292205Sbrueffer	int cnt;
185291716Sken{
186291716Sken	register int i;
187291716Sken
188291716Sken	for (i = 0; i < cnt; i++)
189291716Sken		if (strcmp(target, list[i]) == 0)
190291716Sken			return (i);
191291716Sken	return (-1);
192291716Sken}
193292205Sbrueffer
194292205Sbrueffer/*
195291716Sken * Check to see if a particular quota is to be enabled.
196291716Sken */
197291716Skenhasquota(fs, type, qfnamep)
198291716Sken	register struct fstab *fs;
199291716Sken	int type;
200292205Sbrueffer	char **qfnamep;
201291716Sken{
202291716Sken	register char *opt;
203291716Sken	char *cp, *index(), *strtok();
204291716Sken	static char initname, usrname[100], grpname[100];
205291716Sken	static char buf[BUFSIZ];
206291716Sken
207291716Sken	if (!initname) {
208291716Sken		sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
209291716Sken		sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
210291716Sken		initname = 1;
211291716Sken	}
21240239Sken	strcpy(buf, fs->fs_mntops);
21340239Sken	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
21470466Sru		if (cp = index(opt, '='))
21540239Sken			*cp++ = '\0';
21640239Sken		if (type == USRQUOTA && strcmp(opt, usrname) == 0)
21768962Sru			break;
218117011Sru		if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
219117011Sru			break;
22040239Sken	}
22140239Sken	if (!opt)
22240239Sken		return (0);
22340239Sken	if (cp) {
22440239Sken		*qfnamep = cp;
225291716Sken		return (1);
226291716Sken	}
227291716Sken	(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
22840239Sken	*qfnamep = buf;
229275990Sbrueffer	return (1);
230204705Smav}
231291716Sken
232291716Sken/*
233291716Sken * Verify file system is mounted and not readonly.
234291716Sken */
23540239Skenreadonly(fs)
236291716Sken	register struct fstab *fs;
237291716Sken{
23840239Sken	struct statfs fsbuf;
23940239Sken
24040239Sken	if (statfs(fs->fs_file, &fsbuf) < 0 ||
24140239Sken	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
242267938Sbapt	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
243		printf("%s: not mounted\n", fs->fs_file);
244		return (1);
245	}
246	if (fsbuf.f_flags & MNT_RDONLY) {
247		printf("%s: mounted read-only\n", fs->fs_file);
248		return (1);
249	}
250	return (0);
251}
252