Hi *,
I have worked on a nfs quota module, based on some some patches I got and the old sun nfs quota implementeation in smbd/quota.c
for be it build's and load fine... quota set support is missing
But I haven't a nfs share with quotas, so I can't test it, I'm not shure if this can work ok...
So what I need is someone who tests this and maybe fix some bugs...
Feedback please -- metze
Stefan Metzmacher <metze at samba.org> www.samba.org
Index: Makefile.in
===================================================================
--- Makefile.in (revision 839)
+++ Makefile.in (working copy)
@@ -31,6 +31,7 @@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
@@ -346,6 +347,7 @@
VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o
VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o
VFS_AFSACL_OBJ = modules/vfs_afsacl.o
+VFS_NFS_QUOTA_OBJ = modules/vfs_nfs_quota.o
PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
@@ -816,7 +818,7 @@
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \
$(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \
- $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@
+ $(ACL_LIBS) $(PASSDB_LIBS) $(VFS_LIBS) $(LIBS) @POPTLIBS@
bin/[EMAIL PROTECTED]@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -947,7 +949,7 @@
bin/[EMAIL PROTECTED]@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS)
$(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS)
$(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS)
$(VFS_LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@
$(KRB5LIBS) $(LDAP_LIBS)
bin/[EMAIL PROTECTED]@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -1223,6 +1225,11 @@
@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AFSACL_OBJ:.o=.po) \
@[EMAIL PROTECTED] [EMAIL PROTECTED]
+bin/[EMAIL PROTECTED]@: $(VFS_NFS_QUOTA_OBJ:.o=.po)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NFS_QUOTA_OBJ:.o=.po) @NFS_QUOTA_LIBS@ \
+ @[EMAIL PROTECTED] [EMAIL PROTECTED]
+
bin/[EMAIL PROTECTED]@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@
Index: modules/vfs_nfs_quota.c
===================================================================
--- modules/vfs_nfs_quota.c (revision 0)
+++ modules/vfs_nfs_quota.c (revision 0)
@@ -0,0 +1,292 @@
+/*
+ * NFS Quotas
+ *
+ * Copyright (C) Stefan (metze) Metzmacher 2003
+ * Copyright (C) Alan Romeril <[EMAIL PROTECTED]> 2000
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_QUOTA
+
+static SMB_BIG_UINT nfs_quota_disk_free(vfs_handle_struct *handle, connection_struct
*conn, const char *path,
+ BOOL small_query, SMB_BIG_UINT *bsize,
+ SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
+static int nfs_quota_get_quota(vfs_handle_struct *handle, connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq);
+static int nfs_quota_set_quota(vfs_handle_struct *handle, connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq);
+
+
+#include <rpcsvc/rquota.h>
+
+/****************************************************************************
+normalise for DOS usage
+****************************************************************************/
+static void nfs_disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT
*dfree,SMB_BIG_UINT *dsize)
+{
+ /* check if the disk is beyond the max disk size */
+ SMB_BIG_UINT maxdisksize = lp_maxdisksize();
+ if (maxdisksize) {
+ /* convert to blocks - and don't overflow */
+ maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
+ if (*dsize > maxdisksize) *dsize = maxdisksize;
+ if (*dfree > maxdisksize) *dfree = maxdisksize-1;
+ /* the -1 should stop applications getting div by 0
+ errors */
+ }
+
+ while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) {
+ *dfree /= 2;
+ *dsize /= 2;
+ *bsize *= 2;
+ if(small_query) {
+ /*
+ * Force max to fit in 16 bit fields.
+ */
+ if (*bsize > (WORDMAX*512)) {
+ *bsize = (WORDMAX*512);
+ if (*dsize > WORDMAX)
+ *dsize = WORDMAX;
+ if (*dfree > WORDMAX)
+ *dfree = WORDMAX;
+ break;
+ }
+ }
+ }
+}
+
+static BOOL nfs_disk_quotas(vfs_handle_struct *handle, connection_struct
*conn,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
+{
+ int r;
+ SMB_DISK_QUOTA D;
+ unid_t id;
+
+ id.uid = geteuid();
+
+ r=nfs_quota_get_quota(handle, conn, SMB_USER_QUOTA_TYPE, id, &D);
+
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+ *bsize = D.bsize;
+ if (r == -1) {
+ if (errno == EDQUOT) {
+ *dfree =0;
+ *dsize =D.curblocks;
+ return (True);
+ } else {
+ return False;
+ }
+ }
+
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+ if (
+ (D.softlimit && D.curblocks >= D.softlimit) ||
+ (D.hardlimit && D.curblocks >= D.hardlimit) ||
+ (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
+ (D.ihardlimit && D.curinodes>=D.ihardlimit)
+ ) {
+ *dfree = 0;
+ *dsize = D.curblocks;
+ } else if (D.softlimit==0 && D.hardlimit==0) {
+ return False;
+ } else {
+ if (D.softlimit == 0)
+ D.softlimit = D.hardlimit;
+ *dfree = D.softlimit - D.curblocks;
+ *dsize = D.softlimit;
+ }
+
+ return True;
+}
+
+static SMB_BIG_UINT nfs_quota_disk_free(vfs_handle_struct *handle, connection_struct
*conn, const char *path,
+ BOOL small_query, SMB_BIG_UINT *bsize,
+ SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
+{
+ int dfree_retval;
+ SMB_BIG_UINT dfree_q = 0;
+ SMB_BIG_UINT bsize_q = 0;
+ SMB_BIG_UINT dsize_q = 0;
+
+ (*dfree) = (*dsize) = 0;
+ (*bsize) = 512;
+
+ sys_fsusage(path, dfree, dsize);
+
+ if (nfs_disk_quotas(handle, conn, &bsize_q, &dfree_q, &dsize_q)) {
+ (*bsize) = bsize_q;
+ (*dfree) = MIN(*dfree,dfree_q);
+ (*dsize) = MIN(*dsize,dsize_q);
+ }
+
+ /* FIXME : Any reason for this assumption ? */
+ if (*bsize < 256) {
+ DEBUG(5,("disk_free:Warning: bsize == %d < 256 . Changing to assumed
correct bsize = 512\n",(int)*bsize));
+ *bsize = 512;
+ }
+
+ if ((*dsize)<1) {
+ static int done;
+ if (!done) {
+ DEBUG(0,("WARNING: dfree is broken on this system\n"));
+ done=1;
+ }
+ *dsize = 20*1024*1024/(*bsize);
+ *dfree = MAX(1,*dfree);
+ }
+
+ nfs_disk_norm(small_query,bsize,dfree,dsize);
+
+ if ((*bsize) < 1024) {
+ dfree_retval = (*dfree)/(1024/(*bsize));
+ } else {
+ dfree_retval = ((*bsize)/1024)*(*dfree);
+ }
+
+ return(dfree_retval);
+}
+
+static int nfs_quota_get_quota(vfs_handle_struct *handle, connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ uid_t uid = id.uid;
+ char *mnttype = conn->connectpath;
+ CLIENT *clnt = NULL;
+ struct getquota_rslt gqr;
+ struct getquota_args args;
+ char *host, *testpath;
+ int len;
+ static struct timeval timeout = {2,0};
+ enum clnt_stat clnt_stat;
+ fstring cutstr, machname;
+ int ret = -1;
+
+ switch(qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ len=strcspn(mnttype, ":");
+ host = strncpy(cutstr,mnttype, len);
+ cutstr[len] = '\0';
+ DEBUG(5,("nfs_quota: looking for mount on \"%s\"\n", cutstr));
+ DEBUG(5,("nfs_quota: of path \"%s\"\n", mnttype));
+ testpath=strchr_m(mnttype, ':');
+ if (testpath==NULL) {
+ DEBUG(5,("nfs_quota: no nfs mount\n"));
+ goto out;
+ }
+ args.gqa_pathp = testpath+1;
+ args.gqa_uid = uid;
+
+ DEBUG(5,("nfs_quota: Asking for host \"%s\" rpcprog \"%d\" rpcvers \"%d\""
+ " network \"udp\" path \"%s\" user %u\n",
+ host, RQUOTAPROG, RQUOTAVERS, args.gqa_pathp, args.gqa_uid));
+
+ if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
+ goto out;
+ }
+ clnt->cl_auth = NULL;
+ if (gethostname(machname, sizeof(machname)) == 0) {
+ struct passwd *pw = getpwuid(uid);
+ if (pw) {
+ clnt->cl_auth = authunix_create(machname, uid, pw->pw_gid, 0,
NULL);
+ if (clnt->cl_auth)
+ DEBUG(9,("nfs_quota: created auth for uid %u gid %u\n",
+ uid, pw->pw_gid));
+ }
+ }
+ if (!clnt->cl_auth)
+ clnt->cl_auth = authunix_create_default();
+ DEBUG(9,("nfs_quota: auth_success\n"));
+
+ clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, (xdrproc_t) xdr_getquota_args,
(caddr_t)&args,
+ (xdrproc_t) xdr_getquota_rslt,
(caddr_t)&gqr, timeout);
+
+ if (clnt_stat != RPC_SUCCESS) {
+ DEBUG(9,("nfs_quota: clnt_call fail\n"));
+ goto out;
+ }
+
+ /*
+ * quotastat 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 Q_OK:
+ DEBUG(9,("nfs_quota: Good quota data\n"));
+
+ dp->bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
+ dp->softlimit =
(SMB_BIG_UINT)gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
+ dp->hardlimit =
(SMB_BIG_UINT)gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)0;
+ dp->isoftlimit = (SMB_BIG_UINT)0;
+ dp->curinodes = (SMB_BIG_UINT)1;
+ dp->curblocks =
(SMB_BIG_UINT)gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
+ dp->qflags = 0;
+ ret = 0;
+ break;
+
+ default:
+ DEBUG(9,("nfs_quota: Remote Quotas Questionable! Error \"%i\" \n",
gqr.status ));
+ break;
+ }
+
+ DEBUG(10,("nfs_quota: Let`s look at D a bit closer... status \"%i\" bsize
\"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n",
+ gqr.status,
+ gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
+ gqr.getquota_rslt_u.gqr_rquota.rq_active,
+ gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
+ gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
+ gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
+ out:
+
+ if (clnt) {
+ if (clnt->cl_auth)
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ }
+
+ DEBUG(10,("nfs_quota: End of nfs_quota_get_quota\n"));
+ return ret;
+}
+
+static int nfs_quota_set_quota(vfs_handle_struct *handle, connection_struct *conn,
enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq)
+{
+ DEBUG(10,("nfs_quota: setting quotas not supported!\n"));
+ errno = ENOSYS;
+ return -1;
+}
+
+
+/* VFS operations structure */
+
+static vfs_op_tuple nfs_quota_ops[] = {
+ {SMB_VFS_OP(nfs_quota_disk_free), SMB_VFS_OP_DISK_FREE,
SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(nfs_quota_get_quota), SMB_VFS_OP_GET_QUOTA,
SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(nfs_quota_set_quota), SMB_VFS_OP_SET_QUOTA,
SMB_VFS_LAYER_OPAQUE},
+
+ {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP,
SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_nfs_quota_init(void)
+{
+ return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs_quota", nfs_quota_ops);
+}
Index: configure.in
===================================================================
--- configure.in (revision 839)
+++ configure.in (working copy)
@@ -215,6 +215,7 @@
AC_SUBST(AUTH_LIBS)
AC_SUBST(ACL_LIBS)
AC_SUBST(PASSDB_LIBS)
+AC_SUBST(VFS_LIBS)
AC_SUBST(IDMAP_LIBS)
AC_SUBST(KRB5_LIBS)
AC_SUBST(LDAP_LIBS)
@@ -3220,6 +3221,17 @@
# For quotas on Veritas VxFS filesystems
AC_CHECK_HEADERS(sys/fs/vx_quota.h)
+#################################################
+# nfs quota module
+NFS_QUOTA_LIBS=""
+AC_SUBST(NFS_QUOTA_LIBS)
+AC_CHECK_HEADERS(rpcsvc/rquota.h)
+AC_CHECK_LIB_EXT(rpcsvc, NFS_QUOTA_LIBS, xdr_getquota_rslt)
+if test x"$ac_cv_header_rpcsvc_rquota_h" = x"yes" -a
x"$ac_cv_lib_ext_rpcsvc_xdr_getquota_rslt" = x"yes"; then
+ default_shared_modules="$default_shared_modules vfs_nfs_quota"
+fi
+#
+
# For sys/quota.h and linux/quota.h
AC_CHECK_HEADERS(sys/quota.h)
@@ -4373,6 +4385,8 @@
SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBEXT",
VFS)
SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS)
SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_nfs_quota, \$(VFS_NFS_QUOTA_OBJ), "bin/nfs_quota.$SHLIBEXT", VFS,
+ [ VFS_LIBS="$VFS_LIBS $NFS_QUOTA_LIBS" ] )
SMB_SUBSYSTEM(VFS,smbd/vfs.o)
AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of
builtin modules])
@@ -4396,6 +4410,8 @@
AC_MSG_RESULT([ LDAP_LIBS = $LDAP_LIBS])
fi
AC_MSG_RESULT([ AUTH_LIBS = $AUTH_LIBS])
+AC_MSG_RESULT([ PASSDB_LIBS = $PASSDB_LIBS])
+AC_MSG_RESULT([ VFS_LIBS = $VFS_LIBS])
#################################################
# final configure stuff
signature.asc
Description: OpenPGP digital signature
-- To unsubscribe from this list go to the following URL and read the instructions: http://lists.samba.org/mailman/listinfo/samba
