2 * Copyright (c) 1980, 1990 Regents of the University of California. All
5 * This code is derived from software contributed to Berkeley by Robert Elz at
6 * The University of Melbourne.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 2.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution. 3. All advertising
15 * materials mentioning features or use of this software must display the
16 * following acknowledgement: This product includes software developed by the
17 * University of California, Berkeley and its contributors. 4. Neither the
18 * name of the University nor the names of its contributors may be used to
19 * endorse or promote products derived from this software without specific
20 * prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * Turn quota on/off for a filesystem.
63 static void usage(void)
65 errstr(_("Usage:\n\t%s [-guvp] [-F quotaformat] [-x state] -a\n\
66 \t%s [-guvp] [-F quotaformat] [-x state] filesys ...\n\n\
67 -a, --all turn quotas on for all filesystems\n\
68 -f, --off turn quotas off\n\
69 -u, --user operate on user quotas\n\
70 -g, --group operate on group quotas\n\
71 -p, --print-state print whether quotas are on or off\n\
72 -x, --xfs-command=cmd perform XFS quota command\n\
73 -F, --format=formatname operate on specific quota format\n\
74 -v, --verbose print more messages\n\
75 -h, --help display this help text and exit\n\
76 -V, --version display version information and exit\n"), progname, progname);
80 static void parse_options(int argcnt, char **argstr)
83 struct option long_opts[] = {
84 { "all", 0, NULL, 'a' },
85 { "off", 0, NULL, 'f' },
86 { "verbose", 0, NULL, 'v' },
87 { "user", 0, NULL, 'u' },
88 { "group", 0, NULL, 'g' },
89 { "print-state", 0, NULL, 'p' },
90 { "xfs-command", 1, NULL, 'x' },
91 { "format", 1, NULL, 'F' },
92 { "version", 0, NULL, 'V' },
93 { "help", 0, NULL, 'h' },
97 while ((c = getopt_long(argcnt, argstr, "afvugpx:VF:h", long_opts, NULL)) != -1) {
121 if ((fmt = name2fmt(optarg)) == QF_ERROR)
132 if ((flags & FL_ALL && optind != argcnt) || (!(flags & FL_ALL) && optind == argcnt)) {
133 fputs(_("Bad number of arguments.\n"), stderr);
137 fputs(_("Cannot turn on/off quotas via RPC.\n"), stderr);
140 if (!(flags & (FL_USER | FL_GROUP)))
141 flags |= FL_USER | FL_GROUP;
142 if (!(flags & FL_ALL)) {
143 mntpoints = argstr + optind;
144 mntcnt = argcnt - optind;
149 * Enable/disable rsquash on given filesystem
151 static int quotarsquashonoff(const char *quotadev, int type, int flags)
153 #if defined(MNTOPT_RSQUASH)
156 if (kernel_iface == IFACE_GENERIC) {
157 int qcmd = QCMD(Q_SETINFO, type);
158 struct if_dqinfo info;
160 info.dqi_flags = V1_DQF_RSQUASH;
161 info.dqi_valid = IIF_FLAGS;
162 ret = quotactl(qcmd, quotadev, 0, (void *)&info);
165 int mode = (flags & STATEFLAG_OFF) ? 0 : 1;
166 int qcmd = QCMD(Q_V1_RSQUASH, type);
168 ret = quotactl(qcmd, quotadev, 0, (void *)&mode);
171 errstr(_("set root_squash on %s: %s\n"), quotadev, strerror(errno));
174 if ((flags & STATEFLAG_VERBOSE) && (flags & STATEFLAG_OFF))
175 printf(_("%s: %s root_squash turned off\n"), quotadev, type2name(type));
176 else if ((flags & STATEFLAG_VERBOSE) && (flags & STATEFLAG_ON))
177 printf(_("%s: %s root_squash turned on\n"), quotadev, type2name(type));
183 * Enable/disable VFS quota on given filesystem
185 static int quotaonoff(char *quotadev, char *quotadir, char *quotafile, int type, int fmt, int flags)
189 if (flags & STATEFLAG_OFF) {
190 if (kernel_iface == IFACE_GENERIC)
191 qcmd = QCMD(Q_QUOTAOFF, type);
193 qcmd = QCMD(Q_6_5_QUOTAOFF, type);
194 if (quotactl(qcmd, quotadev, 0, NULL) < 0) {
195 errstr(_("quotactl on %s [%s]: %s\n"), quotadev, quotadir, strerror(errno));
198 if (flags & STATEFLAG_VERBOSE)
199 printf(_("%s [%s]: %s quotas turned off\n"), quotadev, quotadir, type2name(type));
202 if (kernel_iface == IFACE_GENERIC) {
203 qcmd = QCMD(Q_QUOTAON, type);
204 kqf = util2kernfmt(fmt);
207 qcmd = QCMD(Q_6_5_QUOTAON, type);
210 if (quotactl(qcmd, quotadev, kqf, (void *)quotafile) < 0) {
212 errstr(_("cannot find %s on %s [%s]\n"), quotafile, quotadev, quotadir);
214 errstr(_("using %s on %s [%s]: %s\n"), quotafile, quotadev, quotadir, strerror(errno));
216 errstr(_("Maybe create new quota files with quotacheck(8)?\n"));
217 else if (errno == ESRCH)
218 errstr(_("Quota format not supported in kernel.\n"));
221 if (flags & STATEFLAG_VERBOSE)
222 printf(_("%s [%s]: %s quotas turned on\n"), quotadev, quotadir, type2name(type));
227 * Enable/disable quota/rootsquash on given filesystem (version 1)
229 static int v1_newstate(struct mntent *mnt, int type, char *file, int flags, int fmt)
232 const char *dev = get_device_name(mnt->mnt_fsname);
236 if ((flags & STATEFLAG_OFF) && hasmntopt(mnt, MNTOPT_RSQUASH))
237 errs += quotarsquashonoff(dev, type, flags);
238 if (hasquota(mnt, type, 0))
239 errs += quotaonoff((char *)dev, mnt->mnt_dir, file, type, QF_VFSOLD, flags);
240 if ((flags & STATEFLAG_ON) && hasmntopt(mnt, MNTOPT_RSQUASH))
241 errs += quotarsquashonoff(dev, type, flags);
247 * Enable/disable quota on given filesystem (generic VFS quota)
249 static int v2_newstate(struct mntent *mnt, int type, char *file, int flags, int fmt)
251 const char *dev = get_device_name(mnt->mnt_fsname);
256 if (hasquota(mnt, type, 0))
257 errs = quotaonoff((char *)dev, mnt->mnt_dir, file, type, fmt, flags);
263 * For both VFS quota formats, need to pass in the quota file;
264 * for XFS quota manager, pass on the -x command line option.
266 static int newstate(struct mntent *mnt, int type, char *extra)
270 sflags = flags & FL_OFF ? STATEFLAG_OFF : STATEFLAG_ON;
271 if (flags & FL_VERBOSE)
272 sflags |= STATEFLAG_VERBOSE;
274 sflags |= STATEFLAG_ALL;
276 if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) { /* XFS filesystem has special handling... */
277 if (!kern_qfmt_supp(QF_XFS)) {
278 errstr(_("Cannot change state of XFS quota. It's not compiled in kernel.\n"));
281 if ((flags & FL_OFF && (kern_quota_on(mnt->mnt_fsname, USRQUOTA, QF_XFS) != -1
282 || kern_quota_on(mnt->mnt_fsname, GRPQUOTA, QF_XFS) != -1))
283 || (!(flags & FL_OFF) && kern_quota_on(mnt->mnt_fsname, type, QF_XFS) == -1))
284 ret = xfs_newstate(mnt, type, extra, sflags);
286 else if (meta_qf_fstype(mnt->mnt_type)) {
287 if (!hasquota(mnt, type, 0))
289 /* Must be non-empty because empty path is always invalid. */
290 ret = v2_newstate(mnt, type, ".", sflags, QF_VFSV0);
295 if (!hasquota(mnt, type, 0))
298 if (get_qf_name(mnt, type, QF_VFSV0,
299 NF_FORMAT, &extra) >= 0)
301 else if (get_qf_name(mnt, type, QF_VFSV1,
302 NF_FORMAT, &extra) >= 0)
304 else if (get_qf_name(mnt, type, QF_VFSOLD,
305 NF_FORMAT, &extra) >= 0)
308 errstr(_("Cannot find quota file on %s [%s] to turn quotas on/off.\n"), mnt->mnt_dir, mnt->mnt_fsname);
312 if (get_qf_name(mnt, type, fmt, NF_FORMAT, &extra) < 0) {
313 errstr(_("Quota file on %s [%s] does not exist or has wrong format.\n"), mnt->mnt_dir, mnt->mnt_fsname);
318 if (is_tree_qfmt(usefmt))
319 ret = v2_newstate(mnt, type, extra, sflags, usefmt);
321 ret = v1_newstate(mnt, type, extra, sflags, QF_VFSOLD);
327 /* Print state of quota (on/off) */
328 static int print_state(struct mntent *mnt, int type)
332 if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
333 if (kern_qfmt_supp(QF_XFS))
334 on = kern_quota_on(mnt->mnt_fsname, type, QF_XFS) != -1;
336 else if (kernel_iface == IFACE_GENERIC)
337 on = kern_quota_on(mnt->mnt_fsname, type, -1) != -1;
338 else if (kern_qfmt_supp(QF_VFSV0))
339 on = kern_quota_on(mnt->mnt_fsname, type, QF_VFSV0) != -1;
340 else if (kern_qfmt_supp(QF_VFSOLD))
341 on = kern_quota_on(mnt->mnt_fsname, type, QF_VFSOLD) != -1;
343 printf(_("%s quota on %s (%s) is %s\n"), type2name(type), mnt->mnt_dir, mnt->mnt_fsname,
344 on ? _("on") : _("off"));
349 int main(int argc, char **argv)
356 progname = basename(argv[0]);
357 if (strcmp(progname, "quotaoff") == 0)
359 else if (strcmp(progname, "quotaon") != 0)
360 die(1, _("Name must be quotaon or quotaoff not %s\n"), progname);
362 parse_options(argc, argv);
364 init_kernel_interface();
365 if (fmt != -1 && !kern_qfmt_supp(fmt))
366 die(1, _("Required format %s not supported by kernel.\n"), fmt2name(fmt));
367 else if (!kern_qfmt_supp(-1))
368 errstr(_("Warning: No quota format detected in the kernel.\n"));
370 if (init_mounts_scan(mntcnt, mntpoints, MS_XFS_DISABLED | MS_LOCALONLY) < 0)
372 while ((mnt = get_next_mount())) {
373 if (nfs_fstype(mnt->mnt_type)) {
374 if (!(flags & FL_ALL))
375 fprintf(stderr, "%s: Quota cannot be turned on on NFS filesystem\n", mnt->mnt_fsname);
379 if (!(flags & FL_STAT)) {
380 if (flags & FL_GROUP)
381 errs += newstate(mnt, GRPQUOTA, xarg);
383 errs += newstate(mnt, USRQUOTA, xarg);
386 if (flags & FL_GROUP)
387 errs += print_state(mnt, GRPQUOTA);
389 errs += print_state(mnt, USRQUOTA);