GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/quotaon/quotaon.c Lines: 0 111 0.0 %
Date: 2017-11-07 Branches: 0 97 0.0 %

Line Branch Exec Source
1
/*
2
 * Copyright (c) 1980, 1990, 1993
3
 *	The Regents of the University of California.  All rights reserved.
4
 *
5
 * This code is derived from software contributed to Berkeley by
6
 * Robert Elz at The University of Melbourne.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
/*
34
 * Turn quota on/off for a filesystem.
35
 */
36
#include <sys/file.h>
37
#include <sys/mount.h>
38
#include <ufs/ufs/quota.h>
39
#include <err.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <fstab.h>
44
#include <unistd.h>
45
46
char *qfname = QUOTAFILENAME;
47
char *qfextension[] = INITQFNAMES;
48
49
int	aflag;		/* all file systems */
50
int	gflag;		/* operate on group quotas */
51
int	uflag;		/* operate on user quotas */
52
int	vflag;		/* verbose */
53
54
void	usage(char *whoami);
55
int	hasquota(struct fstab *fs, int type, char **qfnamep, int force);
56
int	quotaonoff(struct fstab *fs, int offmode, int type, char *qfpathname);
57
int	oneof(char *target, char *list[], int cnt);
58
int	readonly(struct fstab *fs);
59
60
61
int
62
main(int argc, char *argv[])
63
{
64
	struct fstab *fs;
65
	char *qfnp, *whoami;
66
	long argnum, done = 0;
67
	int i, offmode = 0, errs = 0;
68
	extern int optind;
69
	int ch;
70
71
	whoami = strrchr(*argv, '/') + 1;
72
	if (whoami == (char *)1)
73
		whoami = *argv;
74
	if (strcmp(whoami, "quotaoff") == 0)
75
		offmode = 1;
76
	else if (strcmp(whoami, "quotaon") != 0) {
77
		fprintf(stderr, "Name must be quotaon or quotaoff not %s\n",
78
			whoami);
79
		exit(1);
80
	}
81
	while ((ch = getopt(argc, argv, "avug")) != -1) {
82
		switch (ch) {
83
		case 'a':
84
			aflag = 1;
85
			break;
86
		case 'g':
87
			gflag = 1;
88
			break;
89
		case 'u':
90
			uflag = 1;
91
			break;
92
		case 'v':
93
			vflag = 1;
94
			break;
95
		default:
96
			usage(whoami);
97
		}
98
	}
99
	argc -= optind;
100
	argv += optind;
101
	if (argc <= 0 && !aflag)
102
		usage(whoami);
103
	if (!gflag && !uflag) {
104
		gflag = 1;
105
		uflag = 1;
106
	}
107
	setfsent();
108
	while ((fs = getfsent()) != NULL) {
109
		if (strcmp(fs->fs_type, FSTAB_RW))
110
			continue;
111
		if (strcmp(fs->fs_vfstype, "ffs") &&
112
		    strcmp(fs->fs_vfstype, "ufs") &&
113
		    strcmp(fs->fs_vfstype, "mfs"))
114
			continue;
115
		if (aflag) {
116
			if (gflag && hasquota(fs, GRPQUOTA, &qfnp, 0))
117
				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
118
			if (uflag && hasquota(fs, USRQUOTA, &qfnp, 0))
119
				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
120
			continue;
121
		}
122
		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
123
		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
124
			done |= 1 << argnum;
125
			if (gflag) {
126
				hasquota(fs, GRPQUOTA, &qfnp, 1);
127
				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
128
			}
129
			if (uflag) {
130
				hasquota(fs, USRQUOTA, &qfnp, 1);
131
				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
132
			}
133
		}
134
	}
135
	endfsent();
136
	for (i = 0; i < argc; i++)
137
		if ((done & (1 << i)) == 0)
138
			fprintf(stderr, "%s not found in fstab\n",
139
				argv[i]);
140
	exit(errs);
141
}
142
143
void
144
usage(char *whoami)
145
{
146
147
	fprintf(stderr, "usage: %s [-aguv] filesystem ...\n", whoami);
148
	exit(1);
149
}
150
151
int
152
quotaonoff(struct fstab *fs, int offmode, int type, char *qfpathname)
153
{
154
	if (strcmp(fs->fs_file, "/") && readonly(fs))
155
		return (1);
156
	if (offmode) {
157
		if (quotactl(fs->fs_file, QCMD(Q_QUOTAOFF, type), 0, 0) < 0) {
158
			fprintf(stderr, "quotaoff: ");
159
			perror(fs->fs_file);
160
			return (1);
161
		}
162
		if (vflag)
163
			printf("%s: %s quotas turned off\n", fs->fs_file,
164
			    qfextension[type]);
165
		return (0);
166
	}
167
	if (quotactl(fs->fs_file, QCMD(Q_QUOTAON, type), 0, qfpathname) < 0) {
168
		warn("%s: %s quotas using %s", fs->fs_file,
169
		    qfextension[type], qfpathname);
170
		return (1);
171
	}
172
	if (vflag)
173
		printf("%s: %s quotas turned on\n", fs->fs_file,
174
		    qfextension[type]);
175
	return (0);
176
}
177
178
/*
179
 * Check to see if target appears in list of size cnt.
180
 */
181
int
182
oneof(char *target, char *list[], int cnt)
183
{
184
	int i;
185
186
	for (i = 0; i < cnt; i++)
187
		if (strcmp(target, list[i]) == 0)
188
			return (i);
189
	return (-1);
190
}
191
192
/*
193
 * Check to see if a particular quota is to be enabled.
194
 */
195
int
196
hasquota(struct fstab *fs, int type, char **qfnamep, int force)
197
{
198
	char *opt;
199
	char *cp;
200
	static char initname, usrname[100], grpname[100];
201
	static char buf[BUFSIZ];
202
203
	if (!initname) {
204
		snprintf(usrname, sizeof usrname, "%s%s",
205
		    qfextension[USRQUOTA], qfname);
206
		snprintf(grpname, sizeof grpname, "%s%s",
207
		    qfextension[GRPQUOTA], qfname);
208
		initname = 1;
209
	}
210
	strlcpy(buf, fs->fs_mntops, sizeof buf);
211
	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
212
		if ((cp = strchr(opt, '=')) != NULL)
213
			*cp++ = '\0';
214
		if (type == USRQUOTA && strcmp(opt, usrname) == 0)
215
			break;
216
		if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
217
			break;
218
	}
219
	if (!force && !opt)
220
		return (0);
221
	if (cp) {
222
		*qfnamep = cp;
223
		return (1);
224
	}
225
	(void) snprintf(buf, sizeof buf, "%s/%s.%s", fs->fs_file,
226
	    qfname, qfextension[type]);
227
	*qfnamep = buf;
228
	return (1);
229
}
230
231
/*
232
 * Verify file system is mounted and not readonly.
233
 * MFS is special -- it puts "mfs:" in the kernel's mount table
234
 */
235
int
236
readonly(struct fstab *fs)
237
{
238
	struct statfs fsbuf;
239
240
	if (statfs(fs->fs_file, &fsbuf) < 0 ||
241
	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
242
	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
243
		if (strcmp(fs->fs_file, "mfs") ||
244
		    memcmp(fsbuf.f_mntfromname, "mfs:", sizeof("mfs:")-1))
245
			;
246
		else {
247
			printf("%s: not mounted\n", fs->fs_file);
248
			return (1);
249
		}
250
	}
251
	if (fsbuf.f_flags & MNT_RDONLY) {
252
		printf("%s: mounted read-only\n", fs->fs_file);
253
		return (1);
254
	}
255
	return (0);
256
}