quotaon.c revision 78720
11573Srgrimes/*
21573Srgrimes * Copyright (c) 1980, 1990, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Robert Elz at The University of Melbourne.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
16251069Semaste * 3. All advertising materials mentioning features or use of this software
171573Srgrimes *    must display the following acknowledgement:
181573Srgrimes *	This product includes software developed by the University of
191573Srgrimes *	California, Berkeley and its contributors.
201573Srgrimes * 4. Neither the name of the University nor the names of its contributors
211573Srgrimes *    may be used to endorse or promote products derived from this software
221573Srgrimes *    without specific prior written permission.
231573Srgrimes *
241573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3350476Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341573Srgrimes * SUCH DAMAGE.
35103036Swollman */
361573Srgrimes
371573Srgrimes#ifndef lint
381573Srgrimesstatic const char copyright[] =
391573Srgrimes"@(#) Copyright (c) 1980, 1990, 1993\n\
401573Srgrimes	The Regents of the University of California.  All rights reserved.\n";
4159460Sphantom#endif /* not lint */
4259460Sphantom
431573Srgrimes#ifndef lint
4483206Sasmodai#if 0
451573Srgrimesstatic char sccsid[] = "@(#)quotaon.c	8.1 (Berkeley) 6/6/93";
461573Srgrimes#endif
471573Srgrimesstatic const char rcsid[] =
481573Srgrimes  "$FreeBSD: head/usr.sbin/quotaon/quotaon.c 78720 2001-06-24 20:25:23Z dd $";
491573Srgrimes#endif /* not lint */
501573Srgrimes
511573Srgrimes/*
52108040Sru * Turn quota on/off for a filesystem.
531573Srgrimes */
541573Srgrimes#include <sys/param.h>
551573Srgrimes#include <sys/file.h>
56108040Sru#include <sys/mount.h>
571573Srgrimes#include <ufs/ufs/quota.h>
581573Srgrimes#include <err.h>
59103036Swollman#include <fstab.h>
60103036Swollman#include <stdio.h>
61103036Swollman#include <stdlib.h>
62103036Swollman#include <string.h>
63103036Swollman#include <unistd.h>
64103036Swollman
65107387Sruchar *qfname = QUOTAFILENAME;
66107387Sruchar *qfextension[] = INITQFNAMES;
67103036Swollman
68103036Swollmanint	aflag;		/* all file systems */
69103036Swollmanint	gflag;		/* operate on group quotas */
701573Srgrimesint	uflag;		/* operate on user quotas */
711573Srgrimesint	vflag;		/* verbose */
72103036Swollman
731573Srgrimesint hasquota __P((struct fstab *, int, char **));
741573Srgrimesint oneof __P((char *, char *[], int));
751573Srgrimesint quotaonoff __P((struct fstab *fs, int, int, char *));
7660075Sphantomint readonly __P((struct fstab *));
771573Srgrimesstatic void usage __P((void));
781573Srgrimes
791573Srgrimesint
801573Srgrimesmain(argc, argv)
811573Srgrimes	int argc;
82228322Stheraven	char **argv;
831573Srgrimes{
841573Srgrimes	register struct fstab *fs;
851573Srgrimes	char ch, *qfnp, *whoami;
861573Srgrimes	long argnum, done = 0;
871573Srgrimes	int i, offmode = 0, errs = 0;
881573Srgrimes
8973088Sru	whoami = rindex(*argv, '/') + 1;
90	if (whoami == (char *)1)
91		whoami = *argv;
92	if (strcmp(whoami, "quotaoff") == 0)
93		offmode++;
94	else if (strcmp(whoami, "quotaon") != 0)
95		errx(1, "name must be quotaon or quotaoff");
96	while ((ch = getopt(argc, argv, "avug")) != -1) {
97		switch(ch) {
98		case 'a':
99			aflag++;
100			break;
101		case 'g':
102			gflag++;
103			break;
104		case 'u':
105			uflag++;
106			break;
107		case 'v':
108			vflag++;
109			break;
110		default:
111			usage();
112		}
113	}
114	argc -= optind;
115	argv += optind;
116	if (argc <= 0 && !aflag)
117		usage();
118	if (!gflag && !uflag) {
119		gflag++;
120		uflag++;
121	}
122	setfsent();
123	while ((fs = getfsent()) != NULL) {
124		if (strcmp(fs->fs_vfstype, "ufs") ||
125		    strcmp(fs->fs_type, FSTAB_RW))
126			continue;
127		if (aflag) {
128			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
129				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
130			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
131				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
132			continue;
133		}
134		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
135		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
136			done |= 1 << argnum;
137			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
138				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
139			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
140				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
141		}
142	}
143	endfsent();
144	for (i = 0; i < argc; i++)
145		if ((done & (1 << i)) == 0)
146			warnx("%s not found in fstab", argv[i]);
147	exit(errs);
148}
149
150static void
151usage()
152{
153
154	fprintf(stderr, "%s\n%s\n%s\n%s\n",
155		"usage: quotaon [-g] [-u] [-v] -a",
156		"       quotaon [-g] [-u] [-v] filesystem ...",
157		"       quotaoff [-g] [-u] [-v] -a",
158		"       quotaoff [-g] [-u] [-v] filesystem ...");
159	exit(1);
160}
161
162int
163quotaonoff(fs, offmode, type, qfpathname)
164	register struct fstab *fs;
165	int offmode, type;
166	char *qfpathname;
167{
168
169	if (strcmp(fs->fs_file, "/") && readonly(fs))
170		return (1);
171	if (offmode) {
172		if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
173			warn("%s", fs->fs_file);
174			return (1);
175		}
176		if (vflag)
177			printf("%s: quotas turned off\n", fs->fs_file);
178		return (0);
179	}
180	if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
181		warnx("using %s on", qfpathname);
182		warn("%s", fs->fs_file);
183		return (1);
184	}
185	if (vflag)
186		printf("%s: %s quotas turned on\n", fs->fs_file,
187		    qfextension[type]);
188	return (0);
189}
190
191/*
192 * Check to see if target appears in list of size cnt.
193 */
194int
195oneof(target, list, cnt)
196	register char *target, *list[];
197	int cnt;
198{
199	register int i;
200
201	for (i = 0; i < cnt; i++)
202		if (strcmp(target, list[i]) == 0)
203			return (i);
204	return (-1);
205}
206
207/*
208 * Check to see if a particular quota is to be enabled.
209 */
210int
211hasquota(fs, type, qfnamep)
212	register struct fstab *fs;
213	int type;
214	char **qfnamep;
215{
216	register char *opt;
217	char *cp;
218	static char initname, usrname[100], grpname[100];
219	static char buf[BUFSIZ];
220
221	if (!initname) {
222		sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
223		sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
224		initname = 1;
225	}
226	strcpy(buf, fs->fs_mntops);
227	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
228		if ((cp = index(opt, '=')))
229			*cp++ = '\0';
230		if (type == USRQUOTA && strcmp(opt, usrname) == 0)
231			break;
232		if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
233			break;
234	}
235	if (!opt)
236		return (0);
237	if (cp) {
238		*qfnamep = cp;
239		return (1);
240	}
241	(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
242	*qfnamep = buf;
243	return (1);
244}
245
246/*
247 * Verify file system is mounted and not readonly.
248 */
249int
250readonly(fs)
251	register struct fstab *fs;
252{
253	struct statfs fsbuf;
254
255	if (statfs(fs->fs_file, &fsbuf) < 0 ||
256	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
257	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
258		printf("%s: not mounted\n", fs->fs_file);
259		return (1);
260	}
261	if (fsbuf.f_flags & MNT_RDONLY) {
262		printf("%s: mounted read-only\n", fs->fs_file);
263		return (1);
264	}
265	return (0);
266}
267