From bb62efa3c613427b29abf70b06b7fee1f55dcb5d Mon Sep 17 00:00:00 2001 From: jkar8572 Date: Wed, 1 Jun 2005 07:20:50 +0000 Subject: Parse NFSD export table to find out pseudofilesystem root for NFSv4 (Jan Kara) --- Changelog | 1 + quotaon.c | 4 +++- quotasys.h | 3 +++ rquota_server.c | 38 +++++++++++++++++--------------- rquota_svc.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 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 * @@ -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 * patches by Jani Jaakkola * - * 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 #include #include +#include #ifdef HOSTS_ACCESS #include #include @@ -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 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 listen on given port\n"), progname); + -x --xtab 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 listen on given port\n"), progname); + -p --port listen on given port\n\ + -x --xtab 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; -- cgit v1.2.3