summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog1
-rw-r--r--quotaon.c4
-rw-r--r--quotasys.h3
-rw-r--r--rquota_server.c38
-rw-r--r--rquota_svc.c68
5 files changed, 87 insertions, 27 deletions
diff --git a/Changelog b/Changelog
index 3c2df3e..04b6f13 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,5 @@
Changes in quota-tools from 3.12 to 3.13
+* parse NFSD export table to find pseudofilesystem root for NFSv4 (Jan Kara)
* handle better when quota file should become empty (Niu YaWei)
* minor manpage and help-text fixes (Jan Kara)
* fixed quotacheck(8) to check each block only once (Jan Kara)
diff --git a/quotaon.c b/quotaon.c
index ab8414f..b885565 100644
--- a/quotaon.c
+++ b/quotaon.c
@@ -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.19 2005/03/18 11:21:57 jkar8572 Exp $"
+#ident "$Id: quotaon.c,v 1.20 2005/06/01 07:20:50 jkar8572 Exp $"
/*
* Turn quota on/off for a filesystem.
@@ -318,6 +318,8 @@ int main(int argc, char **argv)
init_kernel_interface();
if (fmt != -1 && !(kernel_formats & (1 << fmt)))
die(1, _("Required format %s not supported by kernel.\n"), fmt2name(fmt));
+ else if (!kernel_formats)
+ errstr(_("Warning: No quota format detected in the kernel.\n"));
if (init_mounts_scan(mntcnt, mntpoints, 0) < 0)
return 1;
diff --git a/quotasys.h b/quotasys.h
index cdefdd7..62eacf9 100644
--- a/quotasys.h
+++ b/quotasys.h
@@ -30,6 +30,9 @@
#define IFACE_VFSV0 2
#define IFACE_GENERIC 3
+/* Path to export table of NFS daemon */
+#define NFSD_XTAB_PATH "/var/lib/nfs/etab"
+
/* Kernel quota format and supported interface */
extern int kernel_formats, kernel_iface;
diff --git a/rquota_server.c b/rquota_server.c
index 2c0f366..863edbb 100644
--- a/rquota_server.c
+++ b/rquota_server.c
@@ -9,7 +9,7 @@
*
* This part does the lookup of the info.
*
- * Version: $Id: rquota_server.c,v 1.15 2004/05/24 19:39:15 jkar8572 Exp $
+ * Version: $Id: rquota_server.c,v 1.16 2005/06/01 07:20:50 jkar8572 Exp $
*
* Author: Marco van Wieringen <mvw@planets.elm.net>
*
@@ -32,6 +32,7 @@
#include "quotaio.h"
#include "quotasys.h"
#include "dqblk_rpc.h"
+#include "common.h"
#define STDIN_FILENO 0
@@ -46,13 +47,12 @@
#define NETTYPE AF_INET
-int allow_severity = LOG_INFO;
-int deny_severity = LOG_WARNING;
-
/* Options from rquota_svc.c */
#define FL_AUTOFS 4
extern int flags;
+extern char nfs_pseudoroot[PATH_MAX];
+
/*
* Global unix authentication credentials.
*/
@@ -111,7 +111,7 @@ static inline void servutil2netdqblk(struct rquota *n, struct util_dqblk *u)
n->rq_ftimeleft = 0;
}
-setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
+setquota_rslt *setquotainfo(int lflags, caddr_t * argp, struct svc_req *rqstp)
{
static setquota_rslt result;
@@ -123,14 +123,16 @@ setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
struct util_dqblk dqblk;
struct dquot *dquot;
struct mntent *mnt;
- char *pathname;
+ char pathname[PATH_MAX];
+ char *pathp = pathname;
int id, qcmd, type;
struct quota_handle *handles[2] = { NULL, NULL };
+ sstrncpy(pathname, nfs_pseudoroot, PATH_MAX);
/*
* First check authentication.
*/
- if (flags & TYPE_EXTENDED) {
+ if (lflags & TYPE_EXTENDED) {
arguments.ext_args = (ext_setquota_args *) argp;
id = arguments.ext_args->sqa_id;
@@ -141,7 +143,7 @@ setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
qcmd = arguments.ext_args->sqa_qcmd;
type = arguments.ext_args->sqa_type;
- pathname = arguments.ext_args->sqa_pathp;
+ sstrncat(pathname, arguments.ext_args->sqa_pathp, PATH_MAX);
servnet2utildqblk(&dqblk, &arguments.ext_args->sqa_dqblk);
}
else {
@@ -155,14 +157,14 @@ setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
qcmd = arguments.args->sqa_qcmd;
type = USRQUOTA;
- pathname = arguments.args->sqa_pathp;
+ sstrncat(pathname, arguments.args->sqa_pathp, PATH_MAX);
servnet2utildqblk(&dqblk, &arguments.args->sqa_dqblk);
}
result.status = Q_NOQUOTA;
result.setquota_rslt_u.sqr_rquota.rq_bsize = RPC_DQBLK_SIZE;
- if (init_mounts_scan(1, &pathname, MS_QUIET | MS_NO_MNTPOINT | ((flags & FL_AUTOFS) ? 0 : MS_NO_AUTOFS)) < 0)
+ if (init_mounts_scan(1, &pathp, MS_QUIET | MS_NO_MNTPOINT | ((flags & FL_AUTOFS) ? 0 : MS_NO_AUTOFS)) < 0)
goto out;
if (!(mnt = get_next_mount())) {
end_mounts_scan();
@@ -201,7 +203,7 @@ out:
return (&result);
}
-getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
+getquota_rslt *getquotainfo(int lflags, caddr_t * argp, struct svc_req * rqstp)
{
static getquota_rslt result;
union {
@@ -210,18 +212,20 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
} arguments;
struct dquot *dquot = NULL;
struct mntent *mnt;
- char *pathname;
+ char pathname[PATH_MAX];
+ char *pathp = pathname;
int id, type;
struct quota_handle *handles[2] = { NULL, NULL };
+ sstrncpy(pathname, nfs_pseudoroot, PATH_MAX);
/*
* First check authentication.
*/
- if (flags & TYPE_EXTENDED) {
+ if (lflags & TYPE_EXTENDED) {
arguments.ext_args = (ext_getquota_args *) argp;
id = arguments.ext_args->gqa_id;
type = arguments.ext_args->gqa_type;
- pathname = arguments.ext_args->gqa_pathp;
+ sstrncat(pathname, arguments.ext_args->gqa_pathp, PATH_MAX);
if (type == USRQUOTA && unix_cred->aup_uid && unix_cred->aup_uid != id) {
result.status = Q_EPERM;
@@ -238,7 +242,7 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
arguments.args = (getquota_args *) argp;
id = arguments.args->gqa_uid;
type = USRQUOTA;
- pathname = arguments.args->gqa_pathp;
+ sstrncat(pathname, arguments.args->gqa_pathp, PATH_MAX);
if (unix_cred->aup_uid && unix_cred->aup_uid != id) {
result.status = Q_EPERM;
@@ -249,7 +253,7 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
result.status = Q_NOQUOTA;
result.getquota_rslt_u.gqr_rquota.rq_bsize = RPC_DQBLK_SIZE;
- if (init_mounts_scan(1, &pathname, MS_QUIET | MS_NO_MNTPOINT | ((flags & FL_AUTOFS) ? 0 : MS_NO_AUTOFS)) < 0)
+ if (init_mounts_scan(1, &pathp, MS_QUIET | MS_NO_MNTPOINT | ((flags & FL_AUTOFS) ? 0 : MS_NO_AUTOFS)) < 0)
goto out;
if (!(mnt = get_next_mount())) {
end_mounts_scan();
@@ -260,7 +264,7 @@ getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
goto out;
}
end_mounts_scan();
- if (!(flags & ACTIVE) || QIO_ENABLED(handles[0]))
+ if (!(lflags & ACTIVE) || QIO_ENABLED(handles[0]))
dquot = handles[0]->qh_ops->read_dquot(handles[0], id);
if (dquot) {
result.status = Q_OK;
diff --git a/rquota_svc.c b/rquota_svc.c
index 191182f..08ebefa 100644
--- a/rquota_svc.c
+++ b/rquota_svc.c
@@ -12,7 +12,7 @@
* changes for new utilities by Jan Kara <jack@suse.cz>
* patches by Jani Jaakkola <jjaakkol@cs.helsinki.fi>
*
- * Version: $Id: rquota_svc.c,v 1.16 2003/12/02 13:04:20 jkar8572 Exp $
+ * Version: $Id: rquota_svc.c,v 1.17 2005/06/01 07:20:50 jkar8572 Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -32,6 +32,7 @@
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
+#include <errno.h>
#ifdef HOSTS_ACCESS
#include <tcpd.h>
#include <netdb.h>
@@ -60,8 +61,10 @@ struct authunix_parms *unix_cred;
#define FL_NODAEMON 2 /* Disable daemon() call */
#define FL_AUTOFS 4 /* Don't ignore autofs mountpoints */
-int flags; /* Options specified on command line */
-int port; /* Port to use (0 for default one) */
+int flags; /* Options specified on command line */
+static int port; /* Port to use (0 for default one) */
+static char xtab_path[PATH_MAX]; /* Path to NFSD export table */
+char nfs_pseudoroot[PATH_MAX]; /* Root of the virtual NFS filesystem ('/' for NFSv3) */
static struct option options[]= {
{ "version", 0, NULL, 'V' },
@@ -73,6 +76,7 @@ static struct option options[]= {
#endif
{ "autofs", 0, NULL, 'I'},
{ "port", 1, NULL, 'p' },
+ { "xtab", 1, NULL, 'x' },
{ NULL, 0, NULL , 0 }
};
@@ -83,10 +87,11 @@ static void show_help(void)
-h --help shows this text\n\
-V --version shows version information\n\
-F --foreground starts the quota service in foreground\n\
+ -I --autofs do not ignore mountpoints mounted by automounter\n\
+ -p --port <port> listen on given port\n\
-s --no-setquota disables remote calls to setquota (default)\n\
-S --setquota enables remote calls to setquota\n\
- -I --autofs do not ignore mountpoints mounted by automounter\n\
- -p --port <port> listen on given port\n"), progname);
+ -x --xtab <path> set an alternative file with NFSD export table\n"), progname);
#else
errstr(_("Usage: %s [options]\nOptions are:\n\
@@ -94,7 +99,8 @@ static void show_help(void)
-V --version shows version information\n\
-F --foreground starts the quota service in foreground\n\
-I --autofs do not ignore mountpoints mounted by automounter\n\
- -p --port <port> listen on given port\n"), progname);
+ -p --port <port> listen on given port\n\
+ -x --xtab <path> set an alternative file with NFSD export table\n"), progname);
#endif
}
@@ -104,9 +110,11 @@ static void parse_options(int argc, char **argv)
int i,opt;
int j=0;
+ sstrncpy(xtab_path, NFSD_XTAB_PATH, PATH_MAX);
for(i=0; options[i].name; i++) {
ostr[j++] = options[i].val;
- if (options[i].has_arg) ostr[j++] = ':';
+ if (options[i].has_arg)
+ ostr[j++] = ':';
}
while ((opt=getopt_long(argc, argv, ostr, options, NULL))>=0) {
switch(opt) {
@@ -138,6 +146,14 @@ static void parse_options(int argc, char **argv)
exit(1);
}
break;
+ case 'x':
+ if (access(optarg, R_OK) < 0) {
+ errstr(_("Cannot access the specified xtab file %s: %s\n"), optarg, strerror(errno));
+ show_help();
+ exit(1);
+ }
+ sstrncpy(xtab_path, optarg, PATH_MAX);
+ break;
default:
errstr(_("Unknown option '%c'.\n"), opt);
show_help();
@@ -394,6 +410,39 @@ unregister (int sig)
exit(0);
}
+/* Parse NFSD export table and find a filesystem pseudoroot if it is there */
+static void get_pseudoroot(void)
+{
+ FILE *f;
+ char exp_line[1024];
+ char *c;
+
+ strcpy(nfs_pseudoroot, "/");
+ if (!(f = fopen(xtab_path, "r"))) {
+ errstr(_("Warning: Cannot open export table %s: %s\nUsing '/' as a pseudofilesystem root.\n"), xtab_path, strerror(errno));
+ return;
+ }
+ while (fgets(exp_line, sizeof(exp_line), f)) {
+ if (exp_line[0] == '#' || exp_line[0] == '\n') /* Comment, empty line? */
+ continue;
+ c = strchr(exp_line, '\t');
+ if (!c) /* Huh, line we don't understand... */
+ continue;
+ *c = 0;
+ /* Find the beginning of export options */
+ c = strchr(c+1, '(');
+ if (!c)
+ continue;
+ c = strstr(c, "fsid=0");
+ if (c) {
+ sstrncpy(nfs_pseudoroot, exp_line, PATH_MAX);
+ sstrncat(nfs_pseudoroot, "/", PATH_MAX);
+ break;
+ }
+ }
+ fclose(f);
+}
+
int main(int argc, char **argv)
{
register SVCXPRT *transp;
@@ -405,8 +454,9 @@ int main(int argc, char **argv)
parse_options(argc, argv);
init_kernel_interface();
- (void)pmap_unset(RQUOTAPROG, RQUOTAVERS);
- (void)pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
+ get_pseudoroot();
+ pmap_unset(RQUOTAPROG, RQUOTAVERS);
+ pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;