[SCM] Samba Shared Repository - branch v3-6-test updated

Michael Adam obnox at samba.org
Wed Aug 25 23:58:59 MDT 2010


The branch, v3-6-test has been updated
       via  5f28c91... s3:smbd: add nfs quota support to the linux-non-sysquota code
       via  2c00b41... s3:smbd: add a nfs backend for sysquotas.
      from  b9b0017... s3-selftest: fix make oldtest (testparm_s3 tests use $LOCAL_PATH).

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 5f28c91c5225656f1e4974e9f4fb2ef80eaa398a
Author: Michael Adam <obnox at samba.org>
Date:   Fri Aug 6 11:58:46 2010 +0200

    s3:smbd: add nfs quota support to the linux-non-sysquota code
    
    This is based on the implementation for solaris and FreeBSD.
    It makes rpc calls out to the nfs server to retrieve quota
    information.
    (cherry picked from commit be598569bbb9dec5cb8035441ef7411ebed29991)

commit 2c00b41672a98eaf1aabf25384b19cf42b564f02
Author: Michael Adam <obnox at samba.org>
Date:   Fri Aug 6 10:21:09 2010 +0200

    s3:smbd: add a nfs backend for sysquotas.
    
    This module is based on the Solaris/FreeBSD implementation
    of NFS quotas in the quotas.c module.
    
    It implements the SMB_USER_QUOTA_TYPE query of the
    get_quotas call. The other types and the set_quota call
    are not implemented.
    (cherry picked from commit 3add3aa17de7954b01e2c9273295195438ac30e5)

-----------------------------------------------------------------------

Summary of changes:
 source3/Makefile.in         |    1 +
 source3/configure.in        |   21 ++++
 source3/include/proto.h     |    7 +
 source3/lib/sysquotas.c     |    3 +
 source3/lib/sysquotas_nfs.c |  271 +++++++++++++++++++++++++++++++++++++++++++
 source3/smbd/quotas.c       |  198 +++++++++++++++++++++++++++++++
 6 files changed, 501 insertions(+), 0 deletions(-)
 create mode 100644 source3/lib/sysquotas_nfs.c


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 028c88a..0d1eca2 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -820,6 +820,7 @@ SMBD_OBJ_SRV = smbd/server_reload.o \
 	       printing/printspoolss.o \
 	       lib/sysquotas.o lib/sysquotas_linux.o \
 	       lib/sysquotas_xfs.o lib/sysquotas_4A.o \
+	       lib/sysquotas_nfs.o \
 	       smbd/fake_file.o \
 	       smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \
 	       $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \
diff --git a/source3/configure.in b/source3/configure.in
index 358cb6b..d28524f 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -5025,6 +5025,27 @@ AC_MSG_CHECKING(whether to use the new lib/sysquotas.c interface)
 fi
 fi
 
+if test x"$samba_cv_SYSQUOTA_FOUND" != x"no"; then
+AC_CACHE_CHECK([whether the sys_quota interface works with NFS],samba_cv_SYSQUOTA_WORKS_NFS,[
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
+AC_TRY_COMPILE([
+#include "confdefs.h"
+#define NO_PROTO_H 1
+#define NO_CONFIG_H 1
+#define HAVE_SYS_QUOTAS 1
+#define HAVE_NFS_QUOTAS 1
+#include "${srcdir-.}/lib/sysquotas_nfs.c"
+],[],samba_cv_SYSQUOTA_WORKS_NFS=yes,samba_cv_SYSQUOTA_WORKS_NFS=no)
+CPPFLAGS="$SAVE_CPPFLAGS"
+])
+if test x"$samba_cv_SYSQUOTA_WORKS_NFS" = x"yes"; then
+    if test x"$samba_cv_WE_USE_SYS_QUOTAS" = x"yes"; then
+	AC_DEFINE(HAVE_NFS_QUOTAS,1,[Whether nfs quota support is available])
+    fi
+fi
+fi
+
 if test x"$samba_cv_SYSQUOTA_FOUND" != x"no" -a x"$samba_cv_found_xfs_header" = x"yes"; then
 AC_CACHE_CHECK([whether the sys_quota interface works with XFS],samba_cv_SYSQUOTA_WORKS_XFS,[
 SAVE_CPPFLAGS="$CPPFLAGS"
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 25c0476..1f8424e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -964,6 +964,13 @@ int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qt
 int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp);
 
+int sys_get_nfs_quota(const char *path, const char *bdev,
+		      enum SMB_QUOTA_TYPE qtype,
+		      unid_t id, SMB_DISK_QUOTA *dp);
+int sys_set_nfs_quota(const char *path, const char *bdev,
+		      enum SMB_QUOTA_TYPE qtype,
+		      unid_t id, SMB_DISK_QUOTA *dp);
+
 /* The following definitions come from lib/system.c  */
 
 void *sys_memalign( size_t align, size_t size );
diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c
index 3d4697c..6abafbd 100644
--- a/source3/lib/sysquotas.c
+++ b/source3/lib/sysquotas.c
@@ -177,6 +177,9 @@ static struct {
 #ifdef HAVE_XFS_QUOTAS
 	{"xfs", sys_get_xfs_quota, 	sys_set_xfs_quota},
 #endif /* HAVE_XFS_QUOTAS */
+#ifdef HAVE_NFS_QUOTAS
+	{"nfs", sys_get_nfs_quota,	sys_set_nfs_quota},
+#endif /* HAVE_NFS_QUOTAS */
 	{NULL, 	NULL, 			NULL}
 };
 
diff --git a/source3/lib/sysquotas_nfs.c b/source3/lib/sysquotas_nfs.c
new file mode 100644
index 0000000..8272f53
--- /dev/null
+++ b/source3/lib/sysquotas_nfs.c
@@ -0,0 +1,271 @@
+/* 
+   Unix SMB/CIFS implementation.
+   System QUOTA function wrappers for NFS
+   Copyright (C) Michael Adam 2010
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_QUOTA
+
+#ifndef HAVE_SYS_QUOTAS
+#ifdef HAVE_NFS_QUOTAS
+#undef HAVE_NFS_QUOTAS
+#endif
+#endif
+
+#ifdef HAVE_NFS_QUOTAS
+
+/*
+ * nfs quota support
+ * This is based on the FreeBSD / SUNOS5 section of quotas.c
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpcsvc/rquota.h>
+#ifdef HAVE_RPC_NETTYPE_H
+#include <rpc/nettype.h>
+#endif
+#include <rpc/xdr.h>
+
+static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
+{
+	if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
+		return(0);
+	if (!xdr_int(xdrsp, &args->gqa_uid))
+		return(0);
+	return (1);
+}
+
+static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
+{
+	int quotastat;
+
+	if (!xdr_int(xdrsp, &quotastat)) {
+		DEBUG(6,("nfs_quotas: Status bad or zero\n"));
+		return 0;
+	}
+	gqr->status = quotastat;
+
+	if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
+		DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
+		DEBUG(6,("nfs_quotas: Active bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
+		DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
+		DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
+		DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
+		return 0;
+	}
+	return (1);
+}
+
+
+int sys_get_nfs_quota(const char *path, const char *bdev,
+		      enum SMB_QUOTA_TYPE qtype,
+		      unid_t id, SMB_DISK_QUOTA *dp)
+{
+	CLIENT *clnt;
+	struct getquota_rslt gq_rslt;
+	struct getquota_args gq_args;
+	const char *mnttype;
+	char *cutstr, *pathname, *host, *testpath;
+	int len;
+	static struct timeval timeout = {2,0};
+	enum clnt_stat clnt_stat;
+
+	int ret = -1;
+	uint32 qflags = 0;
+
+	if (!path || !bdev || !dp) {
+		smb_panic("sys_get_nfs_quota: called with NULL pointer");
+	}
+
+	DEBUG(10, ("sys_get_nfs_quota: path[%s] bdev[%s] qtype[%d]\n",
+		   path, bdev, qtype));
+
+	ZERO_STRUCT(*dp);
+
+	dp->qtype = qtype;
+
+	if (qtype != SMB_USER_QUOTA_TYPE) {
+		DEBUG(3, ("sys_get_nfs_quota: got unsupported quota type '%d', "
+			  "only supported type is '%d' (SMB_USER_QUOTA_TYPE)\n",
+			  qtype, SMB_USER_QUOTA_TYPE));
+		errno = ENOSYS;
+		return -1;
+	}
+
+	mnttype = bdev;
+	len = strcspn(mnttype, ":");
+	pathname = strstr(mnttype, ":");
+	cutstr = (char *) SMB_MALLOC(len+1);
+	if (cutstr == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	memset(cutstr, '\0', len+1);
+	host = strncat(cutstr, mnttype, sizeof(char) * len);
+	testpath = strchr_m(mnttype, ':');
+	testpath++;
+	gq_args.gqa_pathp = testpath;
+	gq_args.gqa_uid = id.uid;
+
+	DEBUG(10, ("sys_get_nfs_quotas: Asking for quota of path '%s' on "
+		   "host '%s', rpcprog '%i', rpcvers '%i', network '%s'\n",
+		    host, testpath+1, RQUOTAPROG, RQUOTAVERS, "udp"));
+
+	clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp");
+	if (clnt == NULL) {
+		ret = -1;
+		goto out;
+	}
+
+	clnt->cl_auth = authunix_create_default();
+	if (clnt->cl_auth == NULL) {
+		DEBUG(3, ("sys_get_nfs_quotas: authunix_create_default "
+			  "failed\n"));
+		ret = -1;
+		goto out;
+	}
+
+	clnt_stat = clnt_call(clnt,
+			      RQUOTAPROC_GETQUOTA,
+			      (const xdrproc_t) my_xdr_getquota_args,
+			      (caddr_t)&gq_args,
+			      (const xdrproc_t) my_xdr_getquota_rslt,
+			      (caddr_t)&gq_rslt,
+			      timeout);
+
+	if (clnt_stat != RPC_SUCCESS) {
+		DEBUG(3, ("sys_get_nfs_quotas: clnt_call failed\n"));
+		ret = -1;
+		goto out;
+	}
+
+	DEBUG(10, ("sys_get_nfs_quotas: getquota_rslt:\n"
+		   "status       : '%i'\n"
+		   "bsize        : '%i'\n"
+		   "active       : '%s'\n"
+		   "bhardlimit   : '%u'\n"
+		   "bsoftlimit   : '%u'\n"
+		   "curblocks    : '%u'\n"
+		   "fhardlimit   : '%u'\n"
+		   "fsoftlimit   : '%u'\n"
+		   "curfiles     : '%u'\n"
+		   "btimeleft    : '%u'\n"
+		   "ftimeleft    : '%u'\n",
+		   gq_rslt.status,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_active?"yes":"no",
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_fhardlimit,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_fsoftlimit,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_curfiles,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_btimeleft,
+		   gq_rslt.getquota_rslt_u.gqr_rquota.rq_ftimeleft));
+
+	/*
+	 * gqr.status returns
+	 *   0 if the rpc call fails,
+	 *   1 if quotas exist,
+	 *   2 if there is no quota set, and
+	 *   3 if no permission to get the quota.
+	 */
+
+	switch (gq_rslt.status) {
+	case 0:
+		DEBUG(3, ("sys_get_nfs_quotas: Remote Quotas Failed! "
+			  "Error '%i'\n", gq_rslt.status));
+		ret = -1;
+		goto out;
+
+	case 1:
+		DEBUG(10, ("sys_get_nfs_quotas: Good quota data\n"));
+		dp->bsize = (uint64_t)gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize;
+		dp->softlimit = gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
+		dp->hardlimit = gq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
+		dp->curblocks = gq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks;
+		break;
+
+	case 2:
+		DEBUG(5, ("sys_get_nfs_quotas: No quota set\n"));
+		SMB_QUOTAS_SET_NO_LIMIT(dp);
+		break;
+
+	case 3:
+		DEBUG(3, ("sys_get_nfs_quotas: no permission to get quota\n"));
+		errno = EPERM;
+		ret = -1;
+		goto out;
+
+	default:
+		DEBUG(5, ("sys_get_nfs_quotas: Unknown remote quota status "
+			  "code '%i'\n", gq_rslt.status));
+		ret = -1;
+		goto out;
+		break;
+	}
+
+	dp->qflags = qflags;
+
+	ret = 0;
+
+out:
+	if (clnt) {
+		if (clnt->cl_auth) {
+			auth_destroy(clnt->cl_auth);
+		}
+		clnt_destroy(clnt);
+	}
+
+	SAFE_FREE(cutstr);
+
+	DEBUG(10, ("sys_get_nfs_quotas: finished\n" ));
+	return ret;
+}
+
+int sys_set_nfs_quota(const char *path, const char *bdev,
+		      enum SMB_QUOTA_TYPE qtype,
+		      unid_t id, SMB_DISK_QUOTA *dp)
+{
+	DEBUG(1, ("sys_set_nfs_quota : not supported\n"));
+	errno = ENOSYS;
+	return -1;
+}
+
+#else /* HAVE_NFS_QUOTAS */
+
+void dummy_sysquotas_nfs(void);
+void dummy_sysquotas_nfs(void) {}
+
+#endif /* HAVE_NFS_QUOTAS */
diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c
index 1ad2b93..ad3973f 100644
--- a/source3/smbd/quotas.c
+++ b/source3/smbd/quotas.c
@@ -73,6 +73,197 @@ typedef struct _LINUX_SMB_DISK_QUOTA {
 } LINUX_SMB_DISK_QUOTA;
 
 
+/*
+ * nfs quota support
+ * (essentially taken from FreeBSD / SUNOS5 section)
+ */
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpcsvc/rquota.h>
+#ifdef HAVE_RPC_NETTYPE_H
+#include <rpc/nettype.h>
+#endif
+#include <rpc/xdr.h>
+
+static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
+{
+	if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
+		return(0);
+	if (!xdr_int(xdrsp, &args->gqa_uid))
+		return(0);
+	return (1);
+}
+
+static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
+{
+	int quotastat;
+
+	if (!xdr_int(xdrsp, &quotastat)) {
+		DEBUG(6,("nfs_quotas: Status bad or zero\n"));
+		return 0;
+	}
+	gqr->status = quotastat;
+
+	if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
+		DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
+		DEBUG(6,("nfs_quotas: Active bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
+		DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
+		DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
+		return 0;
+	}
+	if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
+		DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
+		return 0;
+	}
+	return 1;
+}
+
+static bool nfs_quotas(char *nfspath, uid_t euser_id, uint64_t *bsize,
+		       uint64_t *dfree, uint64_t *dsize)
+{
+	uid_t uid = euser_id;
+	LINUX_SMB_DISK_QUOTA D;
+	char *mnttype = nfspath;
+	CLIENT *clnt;
+	struct getquota_rslt gqr;
+	struct getquota_args args;
+	char *cutstr, *pathname, *host, *testpath;
+	int len;
+	static struct timeval timeout = {2,0};
+	enum clnt_stat clnt_stat;
+	bool ret = True;
+
+	*bsize = *dfree = *dsize = (uint64_t)0;
+
+	len=strcspn(mnttype, ":");
+	pathname=strstr(mnttype, ":");
+	cutstr = (char *) SMB_MALLOC(len+1);
+	if (!cutstr)
+		return False;
+
+	memset(cutstr, '\0', len+1);
+	host = strncat(cutstr,mnttype, sizeof(char) * len );
+	DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
+	DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
+	testpath=strchr_m(mnttype, ':');
+	args.gqa_pathp = testpath+1;
+	args.gqa_uid = uid;
+
+	DEBUG(5, ("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers "
+		  "\"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS,
+		  "udp"));
+
+	if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
+		ret = False;
+		goto out;
+	}
+
+	clnt->cl_auth = authunix_create_default();
+	DEBUG(9,("nfs_quotas: auth_success\n"));
+
+	clnt_stat=clnt_call(clnt,
+			    RQUOTAPROC_GETQUOTA,
+			    (const xdrproc_t)my_xdr_getquota_args,
+			    (caddr_t)&args,
+			    (const xdrproc_t)my_xdr_getquota_rslt,
+			    (caddr_t)&gqr, timeout);
+
+	if (clnt_stat != RPC_SUCCESS) {
+		DEBUG(9,("nfs_quotas: clnt_call fail\n"));
+		ret = False;
+		goto out;
+	}
+
+	/*
+	 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
+	 * no quota set, and 3 if no permission to get the quota.  If 0 or 3 return
+	 * something sensible.
+	 */
+
+	switch (gqr.status) {
+	case 0:
+		DEBUG(9, ("nfs_quotas: Remote Quotas Failed!  Error \"%i\" \n",
+			  gqr.status));
+		ret = False;
+		goto out;
+
+	case 1:
+		DEBUG(9,("nfs_quotas: Good quota data\n"));
+		D.softlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
+		D.hardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
+		D.curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
+		break;
+
+	case 2:
+	case 3:
+		D.softlimit = 1;
+		D.curblocks = 1;
+		DEBUG(9, ("nfs_quotas: Remote Quotas returned \"%i\" \n",
+			  gqr.status));
+		break;
+
+	default:


-- 
Samba Shared Repository


More information about the samba-cvs mailing list