Home | History | Annotate | Line # | Download | only in quotaon
quotaon.c revision 1.26
      1  1.26    bouyer /*	$NetBSD: quotaon.c,v 1.26 2011/03/24 17:05:47 bouyer Exp $	*/
      2   1.8  christos 
      3   1.1       cgd /*
      4   1.4   mycroft  * Copyright (c) 1980, 1990, 1993
      5   1.4   mycroft  *	The Regents of the University of California.  All rights reserved.
      6   1.1       cgd  *
      7   1.1       cgd  * This code is derived from software contributed to Berkeley by
      8   1.1       cgd  * Robert Elz at The University of Melbourne.
      9   1.1       cgd  *
     10   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     11   1.1       cgd  * modification, are permitted provided that the following conditions
     12   1.1       cgd  * are met:
     13   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     14   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     15   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     17   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     18  1.19       agc  * 3. Neither the name of the University nor the names of its contributors
     19   1.1       cgd  *    may be used to endorse or promote products derived from this software
     20   1.1       cgd  *    without specific prior written permission.
     21   1.1       cgd  *
     22   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32   1.1       cgd  * SUCH DAMAGE.
     33   1.1       cgd  */
     34   1.1       cgd 
     35  1.10     lukem #include <sys/cdefs.h>
     36   1.1       cgd #ifndef lint
     37  1.22     lukem __COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\
     38  1.22     lukem  The Regents of the University of California.  All rights reserved.");
     39   1.1       cgd #endif /* not lint */
     40   1.1       cgd 
     41   1.1       cgd #ifndef lint
     42   1.8  christos #if 0
     43   1.8  christos static char sccsid[] = "@(#)quotaon.c	8.1 (Berkeley) 6/6/93";
     44   1.8  christos #else
     45  1.26    bouyer __RCSID("$NetBSD: quotaon.c,v 1.26 2011/03/24 17:05:47 bouyer Exp $");
     46   1.8  christos #endif
     47   1.1       cgd #endif /* not lint */
     48   1.1       cgd 
     49   1.1       cgd /*
     50   1.1       cgd  * Turn quota on/off for a filesystem.
     51   1.1       cgd  */
     52   1.1       cgd #include <sys/param.h>
     53   1.1       cgd #include <sys/file.h>
     54   1.1       cgd #include <sys/mount.h>
     55  1.24    bouyer 
     56  1.26    bouyer #include <quota/quotaprop.h>
     57  1.24    bouyer #include <ufs/ufs/quota1.h>
     58  1.24    bouyer #include <sys/quota.h>
     59  1.24    bouyer 
     60  1.12     perry 
     61  1.12     perry #include <err.h>
     62  1.12     perry #include <fstab.h>
     63   1.1       cgd #include <stdio.h>
     64  1.25  christos #include <errno.h>
     65  1.14      matt #include <stdlib.h>
     66   1.5       cgd #include <string.h>
     67  1.12     perry #include <unistd.h>
     68   1.1       cgd 
     69  1.25  christos #include "quotautil.h"
     70   1.1       cgd 
     71  1.25  christos static int	aflag;		/* all file systems */
     72  1.25  christos static int	gflag;		/* operate on group quotas */
     73  1.25  christos static int	uflag;		/* operate on user quotas */
     74  1.25  christos static int	vflag;		/* verbose */
     75  1.25  christos 
     76  1.25  christos static void usage(void) __attribute__((__noreturn__));
     77  1.25  christos static int quotaonoff(struct fstab *, int, int, const char *);
     78  1.25  christos static int readonly(struct fstab *);
     79   1.8  christos 
     80   1.8  christos int
     81  1.25  christos main(int argc, char *argv[])
     82   1.1       cgd {
     83   1.8  christos 	struct fstab *fs;
     84  1.25  christos 	char qfnp[MAXPATHLEN];
     85   1.1       cgd 	long argnum, done = 0;
     86   1.1       cgd 	int i, offmode = 0, errs = 0;
     87   1.7      mark 	int ch;
     88   1.1       cgd 
     89  1.16       cgd 	if (strcmp(getprogname(), "quotaoff") == 0)
     90   1.1       cgd 		offmode++;
     91  1.16       cgd 	else if (strcmp(getprogname(), "quotaon") != 0)
     92  1.17     grant 		errx(1, "Name must be quotaon or quotaoff");
     93   1.8  christos 
     94   1.7      mark 	while ((ch = getopt(argc, argv, "avug")) != -1) {
     95   1.1       cgd 		switch(ch) {
     96   1.1       cgd 		case 'a':
     97   1.1       cgd 			aflag++;
     98   1.1       cgd 			break;
     99   1.1       cgd 		case 'g':
    100   1.1       cgd 			gflag++;
    101   1.1       cgd 			break;
    102   1.1       cgd 		case 'u':
    103   1.1       cgd 			uflag++;
    104   1.1       cgd 			break;
    105   1.1       cgd 		case 'v':
    106   1.1       cgd 			vflag++;
    107   1.1       cgd 			break;
    108   1.1       cgd 		default:
    109   1.8  christos 			usage();
    110   1.8  christos 			break;
    111   1.1       cgd 		}
    112   1.1       cgd 	}
    113   1.1       cgd 	argc -= optind;
    114   1.1       cgd 	argv += optind;
    115   1.8  christos 
    116   1.1       cgd 	if (argc <= 0 && !aflag)
    117   1.8  christos 		usage();
    118   1.8  christos 
    119   1.1       cgd 	if (!gflag && !uflag) {
    120   1.1       cgd 		gflag++;
    121   1.1       cgd 		uflag++;
    122   1.1       cgd 	}
    123   1.1       cgd 	setfsent();
    124   1.1       cgd 	while ((fs = getfsent()) != NULL) {
    125  1.18  perseant 		if ((strcmp(fs->fs_vfstype, "ffs") &&
    126  1.18  perseant 		     strcmp(fs->fs_vfstype, "lfs")) ||
    127   1.1       cgd 		    strcmp(fs->fs_type, FSTAB_RW))
    128   1.1       cgd 			continue;
    129   1.1       cgd 		if (aflag) {
    130  1.25  christos 			if (gflag && hasquota(qfnp, sizeof(qfnp), fs, GRPQUOTA))
    131   1.1       cgd 				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
    132  1.25  christos 			if (uflag && hasquota(qfnp, sizeof(qfnp), fs, USRQUOTA))
    133   1.1       cgd 				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
    134   1.1       cgd 			continue;
    135   1.1       cgd 		}
    136   1.1       cgd 		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
    137   1.1       cgd 		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
    138  1.25  christos 			done |= 1U << argnum;
    139  1.25  christos 			if (gflag && hasquota(qfnp, sizeof(qfnp), fs, GRPQUOTA))
    140   1.1       cgd 				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
    141  1.25  christos 			if (uflag && hasquota(qfnp, sizeof(qfnp), fs, USRQUOTA))
    142   1.1       cgd 				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
    143   1.1       cgd 		}
    144   1.1       cgd 	}
    145   1.1       cgd 	endfsent();
    146   1.1       cgd 	for (i = 0; i < argc; i++)
    147  1.25  christos 		if ((done & (1U << i)) == 0)
    148   1.8  christos 			warnx("%s not found in fstab", argv[i]);
    149  1.25  christos 	return errs;
    150   1.1       cgd }
    151   1.1       cgd 
    152   1.8  christos static void
    153  1.25  christos usage(void)
    154   1.1       cgd {
    155  1.25  christos 	const char *p = getprogname();
    156  1.25  christos 	(void) fprintf(stderr, "Usage: %s [-g] [-u] [-v] -a\n"
    157  1.25  christos 	    "\t%s [-g] [-u] [-v] filesys ...\n", p, p);
    158   1.1       cgd 	exit(1);
    159   1.1       cgd }
    160   1.1       cgd 
    161   1.8  christos static int
    162  1.25  christos quotaonoff( struct fstab *fs, int offmode, int type, const char *qfpathname)
    163   1.1       cgd {
    164  1.24    bouyer 	const char *mode = (offmode == 1) ? "off" : "on";
    165  1.24    bouyer 	prop_dictionary_t dict, data, cmd;
    166  1.24    bouyer 	prop_array_t cmds, datas;
    167  1.24    bouyer 	struct plistref pref;
    168  1.24    bouyer 	int8_t error8;
    169  1.24    bouyer 
    170  1.26    bouyer 	dict = quota_prop_create();
    171  1.24    bouyer 	cmds = prop_array_create();
    172  1.24    bouyer 	datas = prop_array_create();
    173   1.1       cgd 
    174   1.1       cgd 	if (strcmp(fs->fs_file, "/") && readonly(fs))
    175  1.25  christos 		return 1;
    176  1.24    bouyer 
    177  1.24    bouyer 	if (dict == NULL || cmds == NULL || datas == NULL)
    178  1.24    bouyer 		errx(1, "can't allocate proplist");
    179  1.24    bouyer 
    180   1.1       cgd 	if (offmode) {
    181  1.26    bouyer 		if (!quota_prop_add_command(cmds, "quotaoff",
    182  1.24    bouyer 		    qfextension[type], datas))
    183  1.24    bouyer 			err(1, "prop_add_command");
    184  1.24    bouyer 	} else {
    185  1.24    bouyer 		data = prop_dictionary_create();
    186  1.24    bouyer 		if (data == NULL)
    187  1.24    bouyer 			errx(1, "can't allocate proplist");
    188  1.24    bouyer 		if (!prop_dictionary_set_cstring(data, "quotafile",
    189  1.24    bouyer 		    qfpathname))
    190  1.24    bouyer 			err(1, "prop_dictionary_set(quotafile)");
    191  1.24    bouyer 		if (!prop_array_add_and_rel(datas, data))
    192  1.24    bouyer 			err(1, "prop_array_add(data)");
    193  1.26    bouyer 		if (!quota_prop_add_command(cmds, "quotaon",
    194  1.24    bouyer 		    qfextension[type], datas))
    195  1.24    bouyer 			err(1, "prop_add_command");
    196  1.24    bouyer 	}
    197  1.24    bouyer 	if (!prop_dictionary_set(dict, "commands", cmds))
    198  1.24    bouyer 		err(1, "prop_dictionary_set(command)");
    199  1.24    bouyer 
    200  1.24    bouyer 	if (!prop_dictionary_send_syscall(dict, &pref))
    201  1.24    bouyer 		err(1, "prop_dictionary_send_syscall");
    202  1.24    bouyer 	prop_object_release(dict);
    203  1.24    bouyer 
    204  1.24    bouyer 	if (quotactl(fs->fs_file, &pref) != 0) {
    205  1.24    bouyer 		warn("quotactl(%s)", fs->fs_file);
    206  1.24    bouyer 		return(1);
    207  1.24    bouyer 	}
    208  1.24    bouyer 
    209  1.25  christos 	if ((errno = prop_dictionary_recv_syscall(&pref, &dict)) != 0)
    210  1.25  christos 		err(1, "prop_dictionary_recv_syscall");
    211  1.25  christos 
    212  1.26    bouyer 	if ((errno = quota_get_cmds(dict, &cmds)) != 0)
    213  1.26    bouyer 		err(1, "quota_get_cmds");
    214  1.24    bouyer 
    215  1.24    bouyer 	/* only one command, no need to iter */
    216  1.24    bouyer 	cmd = prop_array_get(cmds, 0);
    217  1.24    bouyer 	if (cmd == NULL)
    218  1.24    bouyer 		err(1, "prop_array_get(cmd)");
    219  1.24    bouyer 
    220  1.24    bouyer 	if (!prop_dictionary_get_int8(cmd, "return", &error8))
    221  1.24    bouyer 		err(1, "prop_get(return)");
    222  1.24    bouyer 
    223  1.24    bouyer 	if (error8) {
    224  1.25  christos 		errno = error8;
    225  1.25  christos 		warn("quota%s for %s", mode, fs->fs_file);
    226  1.24    bouyer 		return 1;
    227   1.1       cgd 	}
    228  1.24    bouyer 
    229  1.24    bouyer 	if (vflag) {
    230  1.24    bouyer 		printf("%s: %s quotas turned %s\n",
    231  1.24    bouyer 		    fs->fs_file, qfextension[type], mode);
    232   1.1       cgd 	}
    233  1.25  christos 	return 0;
    234   1.1       cgd }
    235   1.1       cgd 
    236   1.1       cgd /*
    237   1.1       cgd  * Verify file system is mounted and not readonly.
    238   1.1       cgd  */
    239   1.8  christos static int
    240  1.25  christos readonly(struct fstab *fs)
    241   1.1       cgd {
    242  1.21  christos 	struct statvfs fsbuf;
    243   1.1       cgd 
    244  1.21  christos 	if (statvfs(fs->fs_file, &fsbuf) < 0 ||
    245   1.1       cgd 	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
    246   1.1       cgd 	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
    247   1.1       cgd 		printf("%s: not mounted\n", fs->fs_file);
    248  1.25  christos 		return 1;
    249   1.1       cgd 	}
    250  1.21  christos 	if (fsbuf.f_flag & MNT_RDONLY) {
    251   1.1       cgd 		printf("%s: mounted read-only\n", fs->fs_file);
    252  1.25  christos 		return 1;
    253   1.1       cgd 	}
    254  1.25  christos 	return 0;
    255   1.1       cgd }
    256