[SCM] Samba Shared Repository - branch master updated

Michael Adam obnox at samba.org
Wed Aug 25 06:16:35 MDT 2010


The branch, master has been updated
       via  be59856... s3:smbd: add nfs quota support to the linux-non-sysquota code
       via  3add3aa... s3:smbd: add a nfs backend for sysquotas.
      from  896f3c8... s4-smbtorture: Added a torture test for forest trusts

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit be598569bbb9dec5cb8035441ef7411ebed29991
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.

commit 3add3aa17de7954b01e2c9273295195438ac30e5
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.

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

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 1d31f1a..d80c6c7 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -838,6 +838,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 0290480..d8bf554 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 a344979..67718a9 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -968,6 +968,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