Module Name:    src
Committed By:   dholland
Date:           Mon Jan 30 16:45:13 UTC 2012

Modified Files:
        src/include: quota.h
        src/lib/libquota: quota_oldfiles.c quota_open.c quota_proplib.c
            quotapvt.h
        src/usr.sbin/quotaon: Makefile quotaon.c

Log Message:
Add quota_quotaon() and quota_quotaoff(). Use them in quotaon(8).


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/include/quota.h
cvs rdiff -u -r1.4 -r1.5 src/lib/libquota/quota_oldfiles.c
cvs rdiff -u -r1.5 -r1.6 src/lib/libquota/quota_open.c
cvs rdiff -u -r1.9 -r1.10 src/lib/libquota/quota_proplib.c
cvs rdiff -u -r1.11 -r1.12 src/lib/libquota/quotapvt.h
cvs rdiff -u -r1.8 -r1.9 src/usr.sbin/quotaon/Makefile
cvs rdiff -u -r1.28 -r1.29 src/usr.sbin/quotaon/quotaon.c

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

Modified files:

Index: src/include/quota.h
diff -u src/include/quota.h:1.4 src/include/quota.h:1.5
--- src/include/quota.h:1.4	Mon Jan 30 16:44:08 2012
+++ src/include/quota.h	Mon Jan 30 16:45:13 2012
@@ -55,6 +55,9 @@ unsigned quota_getnumobjtypes(struct quo
 const char *quota_objtype_getname(struct quotahandle *, int /*objtype*/);
 int quota_objtype_isbytes(struct quotahandle *, int /*objtype*/);
 
+int quota_quotaon(struct quotahandle *, int /*idtype*/);
+int quota_quotaoff(struct quotahandle *, int /*idtype*/);
+
 int quota_get(struct quotahandle *, const struct quotakey *,
 	      struct quotaval *);
 

Index: src/lib/libquota/quota_oldfiles.c
diff -u src/lib/libquota/quota_oldfiles.c:1.4 src/lib/libquota/quota_oldfiles.c:1.5
--- src/lib/libquota/quota_oldfiles.c:1.4	Mon Jan 30 06:15:22 2012
+++ src/lib/libquota/quota_oldfiles.c	Mon Jan 30 16:45:13 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: quota_oldfiles.c,v 1.4 2012/01/30 06:15:22 dholland Exp $	*/
+/*	$NetBSD: quota_oldfiles.c,v 1.5 2012/01/30 16:45:13 dholland Exp $	*/
 
 /*
  * Copyright (c) 1980, 1990, 1993
@@ -237,6 +237,57 @@ __quota_oldfiles_infstab(const char *mou
 	return __quota_oldfiles_find_fstabentry(mountpoint) != NULL;
 }
 
+static void
+__quota_oldfiles_defquotafile(struct quotahandle *qh, int idtype,
+			      char *buf, size_t maxlen)
+{
+	static const char *const names[] = INITQFNAMES;
+
+	(void)snprintf(buf, maxlen, "%s/%s.%s",
+		       qh->qh_mountpoint,
+		       QUOTAFILENAME, names[USRQUOTA]);
+}
+
+const char *
+__quota_oldfiles_getquotafile(struct quotahandle *qh, int idtype,
+			      char *buf, size_t maxlen)
+{
+	const struct oldfiles_fstabentry *ofe;
+	const char *file;
+
+	ofe = __quota_oldfiles_find_fstabentry(qh->qh_mountpoint);
+	if (ofe == NULL) {
+		errno = ENXIO;
+		return NULL;
+	}
+
+	switch (idtype) {
+	    case USRQUOTA:
+		if (!ofe->ofe_hasuserquota) {
+			errno = ENXIO;
+			return NULL;
+		}
+		file = ofe->ofe_userquotafile;
+		break;
+	    case GRPQUOTA:
+		if (!ofe->ofe_hasgroupquota) {
+			errno = ENXIO;
+			return NULL;
+		}
+		file = ofe->ofe_groupquotafile;
+		break;
+	    default:
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (file == NULL) {
+		__quota_oldfiles_defquotafile(qh, idtype, buf, maxlen);
+		file = buf;
+	}
+	return file;
+}
+
 static uint64_t
 dqblk_getlimit(uint32_t val)
 {
@@ -316,8 +367,6 @@ __quota_oldfiles_open(struct quotahandle
 int
 __quota_oldfiles_initialize(struct quotahandle *qh)
 {
-	static const char *const names[] = INITQFNAMES;
-
 	const struct oldfiles_fstabentry *ofe;
 	char path[PATH_MAX];
 	const char *userquotafile, *groupquotafile;
@@ -345,9 +394,8 @@ __quota_oldfiles_initialize(struct quota
 	if (ofe->ofe_hasuserquota) {
 		userquotafile = ofe->ofe_userquotafile;
 		if (userquotafile == NULL) {
-			(void)snprintf(path, sizeof(path), "%s/%s.%s",
-				       qh->qh_mountpoint,
-				       QUOTAFILENAME, names[USRQUOTA]);
+			__quota_oldfiles_defquotafile(qh, USRQUOTA,
+						      path, sizeof(path));
 			userquotafile = path;
 		}
 		if (__quota_oldfiles_open(qh, userquotafile,
@@ -358,9 +406,8 @@ __quota_oldfiles_initialize(struct quota
 	if (ofe->ofe_hasgroupquota) {
 		groupquotafile = ofe->ofe_groupquotafile;
 		if (groupquotafile == NULL) {
-			(void)snprintf(path, sizeof(path), "%s/%s.%s",
-				       qh->qh_mountpoint,
-				       QUOTAFILENAME, names[GRPQUOTA]);
+			__quota_oldfiles_defquotafile(qh, GRPQUOTA,
+						      path, sizeof(path));
 			groupquotafile = path;
 		}
 		if (__quota_oldfiles_open(qh, groupquotafile,
@@ -380,6 +427,45 @@ __quota_oldfiles_getimplname(struct quot
 	return "ufs/ffs quota v1 file access";
 }
 
+int
+__quota_oldfiles_quotaon(struct quotahandle *qh, int idtype)
+{
+	int result;
+
+	/*
+	 * If we have the quota files open, close them.
+	 */
+
+	if (qh->qh_oldfilesopen) {
+		if (qh->qh_userfile >= 0) {
+			close(qh->qh_userfile);
+			qh->qh_userfile = -1;
+		}
+		if (qh->qh_groupfile >= 0) {
+			close(qh->qh_groupfile);
+			qh->qh_groupfile = -1;
+		}
+		qh->qh_oldfilesopen = 0;
+	}
+
+	/*
+	 * Go over to the syscall interface.
+	 */
+
+	result = __quota_proplib_quotaon(qh, idtype);
+	if (result < 0) {
+		return -1;
+	}
+
+	/*
+	 * We succeeded, so all further access should be via the
+	 * kernel.
+	 */
+
+	qh->qh_mode = QUOTA_MODE_PROPLIB;
+	return 0;
+}
+
 static int
 __quota_oldfiles_doget(struct quotahandle *qh, const struct quotakey *qk,
 		       struct quotaval *qv, int *isallzero)

Index: src/lib/libquota/quota_open.c
diff -u src/lib/libquota/quota_open.c:1.5 src/lib/libquota/quota_open.c:1.6
--- src/lib/libquota/quota_open.c:1.5	Wed Jan 25 17:43:37 2012
+++ src/lib/libquota/quota_open.c	Mon Jan 30 16:45:13 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: quota_open.c,v 1.5 2012/01/25 17:43:37 dholland Exp $	*/
+/*	$NetBSD: quota_open.c,v 1.6 2012/01/30 16:45:13 dholland Exp $	*/
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: quota_open.c,v 1.5 2012/01/25 17:43:37 dholland Exp $");
+__RCSID("$NetBSD: quota_open.c,v 1.6 2012/01/30 16:45:13 dholland Exp $");
 
 #include <sys/types.h>
 #include <sys/statvfs.h>
@@ -64,6 +64,15 @@ quota_open(const char *path)
 	 *    3. Check if the volume is listed in fstab as one of
 	 *    the filesystem types supported by quota_oldfiles.c,
 	 *    and with the proper mount options to enable quotas.
+	 *
+	 * Note that (as of this writing) the mount options for
+	 * enabling quotas are accepted by mount for *all* filesystem
+	 * types and then ignored -- the kernel mount flag (ST_QUOTA /
+	 * MNT_QUOTA) gets set either by the filesystem based on its
+	 * own criteria, or for old-style quotas, during quotaon. The
+	 * quota filenames specified in fstab are not passed to or
+	 * known by the kernel except via quota_oldfiles.c! This is
+	 * generally gross but not easily fixed.
 	 */
 
 	if (statvfs(path, &stv) < 0) {
@@ -144,3 +153,41 @@ quota_close(struct quotahandle *qh)
 	free(qh->qh_mountpoint);
 	free(qh);
 }
+
+int
+quota_quotaon(struct quotahandle *qh, int idtype)
+{
+	switch (qh->qh_mode) {
+	    case QUOTA_MODE_NFS:
+		errno = EOPNOTSUPP;
+		break;
+	    case QUOTA_MODE_PROPLIB:
+		return __quota_proplib_quotaon(qh, idtype);
+	    case QUOTA_MODE_OLDFILES:
+		return __quota_oldfiles_quotaon(qh, idtype);
+	    default:
+		errno = EINVAL;
+		break;
+	}
+	return -1;
+}
+
+int
+quota_quotaoff(struct quotahandle *qh, int idtype)
+{
+	switch (qh->qh_mode) {
+	    case QUOTA_MODE_NFS:
+		errno = EOPNOTSUPP;
+		break;
+	    case QUOTA_MODE_PROPLIB:
+		return __quota_proplib_quotaoff(qh, idtype);
+	    case QUOTA_MODE_OLDFILES:
+		/* can't quotaoff if we haven't quotaon'd */
+		errno = ENOTCONN;
+		break;
+	    default:
+		errno = EINVAL;
+		break;
+	}
+	return -1;
+}

Index: src/lib/libquota/quota_proplib.c
diff -u src/lib/libquota/quota_proplib.c:1.9 src/lib/libquota/quota_proplib.c:1.10
--- src/lib/libquota/quota_proplib.c:1.9	Mon Jan 30 16:44:08 2012
+++ src/lib/libquota/quota_proplib.c	Mon Jan 30 16:45:13 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: quota_proplib.c,v 1.9 2012/01/30 16:44:08 dholland Exp $	*/
+/*	$NetBSD: quota_proplib.c,v 1.10 2012/01/30 16:45:13 dholland Exp $	*/
 /*-
   * Copyright (c) 2011 Manuel Bouyer
   * All rights reserved.
@@ -26,7 +26,7 @@
   */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: quota_proplib.c,v 1.9 2012/01/30 16:44:08 dholland Exp $");
+__RCSID("$NetBSD: quota_proplib.c,v 1.10 2012/01/30 16:45:13 dholland Exp $");
 
 #include <stdlib.h>
 #include <string.h>
@@ -35,6 +35,7 @@ __RCSID("$NetBSD: quota_proplib.c,v 1.9 
 #include <err.h>
 
 #include <quota.h>
+#include <ufs/ufs/quota1.h>
 #include "quotapvt.h"
 
 #include <quota/quotaprop.h>
@@ -55,6 +56,8 @@ struct proplib_quotacursor {
 	unsigned didblocks;
 };
 
+static const char *const __quota1_qfnames[] = INITQFNAMES;
+
 int
 __quota_proplib_getversion(struct quotahandle *qh, int8_t *version_ret)
 {
@@ -240,6 +243,112 @@ __quota_proplib_objtype_isbytes(int objt
 }
 
 static int
+__quota_proplib_quotaonoff(struct quotahandle *qh, int idtype, int offmode)
+{
+	prop_dictionary_t dict, data, cmd;
+	prop_array_t cmds, datas;
+	struct plistref pref;
+	int8_t error8;
+	const char *file;
+	char path[PATH_MAX];
+
+	/*
+	 * Note that while it is an error to call quotaon on something
+	 * that isn't a volume with old-style quotas that expects
+	 * quotaon to be called, it's not our responsibility to check
+	 * for that; the filesystem will. Also note that it is not an
+	 * error to call quotaon repeatedly -- apparently this is to
+	 * permit changing the quota file in use on the fly or
+	 * something. So all we need to do here is ask the oldfiles
+	 * code if the mount option was set in fstab and fetch back
+	 * the filename.
+	 */
+
+	 if (offmode) {
+		 file = NULL;
+	 } else {
+		 file = __quota_oldfiles_getquotafile(qh, idtype,
+						      path, sizeof(path));
+		 if (file == NULL) {
+			 /*
+			  * This idtype (or maybe any idtype) was
+			  * not enabled in fstab.
+			  */
+			 errno = ENXIO;
+			 return -1;
+		 }
+	 }
+
+	dict = quota_prop_create();
+	cmds = prop_array_create();
+	datas = prop_array_create();
+
+	if (dict == NULL || cmds == NULL || datas == NULL)
+		errx(1, "can't allocate proplist");
+
+	if (offmode) {
+		if (!quota_prop_add_command(cmds, "quotaoff",
+		    __quota1_qfnames[idtype], datas))
+			err(1, "prop_add_command");
+	} else {
+		data = prop_dictionary_create();
+		if (data == NULL)
+			errx(1, "can't allocate proplist");
+		if (!prop_dictionary_set_cstring(data, "quotafile", file))
+			err(1, "prop_dictionary_set(quotafile)");
+		if (!prop_array_add_and_rel(datas, data))
+			err(1, "prop_array_add(data)");
+		if (!quota_prop_add_command(cmds, "quotaon",
+		    __quota1_qfnames[idtype], datas))
+			err(1, "prop_add_command");
+	}
+	if (!prop_dictionary_set(dict, "commands", cmds))
+		err(1, "prop_dictionary_set(command)");
+
+	if (prop_dictionary_send_syscall(dict, &pref) != 0)
+		err(1, "prop_dictionary_send_syscall");
+	prop_object_release(dict);
+
+	if (quotactl(qh->qh_mountpoint, &pref) != 0) {
+		warn("quotactl(%s)", qh->qh_mountpoint);
+		return -1;
+	}
+
+	if (prop_dictionary_recv_syscall(&pref, &dict) != 0)
+		err(1, "prop_dictionary_recv_syscall");
+
+	if ((errno = quota_get_cmds(dict, &cmds)) != 0)
+		err(1, "quota_get_cmds");
+
+	/* 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) {
+		errno = error8;
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+__quota_proplib_quotaon(struct quotahandle *qh, int idtype)
+{
+	return __quota_proplib_quotaonoff(qh, idtype, 0);
+}
+
+int
+__quota_proplib_quotaoff(struct quotahandle *qh, int idtype)
+{
+	return __quota_proplib_quotaonoff(qh, idtype, 1);
+}
+
+static int
 __quota_proplib_extractval(int objtype, prop_dictionary_t data,
 			   struct quotaval *qv)
 {

Index: src/lib/libquota/quotapvt.h
diff -u src/lib/libquota/quotapvt.h:1.11 src/lib/libquota/quotapvt.h:1.12
--- src/lib/libquota/quotapvt.h:1.11	Mon Jan 30 16:44:09 2012
+++ src/lib/libquota/quotapvt.h	Mon Jan 30 16:45:13 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: quotapvt.h,v 1.11 2012/01/30 16:44:09 dholland Exp $	*/
+/*	$NetBSD: quotapvt.h,v 1.12 2012/01/30 16:45:13 dholland Exp $	*/
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -64,6 +64,8 @@ const char *__quota_proplib_idtype_getna
 unsigned __quota_proplib_getnumobjtypes(void);
 const char *__quota_proplib_objtype_getname(int objtype);
 int __quota_proplib_objtype_isbytes(int objtype);
+int __quota_proplib_quotaon(struct quotahandle *, int idtype);
+int __quota_proplib_quotaoff(struct quotahandle *, int idtype);
 int __quota_proplib_get(struct quotahandle *qh, const struct quotakey *qk,
 			struct quotaval *qv);
 int __quota_proplib_put(struct quotahandle *qh, const struct quotakey *qk,
@@ -95,6 +97,9 @@ void __quota_oldfiles_load_fstab(void);
 int __quota_oldfiles_infstab(const char *);
 int __quota_oldfiles_initialize(struct quotahandle *qh);
 const char *__quota_oldfiles_getimplname(struct quotahandle *);
+const char *__quota_oldfiles_getquotafile(struct quotahandle *, int idtype,
+					  char *buf, size_t maxlen);
+int __quota_oldfiles_quotaon(struct quotahandle *, int idtype);
 int __quota_oldfiles_get(struct quotahandle *qh, const struct quotakey *qk,
 			struct quotaval *qv);
 int __quota_oldfiles_put(struct quotahandle *qh, const struct quotakey *qk,

Index: src/usr.sbin/quotaon/Makefile
diff -u src/usr.sbin/quotaon/Makefile:1.8 src/usr.sbin/quotaon/Makefile:1.9
--- src/usr.sbin/quotaon/Makefile:1.8	Thu Mar 24 17:05:47 2011
+++ src/usr.sbin/quotaon/Makefile	Mon Jan 30 16:45:13 2012
@@ -1,5 +1,5 @@
 #	from: @(#)Makefile	8.1 (Berkeley) 6/6/93
-#	$NetBSD: Makefile,v 1.8 2011/03/24 17:05:47 bouyer Exp $
+#	$NetBSD: Makefile,v 1.9 2012/01/30 16:45:13 dholland Exp $
 
 .include <bsd.own.mk>
 WARNS	?= 4
@@ -10,11 +10,6 @@ MAN=	quotaon.8
 MLINKS=	quotaon.8 quotaoff.8
 LINKS=	${BINDIR}/quotaon ${BINDIR}/quotaoff
 
-.PATH:  ${NETBSDSRCDIR}/usr.bin/quota
-SRCS+=  quotautil.c
-CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/quota
-CPPFLAGS+=-I${NETBSDSRCDIR}/sys
-
 DPADD=	${LIBQUOTA} ${LIBPROP} ${LIBRPCSVC}
 LDADD=	-lquota -lprop -lrpcsvc
 

Index: src/usr.sbin/quotaon/quotaon.c
diff -u src/usr.sbin/quotaon/quotaon.c:1.28 src/usr.sbin/quotaon/quotaon.c:1.29
--- src/usr.sbin/quotaon/quotaon.c:1.28	Wed Jan 25 01:28:40 2012
+++ src/usr.sbin/quotaon/quotaon.c	Mon Jan 30 16:45:13 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: quotaon.c,v 1.28 2012/01/25 01:28:40 dholland Exp $	*/
+/*	$NetBSD: quotaon.c,v 1.29 2012/01/30 16:45:13 dholland Exp $	*/
 
 /*
  * Copyright (c) 1980, 1990, 1993
@@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 19
 #if 0
 static char sccsid[] = "@(#)quotaon.c	8.1 (Berkeley) 6/6/93";
 #else
-__RCSID("$NetBSD: quotaon.c,v 1.28 2012/01/25 01:28:40 dholland Exp $");
+__RCSID("$NetBSD: quotaon.c,v 1.29 2012/01/30 16:45:13 dholland Exp $");
 #endif
 #endif /* not lint */
 
@@ -53,10 +53,8 @@ __RCSID("$NetBSD: quotaon.c,v 1.28 2012/
 #include <sys/file.h>
 #include <sys/mount.h>
 
-#include <quota/quotaprop.h>
+#include <quota.h>
 #include <ufs/ufs/quota1.h>
-#include <sys/quota.h>
-
 
 #include <err.h>
 #include <fstab.h>
@@ -66,26 +64,29 @@ __RCSID("$NetBSD: quotaon.c,v 1.28 2012/
 #include <string.h>
 #include <unistd.h>
 
-#include "quotautil.h"
 
-static int	aflag;		/* all file systems */
-static int	gflag;		/* operate on group quotas */
-static int	uflag;		/* operate on user quotas */
 static int	vflag;		/* verbose */
 
 static void usage(void) __dead;
-static int quotaonoff(struct fstab *, int, int, const char *);
+static int quotaonoff(struct fstab *, struct quotahandle *, int, int, int);
 static int readonly(struct fstab *);
+static int oneof(const char *target, char *list[], int cnt);
 
 int
 main(int argc, char *argv[])
 {
 	struct fstab *fs;
-	char qfnp[MAXPATHLEN];
+	struct quotahandle *qh;
 	long argnum, done = 0;
 	int i, offmode = 0, errs = 0;
+	unsigned restrictions;
 	int ch;
 
+	int aflag = 0;		/* all file systems */
+	int gflag = 0;		/* operate on group quotas */
+	int uflag = 0;		/* operate on user quotas */
+	int noguflag = 0;	/* operate on both (by default) */
+
 	if (strcmp(getprogname(), "quotaoff") == 0)
 		offmode++;
 	else if (strcmp(getprogname(), "quotaon") != 0)
@@ -117,30 +118,74 @@ main(int argc, char *argv[])
 		usage();
 
 	if (!gflag && !uflag) {
-		gflag++;
-		uflag++;
+		noguflag = 1;
+	}
+
+	/*
+	 * XXX at the moment quota_open also uses getfsent(), but it
+	 * uses it only up front. To avoid conflicting with it, let it
+	 * initialize first.
+	 */
+	qh = quota_open("/");
+	if (qh != NULL) {
+		quota_close(qh);
 	}
+
 	setfsent();
 	while ((fs = getfsent()) != NULL) {
 		if ((strcmp(fs->fs_vfstype, "ffs") &&
 		     strcmp(fs->fs_vfstype, "lfs")) ||
 		    strcmp(fs->fs_type, FSTAB_RW))
 			continue;
-		if (aflag) {
-			if (gflag && hasquota(qfnp, sizeof(qfnp), fs, GRPQUOTA))
-				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
-			if (uflag && hasquota(qfnp, sizeof(qfnp), fs, USRQUOTA))
-				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
+
+		if (!aflag) {
+			if ((argnum = oneof(fs->fs_file, argv, argc)) < 0 &&
+			    (argnum = oneof(fs->fs_spec, argv, argc)) < 0) {
+				continue;
+			}
+			done |= 1U << argnum;
+		}
+
+		qh = quota_open(fs->fs_file);
+		if (qh == NULL) {
+			if (!aflag) {
+				warn("quota_open");
+				errs++;
+			}
+			continue;
+		}
+
+		restrictions = quota_getrestrictions(qh);
+		if ((restrictions & QUOTA_RESTRICT_NEEDSQUOTACHECK) == 0) {
+			/* Not a quota v1 volume, skip it */
+			if (!aflag) {
+				errno = EBUSY;
+				warn("%s", fs->fs_file);
+				errs++;
+			}
+			quota_close(qh);
 			continue;
 		}
-		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
-		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
-			done |= 1U << argnum;
-			if (gflag && hasquota(qfnp, sizeof(qfnp), fs, GRPQUOTA))
-				errs += quotaonoff(fs, offmode, GRPQUOTA, qfnp);
-			if (uflag && hasquota(qfnp, sizeof(qfnp), fs, USRQUOTA))
-				errs += quotaonoff(fs, offmode, USRQUOTA, qfnp);
+
+		/*
+		 * The idea here is to warn if someone explicitly
+		 * tries to turn on group quotas and there are no
+		 * group quotas, and likewise for user quotas, but not
+		 * to warn if just doing the default thing and one of
+		 * the quota types isn't configured.
+		 */
+
+		if (noguflag) {
+			errs += quotaonoff(fs, qh, offmode, GRPQUOTA, 0);
+			errs += quotaonoff(fs, qh, offmode, USRQUOTA, 0);
 		}
+		if (gflag) {
+			errs += quotaonoff(fs, qh, offmode, GRPQUOTA, 1);
+		}
+		if (uflag) {
+			errs += quotaonoff(fs, qh, offmode, USRQUOTA, 1);
+		}
+		quota_close(qh);
 	}
 	endfsent();
 	for (i = 0; i < argc; i++)
@@ -159,76 +204,34 @@ usage(void)
 }
 
 static int
-quotaonoff( struct fstab *fs, int offmode, int type, const char *qfpathname)
+quotaonoff(struct fstab *fs, struct quotahandle *qh, int offmode, int idtype,
+	   int warn_on_enxio)
 {
 	const char *mode = (offmode == 1) ? "off" : "on";
-	prop_dictionary_t dict, data, cmd;
-	prop_array_t cmds, datas;
-	struct plistref pref;
-	int8_t error8;
-
-	dict = quota_prop_create();
-	cmds = prop_array_create();
-	datas = prop_array_create();
 
-	if (strcmp(fs->fs_file, "/") && readonly(fs))
+	if (strcmp(fs->fs_file, "/") && readonly(fs)) {
 		return 1;
-
-	if (dict == NULL || cmds == NULL || datas == NULL)
-		errx(1, "can't allocate proplist");
+	}
 
 	if (offmode) {
-		if (!quota_prop_add_command(cmds, "quotaoff",
-		    qfextension[type], datas))
-			err(1, "prop_add_command");
+		if (quota_quotaoff(qh, idtype)) {
+			if (warn_on_enxio || errno != ENXIO) {
+				warn("quota%s for %s", mode, fs->fs_file);
+			}
+			return 1;
+		}
 	} else {
-		data = prop_dictionary_create();
-		if (data == NULL)
-			errx(1, "can't allocate proplist");
-		if (!prop_dictionary_set_cstring(data, "quotafile", 
-		    qfpathname))
-			err(1, "prop_dictionary_set(quotafile)");
-		if (!prop_array_add_and_rel(datas, data))
-			err(1, "prop_array_add(data)");
-		if (!quota_prop_add_command(cmds, "quotaon",
-		    qfextension[type], datas))
-			err(1, "prop_add_command");
-	}
-	if (!prop_dictionary_set(dict, "commands", cmds))
-		err(1, "prop_dictionary_set(command)");
-
-	if (prop_dictionary_send_syscall(dict, &pref) != 0)
-		err(1, "prop_dictionary_send_syscall");
-	prop_object_release(dict);
-
-	if (quotactl(fs->fs_file, &pref) != 0) {
-		warn("quotactl(%s)", fs->fs_file);
-		return(1);
-	}
-
-	if (prop_dictionary_recv_syscall(&pref, &dict) != 0)
-		err(1, "prop_dictionary_recv_syscall");
-
-	if ((errno = quota_get_cmds(dict, &cmds)) != 0)
-		err(1, "quota_get_cmds");
-
-	/* 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) {
-		errno = error8;
-		warn("quota%s for %s", mode, fs->fs_file);
-		return 1;
+		if (quota_quotaon(qh, idtype)) {
+			if (warn_on_enxio || errno != ENXIO) {
+				warn("quota%s for %s", mode, fs->fs_file);
+			}
+			return 1;
+		}
 	}
 
 	if (vflag) {
 		printf("%s: %s quotas turned %s\n",
-		    fs->fs_file, qfextension[type], mode);
+		    fs->fs_file, quota_idtype_getname(qh, idtype), mode);
 	}
 	return 0;
 }
@@ -253,3 +256,17 @@ readonly(struct fstab *fs)
 	}
 	return 0;
 }
+
+/*
+ * Check to see if target appears in list of size cnt.
+ */
+static int
+oneof(const char *target, char *list[], int cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++)
+		if (strcmp(target, list[i]) == 0)
+			return i;
+	return -1;
+}

Reply via email to