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$");
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>
56207736Smckusick#include <libutil.h>
571553Srgrimes#include <stdio.h>
5878720Sdd#include <stdlib.h>
5930371Scharnier#include <string.h>
6030371Scharnier#include <unistd.h>
611553Srgrimes
6299822Salfredconst char *qfname = QUOTAFILENAME;
6399822Salfredconst char *qfextension[] = INITQFNAMES;
641553Srgrimes
6596705Strhodesint	aflag;		/* all filesystems */
661553Srgrimesint	gflag;		/* operate on group quotas */
671553Srgrimesint	uflag;		/* operate on user quotas */
681553Srgrimesint	vflag;		/* verbose */
691553Srgrimes
7099822Salfredint oneof(char *, char *[], int);
71207736Smckusickint quotaonoff(struct fstab *fs, int, int);
7299822Salfredstatic void usage(void);
7330371Scharnier
7430371Scharnierint
7599822Salfredmain(int argc, char **argv)
761553Srgrimes{
77180187Sdes	struct fstab *fs;
78207736Smckusick	char *whoami;
791553Srgrimes	long argnum, done = 0;
80124830Sgrehan	int ch, i, offmode = 0, errs = 0;
811553Srgrimes
821553Srgrimes	whoami = rindex(*argv, '/') + 1;
831553Srgrimes	if (whoami == (char *)1)
841553Srgrimes		whoami = *argv;
851553Srgrimes	if (strcmp(whoami, "quotaoff") == 0)
861553Srgrimes		offmode++;
8730371Scharnier	else if (strcmp(whoami, "quotaon") != 0)
8830371Scharnier		errx(1, "name must be quotaon or quotaoff");
8924428Simp	while ((ch = getopt(argc, argv, "avug")) != -1) {
901553Srgrimes		switch(ch) {
911553Srgrimes		case 'a':
921553Srgrimes			aflag++;
931553Srgrimes			break;
941553Srgrimes		case 'g':
951553Srgrimes			gflag++;
961553Srgrimes			break;
971553Srgrimes		case 'u':
981553Srgrimes			uflag++;
991553Srgrimes			break;
1001553Srgrimes		case 'v':
1011553Srgrimes			vflag++;
1021553Srgrimes			break;
1031553Srgrimes		default:
10430371Scharnier			usage();
1051553Srgrimes		}
1061553Srgrimes	}
1071553Srgrimes	argc -= optind;
1081553Srgrimes	argv += optind;
1091553Srgrimes	if (argc <= 0 && !aflag)
11030371Scharnier		usage();
1111553Srgrimes	if (!gflag && !uflag) {
1121553Srgrimes		gflag++;
1131553Srgrimes		uflag++;
1141553Srgrimes	}
1151553Srgrimes	setfsent();
1161553Srgrimes	while ((fs = getfsent()) != NULL) {
1171553Srgrimes		if (strcmp(fs->fs_vfstype, "ufs") ||
1181553Srgrimes		    strcmp(fs->fs_type, FSTAB_RW))
1191553Srgrimes			continue;
1201553Srgrimes		if (aflag) {
121207736Smckusick			if (gflag)
122207736Smckusick				errs += quotaonoff(fs, offmode, GRPQUOTA);
123207736Smckusick			if (uflag)
124207736Smckusick				errs += quotaonoff(fs, offmode, USRQUOTA);
1251553Srgrimes			continue;
1261553Srgrimes		}
1271553Srgrimes		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
1281553Srgrimes		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
1291553Srgrimes			done |= 1 << argnum;
130207736Smckusick			if (gflag)
131207736Smckusick				errs += quotaonoff(fs, offmode, GRPQUOTA);
132207736Smckusick			if (uflag)
133207736Smckusick				errs += quotaonoff(fs, offmode, USRQUOTA);
1341553Srgrimes		}
1351553Srgrimes	}
1361553Srgrimes	endfsent();
1371553Srgrimes	for (i = 0; i < argc; i++)
1381553Srgrimes		if ((done & (1 << i)) == 0)
13930371Scharnier			warnx("%s not found in fstab", argv[i]);
1401553Srgrimes	exit(errs);
1411553Srgrimes}
1421553Srgrimes
14330371Scharnierstatic void
144180187Sdesusage(void)
1451553Srgrimes{
1461553Srgrimes
14730371Scharnier	fprintf(stderr, "%s\n%s\n%s\n%s\n",
14830371Scharnier		"usage: quotaon [-g] [-u] [-v] -a",
14930371Scharnier		"       quotaon [-g] [-u] [-v] filesystem ...",
15030371Scharnier		"       quotaoff [-g] [-u] [-v] -a",
15130371Scharnier		"       quotaoff [-g] [-u] [-v] filesystem ...");
1521553Srgrimes	exit(1);
1531553Srgrimes}
1541553Srgrimes
15530371Scharnierint
156207736Smckusickquotaonoff(struct fstab *fs, int offmode, int type)
1571553Srgrimes{
158207736Smckusick	struct quotafile *qf;
1591553Srgrimes
160207736Smckusick	if ((qf = quota_open(fs, type, O_RDONLY)) == NULL)
161207736Smckusick		return (0);
1621553Srgrimes	if (offmode) {
163207736Smckusick		if (quota_off(qf) != 0) {
164207736Smckusick			warn("%s", quota_fsname(qf));
1651553Srgrimes			return (1);
1661553Srgrimes		}
1671553Srgrimes		if (vflag)
168207736Smckusick			printf("%s: quotas turned off\n", quota_fsname(qf));
169207736Smckusick		quota_close(qf);
170207736Smckusick		return(0);
1711553Srgrimes	}
172207736Smckusick	if (quota_on(qf) != 0) {
173207736Smckusick		warn("using %s on %s", quota_qfname(qf), quota_fsname(qf));
1741553Srgrimes		return (1);
1751553Srgrimes	}
1761553Srgrimes	if (vflag)
177166212Smpp		printf("%s: %s quotas turned on with data file %s\n",
178207736Smckusick		    quota_fsname(qf), qfextension[type], quota_qfname(qf));
179207736Smckusick	quota_close(qf);
180207736Smckusick	return(0);
1811553Srgrimes}
1821553Srgrimes
1831553Srgrimes/*
1841553Srgrimes * Check to see if target appears in list of size cnt.
1851553Srgrimes */
18630371Scharnierint
187180187Sdesoneof(char *target, char *list[], int cnt)
1881553Srgrimes{
189180187Sdes	int i;
1901553Srgrimes
1911553Srgrimes	for (i = 0; i < cnt; i++)
1921553Srgrimes		if (strcmp(target, list[i]) == 0)
1931553Srgrimes			return (i);
1941553Srgrimes	return (-1);
1951553Srgrimes}
196