Module Name:    src
Committed By:   bouyer
Date:           Mon Feb  7 20:31:21 UTC 2011

Modified Files:
        src/usr.sbin/edquota [bouyer-quota2]: edquota.8 edquota.c

Log Message:
Add -c option, which clears quota entries for the specified users/groups


To generate a diff of this commit:
cvs rdiff -u -r1.12.50.1 -r1.12.50.2 src/usr.sbin/edquota/edquota.8
cvs rdiff -u -r1.29.16.9 -r1.29.16.10 src/usr.sbin/edquota/edquota.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/edquota/edquota.8
diff -u src/usr.sbin/edquota/edquota.8:1.12.50.1 src/usr.sbin/edquota/edquota.8:1.12.50.2
--- src/usr.sbin/edquota/edquota.8:1.12.50.1	Sun Feb  6 22:18:38 2011
+++ src/usr.sbin/edquota/edquota.8	Mon Feb  7 20:31:20 2011
@@ -29,7 +29,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	from: @(#)edquota.8	8.2 (Berkeley) 4/27/95
-.\"	$NetBSD: edquota.8,v 1.12.50.1 2011/02/06 22:18:38 bouyer Exp $
+.\"	$NetBSD: edquota.8,v 1.12.50.2 2011/02/07 20:31:20 bouyer Exp $
 .\"
 .Dd February 6, 2011
 .Dt EDQUOTA 8
@@ -74,6 +74,20 @@
 .Op Fl t Ar block grace time/inode grace time
 .Ar -d |
 .Ar groupname ...
+.Nm
+.Op Fl D
+.Op Fl H
+.Op Fl u
+.Fl c
+.Op Fl f Ar filesystem
+.Ar username ...
+.Nm
+.Op Fl D
+.Op Fl H
+.Fl g
+.Fl c
+.Op Fl f Ar filesystem
+.Ar groupname ...
 .Sh DESCRIPTION
 .Nm
 is a quota editor.
@@ -165,6 +179,12 @@
 per-user/group grace time. To edit the filesystem-wide grace time, use
 .Fl d .
 .Pp
+On quota2-enabled filesystems, the
+.Fl c
+flag cause edquota to clear quota entries for the specified users or groups.
+If disk or inode usages is not 0, limits are reverted to the default quota. 
+If disk and inode usages are 0, the existing quota entries are freed.
+.Pp
 The
 .Fl D
 flag cause edquota to print to the standard error property lists sent to

Index: src/usr.sbin/edquota/edquota.c
diff -u src/usr.sbin/edquota/edquota.c:1.29.16.9 src/usr.sbin/edquota/edquota.c:1.29.16.10
--- src/usr.sbin/edquota/edquota.c:1.29.16.9	Sun Feb  6 22:18:38 2011
+++ src/usr.sbin/edquota/edquota.c	Mon Feb  7 20:31:20 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: edquota.c,v 1.29.16.9 2011/02/06 22:18:38 bouyer Exp $ */
+/*      $NetBSD: edquota.c,v 1.29.16.10 2011/02/07 20:31:20 bouyer Exp $ */
 /*
  * Copyright (c) 1980, 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -41,7 +41,7 @@
 #if 0
 static char sccsid[] = "from: @(#)edquota.c	8.3 (Berkeley) 4/27/95";
 #else
-__RCSID("$NetBSD: edquota.c,v 1.29.16.9 2011/02/06 22:18:38 bouyer Exp $");
+__RCSID("$NetBSD: edquota.c,v 1.29.16.10 2011/02/07 20:31:20 bouyer Exp $");
 #endif
 #endif /* not lint */
 
@@ -113,6 +113,7 @@
 void	freeprivs(struct quotause *);
 int	alldigits(const char *);
 int	hasquota(struct fstab *, int, char **);
+static void clearpriv(int, char **, const char *, int);
 
 int Hflag = 0;
 int Dflag = 0;
@@ -131,6 +132,7 @@
 	char *fs = NULL;
 	int ch;
 	int pflag = 0;
+	int cflag = 0;
 
 	if (argc < 2)
 		usage();
@@ -138,7 +140,7 @@
 		errx(1, "permission denied");
 	protoname = NULL;
 	quotatype = USRQUOTA;
-	while ((ch = getopt(argc, argv, "DHdugp:s:h:t:f:")) != -1) {
+	while ((ch = getopt(argc, argv, "DHcdugp:s:h:t:f:")) != -1) {
 		switch(ch) {
 		case 'D':
 			Dflag++;
@@ -146,6 +148,9 @@
 		case 'H':
 			Hflag++;
 			break;
+		case 'c':
+			cflag++;
+			break;
 		case 'd':
 			dflag++;
 			break;
@@ -179,7 +184,7 @@
 	argv += optind;
 
 	if (pflag) {
-		if (soft || hard || grace || dflag)
+		if (soft || hard || grace || dflag || cflag)
 			usage();
 		if ((protoid = getentry(protoname, quotatype)) == -1)
 			exit(1);
@@ -200,6 +205,9 @@
 		u_int64_t softb, hardb, softi, hardi;
 		time_t  graceb, gracei;
 		char *str;
+
+		if (cflag)
+			usage();
 		if (soft) {
 			str = strsep(&soft, "/");
 			if (str[0] == '\0' || soft == NULL || soft[0] == '\0')
@@ -283,6 +291,12 @@
 		}
 		exit(0);
 	}
+	if (cflag) {
+		if (dflag)
+			usage();
+		clearpriv(argc, argv, fs, quotatype);
+		exit(0);
+	}
 	tmpfd = mkstemp(tmpfil);
 	fchown(tmpfd, getuid(), getgid());
 	if (dflag) {
@@ -316,6 +330,8 @@
 	    "  edquota [-D] [-H] -g [-p groupname] [-f filesystem] -d | groupname ...\n"
 	    "  edquota [-D] [-u] [-f filesystem] [-s b#/i#] [-h b#/i#] [-t t#/t#] \\\n\t-d | username ...\n"
 	    "  edquota [-D] -g [-f filesystem] [-s b#/i#] [-h b#/i#] [-t t#/t#] \\\n\t-d | groupname ...\n"
+	    "  edquota [-D] [-H] [-u] -c [-f filesystem] username ...\n"
+	    "  edquota [-D] [-H] -g -c [-f filesystem] groupname ...\n"
 	    );
 	exit(1);
 }
@@ -1060,3 +1076,97 @@
 	    qfextension[type]);
 	return (1);
 }
+
+static void
+clearpriv(int argc, char **argv, const char *filesys, int quotatype)
+{
+	prop_array_t cmds, datas;
+	prop_dictionary_t protodict, dict, data, cmd;
+	struct plistref pref;
+	bool ret;
+	struct statvfs *fst;
+	int nfst, i, error;
+	int8_t error8;
+	int id;
+
+	/* build a generic command */
+	protodict = quota2_prop_create();
+	cmds = prop_array_create();
+	datas = prop_array_create();
+	if (protodict == NULL || cmds == NULL || datas == NULL) {
+		errx(1, "can't allocate proplist");
+	}
+
+	for ( ; argc > 0; argc--, argv++) {
+		if ((id = getentry(*argv, quotatype)) == -1)
+			continue;
+		data = prop_dictionary_create();
+		if (data == NULL)
+			errx(1, "can't allocate proplist");
+
+		ret = prop_dictionary_set_uint32(data, "id", id);
+		if (!ret)
+			err(1, "prop_dictionary_set(id)");
+		if (!prop_array_add_and_rel(datas, data))
+			err(1, "prop_array_add(data)");
+	}
+	if (!quota2_prop_add_command(cmds, "clear", qfextension[quotatype],
+	    datas))
+		err(1, "prop_add_command");
+
+	if (!prop_dictionary_set(protodict, "commands", cmds))
+		err(1, "prop_dictionary_set(command)");
+
+	/* now loop over quota-enabled filesystems */
+	nfst = getmntinfo(&fst, MNT_WAIT);
+	if (nfst == 0)
+		errx(2, "no filesystems mounted!");
+
+	for (i = 0; i < nfst; i++) {
+		if (strcmp(fst[i].f_fstypename, "ffs") != 0 ||
+		    (fst[i].f_flag & ST_QUOTA) == 0)
+			continue;
+		if (filesys && strcmp(fst[i].f_mntonname, filesys) != 0 &&
+		    strcmp(fst[i].f_mntfromname, filesys) != 0)
+			continue;
+		if (Dflag) {
+			fprintf(stderr, "message to kernel for %s:\n%s\n",
+			    fst[i].f_mntonname,
+			    prop_dictionary_externalize(protodict));
+		}
+
+		if (!prop_dictionary_send_syscall(protodict, &pref))
+			err(1, "prop_dictionary_send_syscall");
+		if (quotactl(fst[i].f_mntonname, &pref) != 0)
+			err(1, "quotactl");
+
+		if ((error = prop_dictionary_recv_syscall(&pref, &dict)) != 0) {
+			errx(1, "prop_dictionary_recv_syscall: %s\n",
+			    strerror(error));
+		}
+
+		if (Dflag) {
+			fprintf(stderr, "reply from kernel for %s:\n%s\n",
+			    fst[i].f_mntonname,
+			    prop_dictionary_externalize(dict));
+		}
+		if ((error = quota2_get_cmds(dict, &cmds)) != 0) {
+			errx(1, "quota2_get_cmds: %s\n",
+			    strerror(error));
+		}
+		/* only one command, no need to iter */
+		cmd = prop_array_get(cmds, 0);
+		if (cmd == NULL)
+			err(1, "prop_array_get(cmd)");
+
+		if (!prop_dictionary_get_int8(cmd, "return", &error8))
+			err(1, "prop_get(return)");
+		if (error8) {
+			fprintf(stderr, "clear %s quota entries on %s: %s\n",
+			    qfextension[quotatype], fst[i].f_mntonname,
+			    strerror(error8));
+		}
+		prop_object_release(dict);
+	}
+	prop_object_release(protodict);
+}

Reply via email to