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

Attachment: 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

Reply via email to