Re: any FS with tree-based quota system?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Monday February 13, [email protected] wrote:
> On Tue, 14 Feb 2006, Neil Brown wrote:
> > You still need to assign a uid to each user (the kernel needs some 
> > number to use as an index into the quotas file).  But only the top-level 
> > directory of each tree needs to be owned by the uid.  Files beneath the 
> > top can be owned by anyone.
> 
> I'm hoping to modify your patch to use the inode at the root of the tree 
> instead of a particular uid as the quota owner, so that setting a quota of 
> 50Mb on /some/location would charge usage for any children of 
> /some/location to the inode of /some/location.

That sounds possible...
So you are, in fact, assigning a uid to each user, but you are using
the filesystem to do it - the inode number that the filesystem uses
for the directory becomes the uid for the corresponding user.
You wouldn't even need to change the kernel patch.
When you make a directory do
   mkdir $dir
   chown `stat -c '%i' $dir` $dir

and the quotas will do what you want (you might need to fix
group-access so that you controlling application can access the files
properly. 


> 
> > I can dig-up a patch for quota-utils if you want to proceed with this.
> 
> I would appreciate that.
> 

The following seems to be against 3.09.  There are actually two
patches, the main one and a little fixup afterwards.

These patches *don't* update the documentation (sorry).  They fairly
consistently use 'Y' to request tree quotas, because:
 - a 'Y' looks a bit like a tree and
 - both 't' and 'T' were already taken in some tools.

NeilBrown


-----------------------
diff -Naur quota-tools.orig/configure quota-tools/configure
--- quota-tools.orig/configure	2002-11-13 04:00:32.000000000 +1100
+++ quota-tools/configure	2003-07-14 12:42:00.000000000 +1000
@@ -1133,6 +1133,8 @@
   cat > conftest.$ac_ext <<EOF
 #line 1135 "configure"
 #include "confdefs.h"
+#include <stdio.h>
+#include <ext2fs/ext2_fs.h>
 #include <ext2fs/ext2fs.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
diff -Naur quota-tools.orig/convertquota.c quota-tools/convertquota.c
--- quota-tools.orig/convertquota.c	2002-11-12 21:00:05.000000000 +1100
+++ quota-tools/convertquota.c	2003-07-14 12:42:00.000000000 +1000
@@ -28,7 +28,7 @@
 
 char *mntpoint;
 char *progname;
-int ucv, gcv;
+int ucv, gcv, tcv;
 struct quota_handle *qn;	/* Handle of new file */
 int action;			/* Action to be performed */
 
@@ -44,7 +44,7 @@
 	int ret;
 
 	action = ACT_FORMAT;
-	while ((ret = getopt(argcnt, argstr, "Vugefh:")) != -1) {
+	while ((ret = getopt(argcnt, argstr, "YVugefh:")) != -1) {
 		switch (ret) {
 			case '?':
 			case 'h':
@@ -58,6 +58,9 @@
 			case 'g':
 				gcv = 1;
 				break;
+			case 'Y':
+				tcv = 1;
+				break;
 			case 'e':
 				action = ACT_ENDIAN;
 				break;
@@ -72,7 +75,7 @@
 		usage();
 	}
 
-	if (!(ucv | gcv))
+	if (!(ucv | gcv | tcv))
 		ucv = 1;
 
 	mntpoint = argstr[optind];
@@ -355,6 +358,8 @@
 		ret |= convert_file(USRQUOTA, mnt);
 	if (gcv)
 		ret |= convert_file(GRPQUOTA, mnt);
+	if (tcv)
+		ret |= convert_file(TREEQUOTA, mnt);
 	end_mounts_scan();
 
 	if (ret)
diff -Naur quota-tools.orig/edquota.c quota-tools/edquota.c
--- quota-tools.orig/edquota.c	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/edquota.c	2003-07-14 12:42:00.000000000 +1000
@@ -100,9 +100,9 @@
 	dirname = NULL;
 	quotatype = USRQUOTA;
 #if defined(RPC_SETQUOTA)
-	while ((ret = getopt(argc, argv, "ugrntTVp:F:f:")) != -1) {
+	while ((ret = getopt(argc, argv, "YugrntTVp:F:f:")) != -1) {
 #else
-	while ((ret = getopt(argc, argv, "ugtTVp:F:f:")) != -1) {
+	while ((ret = getopt(argc, argv, "YugtTVp:F:f:")) != -1) {
 #endif
 		switch (ret) {
 		  case 'p':
@@ -112,6 +112,8 @@
 		  case 'g':
 			  quotatype = GRPQUOTA;
 			  break;
+		case 'Y':
+			  quotatype = TREEQUOTA;
 #if defined(RPC_SETQUOTA)
 		  case 'n':
 		  case 'r':
diff -Naur quota-tools.orig/mntopt.h quota-tools/mntopt.h
--- quota-tools.orig/mntopt.h	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/mntopt.h	2003-07-14 12:42:00.000000000 +1000
@@ -18,6 +18,7 @@
 #define MNTOPT_QUOTA		"quota"	/* enforce user quota */
 #define MNTOPT_USRQUOTA		"usrquota"	/* enforce user quota */
 #define MNTOPT_GRPQUOTA		"grpquota"	/* enforce group quota */
+#define MNTOPT_TREEQUOTA	"treequota"	/* enforce tree quota */
 #define MNTOPT_RSQUASH		"rsquash"	/* root as ordinary user */
 #define MNTOPT_BIND		"bind"		/* binded mount */
 #define MNTOPT_LOOP		"loop"		/* loopback mount */
diff -Naur quota-tools.orig/quota.c quota-tools/quota.c
--- quota-tools.orig/quota.c	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/quota.c	2003-07-14 14:17:56.000000000 +1000
@@ -68,6 +68,7 @@
 #define FL_LOCALONLY 32
 #define FL_QUIETREFUSE 64
 #define FL_NOAUTOFS 128
+#define FL_TREE 256
 
 int flags, fmt = -1;
 char *progname;
@@ -85,7 +86,7 @@
 	gettexton();
 	progname = basename(argv[0]);
 
-	while ((ret = getopt(argc, argv, "guqvsVliQF:")) != -1) {
+	while ((ret = getopt(argc, argv, "YtguqvsVliQF:")) != -1) {
 		switch (ret) {
 		  case 'g':
 			  flags |= FL_GROUP;
@@ -93,6 +94,10 @@
 		  case 'u':
 			  flags |= FL_USER;
 			  break;
+		  case 'Y':
+		  case 't':
+			  flags |= FL_TREE;
+			  break;
 		  case 'q':
 			  flags |= FL_QUIET;
 			  break;
@@ -125,7 +130,8 @@
 	argc -= optind;
 	argv += optind;
 
-	if (!(flags & FL_USER) && !(flags & FL_GROUP))
+	if (!(flags & FL_USER) && !(flags & FL_GROUP) 
+	    && !(flags & FL_TREE))
 		flags |= FL_USER;
 	init_kernel_interface();
 
@@ -140,16 +146,21 @@
 			for (i = 0; i < ngroups; i++)
 				ret |= showquotas(GRPQUOTA, gidset[i]);
 		}
+		if (flags & FL_TREE)
+			ret |= showquotas(TREEQUOTA, getuid());
 		exit(ret);
 	}
 
-	if ((flags & FL_USER) && (flags & FL_GROUP))
+	if ((flags & (FL_USER|FL_TREE)) && (flags & FL_GROUP))
 		usage();
 
 	if (flags & FL_USER)
 		for (; argc > 0; argc--, argv++)
 			ret |= showquotas(USRQUOTA, user2uid(*argv));
-	else if (flags & FL_GROUP)
+	if (flags & FL_TREE)
+		for (; argc > 0; argc--, argv++)
+			ret |= showquotas(TREEQUOTA, user2uid(*argv));
+	if (flags & FL_GROUP)
 		for (; argc > 0; argc--, argv++)
 			ret |= showquotas(GRPQUOTA, group2gid(*argv));
 	return ret;
@@ -158,8 +169,9 @@
 void usage(void)
 {
 	errstr( "%s%s%s",
-		_("Usage: quota [-guqvs] [-l | -Q] [-i] [-F quotaformat]\n"),
+		_("Usage: quota [-gutYqvs] [-l | -Q] [-i] [-F quotaformat]\n"),
 		_("\tquota [-qvs] [-l | -Q] [-i] [-F quotaformat] -u username ...\n"),
+		_("\tquota [-qvs] [-l | -Q] [-i] [-F quotaformat] -Y username ...\n"),
 		_("\tquota [-qvs] [-l | -Q] [-i] [-F quotaformat] -g groupname ...\n"));
 	fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
 	exit(1);
diff -Naur quota-tools.orig/quota.h quota-tools/quota.h
--- quota-tools.orig/quota.h	2002-05-31 09:39:26.000000000 +1000
+++ quota-tools/quota.h	2003-07-14 12:42:00.000000000 +1000
@@ -6,9 +6,10 @@
 typedef u_int32_t qid_t;	/* Type in which we store ids in memory */
 typedef u_int64_t qsize_t;	/* Type in which we store size limitations */
 
-#define MAXQUOTAS 2
+#define MAXQUOTAS 3
 #define USRQUOTA  0		/* element used for user quotas */
 #define GRPQUOTA  1		/* element used for group quotas */
+#define TREEQUOTA  2		/* element used for tree quotas */
 
 /*
  * Definitions for the default names of the quotas files.
@@ -16,6 +17,7 @@
 #define INITQFNAMES { \
 	"user",    /* USRQUOTA */ \
 	"group",   /* GRPQUOTA */ \
+	"tree",    /* TREEQUOTA */ \
 	"undefined", \
 }
 
@@ -24,7 +26,8 @@
  */
 #define INITQMAGICS {\
 	0xd9c01f11,	/* USRQUOTA */\
-	0xd9c01927	/* GRPQUOTA */\
+	0xd9c01927,	/* GRPQUOTA */\
+	0xd9c01abc	/* TREEQUOTA */\
 }
 
 /* Size of blocks in which are counted size limits in generic utility parts */
diff -Naur quota-tools.orig/quotacheck.c quota-tools/quotacheck.c
--- quota-tools.orig/quotacheck.c	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/quotacheck.c	2003-07-14 14:14:34.000000000 +1000
@@ -28,7 +28,7 @@
 #include <sys/mount.h>
 
 #if defined(EXT2_DIRECT)
-#include <linux/ext2_fs.h>
+#include <ext2fs/ext2_fs.h>
 #include <ext2fs/ext2fs.h>
 #endif
 
@@ -63,7 +63,7 @@
 dev_t cur_dev;			/* Device we are working on */
 int files_done, dirs_done;
 int flags, fmt = -1, cfmt;	/* Options from command line; Quota format to use spec. by user; Actual format to check */
-int uwant, gwant, ucheck, gcheck;	/* Does user want to check user/group quota; Do we check user/group quota? */
+int uwant, gwant, twant, ucheck, gcheck, tcheck;	/* Does user want to check user/group quota; Do we check user/group quota? */
 char *mntpoint;			/* Mountpoint to check */
 char *progname;
 struct util_dqinfo old_info[MAXQUOTAS];	/* Loaded infos */
@@ -181,7 +181,7 @@
 /*
  * Add a number of blocks and inodes to a quota.
  */
-static void add_to_quota(int type, ino_t i_num, uid_t i_uid, gid_t i_gid, mode_t i_mode,
+static void add_to_quota(int type, ino_t i_num, uid_t i_uid, gid_t i_gid, uid_t i_tid, mode_t i_mode,
 			 nlink_t i_nlink, loff_t i_space, int need_remember)
 {
 	qid_t wanted;
@@ -189,6 +189,8 @@
 
 	if (type == USRQUOTA)
 		wanted = i_uid;
+	else if (type == TREEQUOTA)
+		wanted = i_tid;
 	else
 		wanted = i_gid;
 
@@ -281,7 +283,7 @@
 
 static void usage(void)
 {
-	printf(_("Utility for checking and repairing quota files.\n%s [-gucfinvdmMR] [-F <quota-format>] filesystem|-a\n"), progname);
+	printf(_("Utility for checking and repairing quota files.\n%s [-gucfinvdmtYMR] [-F <quota-format>] filesystem|-a\n"), progname);
 	printf(_("Bugs to %s\n"), MY_EMAIL);
 	exit(1);
 }
@@ -290,7 +292,7 @@
 {
 	int ret;
 
-	while ((ret = getopt(argcnt, argstr, "VhbcvugidnfF:mMRa")) != -1) {
+	while ((ret = getopt(argcnt, argstr, "tYVhbcvugidnfF:mMRa")) != -1) {
   	        switch (ret) {
 		  case 'b':
   		          flags |= FL_BACKUPS;
@@ -301,6 +303,10 @@
 		  case 'u':
 			  uwant = 1;
 			  break;
+		  case 't':
+		  case 'Y':
+			  twant = 1;
+			  break;
 		  case 'd':
 			  flags |= FL_DEBUG;
 			  setlinebuf(stderr);
@@ -343,7 +349,7 @@
 			usage();
 		}
 	}
-	if (!(uwant | gwant))
+	if (!(uwant | gwant | twant))
 		uwant = 1;
 	if ((argcnt == optind && !(flags & FL_ALL)) || (argcnt > optind && flags & FL_ALL)) {
 		fputs(_("Bad number of arguments.\n"), stderr);
@@ -375,6 +381,7 @@
 	uid_t uid;
 	gid_t gid;
 
+#define i_tid i_reserved2
 	if ((error = ext2fs_open(device, 0, 0, 0, unix_io_manager, &fs))) {
 		errstr(_("error (%d) while opening %s\n"), (int)error, device);
 		return -1;
@@ -410,11 +417,15 @@
 			if (inode.i_uid_high | inode.i_gid_high)
 				debug(FL_DEBUG, _("High uid detected.\n"));
 			if (ucheck)
-				add_to_quota(USRQUOTA, i_num, uid, gid,
+				add_to_quota(USRQUOTA, i_num, uid, gid, inode.i_tid,
 					     inode.i_mode, inode.i_links_count,
 					     inode.i_blocks << 9, 0);
 			if (gcheck)
-				add_to_quota(GRPQUOTA, i_num, uid, gid,
+				add_to_quota(GRPQUOTA, i_num, uid, gid, inode.i_tid,
+					     inode.i_mode, inode.i_links_count,
+					     inode.i_blocks << 9, 0);
+			if (tcheck)
+				add_to_quota(TREEQUOTA, i_num, uid, gid, inode.i_tid,
 					     inode.i_mode, inode.i_links_count,
 					     inode.i_blocks << 9, 0);
 			if (S_ISDIR(inode.i_mode))
@@ -453,10 +464,13 @@
 	}
 	qspace = getqsize(pathname, &st);
 	if (ucheck)
-		add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+		add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, 0, st.st_mode,
 			     st.st_nlink, qspace, 0);
 	if (gcheck)
-		add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+		add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, 0, st.st_mode,
+			     st.st_nlink, qspace, 0);
+	if (tcheck)
+		add_to_quota(TREEQUOTA, st.st_ino, st.st_uid, st.st_gid, 0, st.st_mode,
 			     st.st_nlink, qspace, 0);
 
 	if ((dp = opendir(pathname)) == (DIR *) NULL)
@@ -477,10 +491,13 @@
 
 		qspace = getqsize(de->d_name, &st);
 		if (ucheck)
-			add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+			add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, 0, st.st_mode,
 				     st.st_nlink, qspace, !S_ISDIR(st.st_mode));
 		if (gcheck)
-			add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+			add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, 0, st.st_mode,
+				     st.st_nlink, qspace, !S_ISDIR(st.st_mode));
+		if (tcheck)
+			add_to_quota(TREEQUOTA, st.st_ino, st.st_uid, st.st_gid, 0, st.st_mode,
 				     st.st_nlink, qspace, !S_ISDIR(st.st_mode));
 
 		if (S_ISDIR(st.st_mode)) {
@@ -766,7 +783,10 @@
 	if (gcheck)
 		if (process_file(mnt, GRPQUOTA) < 0)
 			gcheck = 0;
-	if (!ucheck && !gcheck)	/* Nothing to check? */
+	if (tcheck)
+		if (process_file(mnt, TREEQUOTA) < 0)
+			tcheck = 0;
+	if (!ucheck && !gcheck && !tcheck)	/* Nothing to check? */
 		return;
 	if (!(flags & FL_NOREMOUNT)) {
 		/* Now we try to remount fs read-only to prevent races when scanning filesystem */
@@ -817,6 +837,8 @@
 		dump_to_file(mnt, USRQUOTA);
 	if (gcheck)
 		dump_to_file(mnt, GRPQUOTA);
+	if (tcheck)
+		dump_to_file(mnt, TREEQUOTA);
 out:
 	remove_list();
 }
@@ -834,6 +856,10 @@
 		else if ((option = hasmntopt(mnt, MNTOPT_QUOTA)))
 			option += strlen(MNTOPT_QUOTA);
 	}
+	else if (type == TREEQUOTA) {
+		if ((option = hasmntopt(mnt, MNTOPT_TREEQUOTA)))
+			option += strlen(MNTOPT_TREEQUOTA);
+	}
 	else {
 		if ((option = hasmntopt(mnt, MNTOPT_GRPQUOTA)))
 			option += strlen(MNTOPT_GRPQUOTA);
@@ -881,10 +907,14 @@
 			gcheck = 1;
 		else
 			gcheck = 0;
-		if (!ucheck && !gcheck)
+		if (twant && hasquota(mnt, TREEQUOTA))
+			tcheck = 1;
+		else
+			tcheck = 0;
+		if (!ucheck && !gcheck && !tcheck)
 			continue;
 		if (cfmt == -1) {
-			if ((cfmt = detect_filename_format(mnt, ucheck ? USRQUOTA : GRPQUOTA)) == -1) {
+			if ((cfmt = detect_filename_format(mnt, ucheck ? USRQUOTA : tcheck ? TREEQUOTA : GRPQUOTA)) == -1) {
 				errstr(_("Cannot guess format from filename on %s. Please specify format on commandline.\n"),
 					mnt->mnt_fsname);
 				continue;
diff -Naur quota-tools.orig/quotaon.c quota-tools/quotaon.c
--- quota-tools.orig/quotaon.c	2002-06-17 05:00:46.000000000 +1000
+++ quota-tools/quotaon.c	2003-07-14 12:42:00.000000000 +1000
@@ -55,6 +55,7 @@
 #define FL_ALL 8
 #define FL_STAT 16
 #define FL_OFF 32
+#define FL_TREE 64
 
 int flags, fmt = -1;
 char *progname;
@@ -72,7 +73,7 @@
 {
 	int c;
 
-	while ((c = getopt(argcnt, argstr, "afvugpx:VF:")) != -1) {
+	while ((c = getopt(argcnt, argstr, "tYafvugpx:VF:")) != -1) {
 		switch (c) {
 		  case 'a':
 			  flags |= FL_ALL;
@@ -86,6 +87,10 @@
 		  case 'u':
 			  flags |= FL_USER;
 			  break;
+		  case 't':
+		  case 'Y':
+			  flags |= FL_TREE;
+			  break;
 		  case 'v':
 			  flags |= FL_VERBOSE;
 			  break;
@@ -114,8 +119,8 @@
 		fputs(_("Can't turn on/off quotas via RPC.\n"), stderr);
 		exit(1);
 	}
-	if (!(flags & (FL_USER | FL_GROUP)))
-		flags |= FL_USER | FL_GROUP;
+	if (!(flags & (FL_USER | FL_GROUP | FL_TREE)))
+		flags |= FL_USER | FL_GROUP | FL_TREE;
 	if (!(flags & FL_ALL)) {
 		mntpoints = argstr + optind;
 		mntcnt = argcnt - optind;
@@ -330,12 +335,16 @@
 				errs += newstate(mnt, GRPQUOTA, xarg);
 			if (flags & FL_USER)
 				errs += newstate(mnt, USRQUOTA, xarg);
+			if (flags & FL_TREE)
+				errs += newstate(mnt, TREEQUOTA, xarg);
 		}
 		else {
 			if (flags & FL_GROUP)
 				errs += print_state(mnt, GRPQUOTA);
 			if (flags & FL_USER)
 				errs += print_state(mnt, USRQUOTA);
+			if (flags & FL_TREE)
+				errs += print_state(mnt, TREEQUOTA);
 		}
 	}
 	end_mounts_scan();
diff -Naur quota-tools.orig/quotaops.c quota-tools/quotaops.c
--- quota-tools.orig/quotaops.c	2002-11-22 05:37:58.000000000 +1100
+++ quota-tools/quotaops.c	2003-07-14 12:42:00.000000000 +1000
@@ -104,6 +104,7 @@
 #if defined(BSD_BEHAVIOUR)
 		switch (handles[i]->qh_type) {
 			case USRQUOTA:
+			case TREEQUOTA:
 				euid = geteuid();
 				if (euid != id && euid != 0) {
 					uid2user(id, name);
diff -Naur quota-tools.orig/quotasys.c quota-tools/quotasys.c
--- quota-tools.orig/quotasys.c	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/quotasys.c	2003-07-14 12:42:00.000000000 +1000
@@ -97,7 +97,7 @@
  */
 int name2id(char *name, int qtype)
 {
-	if (qtype == USRQUOTA)
+	if (qtype == USRQUOTA || qtype == TREEQUOTA)
 		return user2uid(name);
 	else
 		return group2gid(name);
@@ -140,7 +140,7 @@
  */
 int id2name(int id, int qtype, char *buf)
 {
-	if (qtype == USRQUOTA)
+	if (qtype == USRQUOTA || qtype == TREEQUOTA)
 		return uid2user(id, buf);
 	else
 		return gid2group(id, buf);
@@ -393,6 +393,8 @@
 		return 1;
 	if ((type == GRPQUOTA) && hasmntopt(mnt, MNTOPT_GRPQUOTA))
 		return 1;
+	if ((type == TREEQUOTA) && hasmntopt(mnt, MNTOPT_TREEQUOTA))
+		return 1;
 	if ((type == USRQUOTA) && hasmntopt(mnt, MNTOPT_QUOTA))
 		return 1;
 	return 0;
@@ -446,6 +448,10 @@
 		if (*(pathname = option + strlen(MNTOPT_GRPQUOTA)) == '=')
 			has_quota_file_definition = 1;
 	}
+	else if (type == TREEQUOTA && (option = hasmntopt(mnt, MNTOPT_TREEQUOTA))) {
+		if (*(pathname = option + strlen(MNTOPT_TREEQUOTA)) == '=')
+			has_quota_file_definition = 1;
+	}
 	else if (type == USRQUOTA && (option = hasmntopt(mnt, MNTOPT_QUOTA))) {
 		if (*(pathname = option + strlen(MNTOPT_QUOTA)) == '=')
 			has_quota_file_definition = 1;
@@ -625,7 +631,7 @@
 static int v1_kern_quota_on(const char *dev, int type)
 {
 	char tmp[1024];		/* Just temporary buffer */
-	qid_t id = (type == USRQUOTA) ? getuid() : getgid();
+	qid_t id = (type != GRPQUOTA) ? getuid() : getgid();
 
 	if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, id, tmp))	/* OK? */
 		return 1;
@@ -636,7 +642,7 @@
 static int v2_kern_quota_on(const char *dev, int type)
 {
 	char tmp[1024];		/* Just temporary buffer */
-	qid_t id = (type == USRQUOTA) ? getuid() : getgid();
+	qid_t id = (type != GRPQUOTA) ? getuid() : getgid();
 
 	if (!quotactl(QCMD(Q_V2_GETQUOTA, type), dev, id, tmp))	/* OK? */
 		return 1;
diff -Naur quota-tools.orig/repquota.c quota-tools/repquota.c
--- quota-tools.orig/repquota.c	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/repquota.c	2003-07-14 13:45:08.000000000 +1000
@@ -33,6 +33,7 @@
 #define FL_NONAME 64	/* Don't translate ids to names */
 #define FL_NOCACHE 128	/* Don't cache dquots before resolving */
 #define FL_NOAUTOFS 256	/* Ignore autofs mountpoints */
+#define FL_TREE 512	/* Tree-based quotas */
 
 int flags, fmt = -1;
 char **mnt;
@@ -53,7 +54,7 @@
 	int ret;
 	int cache_specified = 0;
 
-	while ((ret = getopt(argcnt, argstr, "VavughtsncCiF:")) != -1) {
+	while ((ret = getopt(argcnt, argstr, "YVavughtsncCiF:")) != -1) {
 		switch (ret) {
 			case '?':
 			case 'h':
@@ -67,6 +68,9 @@
 			case 'g':
 				flags |= FL_GROUP;
 				break;
+			case 'Y':
+				flags |= FL_TREE;
+				break;
 			case 'v':
 				flags |= FL_VERBOSE;
 				break;
@@ -112,7 +116,7 @@
 		fputs(_("Specified both -n and -t but only one of them can be used.\n"), stderr);
 		exit(1);
 	}
-	if (!(flags & (FL_USER | FL_GROUP)))
+	if (!(flags & (FL_USER | FL_GROUP | FL_TREE)))
 		flags |= FL_USER;
 	if (!(flags & FL_ALL)) {
 		mnt = argstr + optind;
@@ -173,13 +177,12 @@
 
 	if (!cached_dquots)
 		return;
-	if (type == USRQUOTA) {
+	if (type == USRQUOTA || type == TREEQUOTA ) {
 		struct passwd *pwent;
 
-		setpwent();
-		while ((pwent = getpwent())) {
-			for (i = 0; i < cached_dquots && pwent->pw_uid != dquot_cache[i].dq_id; i++);
-			if (i < cached_dquots && !(dquot_cache[i].dq_flags & DQ_PRINTED)) {
+		for (i = 0 ; i < cached_dquots; i++) {
+			pwent = getpwuid(dquot_cache[i].dq_id);
+			if (pwent && !(dquot_cache[i].dq_flags & DQ_PRINTED)) {			
 				print(dquot_cache+i, pwent->pw_name);
 				dquot_cache[i].dq_flags |= DQ_PRINTED;
 			}
@@ -189,10 +192,10 @@
 	else {
 		struct group *grent;
 
-		setgrent();
-		while ((grent = getgrent())) {
-			for (i = 0; i < cached_dquots && grent->gr_gid != dquot_cache[i].dq_id; i++);
-			if (i < cached_dquots && !(dquot_cache[i].dq_flags & DQ_PRINTED)) {
+
+		for (i = 0; i < cached_dquots ; i++) {
+			grent = getgrgid(dquot_cache[i].dq_id);
+			if (grent && !(dquot_cache[i].dq_flags & DQ_PRINTED)) {
 				print(dquot_cache+i, grent->gr_name);
 				dquot_cache[i].dq_flags |= DQ_PRINTED;
 			}
@@ -243,7 +246,7 @@
 	time2str(h->qh_info.dqi_igrace, igbuf, TF_ROUND);
 	printf(_("Block grace time: %s; Inode grace time: %s\n"), bgbuf, igbuf);
 	printf(_("                        Block limits                File limits\n"));
-	printf(_("%-9s       used    soft    hard  grace    used  soft  hard  grace\n"), (type == USRQUOTA)?_("User"):_("Group"));
+	printf(_("%-9s       used    soft    hard  grace    used  soft  hard  grace\n"), (type == USRQUOTA)?_("User"):(type == GRPQUOTA)?_("Group"):_("Tree"));
 	printf("----------------------------------------------------------------------\n");
 
 	if (h->qh_ops->scan_dquots(h, output) < 0)
@@ -284,5 +287,8 @@
 	if (flags & FL_GROUP)
 		report(GRPQUOTA);
 
+	if (flags & FL_TREE)
+		report(TREEQUOTA);
+
 	return 0;
 }
diff -Naur quota-tools.orig/rquota_server.c quota-tools/rquota_server.c
--- quota-tools.orig/rquota_server.c	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/rquota_server.c	2003-07-14 12:42:00.000000000 +1000
@@ -223,6 +223,11 @@
 			return (&result);
 		}
 
+		if (type == TREEQUOTA && unix_cred->aup_uid && unix_cred->aup_uid != id) {
+			result.status = Q_EPERM;
+			return (&result);
+		}
+
 		if (type == GRPQUOTA && unix_cred->aup_uid && unix_cred->aup_gid != id &&
 		    !in_group((gid_t *) unix_cred->aup_gids, unix_cred->aup_len, id)) {
 			result.status = Q_EPERM;
diff -Naur quota-tools.orig/set_limits_example.c quota-tools/set_limits_example.c
--- quota-tools.orig/set_limits_example.c	2001-07-18 07:58:31.000000000 +1000
+++ quota-tools/set_limits_example.c	2003-07-14 12:42:00.000000000 +1000
@@ -28,6 +28,29 @@
 	}
 }
 
+int copy_tree_quota_limits(const char *block_device, uid_t from, uid_t to)
+{
+	struct dqblk dq;
+
+	if (quotactl(QCMD(Q_GETQUOTA, TREEQUOTA), block_device, from, (caddr_t) & dq) == 0) {
+		if (quotactl(QCMD(Q_SETQLIM, TREEQUOTA), block_device, to, (caddr_t) & dq) == 0) {
+			return (0);
+		}
+		else {
+			errstr(
+				_("copy_tree_quota_limits: Failed to set treequota for uid %ld : %s\n"),
+				to, strerror(errno));
+			return (1);
+		}
+	}
+	else {
+		errstr(
+			_("copy_tree_quota_limits: Failed to get treequota for uid %ld : %s\n"),
+			from, strerror(errno));
+		return (1);
+	}
+}
+
 int copy_group_quota_limits(const char *block_device, gid_t from, gid_t to)
 {
 	struct dqblk dq;
diff -Naur quota-tools.orig/setquota.c quota-tools/setquota.c
--- quota-tools.orig/setquota.c	2003-07-14 14:18:16.000000000 +1000
+++ quota-tools/setquota.c	2003-07-14 12:42:00.000000000 +1000
@@ -28,6 +28,7 @@
 #define FL_PROTO 16
 #define FL_GRACE 32
 #define FL_INDIVIDUAL_GRACE 64
+#define FL_TREE 128
 
 int flags, fmt = -1;
 char **mnt;
@@ -78,6 +79,8 @@
 		return USRQUOTA;
 	if (flags & FL_GROUP)
 		return GRPQUOTA;
+	if (flags & FL_TREE)
+		return TREEQUOTA;
 	return -1;
 }
 
@@ -88,9 +91,9 @@
 	char *protoname = NULL;
 
 #ifdef RPC_SETQUOTA
-	char *opts = "igp:urVF:taT";
+	char *opts = "Yigp:urVF:taT";
 #else
-	char *opts = "igp:uVF:taT";
+	char *opts = "Yigp:uVF:taT";
 #endif
 
 	while ((ret = getopt(argcnt, argstr, opts)) != -1) {
@@ -104,6 +107,9 @@
 		  case 'u':
 			  flags |= FL_USER;
 			  break;
+		  case 'Y':
+			  flags |= FL_TREE;
+			  break;
 		  case 'p':
 			  flags |= FL_PROTO;
 			  protoname = optarg;
@@ -150,7 +156,7 @@
 		fputs(_("Bad number of arguments.\n"), stderr);
 		usage();
 	}
-	if (!(flags & (FL_USER | FL_GROUP)))
+	if (!(flags & (FL_USER | FL_GROUP | FL_TREE)))
 		flags |= FL_USER;
 	if (!(flags & FL_GRACE)) {
 		id = name2id(argstr[optind++], flag2type(flags));
@@ -247,7 +253,7 @@
 		q->dq_dqb.dqb_itime = toset.dqb_itime;
 	}
 	if (putprivs(curprivs, COMMIT_TIMES) == -1)
-		errstr(_("Can't write times for %s. Maybe kernel doesn't support such operation?\n"), type2name(flags & FL_USER ? USRQUOTA : GRPQUOTA));
+		errstr(_("Can't write times for %s. Maybe kernel doesn't support such operation?\n"), type2name(flags & FL_USER ? USRQUOTA : flags & FL_GROUP ? GRPQUOTA : TREEQUOTA));
 	freeprivs(curprivs);
 }
 
------------------------------------------------------
--- quotatools/quotasys.c~	2003-08-04 16:23:59.000000000 +1000
+++ quotatools/quotasys.c	2003-08-04 16:28:54.000000000 +1000
@@ -775,7 +775,7 @@
 		
 		/* Further we are not interested in mountpoints without quotas and
 		   we don't want to touch them */
-		if (!CORRECT_FSTYPE(mnt->mnt_type) || hasmntopt(mnt, MNTOPT_NOQUOTA) || !(hasmntopt(mnt, MNTOPT_USRQUOTA) || hasmntopt(mnt, MNTOPT_GRPQUOTA) || hasmntopt(mnt, MNTOPT_QUOTA) || !strcmp(mnt->mnt_type, MNTTYPE_NFS))) {
+		if (!CORRECT_FSTYPE(mnt->mnt_type) || hasmntopt(mnt, MNTOPT_NOQUOTA) || !(hasmntopt(mnt, MNTOPT_USRQUOTA) || hasmntopt(mnt, MNTOPT_GRPQUOTA) || hasmntopt(mnt, MNTOPT_TREEQUOTA) || hasmntopt(mnt, MNTOPT_QUOTA) || !strcmp(mnt->mnt_type, MNTTYPE_NFS))) {
 			free((char *)devname);
 			continue;
 		}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux