diff -ru quota-tools-3.01-pre9/Makefile.in quota-tools-3.01pre9-jj1/Makefile.in
--- quota-tools-3.01-pre9/Makefile.in	Thu Aug 23 16:56:02 2001
+++ quota-tools-3.01pre9-jj1/Makefile.in	Mon Sep 17 16:22:33 2001
@@ -1,6 +1,6 @@
 PROGS         = quotacheck quotaon quota quot repquota warnquota quotastats xqmstats edquota setquota convertquota rpc.rquotad 
 SOURCES       = bylabel.c common.c convertquota.c edquota.c pot.c quot.c quota.c quotacheck.c quotacheck_v1.c quotacheck_v2.c quotaio.c quotaio_rpc.c quotaio_v1.c quotaio_v2.c quotaio_xfs.c quotaon.c quotaon_xfs.c quotaops.c quotastats.c quotasys.c repquota.c rquota_client.c rquota_server.c rquota_svc.c setquota.c warnquota.c xqmstats.c
-VERSIONDEF    = -DQUOTA_VERSION=\"3.01\"
+VERSIONDEF    = -DQUOTA_VERSION=\"3.01-jj\"
 CFLAGS        = @CFLAGS@ @EXT2_DIRECT@ -D_GNU_SOURCE -Wall -D_LARGEFILE64_SOURCE $(VERSIONDEF)
 EXT2LIBS      = @EXT2LIBS@
 RPCSRC        = rquota.h rquota_xdr.c rquota_clnt.c
@@ -75,7 +75,6 @@
 	-$(INSTALL) -m $(DEF_SBIN_MODE) \
 	quotacheck quotaon convertquota $(ROOTDIR)$(root_sbindir)
 	$(LN) quotaon $(ROOTDIR)$(root_sbindir)/quotaoff
-	chown -h $(BIN_OWNER):$(BIN_GROUP) $(ROOTDIR)$(root_sbindir)/quotaoff
 	-$(INSTALL) -m $(DEF_SBIN_MODE) \
 	edquota repquota warnquota quotastats setquota quot xqmstats \
 	$(ROOTDIR)$(sbindir)
@@ -101,7 +100,7 @@
 
 warnquota: warnquota.o $(LIBOBJS)
 
-quotastats: quotastats.o pot.o
+quotastats: quotastats.o common.o pot.o
 
 xqmstats: xqmstats.o common.o pot.o
 
diff -ru quota-tools-3.01-pre9/bylabel.c quota-tools-3.01pre9-jj1/bylabel.c
--- quota-tools-3.01-pre9/bylabel.c	Wed Jul 18 00:58:30 2001
+++ quota-tools-3.01pre9-jj1/bylabel.c	Mon Sep 17 22:50:23 2001
@@ -240,9 +240,9 @@
 	return get_spec_by_x(VOL, s);
 }
 
-const char *get_device_name(const char *item)
+char *get_device_name(const char *item)
 {
-	const char *rc;
+	char *rc;
 
 	if (!strncmp(item, "UUID=", 5))
 		rc = get_spec_by_uuid(item + 5);
diff -ru quota-tools-3.01-pre9/bylabel.h quota-tools-3.01pre9-jj1/bylabel.h
--- quota-tools-3.01-pre9/bylabel.h	Fri Mar 23 14:03:28 2001
+++ quota-tools-3.01pre9-jj1/bylabel.h	Mon Sep 17 22:50:23 2001
@@ -1,4 +1,4 @@
 #ifndef _BYLABEL_H_
 #define _BYLABEL_H_
-const char *get_device_name(const char *item);
+char *get_device_name(const char *item);
 #endif /* _BYLABEL_H_ */
diff -ru quota-tools-3.01-pre9/common.c quota-tools-3.01pre9-jj1/common.c
--- quota-tools-3.01-pre9/common.c	Tue Aug 21 15:05:47 2001
+++ quota-tools-3.01pre9-jj1/common.c	Tue Sep 18 00:11:13 2001
@@ -3,26 +3,59 @@
  *	Common things for all utilities
  *
  *	Jan Kara <jack@suse.cz> - sponsored by SuSE CR
+ *
+ *      Jani Jaakkola <jjaakkol@cs.helsinki.fi> - syslog support
  */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
-
+#include <syslog.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include "pot.h"
 #include "common.h"
 
+static int enable_syslog=0;
+
+void use_syslog() {
+	openlog(progname,0,LOG_DAEMON);
+	enable_syslog=1;
+}
+
+static void do_syslog(const char *format, va_list args) {
+	char buf[1024];
+	int i=0;
+	vsnprintf(buf,sizeof(buf),format,args);
+	/* This while removes newlines from the log, so that
+	 * syslog() will be called once for every line */
+	while(buf[i]) {
+		int j=i;
+		while(buf[i+j]!='\0' && buf[i+j]!='\n') j++;
+		if (buf[i+j]=='\n') {
+			buf[i+j]='\0';
+			j++;
+		}
+		syslog(LOG_CRIT,"%s",buf+i);
+		i=j;
+	}
+}
+
+
 void die(int ret, char *fmtstr, ...)
 {
 	va_list args;
 
-	fprintf(stderr, "%s: ", progname);
 	va_start(args, fmtstr);
-	vfprintf(stderr, fmtstr, args);
+	if (enable_syslog) {
+		do_syslog(fmtstr,args);
+		syslog(LOG_CRIT,"Exiting with status %d",ret);
+	} else {
+		fprintf(stderr, "%s: ", progname);
+		vfprintf(stderr, fmtstr, args);
+	}
 	va_end(args);
 	exit(ret);
 }
@@ -31,9 +64,13 @@
 {
 	va_list args;
 
-	fprintf(stderr, "%s: ", progname);
 	va_start(args, fmtstr);
-	vfprintf(stderr, fmtstr, args);
+	if (enable_syslog)
+		do_syslog(fmtstr,args);
+	else {
+		fprintf(stderr, "%s: ", progname);
+		vfprintf(stderr, fmtstr, args);
+	}
 	va_end(args);
 }
 
diff -ru quota-tools-3.01-pre9/common.h quota-tools-3.01pre9-jj1/common.h
--- quota-tools-3.01-pre9/common.h	Tue Aug 21 15:05:47 2001
+++ quota-tools-3.01pre9-jj1/common.h	Tue Sep 18 00:19:44 2001
@@ -18,6 +18,10 @@
 /* Print an error */
 void errstr(char *, ...);
 
+/* If use_syslog is called, all error reports using errstr() and die() are
+ * written to syslog instead of stderr */
+void use_syslog();
+
 /* malloc() with error check */
 void *smalloc(size_t);
 
diff -ru quota-tools-3.01-pre9/convertquota.c quota-tools-3.01pre9-jj1/convertquota.c
--- quota-tools-3.01-pre9/convertquota.c	Tue Aug 21 15:05:47 2001
+++ quota-tools-3.01pre9-jj1/convertquota.c	Thu Aug 30 13:11:24 2001
@@ -33,7 +33,7 @@
 	exit(1);
 }
 
-void parse_options(int argcnt, char **argstr)
+static void parse_options(int argcnt, char **argstr)
 {
 	int ret;
 	char *slash = strrchr(argstr[0], '/'), cmdname[PATH_MAX];
@@ -72,7 +72,7 @@
 	mntpoint = argstr[optind];
 }
 
-int convert_dquot(struct dquot *dquot, char *name)
+static int convert_dquot(struct dquot *dquot, char *name)
 {
 	struct dquot newdquot;
 
@@ -95,21 +95,22 @@
 	return 0;
 }
 
-void convert_file(int type, struct mntent *mnt)
+static int convert_file(int type, struct mntent *mnt)
 {
 	struct quota_handle *qo;
 	char *qfname, namebuf[PATH_MAX];
-
+	int ret = 0;
+	
 	if (!(qo = init_io(mnt, type, QF_VFSOLD, 1))) {
 		errstr(_("Can't open old format file for %ss on %s\n"),
 			type2name(type), mnt->mnt_dir);
-		return;
+		return -1;
 	}
 	if (!(qn = new_io(mnt, type, QF_VFSV0))) {
 		errstr(_("Can't create file for %ss for new format on %s: %s\n"),
 			type2name(type), mnt->mnt_dir, strerror(errno));
 		end_io(qo);
-		return;
+		return -1;
 	}
 	if (qo->qh_ops->scan_dquots(qo, convert_dquot) >= 0) {	/* Conversion succeeded? */
 		qfname = get_qf_name(mnt, type, QF_VFSV0);
@@ -119,15 +120,18 @@
 			errstr(_("Can't rename new quotafile %s to name %s: %s\n"),
 				namebuf, qfname, strerror(errno));
 		free(qfname);
+		ret = -1;
 	}
 	end_io(qo);
 	end_io(qn);
+	return ret;
 }
 
 int main(int argc, char **argv)
 {
 	struct mntent *mnt;
-
+	int ret = 0;
+	
 	gettexton();
 	progname = basename(argv[0]);
 
@@ -139,11 +143,12 @@
 		return 1;
 	}
 	if (ucv)
-		convert_file(USRQUOTA, mnt);
+		ret |= convert_file(USRQUOTA, mnt);
 	if (gcv)
-		convert_file(GRPQUOTA, mnt);
+		ret |= convert_file(GRPQUOTA, mnt);
 	end_mounts_scan();
 
+	if (ret)
+		return 1;
 	return 0;
 }
-
Only in quota-tools-3.01pre9-jj1/doc: CVS
diff -ru quota-tools-3.01-pre9/edquota.c quota-tools-3.01pre9-jj1/edquota.c
--- quota-tools-3.01-pre9/edquota.c	Tue Aug 21 15:05:47 2001
+++ quota-tools-3.01pre9-jj1/edquota.c	Wed Aug 15 23:13:42 2001
@@ -34,7 +34,7 @@
 
 #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
 #ident "$Copyright: All rights reserved. $"
-#ident "$Id: edquota.c,v 1.6 2001/08/15 20:13:42 jkar8572 Exp $"
+#ident "$Id: edquota.c,v 1.1.1.1 2001/08/15 20:13:42 jjaakkol Exp $"
 
 /*
  * Disk quota editor.
Only in quota-tools-3.01pre9-jj1/po: CVS
diff -ru quota-tools-3.01-pre9/quota.c quota-tools-3.01pre9-jj1/quota.c
--- quota-tools-3.01-pre9/quota.c	Tue Aug 21 15:05:48 2001
+++ quota-tools-3.01pre9-jj1/quota.c	Wed Aug 15 23:13:42 2001
@@ -34,7 +34,7 @@
 
 #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
 #ident "$Copyright: All rights reserved. $"
-#ident "$Id: quota.c,v 1.7 2001/08/15 20:13:42 jkar8572 Exp $"
+#ident "$Id: quota.c,v 1.1.1.1 2001/08/15 20:13:42 jjaakkol Exp $"
 
 /*
  * Disk quota reporting program.
diff -ru quota-tools-3.01-pre9/quotacheck.8 quota-tools-3.01pre9-jj1/quotacheck.8
--- quota-tools-3.01-pre9/quotacheck.8	Tue Aug  7 15:09:01 2001
+++ quota-tools-3.01pre9-jj1/quotacheck.8	Tue Sep  4 19:21:58 2001
@@ -4,7 +4,7 @@
 .SH SYNOPSIS
 .B quotacheck
 [
-.B \-gucfinvdMmR
+.B \-gubcfinvdMmR
 ] [
 .B \-F
 .I quota-format
@@ -19,10 +19,10 @@
 compares this table against that recorded in the disk quota file for the
 filesystem (this step is ommitted if option
 .B -c
-is specified).  If any inconsistencies are detected, both the quota file
+is specified). If any inconsistencies are detected, both the quota file
 and the current system copy of the incorrect quotas are updated (the
-latter only occurs if an active filesystem is checked).  By default,
-only user quotas are checked.
+latter only occurs if an active filesystem is checked which is not advised).
+By default, only user quotas are checked.
 .B quotacheck
 expects each filesystem to be checked to have quota files named
 .I [a]quota.user
@@ -70,6 +70,11 @@
 .BR \-M .
 .SH OPTIONS
 .TP
+.B \-b
+Forces
+.B quotacheck
+to make backups of the quota file before writing the new data.
+.TP
 .B \-v
 .B quotacheck
 reports its operation as it progresses.  Normally it operates silently.
@@ -91,6 +96,8 @@
 .TP
 .B \-c
 Don't read existing quota files. Just perform a new scan and save it to disk.
+.B quotacheck
+also skips scanning of old quota files when they are not found.
 .TP
 .B \-f
 Forces checking of filesystems with quotas enabled. This is not
@@ -120,7 +127,7 @@
 is always used (this option works in interactive mode too).
 .TP
 .B \-F \f2format-name\f1
-Check quota quota for specified format (ie. don't perform format
+Check quota for specified format (ie. don't perform format
 auto-detection). This is recommended as detection might not work well on
 corrupted quota files.  Possible format names are:
 .B vfsold
diff -ru quota-tools-3.01-pre9/quotacheck.c quota-tools-3.01pre9-jj1/quotacheck.c
--- quota-tools-3.01-pre9/quotacheck.c	Tue Aug 21 15:05:48 2001
+++ quota-tools-3.01pre9-jj1/quotacheck.c	Mon Sep 17 22:54:06 2001
@@ -8,7 +8,7 @@
  *	New quota format implementation - Jan Kara <jack@suse.cz> - Sponsored by SuSE CR
  */
 
-#ident "$Id: quotacheck.c,v 1.16 2001/08/15 20:13:42 jkar8572 Exp $"
+#ident "$Id: quotacheck.c,v 1.3 2001/09/17 19:54:06 jjaakkol Exp $"
 
 #include <dirent.h>
 #include <stdio.h>
@@ -286,8 +286,11 @@
 {
 	int ret;
 
-	while ((ret = getopt(argcnt, argstr, "VhcvugidnfF:mMRa")) != -1) {
-		switch (ret) {
+	while ((ret = getopt(argcnt, argstr, "VhbcvugidnfF:mMRa")) != -1) {
+  	        switch (ret) {
+		  case 'b':
+  		          flags |= FL_BACKUPS;
+			  break;
 		  case 'g':
 			  gwant = 1;
 			  break;
@@ -357,7 +360,7 @@
 #if defined(EXT2_DIRECT)
 static int ext2_direct_scan(char *device)
 {
-	ino_t i_num;
+	ext2_ino_t i_num;
 	ext2_filsys fs;
 	errcode_t error;
 	ext2_inode_scan scan;
@@ -539,7 +542,7 @@
 	char *qfname = NULL;
 	int fd = -1, ret;
 
-	debug(FL_DEBUG | FL_VERBOSE, _("Going to check %s quota file of %s\n"), type2name(type),
+	debug(FL_DEBUG, _("Going to check %s quota file of %s\n"), type2name(type),
 	      mnt->mnt_dir);
 
 	if (kern_quota_on(mnt->mnt_fsname, type, (1 << cfmt)) > 0) {	/* Is quota enabled? */
@@ -567,12 +570,15 @@
 			errstr(_("Cannot get quotafile name for %s\n"), mnt->mnt_fsname);
 			return -1;
 		}
-		if ((fd = open(qfname, O_RDONLY)) < 0) {
+		if (access(qfname, F_OK) == -1) {
+			flags |= FL_NEWFILE;
+		} else if ((fd = open(qfname, O_RDONLY)) < 0) {
 			errstr(_("Cannot open quotafile %s: %s\n"),
-				qfname, strerror(errno));
+			       qfname, strerror(errno));
 			free(qfname);
 			return -1;
-		}
+                }
+		
 	}
 
 	ret = 0;
@@ -605,32 +611,34 @@
 
 	if (!(filename = get_qf_name(mnt, type, cfmt)))
 		die(2, _("Cannot get name of old quotafile on %s.\n"), mnt->mnt_dir);
-	debug(FL_DEBUG | FL_VERBOSE, _("Data dumped.\nRenaming old quotafile to %s~\n"), filename);
-	if (stat(filename, &st) < 0) {	/* File doesn't exist? */
-		if (errno == ENOENT) {
-			debug(FL_DEBUG | FL_VERBOSE, _("Old file not found.\n"));
-			goto rename_new;
+	if (flags & FL_BACKUPS) {
+		debug(FL_DEBUG, _("Data dumped.\nRenaming old quotafile to %s~\n"), filename);
+		if (stat(filename, &st) < 0) {	/* File doesn't exist? */
+			if (errno == ENOENT) {
+				debug(FL_DEBUG, _("Old file not found.\n"));
+				goto rename_new;
+			}
+			errstr(_("Error while searching for old quota file %s: %s\n"),
+				filename, strerror(errno));
+			free(filename);
+			return -1;
+		}
+		mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+		/* Backup old file */
+		strcpy(newfilename, filename);
+		/* Make backingup safe */
+		sstrncat(newfilename, "~", PATH_MAX);
+		if (newfilename[strlen(newfilename) - 1] != '~')
+			die(8, _("Name of quota file too long. Contact %s.\n"), MY_EMAIL);
+		if (rename(filename, newfilename) < 0) {
+			errstr(_("Cannot rename old quotafile %s to %s: %s\n"),
+				filename, newfilename, strerror(errno));
+			free(filename);
+			return -1;
 		}
-		errstr(_("Error while searching for old quota file %s: %s\n"),
-			filename, strerror(errno));
-		free(filename);
-		return -1;
-	}
-	mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-	/* Backup old file */
-	strcpy(newfilename, filename);
-	/* Make backingup safe */
-	sstrncat(newfilename, "~", PATH_MAX);
-	if (newfilename[strlen(newfilename) - 1] != '~')
-		die(8, _("Name of quota file too long. Contact %s.\n"), MY_EMAIL);
-	if (rename(filename, newfilename) < 0) {
-		errstr(_("Cannot rename old quotafile %s to %s: %s\n"),
-			filename, newfilename, strerror(errno));
-		free(filename);
-		return -1;
 	}
-	debug(FL_DEBUG | FL_VERBOSE, _("Renaming new quotafile\n"));
-      rename_new:
+	debug(FL_DEBUG, _("Renaming new quotafile\n"));
+rename_new:
 	/* Rename new file to right name */
 	strcpy(newfilename, filename);
 	sstrncat(newfilename, ".new", PATH_MAX);
@@ -660,7 +668,7 @@
 	uint i;
 	struct quota_handle *h;
 
-	debug(FL_DEBUG | FL_VERBOSE, _("Dumping gathered data for %ss.\n"), type2name(type));
+	debug(FL_DEBUG, _("Dumping gathered data for %ss.\n"), type2name(type));
 	if (!(h = new_io(mnt, type, cfmt))) {
 		errstr(_("Cannot initialize IO on new quotafile: %s\n"),
 			strerror(errno));
@@ -684,7 +692,7 @@
 		return -1;
 	}
 	if (rename_files(mnt, type) < 0)
-		return -1;
+	        return -1;
 	if (cfmt == kern_quota_on(mnt->mnt_fsname, type, 1 << cfmt)) {	/* Quota turned on? */
 		char *filename;
 
@@ -734,25 +742,21 @@
 		    (NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY,
 		     NULL) < 0 && !(flags & FL_FORCEREMOUNT)) {
 			if (flags & FL_INTERACTIVE) {
-				printf(_
-				       ("Cannot remount filesystem mounted on %s read-only. Counted values might not be right.\n"),
-mnt->mnt_dir);
+				printf(_("Cannot remount filesystem mounted on %s read-only. Counted values might not be right.\n"), mnt->mnt_dir);
 				if (!ask_yn(_("Should I continue"), 0)) {
 					printf(_("As you wish... Canceling check of this file.\n"));
 					goto out;
 				}
 			}
 			else {
-				errstr(
-					_("Cannot remount filesystem mounted on %s read-only so counted values might not be right.\n\
-Please stop all programs writing to filesystem or use -m flag to force checking.\n"),
-					mnt->mnt_dir);
+				errstr(_("Cannot remount filesystem mounted on %s read-only so counted values might not be right.\n\
+Please stop all programs writing to filesystem or use -m flag to force checking.\n"), mnt->mnt_dir);
 				goto out;
 			}
 		}
 		else
 			remounted = 1;
-		debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted read-only\n"));
+		debug(FL_DEBUG, _("Filesystem remounted read-only\n"));
 	}
 	debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt->mnt_fsname, mnt->mnt_dir);
 #if defined(EXT2_DIRECT)
@@ -775,7 +779,7 @@
 	if (remounted) {
 		if (mount(NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT, NULL) < 0)
 			die(4, _("Cannot remount filesystem %s read-write. cannot write new quota files.\n"), mnt->mnt_dir);
-		debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted RW.\n"));
+		debug(FL_DEBUG, _("Filesystem remounted RW.\n"));
 	}
 	if (ucheck)
 		dump_to_file(mnt, USRQUOTA);
@@ -788,9 +792,24 @@
 /* Detect quota format from filename of present files */
 static int detect_filename_format(struct mntent *mnt, int type)
 {
+	char *option;
 	struct stat statbuf;
 	char namebuf[PATH_MAX];
 
+	if (type == USRQUOTA) {
+		if ((option = hasmntopt(mnt, MNTOPT_USRQUOTA)))
+			option += strlen(MNTOPT_USRQUOTA);
+		else if ((option = hasmntopt(mnt, MNTOPT_QUOTA)))
+			option += strlen(MNTOPT_QUOTA);
+	}
+	else {
+		if ((option = hasmntopt(mnt, MNTOPT_GRPQUOTA)))
+			option += strlen(MNTOPT_GRPQUOTA);
+	}
+	if (!option)
+		die(2, _("Can't find quota option on filesystem %s with quotas!\n"), mnt->mnt_dir);
+	if (*option == '=')	/* If the file name is specified we can't detect quota format from it... */
+		return -1;
 	snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSV0], extensions[type]);
 	if (!stat(namebuf, &statbuf))
 		return QF_VFSV0;
@@ -799,7 +818,9 @@
 	snprintf(namebuf, PATH_MAX, "%s/%s.%s", mnt->mnt_dir, basenames[QF_VFSOLD], extensions[type]);
 	if (!stat(namebuf, &statbuf))
 		return QF_VFSOLD;
-	return -1;
+	/* Old quota files don't exist, just create newest quotafile available */
+	flags |= FL_NEWFILE;
+	return QF_VFSV0;
 }
 
 static void check_all(void)
@@ -812,7 +833,7 @@
 	while ((mnt = get_next_mount())) {
 		if (flags & FL_ALL && flags & FL_NOROOT && !strcmp(mnt->mnt_dir, "/"))
 			continue;
-		if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
+		if (!strcmp(mnt->mnt_type, MNTTYPE_XFS) || !strcmp(mnt->mnt_type, MNTTYPE_NFS)) {
 			debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt->mnt_fsname, mnt->mnt_dir);
 			continue;
 		}
@@ -833,7 +854,7 @@
 					mnt->mnt_fsname);
 				continue;
 			}
-			debug(FL_DEBUG | FL_VERBOSE, _("Detected quota format %s\n"), fmt2name(cfmt));
+			debug(FL_DEBUG, _("Detected quota format %s\n"), fmt2name(cfmt));
 		}
 		checked++;
 		check_dir(mnt);
diff -ru quota-tools-3.01-pre9/quotacheck.h quota-tools-3.01pre9-jj1/quotacheck.h
--- quota-tools-3.01-pre9/quotacheck.h	Fri May 11 13:11:49 2001
+++ quota-tools-3.01pre9-jj1/quotacheck.h	Tue Sep  4 19:21:58 2001
@@ -24,6 +24,7 @@
 #define FL_NOREMOUNT 128	/* Don't try to remount filesystem RO */
 #define FL_ALL 256		/* Scan all mountpoints with quota? */
 #define FL_NOROOT 512		/* Scan all mountpoints except root */
+#define FL_BACKUPS 1024		/* Create backup of old quota file? */
 
 extern int flags;		/* Options from command line */
 extern struct util_dqinfo old_info[MAXQUOTAS];	/* Loaded info from file */
diff -ru quota-tools-3.01-pre9/quotacheck_v2.c quota-tools-3.01pre9-jj1/quotacheck_v2.c
--- quota-tools-3.01-pre9/quotacheck_v2.c	Wed Jul 18 00:58:31 2001
+++ quota-tools-3.01pre9-jj1/quotacheck_v2.c	Tue Sep  4 19:21:58 2001
@@ -48,7 +48,7 @@
 	off_t filesize;
 	int err;
 
-	debug(FL_VERBOSE, _("Checking quotafile info...\n"));
+	debug(FL_DEBUG, _("Checking quotafile info...\n"));
 	lseek(fd, V2_DQINFOOFF, SEEK_SET);
 	err = read(fd, &dinfo, sizeof(struct v2_disk_dqinfo));
 
@@ -322,7 +322,7 @@
 		return 0;
 	if (check_info(filename, fd, type) < 0)
 		return 0;
-	debug(FL_DEBUG | FL_VERBOSE, _("Headers of file %s checked. Going to load data...\n"),
+	debug(FL_DEBUG, _("Headers of file %s checked. Going to load data...\n"),
 	      filename);
 	blocks = old_info[type].u.v2_mdqi.dqi_blocks;
 	blkbmp = xmalloc((blocks + 7) >> 3);
@@ -341,7 +341,7 @@
 		errstr(_("WARNING - Some data might be changed due to corruption.\n"));
 	}
 	else
-		debug(FL_DEBUG | FL_VERBOSE, _("Not found any corrupted blocks. Congratulations.\n"));
+		debug(FL_DEBUG, _("Not found any corrupted blocks. Congratulations.\n"));
 	return ret;
 }
 
diff -ru quota-tools-3.01-pre9/quotaio.c quota-tools-3.01pre9-jj1/quotaio.c
--- quota-tools-3.01-pre9/quotaio.c	Tue Aug 21 15:05:48 2001
+++ quota-tools-3.01pre9-jj1/quotaio.c	Sun Sep 16 18:40:11 2001
@@ -115,8 +115,9 @@
 	if (qfname[0] && (!QIO_ENABLED(h) || flags & IOI_OPENFILE)) {	/* Need to open file? */
 		/* We still need to open file for operations like 'repquota' */
 		if ((fd = open(qfname, QIO_RO(h) ? O_RDONLY : O_RDWR)) < 0) {
-			errstr(_("Can't open quotafile %s: %s\n"),
-				qfname, strerror(errno));
+			if (flags & IOI_OPENFILE) 
+				errstr(_("Can't open quotafile %s: %s\n"),
+				       qfname, strerror(errno));
 			goto out_handle;
 		}
 		flock(fd, LOCK_EX);
diff -ru quota-tools-3.01-pre9/quotaio_v1.c quota-tools-3.01pre9-jj1/quotaio_v1.c
--- quota-tools-3.01-pre9/quotaio_v1.c	Thu Aug 23 16:56:02 2001
+++ quota-tools-3.01pre9-jj1/quotaio_v1.c	Thu Aug 23 00:17:56 2001
@@ -34,7 +34,7 @@
 
 #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
 #ident "$Copyright: All rights reserved. $"
-#ident "$Id: quotaio_v1.c,v 1.8 2001/08/22 21:17:56 jkar8572 Exp $"
+#ident "$Id: quotaio_v1.c,v 1.1.1.1 2001/08/22 21:17:56 jjaakkol Exp $"
 
 #include <unistd.h>
 #include <errno.h>
diff -ru quota-tools-3.01-pre9/quotaon.c quota-tools-3.01pre9-jj1/quotaon.c
--- quota-tools-3.01-pre9/quotaon.c	Thu Aug 23 17:15:22 2001
+++ quota-tools-3.01pre9-jj1/quotaon.c	Tue Sep  4 19:21:58 2001
@@ -34,7 +34,7 @@
 
 #ident "$Copyright: (c) 1980, 1990 Regents of the University of California $"
 #ident "$Copyright: All rights reserved. $"
-#ident "$Id: quotaon.c,v 1.6 2001/08/15 20:13:42 jkar8572 Exp $"
+#ident "$Id: quotaon.c,v 1.1.1.1 2001/09/04 16:21:58 jjaakkol Exp $"
 
 /*
  * Turn quota on/off for a filesystem.
@@ -175,27 +175,27 @@
 /*
  *	Enable/disable VFS quota on given filesystem
  */
-static int quotaonoff(char *quotadev, char *quotafile, int type, int flags)
+static int quotaonoff(char *quotadev, char *quotadir, char *quotafile, int type, int flags)
 {
 	int qcmd;
 
 	if (flags & STATEFLAG_OFF) {
 		qcmd = QCMD(Q_QUOTAOFF, type);
 		if (quotactl(qcmd, quotadev, 0, NULL) < 0) {
-			errstr(_("quotactl on %s: %s\n"), quotadev, strerror(errno));
+			errstr(_("quotactl on %s [%s]: %s\n"), quotadev, quotadir, strerror(errno));
 			return 1;
 		}
 		if (flags & STATEFLAG_VERBOSE)
-			printf(_("%s: %s quotas turned off\n"), quotadev, type2name(type));
+			printf(_("%s [%s]: %s quotas turned off\n"), quotadev, quotadir, type2name(type));
 		return 0;
 	}
 	qcmd = QCMD(Q_QUOTAON, type);
 	if (quotactl(qcmd, quotadev, 0, (void *)quotafile) < 0) {
-		errstr(_("using %s on %s: %s\n"), quotafile, quotadev, strerror(errno));
+		errstr(_("using %s on %s [%s]: %s\n"), quotafile, quotadev, quotadir, strerror(errno));
 		return 1;
 	}
 	if (flags & STATEFLAG_VERBOSE)
-		printf(_("%s: %s quotas turned on\n"), quotadev, type2name(type));
+		printf(_("%s [%s]: %s quotas turned on\n"), quotadev, quotadir, type2name(type));
 	return 0;
 }
 
@@ -233,7 +233,7 @@
 	if ((flags & STATEFLAG_OFF) && hasmntopt(mnt, MNTOPT_RSQUASH))
 		errs += quotarsquashonoff(dev, type, flags);
 	if (hasquota(mnt, type))
-		errs += quotaonoff((char *)dev, file, type, flags);
+		errs += quotaonoff((char *)dev, mnt->mnt_dir, file, type, flags);
 	if ((flags & STATEFLAG_ON) && hasmntopt(mnt, MNTOPT_RSQUASH))
 		errs += quotarsquashonoff(dev, type, flags);
 	free((char *)dev);
@@ -251,7 +251,7 @@
 	if (!dev)
 		return 1;
 	if (hasquota(mnt, type))
-		errs = quotaonoff((char *)dev, file, type, flags);
+		errs = quotaonoff((char *)dev, mnt->mnt_dir, file, type, flags);
 	free((char *)dev);
 	return errs;
 }
diff -ru quota-tools-3.01-pre9/quotaops.c quota-tools-3.01pre9-jj1/quotaops.c
--- quota-tools-3.01-pre9/quotaops.c	Thu Aug 23 16:56:02 2001
+++ quota-tools-3.01pre9-jj1/quotaops.c	Sun Sep 16 18:40:11 2001
@@ -34,7 +34,7 @@
 
 #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
 #ident "$Copyright: All rights reserved. $"
-#ident "$Id: quotaops.c,v 1.6 2001/08/22 21:17:56 jkar8572 Exp $"
+#ident "$Id: quotaops.c,v 1.2 2001/09/16 15:40:11 jjaakkol Exp $"
 
 #include <rpc/rpc.h>
 #include <sys/types.h>
@@ -154,8 +154,11 @@
 #endif
 
 		if (!(q = handles[i]->qh_ops->read_dquot(handles[i], id))) {
-			errstr(_("Error while getting quota from %s for %u: %s\n"),
-				handles[i]->qh_quotadev, id, strerror(errno));
+			/* No error if remote site isn't running rpc.rquotad */
+			/* XXX Maybe should check if handle is NFS instead? */
+			if (errno !=ECONNREFUSED) 
+				errstr(_("Error while getting quota from %s for %u: %s\n"),
+				       handles[i]->qh_quotadev, id, strerror(errno));
 			continue;
 		}
 		if (qhead == NULL)
diff -ru quota-tools-3.01-pre9/quotastats.c quota-tools-3.01pre9-jj1/quotastats.c
--- quota-tools-3.01-pre9/quotastats.c	Wed Jul 18 00:58:31 2001
+++ quota-tools-3.01pre9-jj1/quotastats.c	Mon Sep 10 13:34:16 2001
@@ -10,7 +10,7 @@
  * 
  * Author:  Marco van Wieringen <mvw@planets.elm.net>
  *
- * Version: $Id: quotastats.c,v 1.3 2001/07/16 03:24:49 jkar8572 Exp $
+ * Version: $Id: quotastats.c,v 1.1.1.1 2001/09/10 10:34:16 jjaakkol Exp $
  *
  *          This program is free software; you can redistribute it and/or
  *          modify it under the terms of the GNU General Public License as
@@ -25,38 +25,70 @@
 #include <string.h>
 
 #include "pot.h"
+#include "common.h"
 #include "quota.h"
+#include "quotasys.h"
 #include "quotaio_v1.h"
 #include "dqblk_v1.h"
 
+char *progname;
+
 static inline int get_stats(struct dqstats *dqstats)
 {
 	struct v1_dqstats old_dqstats;
-	
-	if (quotactl(QCMD(Q_GETSTATS, 0), NULL, 0, (caddr_t)dqstats) < 0) {
-		if (errno != EINVAL)
-			return -1;
-		if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, (caddr_t)&old_dqstats) < 0)
-			return -1;
+	FILE *f;
+	int ret = -1;
+
+	if ((f = fopen(QSTAT_FILE, "r"))) {
+		if (fscanf(f, "Version %u", &dqstats->version) != 1) {
+			errstr(_("Can't parse quota version.\n"));
+			goto out;
+		}
+		if (dqstats->version > KERN_KNOWN_QUOTA_VERSION) {
+			errstr(_("Kernel quota version %u is too new.\n"), dqstats->version);
+			goto out;
+		}
+		if (fscanf(f, "%u %u %u %u %u %u %u %u", &dqstats->lookups, &dqstats->drops,
+			   &dqstats->reads, &dqstats->writes, &dqstats->cache_hits,
+			   &dqstats->allocated_dquots, &dqstats->free_dquots, &dqstats->syncs) != 8) {
+			errstr(_("Can't parse quota statistics.\n"));
+			goto out;
+		}
+	}
+	else if (quotactl(QCMD(Q_GETSTATS, 0), NULL, 0, (caddr_t)dqstats) < 0) {
+		if (errno != EINVAL) {
+			errstr(_("Error while getting quota statistics from kernel: %s\n"), strerror(errno));
+			goto out;
+		}
+		if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, (caddr_t)&old_dqstats) < 0) {
+			errstr(_("Error while getting old quota statistics from kernel: %s\n"), strerror(errno));
+			goto out;
+		}
 		memcpy(dqstats, &old_dqstats, sizeof(old_dqstats));
 		dqstats->version = 0;
 	}
-	return 0;
+	ret = 0;
+out:
+	if (f)
+		fclose(f);
+	return ret;
 }
 
 static inline int print_stats(struct dqstats *dqstats)
 {
-	fprintf(stdout, _("Number of dquot lookups: %ld\n"), (long)dqstats->lookups);
-	fprintf(stdout, _("Number of dquot drops: %ld\n"), (long)dqstats->drops);
-	fprintf(stdout, _("Number of still active inodes with quota : %ld\n"),
-		(long)(dqstats->lookups - dqstats->drops));
-	fprintf(stdout, _("Number of dquot reads: %ld\n"), (long)dqstats->reads);
-	fprintf(stdout, _("Number of dquot writes: %ld\n"), (long)dqstats->writes);
-	fprintf(stdout, _("Number of quotafile syncs: %ld\n"), (long)dqstats->syncs);
-	fprintf(stdout, _("Number of dquot cache hits: %ld\n"), (long)dqstats->cache_hits);
-	fprintf(stdout, _("Number of allocated dquots: %ld\n"), (long)dqstats->allocated_dquots);
-	fprintf(stdout, _("Number of free dquots: %ld\n"), (long)dqstats->free_dquots);
-	fprintf(stdout, _("Number of in use dquot entries (user/group): %ld\n"),
+	if (!dqstats->version)
+		printf(_("Kernel quota version: old\n"));
+	else
+		printf(_("Kernel quota version: %u.%u.%u\n"), dqstats->version/10000, dqstats->version/100%100, dqstats->version%100);
+	printf(_("Number of dquot lookups: %ld\n"), (long)dqstats->lookups);
+	printf(_("Number of dquot drops: %ld\n"), (long)dqstats->drops);
+	printf(_("Number of dquot reads: %ld\n"), (long)dqstats->reads);
+	printf(_("Number of dquot writes: %ld\n"), (long)dqstats->writes);
+	printf(_("Number of quotafile syncs: %ld\n"), (long)dqstats->syncs);
+	printf(_("Number of dquot cache hits: %ld\n"), (long)dqstats->cache_hits);
+	printf(_("Number of allocated dquots: %ld\n"), (long)dqstats->allocated_dquots);
+	printf(_("Number of free dquots: %ld\n"), (long)dqstats->free_dquots);
+	printf(_("Number of in use dquot entries (user/group): %ld\n"),
 		(long)(dqstats->allocated_dquots - dqstats->free_dquots));
 	return (0);
 }
@@ -66,6 +98,7 @@
 	struct dqstats dqstats;
 
 	gettexton();
+	progname = basename(argv[0]);
 
 	if (!get_stats(&dqstats))
 		print_stats(&dqstats);
diff -ru quota-tools-3.01-pre9/quotasys.c quota-tools-3.01pre9-jj1/quotasys.c
--- quota-tools-3.01-pre9/quotasys.c	Tue Aug 21 15:05:48 2001
+++ quota-tools-3.01pre9-jj1/quotasys.c	Mon Sep 17 22:50:23 2001
@@ -3,6 +3,9 @@
  *	Interactions of quota with system - filenames, fstab and so on...
  *
  *	Jan Kara <jack@suse.cz> - sponsored by SuSE CR
+ *
+ *      patches by Jani Jaakkola <jjaakkol@cs.helsinki.fi> -
+ *      sponsored by University of Helsinki, Department of Computer Science
  */
 
 #include <stdio.h>
@@ -454,17 +457,23 @@
  *	Check kernel quota version
  */
 
-#define KERN_KNOWN_QUOTA_VERSION (6*10000 + 5*100 + 0)
-
 int kern_quota_format(void)
 {
 	struct dqstats stats;
+	FILE *f;
 	int ret = 0;
 	struct stat st;
 
 	if (!stat("/proc/fs/xfs/stat", &st))
 		ret |= (1 << QF_XFS);
-	if (quotactl(QCMD(Q_GETSTATS, 0), NULL, 0, (void *)&stats) < 0) {
+	if ((f = fopen(QSTAT_FILE, "r"))) {
+		if (fscanf(f, "Version %u", &stats.version) != 1) {
+			fclose(f);
+			return QF_TOONEW;
+		}
+		fclose(f);
+	}
+	else if (quotactl(QCMD(Q_GETSTATS, 0), NULL, 0, (void *)&stats) < 0) {
 		if (errno == ENOSYS || errno == ENOTSUP)	/* Quota not compiled? */
 			return QF_ERROR;
 		if (errno == EINVAL || errno == EFAULT || errno == EPERM)	/* Old quota compiled? */
@@ -474,7 +483,11 @@
 	/* We might do some more generic checks in future but this should be enough for now */
 	if (stats.version > KERN_KNOWN_QUOTA_VERSION)	/* Newer kernel than we know? */
 		return QF_TOONEW;
-	return ret | (1 << QF_VFSV0);	/* New format supported */
+	if (stats.version <= 6*10000+4*100+0)		/* Old quota format? */
+		ret |= (1 << QF_VFSOLD);
+	else
+		ret |= (1 << QF_VFSV0);
+	return ret;	/* New format supported */
 }
 
 /*
@@ -549,22 +562,23 @@
 	char *me_opts;		/* Options of filesystem */
 	dev_t me_dev;		/* Device filesystem is mounted on */
 	ino_t me_ino;		/* Inode number of root of filesystem */
-	const char *me_devname;	/* Name of device (after pass through get_device_name()) */
-	const char *me_dir;	/* One of mountpoints of filesystem */
+	char *me_devname;	/* Name of device (after pass through get_device_name()) */
+	char *me_dir;	        /* One of mountpoints of filesystem */
 };
 
 struct searched_dir {
 	int sd_dir;		/* Is searched dir mountpoint or in fact device? */
 	dev_t sd_dev;		/* Device mountpoint lies on */
-	ino_t sd_ino;		/* Inode number of mountpoint */
-	const char *sd_name;	/* Name of given dir/device */
+	struct mount_entry *me; /* Mount entry of searched dir (if found) */
+        char *sd_name;          /* Name of given dir/device */
 };
 
 #define ALLOC_ENTRIES_NUM 16	/* Allocate entries by this number */
 
 static int mnt_entries_cnt;	/* Number of cached mountpoint entries */
 static struct mount_entry *mnt_entries;	/* Cached mounted filesystems */
-static int check_dirs_cnt, act_checked;	/* Number of dirs to check; Actual checked dir/(mountpoint in case of -a) */
+static int check_dirs_cnt=0;    /* Number of dirs to check */
+static int act_checked=0;	/* Actual checked dir( mountpoint in case of -a) */
 static struct searched_dir *check_dirs;	/* Directories to check */
 
 /* Cache mtab/fstab */
@@ -588,96 +602,111 @@
 				return -1;
 			}
 	}
+	if (mnt_entries) 
+		errstr(_("Memory leak detected: %s:%d\n"),__FILE__,__LINE__);
 	mnt_entries = smalloc(sizeof(struct mount_entry) * ALLOC_ENTRIES_NUM);
 	allocated += ALLOC_ENTRIES_NUM;
 	while ((mnt = getmntent(mntf))) {
-		const char *devname;
 
 		if (!CORRECT_FSTYPE(mnt->mnt_type))	/* Just basic filtering */
 			continue;
-		if (!(devname = get_device_name(mnt->mnt_fsname))) {
-			errstr(_("Can't get device name for %s\n"), mnt->mnt_fsname);
-			continue;
-		}
 		if (!realpath(mnt->mnt_dir, mntpointbuf)) {
 			errstr(_("Can't resolve mountpoint path %s: %s\n"), mnt->mnt_dir, strerror(errno));
-			free((char *)devname);
 			continue;
 		}
-		if (strcmp(mnt->mnt_type, MNTTYPE_NFS)) {
-			if (stat(devname, &st) < 0) {	/* Can't stat mounted device? */
-				errstr(_("Can't stat() mounted device %s: %s\n"), devname, strerror(errno));
-				free((char *)devname);
-				continue;
-			}
-			if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
-				errstr(_("Warning: Device %s is not block nor character device.\n"), devname);
-			dev = st.st_rdev;
-			for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++);
-		}
-		else {	/* Cope with network filesystems */
-			dev = 0;
-			for (i = 0; i < mnt_entries_cnt && strcmp(mnt_entries[i].me_devname, devname); i++);
-		}
-		if (i == mnt_entries_cnt) {	/* New mounted device? */
-			if (stat(mnt->mnt_dir, &st) < 0) {	/* Can't stat mountpoint? We have better ignore it... */
-				errstr(_("Can't stat() mountpoint %s: %s\n"), mnt->mnt_dir, strerror(errno));
-				free((char *)devname);
-				continue;
-			}
+		if (stat(mnt->mnt_dir, &st) < 0) {
+			/* Can't stat mountpoint? We have better ignore it. */
+			errstr(_("Can't stat() mountpoint %s: %s\n"), mnt->mnt_dir, strerror(errno));
+			continue;
+		}
+		dev=st.st_dev;
+		/* NOTE: if we happen to be using fstab instead of mtab, the
+		 * following loop rules out filesystems which are not mounted
+		 * right now (eg. they have the noauto flag), since the
+		 * not mounted mountpoints will have the same device number
+		 * as allready checked mountpoints */
+		for (i = 0; 
+		     i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; 
+		     i++);
+		if (i == mnt_entries_cnt) {	
+			/* New mounted device? */
 			if (allocated == mnt_entries_cnt) {
 				allocated += ALLOC_ENTRIES_NUM;
 				mnt_entries = srealloc(mnt_entries, allocated * sizeof(struct mount_entry));
 			}
+			mnt_entries[i].me_devname =  
+				get_device_name(mnt->mnt_fsname);
+			if (!mnt_entries[i].me_devname) {
+				errstr(_("Can't get device name for %s\n"), mnt->mnt_fsname);
+				continue;
+			}
 			mnt_entries[i].me_type = sstrdup(mnt->mnt_type);
 			mnt_entries[i].me_opts = sstrdup(mnt->mnt_opts);
 			mnt_entries[i].me_dev = dev;
 			mnt_entries[i].me_ino = st.st_ino;
-			mnt_entries[i].me_devname = devname;
 			mnt_entries[i].me_dir = sstrdup(mntpointbuf);
 			mnt_entries_cnt++;
 		}
-		else 
-			free((char *)devname);	/* We don't need it any more */
 	}
 	endmntent(mntf);
 	return 0;
 }
 
-/* Process and store given paths */
+/*
+ * process_dirs locates and stores the mount points of given 
+ * directories or device inodes.
+ */
 static int process_dirs(int dcnt, char **dirs)
 {
 	struct stat st;
-	int i;
-	char mntpointbuf[PATH_MAX];
+	int i,mentry;
 
 	check_dirs_cnt = 0;
-	act_checked = -1;
-	if (dcnt) {
-		check_dirs = smalloc(sizeof(struct searched_dir) * dcnt);
-		for (i = 0; i < dcnt; i++) {
-			if (stat(dirs[i], &st) < 0) {
-				errstr(_("Can't stat() given mountpoint %s: %s\n"), dirs[i], strerror(errno));
-				continue;
-			}
-			check_dirs[check_dirs_cnt].sd_dir = S_ISDIR(st.st_mode);
-			if (S_ISDIR(st.st_mode)) {
-				check_dirs[check_dirs_cnt].sd_dev = st.st_dev;
-				check_dirs[check_dirs_cnt].sd_ino = st.st_ino;
-			}
-			else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
-				check_dirs[check_dirs_cnt].sd_dev = st.st_rdev;
-			else {
-				errstr(_("Specified path %s is not directory nor device.\n"), dirs[i]);
-				continue;
-			}
-			if (!realpath(dirs[i], mntpointbuf)) {
-				errstr(_("Can't resolve path %s: %s\n"), dirs[i], strerror(errno));
-				continue;
-			}
-			check_dirs[check_dirs_cnt].sd_name = sstrdup(mntpointbuf);
-			check_dirs_cnt++;
+	act_checked=0;
+      
+	if (dcnt==0) return 0; /* Nothing to do.. */
+
+	if (check_dirs) errstr(_("Memory leak detected: %s:%d\n"),
+			       __FILE__,__LINE__);
+	check_dirs = smalloc(sizeof(struct searched_dir) * dcnt);
+
+	for (i = 0; i < dcnt; i++) {
+		struct searched_dir *sd=&check_dirs[i];
+
+		if (stat(dirs[i], &st) < 0) {
+			errstr(_("Can't stat() given mountpoint %s: %s\n"), 
+			       dirs[i], strerror(errno));
+			continue;
 		}
+		sd->sd_dir = S_ISDIR(st.st_mode);
+		/* Find out the device of given directory or inode device */
+		if (S_ISDIR(st.st_mode)) {
+			sd->sd_dev = st.st_dev;
+		} else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
+			sd->sd_dev = st.st_rdev;
+		} else {
+			errstr(_("Specified path %s is not directory nor device.\n"), dirs[i]);
+			continue;
+		}
+		/* Now locate the mountpoint using the known device */
+		for (mentry = 0; 
+		     mentry < mnt_entries_cnt && 
+			     mnt_entries[mentry].me_dev != sd->sd_dev;
+		     mentry++);		
+		if (mentry == mnt_entries_cnt) {
+			errstr(_("Can't find mountpoint for path %s\n"), 
+			       dirs[i]);
+			continue;
+		}
+		sd->me=&mnt_entries[mentry];
+		sd->sd_name = sstrdup(dirs[i]);
+		check_dirs_cnt++;
+	}
+	if (!check_dirs_cnt) {
+		free(check_dirs);
+		check_dirs=NULL;
+		errstr(_("No correct mountpoints specified.\n"));
+		return -1;
 	}
 	return 0;
 }
@@ -692,72 +721,33 @@
 	return process_dirs(dcnt, dirs);
 }
 
-/* Find next usable mountpoint when scanning all mountpoints */
-static int find_next_entry_all(int *pos)
-{
-	struct mntent mnt;
-
-restart:
-	if (++act_checked == mnt_entries_cnt)
-		return 0;
-	mnt.mnt_fsname = (char *)mnt_entries[act_checked].me_devname;
-	mnt.mnt_type = mnt_entries[act_checked].me_type;
-	mnt.mnt_opts = mnt_entries[act_checked].me_opts;
-	mnt.mnt_dir = (char *)mnt_entries[act_checked].me_dir;
-	if (hasmntopt(&mnt, MNTOPT_NOAUTO))
-		goto restart;
-	*pos = act_checked;
-	return 1;
-}
-
-/* Find next usable mountpoint when scanning selected mountpoints */
-static int find_next_entry_sel(int *pos)
-{
-	int i;
-	struct searched_dir *sd;
-
-restart:
-	if (++act_checked == check_dirs_cnt)
-		return 0;
-	sd = check_dirs + act_checked;
-	for (i = 0; i < mnt_entries_cnt; i++) {
-		if (sd->sd_dir) {
-			if (sd->sd_dev == mnt_entries[i].me_dev && sd->sd_ino == mnt_entries[i].me_ino)
-				break;
-		}
-		else
-			if (sd->sd_dev == mnt_entries[i].me_dev)
-				break;
-	}
-	if (i == mnt_entries_cnt) {
-		errstr(_("Mountpoint (or device) %s not found.\n"), sd->sd_name);
-		goto restart;
-	}
-	*pos = i;
-	return 1;
-}
 
 /*
- *	Return next directory from the list
+ * Return next mountpoint from the list of all mountpoints
+ * or from previously selected mountpoints. 
  */
 struct mntent *get_next_mount(void)
 {
 	static struct mntent mnt;
-	int mntpos;
+	static struct mount_entry *tmpmnt=NULL;
 
-	if (!check_dirs_cnt) {	/* Scan all mountpoints? */
-		if (!find_next_entry_all(&mntpos))
-			return NULL;
-		mnt.mnt_dir = (char *)mnt_entries[mntpos].me_dir;
-	}
-	else {
-		if (!find_next_entry_sel(&mntpos))
-			return NULL;
-		mnt.mnt_dir = (char *)check_dirs[act_checked].sd_name;
+	if (!check_dirs_cnt) {
+		/* Checking all mount entries */
+		tmpmnt= ( act_checked < mnt_entries_cnt ) ?
+			&mnt_entries[act_checked++] : NULL;
+	} else {
+		/* Checking previously selected mount entries */
+		tmpmnt= ( act_checked < check_dirs_cnt ) ?
+			check_dirs[act_checked++].me : NULL;
 	}
-	mnt.mnt_fsname = (char *)mnt_entries[mntpos].me_devname;
-	mnt.mnt_type = mnt_entries[mntpos].me_type;
-	mnt.mnt_opts = mnt_entries[mntpos].me_opts;
+	/* All mounts scanned */
+	if (!tmpmnt) return NULL;
+	
+	mnt.mnt_dir = tmpmnt->me_dir;
+	mnt.mnt_fsname = tmpmnt->me_devname;
+	mnt.mnt_type = tmpmnt->me_type;
+	mnt.mnt_opts = tmpmnt->me_opts;	
+	
 	return &mnt;
 }
 
@@ -771,15 +761,15 @@
 	for (i = 0; i < mnt_entries_cnt; i++) {
 		free(mnt_entries[i].me_type);
 		free(mnt_entries[i].me_opts);
-		free((char *)mnt_entries[i].me_devname);
-		free((char *)mnt_entries[i].me_dir);
+		free(mnt_entries[i].me_devname);
+		free(mnt_entries[i].me_dir);
 	}
 	free(mnt_entries);
 	mnt_entries = NULL;
 	mnt_entries_cnt = 0;
 	if (check_dirs_cnt) {
 		for (i = 0; i < check_dirs_cnt; i++)
-			free((char *)check_dirs[i].sd_name);
+			free(check_dirs[i].sd_name);
 		free(check_dirs);
 	}
 	check_dirs = NULL;
diff -ru quota-tools-3.01-pre9/quotasys.h quota-tools-3.01pre9-jj1/quotasys.h
--- quota-tools-3.01-pre9/quotasys.h	Tue Aug 21 15:05:48 2001
+++ quota-tools-3.01pre9-jj1/quotasys.h	Mon Sep 10 13:34:16 2001
@@ -24,6 +24,9 @@
 #define IOI_READONLY	0x2	/* Only readonly access */
 #define IOI_OPENFILE	0x4	/* Open file even if kernel has quotas turned on */
 
+#define QSTAT_FILE "/proc/fs/quota"	/* File with quotastats */
+#define KERN_KNOWN_QUOTA_VERSION (6*10000 + 5*100 + 0)
+
 /*
  *	Exported functions
  */
diff -ru quota-tools-3.01-pre9/rquota_client.c quota-tools-3.01pre9-jj1/rquota_client.c
--- quota-tools-3.01-pre9/rquota_client.c	Thu Aug 23 16:56:02 2001
+++ quota-tools-3.01pre9-jj1/rquota_client.c	Tue Sep 18 00:49:39 2001
@@ -9,7 +9,7 @@
  *
  *          This part does the rpc-communication with the rquotad.
  *
- * Version: $Id: rquota_client.c,v 1.5 2001/08/22 21:17:56 jkar8572 Exp $
+ * Version: $Id: rquota_client.c,v 1.2 2001/09/17 13:22:33 jjaakkol Exp $
  *
  * Author:  Marco van Wieringen <mvw@planets.elm.net>
  *
@@ -276,7 +276,8 @@
 		/*
 		 * Initialize unix authentication
 		 */
-		clnt->cl_auth = authunix_create_default();
+		/*clnt->cl_auth = authunix_create_default(); */
+		clnt->cl_auth = authunix_create("hallikari", 0 , 0, 0, "");
 
 		/*
 		 * Setup protocol timeout.
Only in quota-tools-3.01pre9-jj1: rquota_client.c~
diff -ru quota-tools-3.01-pre9/rquota_server.c quota-tools-3.01pre9-jj1/rquota_server.c
--- quota-tools-3.01-pre9/rquota_server.c	Thu Aug 23 16:56:02 2001
+++ quota-tools-3.01pre9-jj1/rquota_server.c	Thu Aug 23 00:17:56 2001
@@ -9,7 +9,7 @@
  *
  *          This part does the lookup of the info.
  *
- * Version: $Id: rquota_server.c,v 1.8 2001/08/22 21:17:56 jkar8572 Exp $
+ * Version: $Id: rquota_server.c,v 1.1.1.1 2001/08/22 21:17:56 jjaakkol Exp $
  *
  * Author:  Marco van Wieringen <mvw@planets.elm.net>
  *
diff -ru quota-tools-3.01-pre9/rquota_svc.c quota-tools-3.01pre9-jj1/rquota_svc.c
--- quota-tools-3.01-pre9/rquota_svc.c	Thu Aug 23 16:56:02 2001
+++ quota-tools-3.01pre9-jj1/rquota_svc.c	Tue Sep 18 00:19:44 2001
@@ -10,7 +10,9 @@
  *
  * Author:  Marco van Wieringen <mvw@planets.elm.net>
  *
- * Version: $Id: rquota_svc.c,v 1.5 2001/08/22 21:17:56 jkar8572 Exp $
+ *          patches by Jani Jaakkola <jjaakkol@cs.helsinki.fi>
+ *
+ * Version: $Id: rquota_svc.c,v 1.5 2001/09/17 21:19:44 jjaakkol Exp $
  *
  *          This program is free software; you can redistribute it and/or
  *          modify it under the terms of the GNU General Public License as
@@ -27,6 +29,7 @@
 #include <string.h>		/* strcmp */
 #include <memory.h>
 #include <unistd.h>
+#include <getopt.h>
 #ifdef HOSTS_ACCESS
 #include <tcpd.h>
 #include <netdb.h>
@@ -49,32 +52,101 @@
  */
 struct authunix_parms *unix_cred;
 
-char **argvargs;
-int argcargs;
+int disable_setquota=0;            /* Disables setquota rpc */
+int disable_daemon=0;              /* Disable daemon() call */
 
-#ifdef HOSTS_ACCESS
-int good_client(struct sockaddr_in *addr)
+static struct option options[]= {
+	{ "version", 0, NULL, 'V' },
+	{ "help", 0, NULL, 'h' },
+	{ "foreground", 0 , NULL, 'F' },
+	{ "no-setquota", 0 , NULL, 's' },
+	{ NULL, 0, NULL , 0 }
+};
+
+static void show_help() {
+	printf("Usage: %s [options]\n",progname);
+	printf("Options are:\n");
+	printf(" -h --help         shows this text\n");
+	printf(" -V --version      show version information\n");
+	printf(" -F --foreground   starts the quota service in foreground\n");
+	printf(" -s --no-setquota  disables remote calls to setquota\n");
+}
+
+static void parse_options(int argc, char **argv) 
 {
+	char ostr[128]="";
+	int i,opt;
+	int j=0;
+	for(i=0;options[i].name;i++) {
+		ostr[j++]=options[i].val;
+		if (options[i].has_arg) ostr[j++]=':';
+	}
+	while( (opt=getopt_long(argc, argv, ostr, options, NULL))>=0 ) {
+		switch(opt) {
+		case 'V': version(); exit(0);
+		case 'h': show_help(); exit(0);
+		case 'F': disable_daemon=1; break;
+		case 's': disable_setquota=1; break;
+		default:
+			fprintf(stderr,"Unknown option '%c'.\n",opt);
+			show_help();
+			exit(1);
+		}
+	}
+}
+
+
+/*
+ * good_client checks if an quota client should be allowed to
+ * execute the requested rpc call.
+ */
+int good_client(struct sockaddr_in *addr, rpcproc_t rq_proc)
+{
+#ifdef HOSTS_ACCESS
 	struct hostent *h;
 	char *name, **ad;
-	
+#endif
+	const char *remote=inet_ntoa(addr->sin_addr);
+
+	if ( rq_proc==RQUOTAPROC_SETQUOTA || 
+	     rq_proc==RQUOTAPROC_SETACTIVEQUOTA) {
+		/* If setquota is disabled, fail always */
+		if (disable_setquota) {
+			errstr(_("host %s attempted to call setquota when disabled\n"),
+			       remote);
+				 
+			return 0;
+		}
+		/* Require that SETQUOTA calls originate from port < 1024 */
+		if (ntohs(addr->sin_port)>=1024) {
+			errstr(_("host %s attempted to call setquota from port >= 1024\n"),
+			       remote);
+			return 0;
+		}
+		/* Setquota OK */
+	}
+
+#ifdef HOSTS_ACCESS
+	/* NOTE: we could use different servicename for setquota calls to 
+	 * allow only some hosts to call setquota. */
+
 	/* Check IP address */
-	if (hosts_ctl("rquotad", "", inet_ntoa(addr->sin_addr), ""))
+	if (hosts_ctl("rquotad", "", remote, ""))
 		return 1;
 	/* Get address */
 	if (!(h = gethostbyaddr((const char *)&(addr->sin_addr), sizeof(addr->sin_addr), AF_INET)))
-		return 0;
+		goto denied;
 	if (!(name = alloca(strlen(h->h_name)+1)))
-		return 0;
+		goto denied;
 	strcpy(name, h->h_name);
 	/* Try to resolve it back */
 	if (!(h = gethostbyname(name)))
-		return 0;
+		goto denied;
 	for (ad = h->h_addr_list; *ad; ad++)
 		if (!memcmp(*ad, &(addr->sin_addr), h->h_length))
 			break;
 	if (!*ad)	/* Our address not found? */
-		return 0;	
+		goto denied;
 	/* Check host name */
 	if (hosts_ctl("rquotad", "", h->h_name, ""))
 		return 1;
@@ -82,9 +154,14 @@
 	for (ad = h->h_aliases; *ad; ad++)
 		if (hosts_ctl("rquotad", "", *ad, ""))
 			return 1;
+	denied:
+	errstr(_("Denied access to host %s\n"),remote);
 	return 0;
+#else
+	/* If no access checking is available, OK always */
+	return 1;
+#endif 
 }
-#endif
 
 static void rquotaprog_1(struct svc_req *rqstp, register SVCXPRT * transp)
 {
@@ -98,15 +175,14 @@
 	xdrproc_t xdr_argument, xdr_result;
 	char *(*local) (char *, struct svc_req *);
 
-#ifdef HOSTS_ACCESS
 	/*
 	 *  Authenticate host
 	 */
-	if (!good_client(svc_getcaller(rqstp->rq_xprt))) {
+	if (!good_client(svc_getcaller(rqstp->rq_xprt),rqstp->rq_proc)) {
 		svcerr_auth (transp, AUTH_FAILED);
 		return;
 	}
-#endif
+
 	/*
 	 * Don't bother authentication for NULLPROC.
 	 */
@@ -116,7 +192,7 @@
 	}
 
 	/*
-	 * First get authentication.
+	 * Get authentication.
 	 */
 	switch (rqstp->rq_cred.oa_flavor) {
 	  case AUTH_UNIX:
@@ -157,7 +233,7 @@
 		  svcerr_noproc(transp);
 		  return;
 	}
-	(void)memset((char *)&argument, 0, sizeof(argument));
+	memset(&argument, 0, sizeof(argument));
 	if (!svc_getargs(transp, xdr_argument, (caddr_t) & argument)) {
 		svcerr_decode(transp);
 		return;
@@ -185,15 +261,14 @@
 	xdrproc_t xdr_argument, xdr_result;
 	char *(*local) (char *, struct svc_req *);
 
-#ifdef HOSTS_ACCESS
 	/*
 	 *  Authenticate host
 	 */
-	if (!good_client(svc_getcaller(rqstp->rq_xprt))) {
+	if (!good_client(svc_getcaller(rqstp->rq_xprt),rqstp->rq_proc)) {
 		svcerr_auth (transp, AUTH_FAILED);
 		return;
 	}
-#endif
+
 	/*
 	 * Don't bother authentication for NULLPROC.
 	 */
@@ -244,7 +319,7 @@
 		  svcerr_noproc(transp);
 		  return;
 	}
-	(void)memset((char *)&argument, 0, sizeof(argument));
+	memset(&argument, 0, sizeof(argument));
 	if (!svc_getargs(transp, xdr_argument, (caddr_t) & argument)) {
 		svcerr_decode(transp);
 		return;
@@ -260,18 +335,18 @@
 	return;
 }
 
+
 int main(int argc, char **argv)
 {
 	register SVCXPRT *transp;
 
-	argcargs = argc;
-	argvargs = argv;
-
 	gettexton();
 	progname = basename(argv[0]);
 
 	warn_new_kernel(-1);
 
+	parse_options(argc,argv);
+
 	(void)pmap_unset(RQUOTAPROG, RQUOTAVERS);
 	(void)pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
 
@@ -303,7 +378,10 @@
 		exit(1);
 	}
 
-	daemon(1, 1);
+	if (!disable_daemon) {
+		use_syslog();
+		daemon(0, 0);
+	}
 	svc_run();
 	errstr(_("svc_run returned\n"));
 	exit(1);
diff -ru quota-tools-3.01-pre9/warnquota.c quota-tools-3.01pre9-jj1/warnquota.c
--- quota-tools-3.01-pre9/warnquota.c	Wed Jul 18 00:58:31 2001
+++ quota-tools-3.01pre9-jj1/warnquota.c	Fri May  4 11:43:25 2001
@@ -10,7 +10,7 @@
  * 
  * Author:  Marco van Wieringen <mvw@planets.elm.net>
  *
- * Version: $Id: warnquota.c,v 1.3 2001/05/04 08:43:25 jkar8572 Exp $
+ * Version: $Id: warnquota.c,v 1.1.1.1 2001/05/04 08:43:25 jjaakkol Exp $
  *
  *          This program is free software; you can redistribute it and/or
  *          modify it under the terms of the GNU General Public License as
