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.
58 static int flags, fmt = -1;
60 static char **mntpoints;
62 static char *xarg = NULL;
64 static void usage(void)
66 errstr(_("Usage:\n\t%s [-guvp] [-F quotaformat] [-x state] -a\n\
67 \t%s [-guvp] [-F quotaformat] [-x state] filesys ...\n\n\
69 -f, --off turn quotas off\n\
70 -u, --user operate on user quotas\n\
71 -g, --group operate on group quotas\n\
72 -p, --print-state print whether quotas are on or off\n\
73 -x, --xfs-command=cmd perform XFS quota command\n\
74 -F, --format=formatname operate on specific quota format\n\
75 -v, --verbose print more messages\n\
76 -h, --help display this help text and exit\n\
77 -V, --version display version information and exit\n"),
79 strcmp(progname, "quotaon") ? _("turn quotas off for all filesystems") :
80 _("turn quotas on for all filesystems"));
84 static void parse_options(int argcnt, char **argstr)
87 struct option long_opts[] = {
88 { "all", 0, NULL, 'a' },
89 { "off", 0, NULL, 'f' },
90 { "verbose", 0, NULL, 'v' },
91 { "user", 0, NULL, 'u' },
92 { "group", 0, NULL, 'g' },
93 { "print-state", 0, NULL, 'p' },
94 { "xfs-command", 1, NULL, 'x' },
95 { "format", 1, NULL, 'F' },
96 { "version", 0, NULL, 'V' },
97 { "help", 0, NULL, 'h' },
101 while ((c = getopt_long(argcnt, argstr, "afvugpx:VF:h", long_opts, NULL)) != -1) {
125 if ((fmt = name2fmt(optarg)) == QF_ERROR)
136 if ((flags & FL_ALL && optind != argcnt) || (!(flags & FL_ALL) && optind == argcnt)) {
137 fputs(_("Bad number of arguments.\n"), stderr);
141 fputs(_("Cannot turn on/off quotas via RPC.\n"), stderr);
144 if (!(flags & (FL_USER | FL_GROUP)))
145 flags |= FL_USER | FL_GROUP;
146 if (!(flags & FL_ALL)) {
147 mntpoints = argstr + optind;
148 mntcnt = argcnt - optind;
152 int pinfo(char *fmt, ...)
157 if (!(flags & FL_VERBOSE))
160 ret = vprintf(fmt, arg);
166 * Enable/disable rsquash on given filesystem
168 static int quotarsquashonoff(const char *quotadev, int type, int flags)
170 #if defined(MNTOPT_RSQUASH)
173 if (kernel_iface == IFACE_GENERIC) {
174 int qcmd = QCMD(Q_SETINFO, type);
175 struct if_dqinfo info;
177 info.dqi_flags = V1_DQF_RSQUASH;
178 info.dqi_valid = IIF_FLAGS;
179 ret = quotactl(qcmd, quotadev, 0, (void *)&info);
182 int mode = (flags & STATEFLAG_OFF) ? 0 : 1;
183 int qcmd = QCMD(Q_V1_RSQUASH, type);
185 ret = quotactl(qcmd, quotadev, 0, (void *)&mode);
188 errstr(_("set root_squash on %s: %s\n"), quotadev, strerror(errno));
191 if (flags & STATEFLAG_OFF)
192 pinfo(_("%s: %s root_squash turned off\n"), quotadev, type2name(type));
193 else if (flags & STATEFLAG_ON)
194 pinfo(_("%s: %s root_squash turned on\n"), quotadev, type2name(type));
200 * Enable/disable VFS quota on given filesystem
202 static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafile, int type, int fmt, int flags)
206 if (flags & STATEFLAG_OFF) {
207 if (kernel_iface == IFACE_GENERIC)
208 qcmd = QCMD(Q_QUOTAOFF, type);
210 qcmd = QCMD(Q_6_5_QUOTAOFF, type);
211 if (quotactl(qcmd, quotadev, 0, NULL) < 0) {
212 errstr(_("quotactl on %s [%s]: %s\n"), quotadev, quotadir, strerror(errno));
215 pinfo(_("%s [%s]: %s quotas turned off\n"), quotadev, quotadir, _(type2name(type)));
218 if (kernel_iface == IFACE_GENERIC) {
219 qcmd = QCMD(Q_QUOTAON, type);
220 kqf = util2kernfmt(fmt);
223 qcmd = QCMD(Q_6_5_QUOTAON, type);
226 if (quotactl(qcmd, quotadev, kqf, (void *)quotafile) < 0) {
228 errstr(_("cannot find %s on %s [%s]\n"), quotafile, quotadev, quotadir);
230 errstr(_("using %s on %s [%s]: %s\n"), quotafile, quotadev, quotadir, strerror(errno));
232 errstr(_("Maybe create new quota files with quotacheck(8)?\n"));
233 else if (errno == ESRCH)
234 errstr(_("Quota format not supported in kernel.\n"));
237 pinfo(_("%s [%s]: %s quotas turned on\n"), quotadev, quotadir, _(type2name(type)));
242 * Enable/disable quota/rootsquash on given filesystem (version 1)
244 static int v1_newstate(struct mount_entry *mnt, int type, char *file, int flags, int fmt)
248 if ((flags & STATEFLAG_OFF) && str_hasmntopt(mnt->me_opts, MNTOPT_RSQUASH))
249 errs += quotarsquashonoff(mnt->me_devname, type, flags);
250 errs += quotaonoff(mnt->me_devname, mnt->me_dir, file, type, QF_VFSOLD, flags);
251 if ((flags & STATEFLAG_ON) && str_hasmntopt(mnt->me_opts, MNTOPT_RSQUASH))
252 errs += quotarsquashonoff(mnt->me_devname, type, flags);
257 * Enable/disable quota on given filesystem (generic VFS quota)
259 static int v2_newstate(struct mount_entry *mnt, int type, char *file, int flags, int fmt)
261 return quotaonoff(mnt->me_devname, mnt->me_dir, file, type, fmt, flags);
265 * For both VFS quota formats, need to pass in the quota file;
266 * for XFS quota manager, pass on the -x command line option.
268 static int newstate(struct mount_entry *mnt, int type, char *extra)
272 sflags = flags & FL_OFF ? STATEFLAG_OFF : STATEFLAG_ON;
274 sflags |= STATEFLAG_ALL;
276 if (!strcmp(mnt->me_type, MNTTYPE_GFS2)) {
277 errstr(_("Cannot change state of GFS2 quota.\n"));
279 } else if (!strcmp(mnt->me_type, MNTTYPE_XFS)) { /* XFS filesystem has special handling... */
280 if (!kern_qfmt_supp(QF_XFS)) {
281 errstr(_("Cannot change state of XFS quota. It's not compiled in kernel.\n"));
284 ret = xfs_newstate(mnt, type, extra, sflags);
286 else if (mnt->me_qfmt[type] == QF_META) {
287 /* Must be non-empty because empty path is always invalid. */
288 ret = v2_newstate(mnt, type, ".", sflags, QF_VFSV0);
293 if (!me_hasquota(mnt, type))
296 if (get_qf_name(mnt, type, QF_VFSV0,
297 NF_FORMAT, &extra) >= 0)
299 else if (get_qf_name(mnt, type, QF_VFSV1,
300 NF_FORMAT, &extra) >= 0)
302 else if (get_qf_name(mnt, type, QF_VFSOLD,
303 NF_FORMAT, &extra) >= 0)
306 errstr(_("Cannot find quota file on %s [%s] to turn quotas on/off.\n"), mnt->me_dir, mnt->me_devname);
310 if (get_qf_name(mnt, type, fmt, NF_FORMAT, &extra) < 0) {
311 errstr(_("Quota file on %s [%s] does not exist or has wrong format.\n"), mnt->me_dir, mnt->me_devname);
316 if (is_tree_qfmt(usefmt))
317 ret = v2_newstate(mnt, type, extra, sflags, usefmt);
319 ret = v1_newstate(mnt, type, extra, sflags, QF_VFSOLD);
325 /* Print state of quota (on/off) */
326 static int print_state(struct mount_entry *mnt, int type)
330 if (!strcmp(mnt->me_type, MNTTYPE_XFS) ||
331 !strcmp(mnt->me_type, MNTTYPE_GFS2)) {
332 if (kern_qfmt_supp(QF_XFS))
333 on = kern_quota_on(mnt, type, QF_XFS) != -1;
335 else if (kernel_iface == IFACE_GENERIC)
336 on = kern_quota_on(mnt, type, -1) != -1;
337 else if (kern_qfmt_supp(QF_VFSV0))
338 on = kern_quota_on(mnt, type, QF_VFSV0) != -1;
339 else if (kern_qfmt_supp(QF_VFSOLD))
340 on = kern_quota_on(mnt, type, QF_VFSOLD) != -1;
342 printf(_("%s quota on %s (%s) is %s\n"), _(type2name(type)), mnt->me_dir, mnt->me_devname,
343 on ? _("on") : _("off"));
348 int main(int argc, char **argv)
350 struct mount_entry *mnt;
355 progname = basename(argv[0]);
356 if (strcmp(progname, "quotaoff") == 0)
358 else if (strcmp(progname, "quotaon") != 0)
359 die(1, _("Name must be quotaon or quotaoff not %s\n"), progname);
361 parse_options(argc, argv);
363 init_kernel_interface();
364 if (fmt != -1 && !kern_qfmt_supp(fmt))
365 die(1, _("Required format %s not supported by kernel.\n"), fmt2name(fmt));
366 else if (!kern_qfmt_supp(-1))
367 errstr(_("Warning: No quota format detected in the kernel.\n"));
369 if (init_mounts_scan(mntcnt, mntpoints, MS_XFS_DISABLED | MS_LOCALONLY) < 0)
371 while ((mnt = get_next_mount())) {
372 if (nfs_fstype(mnt->me_type)) {
373 if (!(flags & FL_ALL))
374 errstr(_("%s: Quota cannot be turned on on NFS filesystem\n"), mnt->me_devname);
378 if (!(flags & FL_STAT)) {
379 if (flags & FL_GROUP)
380 errs += newstate(mnt, GRPQUOTA, xarg);
382 errs += newstate(mnt, USRQUOTA, xarg);
385 if (flags & FL_GROUP)
386 errs += print_state(mnt, GRPQUOTA);
388 errs += print_state(mnt, USRQUOTA);