quotaon.c revision 166212
11553Srgrimes/*
21553Srgrimes * Copyright (c) 1980, 1990, 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * This code is derived from software contributed to Berkeley by
61553Srgrimes * Robert Elz at The University of Melbourne.
71553Srgrimes *
81553Srgrimes * Redistribution and use in source and binary forms, with or without
91553Srgrimes * modification, are permitted provided that the following conditions
101553Srgrimes * are met:
111553Srgrimes * 1. Redistributions of source code must retain the above copyright
121553Srgrimes *    notice, this list of conditions and the following disclaimer.
131553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141553Srgrimes *    notice, this list of conditions and the following disclaimer in the
151553Srgrimes *    documentation and/or other materials provided with the distribution.
161553Srgrimes * 4. Neither the name of the University nor the names of its contributors
171553Srgrimes *    may be used to endorse or promote products derived from this software
181553Srgrimes *    without specific prior written permission.
191553Srgrimes *
201553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301553Srgrimes * SUCH DAMAGE.
311553Srgrimes */
321553Srgrimes
33114601Sobrien#if 0
341553Srgrimes#ifndef lint
3530371Scharnierstatic const char copyright[] =
361553Srgrimes"@(#) Copyright (c) 1980, 1990, 1993\n\
371553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381553Srgrimes#endif /* not lint */
391553Srgrimes
401553Srgrimes#ifndef lint
411553Srgrimesstatic char sccsid[] = "@(#)quotaon.c	8.1 (Berkeley) 6/6/93";
42114601Sobrien#endif /* not lint */
4330371Scharnier#endif
44114601Sobrien#include <sys/cdefs.h>
45114601Sobrien__FBSDID("$FreeBSD: head/usr.sbin/quotaon/quotaon.c 166212 2007-01-24 22:52:32Z mpp $");
461553Srgrimes
471553Srgrimes/*
481553Srgrimes * Turn quota on/off for a filesystem.
491553Srgrimes */
501553Srgrimes#include <sys/param.h>
511553Srgrimes#include <sys/file.h>
521553Srgrimes#include <sys/mount.h>
531553Srgrimes#include <ufs/ufs/quota.h>
5430371Scharnier#include <err.h>
5530371Scharnier#include <fstab.h>
561553Srgrimes#include <stdio.h>
5778720Sdd#include <stdlib.h>
5830371Scharnier#include <string.h>
5930371Scharnier#include <unistd.h>
601553Srgrimes
6199822Salfredconst char *qfname = QUOTAFILENAME;
6299822Salfredconst char *qfextension[] = INITQFNAMES;
631553Srgrimes
6496705Strhodesint	aflag;		/* all filesystems */
651553Srgrimesint	gflag;		/* operate on group quotas */
661553Srgrimesint	uflag;		/* operate on user quotas */
671553Srgrimesint	vflag;		/* verbose */
681553Srgrimes
6999822Salfredint hasquota(struct fstab *, int, char **);
7099822Salfredint oneof(char *, char *[], int);
7199822Salfredint quotaonoff(struct fstab *fs, int, int, char *);
7299822Salfredint readonly(struct fstab *);
7399822Salfredstatic void usage(void);
7430371Scharnier
7530371Scharnierint
7699822Salfredmain(int argc, char **argv)
771553Srgrimes{
781553Srgrimes	register struct fstab *fs;
79124830Sgrehan	char *qfnp, *whoami;
801553Srgrimes	long argnum, done = 0;
81124830Sgrehan	int ch, i, offmode = 0, errs = 0;
821553Srgrimes
831553Srgrimes	whoami = rindex(*argv, '/') + 1;
841553Srgrimes	if (whoami == (char *)1)
851553Srgrimes		whoami = *argv;
861553Srgrimes	if (strcmp(whoami, "quotaoff") == 0)
871553Srgrimes		offmode++;
8830371Scharnier	else if (strcmp(whoami, "quotaon") != 0)
8930371Scharnier		errx(1, "name must be quotaon or quotaoff");
9024428Simp	while ((ch = getopt(argc, argv, "avug")) != -1) {
911553Srgrimes		switch(ch) {
921553Srgrimes		case 'a':
931553Srgrimes			aflag++;
941553Srgrimes			break;
951553Srgrimes		case 'g':
961553Srgrimes			gflag++;
971553Srgrimes			break;
981553Srgrimes		case 'u':
991553Srgrimes			uflag++;
1001553Srgrimes			break;
1011553Srgrimes		case 'v':
1021553Srgrimes			vflag++;
1031553Srgrimes			break;
1041553Srgrimes		default:
10530371Scharnier			usage();
1061553Srgrimes		}
1071553Srgrimes	}
1081553Srgrimes	argc -= optind;
1091553Srgrimes	argv += optind;
1101553Srgrimes	if (argc <= 0 && !aflag)
11130371Scharnier		usage();
1121553Srgrimes	if (!gflag && !uflag) {
1131553Srgrimes		gflag++;
1141553Srgrimes		uflag++;
1151553Srgrimes	}
1161553Srgrimes	setfsent();
1171553Srgrimes	while ((fs = getfsent()) != NULL) {
1181553Srgrimes		if (strcmp(fs->fs_vfstype, "ufs") ||
1191553Srgrimes		    strcmp(fs->fs_type, FSTAB_RW))
1201553Srgrimes			continue;
1211553Srgrimes		if (aflag) {
1221553Srgrimes			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
1231553Srgrimes				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
1241553Srgrimes			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
1251553Srgrimes				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
1261553Srgrimes			continue;
1271553Srgrimes		}
1281553Srgrimes		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
1291553Srgrimes		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
1301553Srgrimes			done |= 1 << argnum;
1311553Srgrimes			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
1321553Srgrimes				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
1331553Srgrimes			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
1341553Srgrimes				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
1351553Srgrimes		}
1361553Srgrimes	}
1371553Srgrimes	endfsent();
1381553Srgrimes	for (i = 0; i < argc; i++)
1391553Srgrimes		if ((done & (1 << i)) == 0)
14030371Scharnier			warnx("%s not found in fstab", argv[i]);
1411553Srgrimes	exit(errs);
1421553Srgrimes}
1431553Srgrimes
14430371Scharnierstatic void
14530371Scharnierusage()
1461553Srgrimes{
1471553Srgrimes
14830371Scharnier	fprintf(stderr, "%s\n%s\n%s\n%s\n",
14930371Scharnier		"usage: quotaon [-g] [-u] [-v] -a",
15030371Scharnier		"       quotaon [-g] [-u] [-v] filesystem ...",
15130371Scharnier		"       quotaoff [-g] [-u] [-v] -a",
15230371Scharnier		"       quotaoff [-g] [-u] [-v] filesystem ...");
1531553Srgrimes	exit(1);
1541553Srgrimes}
1551553Srgrimes
15630371Scharnierint
1571553Srgrimesquotaonoff(fs, offmode, type, qfpathname)
1581553Srgrimes	register struct fstab *fs;
1591553Srgrimes	int offmode, type;
1601553Srgrimes	char *qfpathname;
1611553Srgrimes{
1621553Srgrimes
1631553Srgrimes	if (strcmp(fs->fs_file, "/") && readonly(fs))
1641553Srgrimes		return (1);
1651553Srgrimes	if (offmode) {
1661553Srgrimes		if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
16730371Scharnier			warn("%s", fs->fs_file);
1681553Srgrimes			return (1);
1691553Srgrimes		}
1701553Srgrimes		if (vflag)
1711553Srgrimes			printf("%s: quotas turned off\n", fs->fs_file);
1721553Srgrimes		return (0);
1731553Srgrimes	}
1741553Srgrimes	if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
17530371Scharnier		warnx("using %s on", qfpathname);
17630371Scharnier		warn("%s", fs->fs_file);
1771553Srgrimes		return (1);
1781553Srgrimes	}
1791553Srgrimes	if (vflag)
180166212Smpp		printf("%s: %s quotas turned on with data file %s\n",
181166212Smpp		    fs->fs_file, qfextension[type], qfpathname);
1821553Srgrimes	return (0);
1831553Srgrimes}
1841553Srgrimes
1851553Srgrimes/*
1861553Srgrimes * Check to see if target appears in list of size cnt.
1871553Srgrimes */
18830371Scharnierint
1891553Srgrimesoneof(target, list, cnt)
1901553Srgrimes	register char *target, *list[];
1911553Srgrimes	int cnt;
1921553Srgrimes{
1931553Srgrimes	register int i;
1941553Srgrimes
1951553Srgrimes	for (i = 0; i < cnt; i++)
1961553Srgrimes		if (strcmp(target, list[i]) == 0)
1971553Srgrimes			return (i);
1981553Srgrimes	return (-1);
1991553Srgrimes}
2001553Srgrimes
2011553Srgrimes/*
2021553Srgrimes * Check to see if a particular quota is to be enabled.
2031553Srgrimes */
20430371Scharnierint
2051553Srgrimeshasquota(fs, type, qfnamep)
2061553Srgrimes	register struct fstab *fs;
2071553Srgrimes	int type;
2081553Srgrimes	char **qfnamep;
2091553Srgrimes{
2101553Srgrimes	register char *opt;
21130371Scharnier	char *cp;
2121553Srgrimes	static char initname, usrname[100], grpname[100];
2131553Srgrimes	static char buf[BUFSIZ];
2141553Srgrimes
2151553Srgrimes	if (!initname) {
2161553Srgrimes		sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
2171553Srgrimes		sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
2181553Srgrimes		initname = 1;
2191553Srgrimes	}
2201553Srgrimes	strcpy(buf, fs->fs_mntops);
2211553Srgrimes	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
22230371Scharnier		if ((cp = index(opt, '=')))
2231553Srgrimes			*cp++ = '\0';
2241553Srgrimes		if (type == USRQUOTA && strcmp(opt, usrname) == 0)
2251553Srgrimes			break;
2261553Srgrimes		if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
2271553Srgrimes			break;
2281553Srgrimes	}
2291553Srgrimes	if (!opt)
2301553Srgrimes		return (0);
2311553Srgrimes	if (cp) {
2321553Srgrimes		*qfnamep = cp;
2331553Srgrimes		return (1);
2341553Srgrimes	}
2351553Srgrimes	(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
2361553Srgrimes	*qfnamep = buf;
2371553Srgrimes	return (1);
2381553Srgrimes}
2391553Srgrimes
2401553Srgrimes/*
24196705Strhodes * Verify filesystem is mounted and not readonly.
2421553Srgrimes */
24330371Scharnierint
2441553Srgrimesreadonly(fs)
2451553Srgrimes	register struct fstab *fs;
2461553Srgrimes{
2471553Srgrimes	struct statfs fsbuf;
2481553Srgrimes
2491553Srgrimes	if (statfs(fs->fs_file, &fsbuf) < 0 ||
2501553Srgrimes	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
2511553Srgrimes	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
2521553Srgrimes		printf("%s: not mounted\n", fs->fs_file);
2531553Srgrimes		return (1);
2541553Srgrimes	}
2551553Srgrimes	if (fsbuf.f_flags & MNT_RDONLY) {
2561553Srgrimes		printf("%s: mounted read-only\n", fs->fs_file);
2571553Srgrimes		return (1);
2581553Srgrimes	}
2591553Srgrimes	return (0);
2601553Srgrimes}
261