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
62241737Sedstatic const char *qfextension[] = INITQFNAMES;
631553Srgrimes
64241737Sedstatic int	aflag;		/* all filesystems */
65241737Sedstatic int	gflag;		/* operate on group quotas */
66241737Sedstatic int	uflag;		/* operate on user quotas */
67241737Sedstatic int	vflag;		/* verbose */
681553Srgrimes
69241737Sedstatic int oneof(char *, char *[], int);
70241737Sedstatic int quotaonoff(struct fstab *fs, int, int);
7199822Salfredstatic void usage(void);
7230371Scharnier
7330371Scharnierint
7499822Salfredmain(int argc, char **argv)
751553Srgrimes{
76180187Sdes	struct fstab *fs;
77229384Sed	const char *whoami;
781553Srgrimes	long argnum, done = 0;
79124830Sgrehan	int ch, i, offmode = 0, errs = 0;
801553Srgrimes
81229384Sed	whoami = getprogname();
821553Srgrimes	if (strcmp(whoami, "quotaoff") == 0)
831553Srgrimes		offmode++;
8430371Scharnier	else if (strcmp(whoami, "quotaon") != 0)
8530371Scharnier		errx(1, "name must be quotaon or quotaoff");
8624428Simp	while ((ch = getopt(argc, argv, "avug")) != -1) {
871553Srgrimes		switch(ch) {
881553Srgrimes		case 'a':
891553Srgrimes			aflag++;
901553Srgrimes			break;
911553Srgrimes		case 'g':
921553Srgrimes			gflag++;
931553Srgrimes			break;
941553Srgrimes		case 'u':
951553Srgrimes			uflag++;
961553Srgrimes			break;
971553Srgrimes		case 'v':
981553Srgrimes			vflag++;
991553Srgrimes			break;
1001553Srgrimes		default:
10130371Scharnier			usage();
1021553Srgrimes		}
1031553Srgrimes	}
1041553Srgrimes	argc -= optind;
1051553Srgrimes	argv += optind;
1061553Srgrimes	if (argc <= 0 && !aflag)
10730371Scharnier		usage();
1081553Srgrimes	if (!gflag && !uflag) {
1091553Srgrimes		gflag++;
1101553Srgrimes		uflag++;
1111553Srgrimes	}
1121553Srgrimes	setfsent();
1131553Srgrimes	while ((fs = getfsent()) != NULL) {
1141553Srgrimes		if (strcmp(fs->fs_vfstype, "ufs") ||
1151553Srgrimes		    strcmp(fs->fs_type, FSTAB_RW))
1161553Srgrimes			continue;
1171553Srgrimes		if (aflag) {
118207736Smckusick			if (gflag)
119207736Smckusick				errs += quotaonoff(fs, offmode, GRPQUOTA);
120207736Smckusick			if (uflag)
121207736Smckusick				errs += quotaonoff(fs, offmode, USRQUOTA);
1221553Srgrimes			continue;
1231553Srgrimes		}
1241553Srgrimes		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
1251553Srgrimes		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
1261553Srgrimes			done |= 1 << argnum;
127207736Smckusick			if (gflag)
128207736Smckusick				errs += quotaonoff(fs, offmode, GRPQUOTA);
129207736Smckusick			if (uflag)
130207736Smckusick				errs += quotaonoff(fs, offmode, USRQUOTA);
1311553Srgrimes		}
1321553Srgrimes	}
1331553Srgrimes	endfsent();
1341553Srgrimes	for (i = 0; i < argc; i++)
1351553Srgrimes		if ((done & (1 << i)) == 0)
13630371Scharnier			warnx("%s not found in fstab", argv[i]);
1371553Srgrimes	exit(errs);
1381553Srgrimes}
1391553Srgrimes
14030371Scharnierstatic void
141180187Sdesusage(void)
1421553Srgrimes{
1431553Srgrimes
14430371Scharnier	fprintf(stderr, "%s\n%s\n%s\n%s\n",
14530371Scharnier		"usage: quotaon [-g] [-u] [-v] -a",
14630371Scharnier		"       quotaon [-g] [-u] [-v] filesystem ...",
14730371Scharnier		"       quotaoff [-g] [-u] [-v] -a",
14830371Scharnier		"       quotaoff [-g] [-u] [-v] filesystem ...");
1491553Srgrimes	exit(1);
1501553Srgrimes}
1511553Srgrimes
152241737Sedstatic int
153207736Smckusickquotaonoff(struct fstab *fs, int offmode, int type)
1541553Srgrimes{
155207736Smckusick	struct quotafile *qf;
1561553Srgrimes
157207736Smckusick	if ((qf = quota_open(fs, type, O_RDONLY)) == NULL)
158207736Smckusick		return (0);
1591553Srgrimes	if (offmode) {
160207736Smckusick		if (quota_off(qf) != 0) {
161207736Smckusick			warn("%s", quota_fsname(qf));
1621553Srgrimes			return (1);
1631553Srgrimes		}
1641553Srgrimes		if (vflag)
165207736Smckusick			printf("%s: quotas turned off\n", quota_fsname(qf));
166207736Smckusick		quota_close(qf);
167207736Smckusick		return(0);
1681553Srgrimes	}
169207736Smckusick	if (quota_on(qf) != 0) {
170207736Smckusick		warn("using %s on %s", quota_qfname(qf), quota_fsname(qf));
1711553Srgrimes		return (1);
1721553Srgrimes	}
1731553Srgrimes	if (vflag)
174166212Smpp		printf("%s: %s quotas turned on with data file %s\n",
175207736Smckusick		    quota_fsname(qf), qfextension[type], quota_qfname(qf));
176207736Smckusick	quota_close(qf);
177207736Smckusick	return(0);
1781553Srgrimes}
1791553Srgrimes
1801553Srgrimes/*
1811553Srgrimes * Check to see if target appears in list of size cnt.
1821553Srgrimes */
183241737Sedstatic int
184180187Sdesoneof(char *target, char *list[], int cnt)
1851553Srgrimes{
186180187Sdes	int i;
1871553Srgrimes
1881553Srgrimes	for (i = 0; i < cnt; i++)
1891553Srgrimes		if (strcmp(target, list[i]) == 0)
1901553Srgrimes			return (i);
1911553Srgrimes	return (-1);
1921553Srgrimes}
193