quotaon.c revision 124830
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 * 3. All advertising materials mentioning features or use of this software
171553Srgrimes *    must display the following acknowledgement:
181553Srgrimes *	This product includes software developed by the University of
191553Srgrimes *	California, Berkeley and its contributors.
201553Srgrimes * 4. Neither the name of the University nor the names of its contributors
211553Srgrimes *    may be used to endorse or promote products derived from this software
221553Srgrimes *    without specific prior written permission.
231553Srgrimes *
241553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341553Srgrimes * SUCH DAMAGE.
351553Srgrimes */
361553Srgrimes
37114601Sobrien#if 0
381553Srgrimes#ifndef lint
3930371Scharnierstatic const char copyright[] =
401553Srgrimes"@(#) Copyright (c) 1980, 1990, 1993\n\
411553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
421553Srgrimes#endif /* not lint */
431553Srgrimes
441553Srgrimes#ifndef lint
451553Srgrimesstatic char sccsid[] = "@(#)quotaon.c	8.1 (Berkeley) 6/6/93";
46114601Sobrien#endif /* not lint */
4730371Scharnier#endif
48114601Sobrien#include <sys/cdefs.h>
49114601Sobrien__FBSDID("$FreeBSD: head/usr.sbin/quotaon/quotaon.c 124830 2004-01-22 07:23:36Z grehan $");
501553Srgrimes
511553Srgrimes/*
521553Srgrimes * Turn quota on/off for a filesystem.
531553Srgrimes */
541553Srgrimes#include <sys/param.h>
551553Srgrimes#include <sys/file.h>
561553Srgrimes#include <sys/mount.h>
571553Srgrimes#include <ufs/ufs/quota.h>
5830371Scharnier#include <err.h>
5930371Scharnier#include <fstab.h>
601553Srgrimes#include <stdio.h>
6178720Sdd#include <stdlib.h>
6230371Scharnier#include <string.h>
6330371Scharnier#include <unistd.h>
641553Srgrimes
6599822Salfredconst char *qfname = QUOTAFILENAME;
6699822Salfredconst char *qfextension[] = INITQFNAMES;
671553Srgrimes
6896705Strhodesint	aflag;		/* all filesystems */
691553Srgrimesint	gflag;		/* operate on group quotas */
701553Srgrimesint	uflag;		/* operate on user quotas */
711553Srgrimesint	vflag;		/* verbose */
721553Srgrimes
7399822Salfredint hasquota(struct fstab *, int, char **);
7499822Salfredint oneof(char *, char *[], int);
7599822Salfredint quotaonoff(struct fstab *fs, int, int, char *);
7699822Salfredint readonly(struct fstab *);
7799822Salfredstatic void usage(void);
7830371Scharnier
7930371Scharnierint
8099822Salfredmain(int argc, char **argv)
811553Srgrimes{
821553Srgrimes	register struct fstab *fs;
83124830Sgrehan	char *qfnp, *whoami;
841553Srgrimes	long argnum, done = 0;
85124830Sgrehan	int ch, i, offmode = 0, errs = 0;
861553Srgrimes
871553Srgrimes	whoami = rindex(*argv, '/') + 1;
881553Srgrimes	if (whoami == (char *)1)
891553Srgrimes		whoami = *argv;
901553Srgrimes	if (strcmp(whoami, "quotaoff") == 0)
911553Srgrimes		offmode++;
9230371Scharnier	else if (strcmp(whoami, "quotaon") != 0)
9330371Scharnier		errx(1, "name must be quotaon or quotaoff");
9424428Simp	while ((ch = getopt(argc, argv, "avug")) != -1) {
951553Srgrimes		switch(ch) {
961553Srgrimes		case 'a':
971553Srgrimes			aflag++;
981553Srgrimes			break;
991553Srgrimes		case 'g':
1001553Srgrimes			gflag++;
1011553Srgrimes			break;
1021553Srgrimes		case 'u':
1031553Srgrimes			uflag++;
1041553Srgrimes			break;
1051553Srgrimes		case 'v':
1061553Srgrimes			vflag++;
1071553Srgrimes			break;
1081553Srgrimes		default:
10930371Scharnier			usage();
1101553Srgrimes		}
1111553Srgrimes	}
1121553Srgrimes	argc -= optind;
1131553Srgrimes	argv += optind;
1141553Srgrimes	if (argc <= 0 && !aflag)
11530371Scharnier		usage();
1161553Srgrimes	if (!gflag && !uflag) {
1171553Srgrimes		gflag++;
1181553Srgrimes		uflag++;
1191553Srgrimes	}
1201553Srgrimes	setfsent();
1211553Srgrimes	while ((fs = getfsent()) != NULL) {
1221553Srgrimes		if (strcmp(fs->fs_vfstype, "ufs") ||
1231553Srgrimes		    strcmp(fs->fs_type, FSTAB_RW))
1241553Srgrimes			continue;
1251553Srgrimes		if (aflag) {
1261553Srgrimes			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
1271553Srgrimes				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
1281553Srgrimes			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
1291553Srgrimes				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
1301553Srgrimes			continue;
1311553Srgrimes		}
1321553Srgrimes		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
1331553Srgrimes		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
1341553Srgrimes			done |= 1 << argnum;
1351553Srgrimes			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
1361553Srgrimes				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
1371553Srgrimes			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
1381553Srgrimes				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
1391553Srgrimes		}
1401553Srgrimes	}
1411553Srgrimes	endfsent();
1421553Srgrimes	for (i = 0; i < argc; i++)
1431553Srgrimes		if ((done & (1 << i)) == 0)
14430371Scharnier			warnx("%s not found in fstab", argv[i]);
1451553Srgrimes	exit(errs);
1461553Srgrimes}
1471553Srgrimes
14830371Scharnierstatic void
14930371Scharnierusage()
1501553Srgrimes{
1511553Srgrimes
15230371Scharnier	fprintf(stderr, "%s\n%s\n%s\n%s\n",
15330371Scharnier		"usage: quotaon [-g] [-u] [-v] -a",
15430371Scharnier		"       quotaon [-g] [-u] [-v] filesystem ...",
15530371Scharnier		"       quotaoff [-g] [-u] [-v] -a",
15630371Scharnier		"       quotaoff [-g] [-u] [-v] filesystem ...");
1571553Srgrimes	exit(1);
1581553Srgrimes}
1591553Srgrimes
16030371Scharnierint
1611553Srgrimesquotaonoff(fs, offmode, type, qfpathname)
1621553Srgrimes	register struct fstab *fs;
1631553Srgrimes	int offmode, type;
1641553Srgrimes	char *qfpathname;
1651553Srgrimes{
1661553Srgrimes
1671553Srgrimes	if (strcmp(fs->fs_file, "/") && readonly(fs))
1681553Srgrimes		return (1);
1691553Srgrimes	if (offmode) {
1701553Srgrimes		if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
17130371Scharnier			warn("%s", fs->fs_file);
1721553Srgrimes			return (1);
1731553Srgrimes		}
1741553Srgrimes		if (vflag)
1751553Srgrimes			printf("%s: quotas turned off\n", fs->fs_file);
1761553Srgrimes		return (0);
1771553Srgrimes	}
1781553Srgrimes	if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
17930371Scharnier		warnx("using %s on", qfpathname);
18030371Scharnier		warn("%s", fs->fs_file);
1811553Srgrimes		return (1);
1821553Srgrimes	}
1831553Srgrimes	if (vflag)
1841553Srgrimes		printf("%s: %s quotas turned on\n", fs->fs_file,
1851553Srgrimes		    qfextension[type]);
1861553Srgrimes	return (0);
1871553Srgrimes}
1881553Srgrimes
1891553Srgrimes/*
1901553Srgrimes * Check to see if target appears in list of size cnt.
1911553Srgrimes */
19230371Scharnierint
1931553Srgrimesoneof(target, list, cnt)
1941553Srgrimes	register char *target, *list[];
1951553Srgrimes	int cnt;
1961553Srgrimes{
1971553Srgrimes	register int i;
1981553Srgrimes
1991553Srgrimes	for (i = 0; i < cnt; i++)
2001553Srgrimes		if (strcmp(target, list[i]) == 0)
2011553Srgrimes			return (i);
2021553Srgrimes	return (-1);
2031553Srgrimes}
2041553Srgrimes
2051553Srgrimes/*
2061553Srgrimes * Check to see if a particular quota is to be enabled.
2071553Srgrimes */
20830371Scharnierint
2091553Srgrimeshasquota(fs, type, qfnamep)
2101553Srgrimes	register struct fstab *fs;
2111553Srgrimes	int type;
2121553Srgrimes	char **qfnamep;
2131553Srgrimes{
2141553Srgrimes	register char *opt;
21530371Scharnier	char *cp;
2161553Srgrimes	static char initname, usrname[100], grpname[100];
2171553Srgrimes	static char buf[BUFSIZ];
2181553Srgrimes
2191553Srgrimes	if (!initname) {
2201553Srgrimes		sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
2211553Srgrimes		sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
2221553Srgrimes		initname = 1;
2231553Srgrimes	}
2241553Srgrimes	strcpy(buf, fs->fs_mntops);
2251553Srgrimes	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
22630371Scharnier		if ((cp = index(opt, '=')))
2271553Srgrimes			*cp++ = '\0';
2281553Srgrimes		if (type == USRQUOTA && strcmp(opt, usrname) == 0)
2291553Srgrimes			break;
2301553Srgrimes		if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
2311553Srgrimes			break;
2321553Srgrimes	}
2331553Srgrimes	if (!opt)
2341553Srgrimes		return (0);
2351553Srgrimes	if (cp) {
2361553Srgrimes		*qfnamep = cp;
2371553Srgrimes		return (1);
2381553Srgrimes	}
2391553Srgrimes	(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
2401553Srgrimes	*qfnamep = buf;
2411553Srgrimes	return (1);
2421553Srgrimes}
2431553Srgrimes
2441553Srgrimes/*
24596705Strhodes * Verify filesystem is mounted and not readonly.
2461553Srgrimes */
24730371Scharnierint
2481553Srgrimesreadonly(fs)
2491553Srgrimes	register struct fstab *fs;
2501553Srgrimes{
2511553Srgrimes	struct statfs fsbuf;
2521553Srgrimes
2531553Srgrimes	if (statfs(fs->fs_file, &fsbuf) < 0 ||
2541553Srgrimes	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
2551553Srgrimes	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
2561553Srgrimes		printf("%s: not mounted\n", fs->fs_file);
2571553Srgrimes		return (1);
2581553Srgrimes	}
2591553Srgrimes	if (fsbuf.f_flags & MNT_RDONLY) {
2601553Srgrimes		printf("%s: mounted read-only\n", fs->fs_file);
2611553Srgrimes		return (1);
2621553Srgrimes	}
2631553Srgrimes	return (0);
2641553Srgrimes}
265