quotaon.c revision 96705
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
371553Srgrimes#ifndef lint
3830371Scharnierstatic const char copyright[] =
391553Srgrimes"@(#) Copyright (c) 1980, 1990, 1993\n\
401553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
411553Srgrimes#endif /* not lint */
421553Srgrimes
431553Srgrimes#ifndef lint
4430371Scharnier#if 0
451553Srgrimesstatic char sccsid[] = "@(#)quotaon.c	8.1 (Berkeley) 6/6/93";
4630371Scharnier#endif
4730371Scharnierstatic const char rcsid[] =
4850479Speter  "$FreeBSD: head/usr.sbin/quotaon/quotaon.c 96705 2002-05-16 02:28:39Z trhodes $";
491553Srgrimes#endif /* not lint */
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
651553Srgrimeschar *qfname = QUOTAFILENAME;
661553Srgrimeschar *qfextension[] = INITQFNAMES;
671553Srgrimes
6896705Strhodesint	aflag;		/* all filesystems */
691553Srgrimesint	gflag;		/* operate on group quotas */
701553Srgrimesint	uflag;		/* operate on user quotas */
711553Srgrimesint	vflag;		/* verbose */
721553Srgrimes
7330371Scharnierint hasquota __P((struct fstab *, int, char **));
7430371Scharnierint oneof __P((char *, char *[], int));
7530371Scharnierint quotaonoff __P((struct fstab *fs, int, int, char *));
7630371Scharnierint readonly __P((struct fstab *));
7730371Scharnierstatic void usage __P((void));
7830371Scharnier
7930371Scharnierint
801553Srgrimesmain(argc, argv)
811553Srgrimes	int argc;
821553Srgrimes	char **argv;
831553Srgrimes{
841553Srgrimes	register struct fstab *fs;
8530371Scharnier	char ch, *qfnp, *whoami;
861553Srgrimes	long argnum, done = 0;
871553Srgrimes	int i, offmode = 0, errs = 0;
881553Srgrimes
891553Srgrimes	whoami = rindex(*argv, '/') + 1;
901553Srgrimes	if (whoami == (char *)1)
911553Srgrimes		whoami = *argv;
921553Srgrimes	if (strcmp(whoami, "quotaoff") == 0)
931553Srgrimes		offmode++;
9430371Scharnier	else if (strcmp(whoami, "quotaon") != 0)
9530371Scharnier		errx(1, "name must be quotaon or quotaoff");
9624428Simp	while ((ch = getopt(argc, argv, "avug")) != -1) {
971553Srgrimes		switch(ch) {
981553Srgrimes		case 'a':
991553Srgrimes			aflag++;
1001553Srgrimes			break;
1011553Srgrimes		case 'g':
1021553Srgrimes			gflag++;
1031553Srgrimes			break;
1041553Srgrimes		case 'u':
1051553Srgrimes			uflag++;
1061553Srgrimes			break;
1071553Srgrimes		case 'v':
1081553Srgrimes			vflag++;
1091553Srgrimes			break;
1101553Srgrimes		default:
11130371Scharnier			usage();
1121553Srgrimes		}
1131553Srgrimes	}
1141553Srgrimes	argc -= optind;
1151553Srgrimes	argv += optind;
1161553Srgrimes	if (argc <= 0 && !aflag)
11730371Scharnier		usage();
1181553Srgrimes	if (!gflag && !uflag) {
1191553Srgrimes		gflag++;
1201553Srgrimes		uflag++;
1211553Srgrimes	}
1221553Srgrimes	setfsent();
1231553Srgrimes	while ((fs = getfsent()) != NULL) {
1241553Srgrimes		if (strcmp(fs->fs_vfstype, "ufs") ||
1251553Srgrimes		    strcmp(fs->fs_type, FSTAB_RW))
1261553Srgrimes			continue;
1271553Srgrimes		if (aflag) {
1281553Srgrimes			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
1291553Srgrimes				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
1301553Srgrimes			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
1311553Srgrimes				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
1321553Srgrimes			continue;
1331553Srgrimes		}
1341553Srgrimes		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
1351553Srgrimes		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
1361553Srgrimes			done |= 1 << argnum;
1371553Srgrimes			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
1381553Srgrimes				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
1391553Srgrimes			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
1401553Srgrimes				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
1411553Srgrimes		}
1421553Srgrimes	}
1431553Srgrimes	endfsent();
1441553Srgrimes	for (i = 0; i < argc; i++)
1451553Srgrimes		if ((done & (1 << i)) == 0)
14630371Scharnier			warnx("%s not found in fstab", argv[i]);
1471553Srgrimes	exit(errs);
1481553Srgrimes}
1491553Srgrimes
15030371Scharnierstatic void
15130371Scharnierusage()
1521553Srgrimes{
1531553Srgrimes
15430371Scharnier	fprintf(stderr, "%s\n%s\n%s\n%s\n",
15530371Scharnier		"usage: quotaon [-g] [-u] [-v] -a",
15630371Scharnier		"       quotaon [-g] [-u] [-v] filesystem ...",
15730371Scharnier		"       quotaoff [-g] [-u] [-v] -a",
15830371Scharnier		"       quotaoff [-g] [-u] [-v] filesystem ...");
1591553Srgrimes	exit(1);
1601553Srgrimes}
1611553Srgrimes
16230371Scharnierint
1631553Srgrimesquotaonoff(fs, offmode, type, qfpathname)
1641553Srgrimes	register struct fstab *fs;
1651553Srgrimes	int offmode, type;
1661553Srgrimes	char *qfpathname;
1671553Srgrimes{
1681553Srgrimes
1691553Srgrimes	if (strcmp(fs->fs_file, "/") && readonly(fs))
1701553Srgrimes		return (1);
1711553Srgrimes	if (offmode) {
1721553Srgrimes		if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
17330371Scharnier			warn("%s", fs->fs_file);
1741553Srgrimes			return (1);
1751553Srgrimes		}
1761553Srgrimes		if (vflag)
1771553Srgrimes			printf("%s: quotas turned off\n", fs->fs_file);
1781553Srgrimes		return (0);
1791553Srgrimes	}
1801553Srgrimes	if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
18130371Scharnier		warnx("using %s on", qfpathname);
18230371Scharnier		warn("%s", fs->fs_file);
1831553Srgrimes		return (1);
1841553Srgrimes	}
1851553Srgrimes	if (vflag)
1861553Srgrimes		printf("%s: %s quotas turned on\n", fs->fs_file,
1871553Srgrimes		    qfextension[type]);
1881553Srgrimes	return (0);
1891553Srgrimes}
1901553Srgrimes
1911553Srgrimes/*
1921553Srgrimes * Check to see if target appears in list of size cnt.
1931553Srgrimes */
19430371Scharnierint
1951553Srgrimesoneof(target, list, cnt)
1961553Srgrimes	register char *target, *list[];
1971553Srgrimes	int cnt;
1981553Srgrimes{
1991553Srgrimes	register int i;
2001553Srgrimes
2011553Srgrimes	for (i = 0; i < cnt; i++)
2021553Srgrimes		if (strcmp(target, list[i]) == 0)
2031553Srgrimes			return (i);
2041553Srgrimes	return (-1);
2051553Srgrimes}
2061553Srgrimes
2071553Srgrimes/*
2081553Srgrimes * Check to see if a particular quota is to be enabled.
2091553Srgrimes */
21030371Scharnierint
2111553Srgrimeshasquota(fs, type, qfnamep)
2121553Srgrimes	register struct fstab *fs;
2131553Srgrimes	int type;
2141553Srgrimes	char **qfnamep;
2151553Srgrimes{
2161553Srgrimes	register char *opt;
21730371Scharnier	char *cp;
2181553Srgrimes	static char initname, usrname[100], grpname[100];
2191553Srgrimes	static char buf[BUFSIZ];
2201553Srgrimes
2211553Srgrimes	if (!initname) {
2221553Srgrimes		sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
2231553Srgrimes		sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
2241553Srgrimes		initname = 1;
2251553Srgrimes	}
2261553Srgrimes	strcpy(buf, fs->fs_mntops);
2271553Srgrimes	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
22830371Scharnier		if ((cp = index(opt, '=')))
2291553Srgrimes			*cp++ = '\0';
2301553Srgrimes		if (type == USRQUOTA && strcmp(opt, usrname) == 0)
2311553Srgrimes			break;
2321553Srgrimes		if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
2331553Srgrimes			break;
2341553Srgrimes	}
2351553Srgrimes	if (!opt)
2361553Srgrimes		return (0);
2371553Srgrimes	if (cp) {
2381553Srgrimes		*qfnamep = cp;
2391553Srgrimes		return (1);
2401553Srgrimes	}
2411553Srgrimes	(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
2421553Srgrimes	*qfnamep = buf;
2431553Srgrimes	return (1);
2441553Srgrimes}
2451553Srgrimes
2461553Srgrimes/*
24796705Strhodes * Verify filesystem is mounted and not readonly.
2481553Srgrimes */
24930371Scharnierint
2501553Srgrimesreadonly(fs)
2511553Srgrimes	register struct fstab *fs;
2521553Srgrimes{
2531553Srgrimes	struct statfs fsbuf;
2541553Srgrimes
2551553Srgrimes	if (statfs(fs->fs_file, &fsbuf) < 0 ||
2561553Srgrimes	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
2571553Srgrimes	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
2581553Srgrimes		printf("%s: not mounted\n", fs->fs_file);
2591553Srgrimes		return (1);
2601553Srgrimes	}
2611553Srgrimes	if (fsbuf.f_flags & MNT_RDONLY) {
2621553Srgrimes		printf("%s: mounted read-only\n", fs->fs_file);
2631553Srgrimes		return (1);
2641553Srgrimes	}
2651553Srgrimes	return (0);
2661553Srgrimes}
267