diff -urNp quota-tools-orig/quotaio.c quota-tools/quotaio.c --- quota-tools-orig/quotaio.c 2005-03-18 12:23:12.000000000 +0100 +++ quota-tools/quotaio.c 2008-07-17 22:16:08.000000000 +0200 @@ -54,6 +54,7 @@ struct quota_handle *init_io(struct mnte h->qh_type = type; sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev)); free((char *)mnt_fsname); + sstrncpy(h->qh_fstype, mnt->mnt_type, MAX_FSTYPE_LEN); if (nfs_fstype(mnt->mnt_type)) { /* NFS filesystem? */ if (fmt != -1 && fmt != QF_RPC) { /* User wanted some other format? */ errstr(_("Only RPC quota format is allowed on NFS filesystem.\n")); diff -urNp quota-tools-orig/quotaio.h quota-tools/quotaio.h --- quota-tools-orig/quotaio.h 2002-11-21 19:36:04.000000000 +0100 +++ quota-tools/quotaio.h 2008-07-17 22:21:45.000000000 +0200 @@ -40,6 +40,8 @@ "xfs"\ } +#define MAX_FSTYPE_LEN 16 /* Maximum length of filesystem type name */ + /* Values for format handling */ #define QF_UNKNOWN -3 /* Format cannot be detected from filename */ #define QF_TOONEW -2 /* Quota format is too new to handle */ @@ -82,6 +84,7 @@ struct quota_handle { int qh_fd; /* Handle of file (-1 when IOFL_QUOTAON) */ int qh_io_flags; /* IO flags for file */ char qh_quotadev[PATH_MAX]; /* Device file is for */ + char qh_fstype[MAX_FSTYPE_LEN]; /* Type of the filesystem on qh_quotadev */ int qh_type; /* Type of quotafile */ int qh_fmt; /* Quotafile format */ struct stat qh_stat; /* stat(2) for qh_quotadev */ diff -urNp quota-tools-orig/rquota_client.c quota-tools/rquota_client.c --- quota-tools-orig/rquota_client.c 2005-06-01 09:21:30.000000000 +0200 +++ quota-tools/rquota_client.c 2008-07-17 22:20:15.000000000 +0200 @@ -155,6 +155,12 @@ int rpc_rquota_get(struct dquot *dquot) } *pathname++ = '\0'; + /* For NFSv4, we send the filesystem path without initial /. Server prepends proper + * NFS pseudoroot automatically and uses this for detection of NFSv4 mounts. */ + if (!strcmp(dquot->dq_h->qh_fstype, MNTTYPE_NFS4)) { + while (*pathname == '/') + pathname++; + } /* * First try EXT_RQUOTAPROG (Extended (LINUX) RPC quota program) @@ -265,6 +271,13 @@ int rpc_rquota_set(int qcmd, struct dquo return -ENOENT; *pathname++ = '\0'; + /* For NFSv4, we send the filesystem path without initial /. Server prepends proper + * NFS pseudoroot automatically and uses this for detection of NFSv4 mounts. */ + if (!strcmp(dquot->dq_h->qh_fstype, MNTTYPE_NFS4)) { + while (*pathname == '/') + pathname++; + } + /* * First try EXT_RQUOTAPROG (Extended (LINUX) RPC quota program) diff -urNp quota-tools-orig/rquota_server.c quota-tools/rquota_server.c --- quota-tools-orig/rquota_server.c 2005-06-01 09:21:30.000000000 +0200 +++ quota-tools/rquota_server.c 2008-07-17 22:26:39.000000000 +0200 @@ -123,12 +123,11 @@ setquota_rslt *setquotainfo(int lflags, struct util_dqblk dqblk; struct dquot *dquot; struct mntent *mnt; - char pathname[PATH_MAX]; + char pathname[PATH_MAX] = {0}; char *pathp = pathname; int id, qcmd, type; struct quota_handle *handles[2] = { NULL, NULL }; - sstrncpy(pathname, nfs_pseudoroot, PATH_MAX); /* * First check authentication. */ @@ -143,6 +142,8 @@ setquota_rslt *setquotainfo(int lflags, qcmd = arguments.ext_args->sqa_qcmd; type = arguments.ext_args->sqa_type; + if (arguments.ext_args->sqa_pathp[0] != '/') + sstrncpy(pathname, nfs_pseudoroot, PATH_MAX); sstrncat(pathname, arguments.ext_args->sqa_pathp, PATH_MAX); servnet2utildqblk(&dqblk, &arguments.ext_args->sqa_dqblk); } @@ -157,6 +158,8 @@ setquota_rslt *setquotainfo(int lflags, qcmd = arguments.args->sqa_qcmd; type = USRQUOTA; + if (arguments.args->sqa_pathp[0] != '/') + sstrncpy(pathname, nfs_pseudoroot, PATH_MAX); sstrncat(pathname, arguments.args->sqa_pathp, PATH_MAX); servnet2utildqblk(&dqblk, &arguments.args->sqa_dqblk); } @@ -212,18 +215,19 @@ getquota_rslt *getquotainfo(int lflags, } arguments; struct dquot *dquot = NULL; struct mntent *mnt; - char pathname[PATH_MAX]; + char pathname[PATH_MAX] = {0}; char *pathp = pathname; int id, type; struct quota_handle *handles[2] = { NULL, NULL }; - sstrncpy(pathname, nfs_pseudoroot, PATH_MAX); /* * First check authentication. */ if (lflags & TYPE_EXTENDED) { arguments.ext_args = (ext_getquota_args *) argp; id = arguments.ext_args->gqa_id; + if (arguments.ext_args->gqa_pathp[0] != '/') + sstrncpy(pathname, nfs_pseudoroot, PATH_MAX); type = arguments.ext_args->gqa_type; sstrncat(pathname, arguments.ext_args->gqa_pathp, PATH_MAX); @@ -241,6 +245,8 @@ getquota_rslt *getquotainfo(int lflags, else { arguments.args = (getquota_args *) argp; id = arguments.args->gqa_uid; + if (arguments.args->gqa_pathp[0] != '/') + sstrncpy(pathname, nfs_pseudoroot, PATH_MAX); type = USRQUOTA; sstrncat(pathname, arguments.args->gqa_pathp, PATH_MAX);