[PATCH] better quota support on linux

Stefan Metzmacher metze at metzemix.de
Mon Jan 5 08:00:46 GMT 2004


Hi *,

here's a patch which ports the samba 2.2 samba_linux_quota.h stuff to 3_0.

This is needed because of so many broken quota files outthere.

Please, test this with old, new kernels
(strucr dqblk, struct mem_dqblk, and struct if_dqblk)
, quota.user, aquota.user formats

what is when a user is over soft quota and over hard quotas...

-- 

metze

-------------------------------------------
Stefan (metze) Metzmacher <metze at metzemix.de>
-------------- next part --------------
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/Makefile.in 3_0-ioctl/source/Makefile.in
--- 3_0/source/Makefile.in	Mon Jan  5 07:32:44 2004
+++ 3_0-ioctl/source/Makefile.in	Mon Jan  5 07:58:59 2004
@@ -351,8 +351,9 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpass
 	       smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
                smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \
 	       smbd/process.o smbd/service.o smbd/error.o \
-	       printing/printfsp.o \
-               lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \
+	       printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
+	       lib/sysquotas_xfs.o \
+	       smbd/change_trust_pw.o smbd/fake_file.o \
 	       smbd/quotas.o smbd/ntquotas.o lib/afs.o \
 	       $(MANGLE_OBJ) @VFS_STATIC@
 
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/configure.in 3_0-ioctl/source/configure.in
--- 3_0/source/configure.in	Mon Jan  5 07:32:44 2004
+++ 3_0-ioctl/source/configure.in	Mon Jan  5 07:36:07 2004
@@ -3009,6 +3009,7 @@ samba_cv_TRY_QUOTAS=no
 samba_cv_RUN_QUOTA_TESTS=auto
 samba_cv_WITH_SYS_QUOTAS=auto
 samba_cv_TRY_SYS_QUOTAS=no
+samba_cv_SYSQUOTA_FOUND=no;
 
 AC_MSG_CHECKING(whether to try disk-quotas support)
 AC_ARG_WITH(quotas,
@@ -3078,6 +3079,10 @@ AC_MSG_CHECKING(whether to try the lib/s
 	    AC_MSG_RESULT(yes)
             samba_cv_TRY_SYS_QUOTAS=yes
             samba_cv_RUN_QUOTA_TESTS=yes
+            samba_cv_SYSQUOTA_FOUND=yes
+            AC_DEFINE(HAVE_QUOTACTL_LINUX,1,[Whether Linux quota support is available])
+            AC_DEFINE(HAVE_LINUX_XFS_QUOTAS,1,[Whether Linux xfs quota support is available])
+            samba_cv_sysquotas_file="lib/sysquotas_linux.c"
 	    ;;
 	*)
 	    AC_MSG_RESULT(no)
@@ -3090,21 +3095,21 @@ fi
 # only check for quota stuff if --with-quotas
 if test x"$samba_cv_RUN_QUOTA_TESTS" != x"no"; then
 
+# some broken header files need this
+AC_CHECK_HEADER(asm/types.h,[
+	    AC_DEFINE(HAVE_ASM_TYPES_H,1,[check for <asm/types.h>])
+	    AC_ADD_INCLUDE(<asm/types.h>)
+	    ])
+
 # For quotas on Veritas VxFS filesystems
 AC_CHECK_HEADERS(sys/fs/vx_quota.h)
 
 # For sys/quota.h and linux/quota.h
 AC_CHECK_HEADERS(sys/quota.h)
-AC_CHECK_HEADERS(asm/types.h linux/quota.h)
 
-# For quotas on Linux XFS filesystems
-AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h)
-AC_CHECK_HEADERS(xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h)
-# For linux > 2.5.56 
-AC_CHECK_HEADERS(linux/dqblk_xfs.h)
-
-# if we have struct if_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct if_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_IF_DQBLK, [
+if test x"$samba_cv_found_xfs_header" = x"no"; then
+# if we have xfs quota support <sys/quota.h> (IRIX) we should use it
+AC_CACHE_CHECK([for XFS QUOTA in <sys/quota.h>],samba_cv_HAVE_SYS_QUOTA_XFS, [
 AC_TRY_COMPILE([
 #include "confdefs.h"
 #ifdef HAVE_SYS_TYPES_H
@@ -3113,30 +3118,15 @@ AC_TRY_COMPILE([
 #ifdef HAVE_ASM_TYPES_H
 #include <asm/types.h>
 #endif
-#include <linux/quota.h>
-],[struct if_dqblk D;],
-samba_cv_HAVE_STRUCT_IF_DQBLK=yes,samba_cv_HAVE_STRUCT_IF_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_IF_DQBLK"x = "yes"x; then
-	AC_DEFINE(HAVE_STRUCT_IF_DQBLK,1,[struct if_dqblk])
+#include <sys/quota.h>
+],[int i = Q_XGETQUOTA;],
+samba_cv_HAVE_SYS_QUOTA_XFS=yes,samba_cv_HAVE_SYS_QUOTA_XFS=no)])
+if test "$samba_cv_HAVE_SYS_QUOTA_XFS"x = "yes"x; then
+	AC_DEFINE(HAVE_IRIX_XFS_QUOTAS,1,[Whether IRIX xfs quota support is available])
 fi
-
-# if we have struct mem_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct mem_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_MEM_DQBLK, [
-AC_TRY_COMPILE([
-#include "confdefs.h"
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-#include <linux/quota.h>
-],[struct mem_dqblk D;],
-samba_cv_HAVE_STRUCT_MEM_DQBLK=yes,samba_cv_HAVE_STRUCT_MEM_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_MEM_DQBLK"x = "yes"x; then
-	AC_DEFINE(HAVE_STRUCT_MEM_DQBLK,1,[struct mem_dqblk])
 fi
 
+
 # if we have struct dqblk .dqb_fsoftlimit instead of .dqb_isoftlimit on IRIX 
 AC_CACHE_CHECK([if struct dqblk has .dqb_fsoftlimit],samba_cv_HAVE_DQB_FSOFTLIMIT, [
 AC_TRY_COMPILE([
@@ -3154,7 +3144,6 @@ fi
 
 ##################
 # look for a working quota system
-samba_cv_SYSQUOTA_FOUND=no;
 
 if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then
 AC_CACHE_CHECK([for long quotactl(int cmd, char *special, qid_t id, caddr_t addr)],samba_cv_HAVE_QUOTACTL_4A,[
@@ -3165,7 +3154,9 @@ AC_TRY_RUN_STRICT([
 #include "${srcdir-.}/tests/sysquotas.c"],[$Werror_FLAGS],[$CPPFLAGS],[$LDFLAGS],
            samba_cv_HAVE_QUOTACTL_4A=yes,samba_cv_HAVE_QUOTACTL_4A=no,samba_cv_HAVE_QUOTACTL_4A=cross)])
 if test x"$samba_cv_HAVE_QUOTACTL_4A" = x"yes"; then
-    samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+    samba_cv_SYSQUOTA_FOUND=yes;
+    AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+    samba_cv_sysquotas_file="lib/sysquotas_4A.c"
 fi
 fi
 
@@ -3179,7 +3170,9 @@ AC_TRY_RUN_STRICT([
            samba_cv_HAVE_QUOTACTL_4B=yes,samba_cv_HAVE_QUOTACTL_4B=no,samba_cv_HAVE_QUOTACTL_4B=cross)])
 if test x"$samba_cv_HAVE_QUOTACTL_4B" = x"yes"; then
     echo "int quotactl(const char *path, int cmd, int id, char *addr) is not reworked for the new sys_quota api"
-#    samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+    samba_cv_SYSQUOTA_FOUND=yes;
+    AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+    samba_cv_sysquotas_file="lib/sysquotas_4B.c"
 fi
 fi
 
@@ -3193,7 +3186,9 @@ AC_TRY_RUN_STRICT([
            samba_cv_HAVE_QUOTACTL_3=yes,samba_cv_HAVE_QUOTACTL_3=no,samba_cv_HAVE_QUOTACTL_3=cross)])
 if test x"$samba_cv_HAVE_QUOTACTL_3" = x"yes"; then
     echo "CRAY int quotactl (char *spec, int request, char *arg) is NOT reworked for the sys_quota api"
-#    samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+    samba_cv_SYSQUOTA_FOUND=yes;
+    AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+    samba_cv_sysquotas_file="lib/sysquotas_3.c"
 fi
 fi
 
@@ -3235,6 +3230,7 @@ AC_TRY_COMPILE([
 #define NO_PROTO_H 1
 #define NO_CONFIG_H 1
 #define HAVE_SYS_QUOTAS 1
+#include "${srcdir-.}/${samba_cv_sysquotas_file}"
 #include "${srcdir-.}/lib/sysquotas.c"
 ],[],samba_cv_SYSQUOTA_WORKS=yes,samba_cv_SYSQUOTA_WORKS=no)
 CPPFLAGS="$SAVE_CPPFLAGS"
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/include/samba_linux_quota.h 3_0-ioctl/source/include/samba_linux_quota.h
--- 3_0/source/include/samba_linux_quota.h	Thu Jan  1 01:00:00 1970
+++ 3_0-ioctl/source/include/samba_linux_quota.h	Thu Dec 11 20:15:15 2003
@@ -0,0 +1,336 @@
+#ifndef _SAMBA_LINUX_QUOTA_H_
+#define _SAMBA_LINUX_QUOTA_H_
+/*
+   Unix SMB/CIFS implementation.
+   Copyright (C) Andrew Tridgell 1994-2002
+
+   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.
+*/
+
+/*
+	This file is needed because Quota support on Linux has
+	been broken since Linus kernel 2.4.x. It will only get
+	better (and this file be removed) when all the distributions
+	ship a glibc with a working quota.h file. This is very
+	bad. JRA.
+
+	Original file came from Christoph Hellwig <hch at infradead.org>.
+	Massaged into one nasty include file (to stop us having to
+	add multiple files into Samba just for Linux braindamage)
+	by JRA.
+*/
+
+#undef QUOTABLOCK_SIZE
+
+#ifndef _QUOTAIO_LINUX_V1
+#define _QUOTAIO_LINUX_V1
+
+/*
+ *	Headerfile for old quotafile format
+ */
+
+#include <sys/types.h>
+
+#define V1_DQBLK_SIZE_BITS 10
+#define V1_DQBLK_SIZE (1 << V1_DQBLK_SIZE_BITS)	/* Size of one quota block in bytes in old format */
+
+#define V1_DQOFF(__id) ((loff_t) ((__id) * sizeof(struct v1_disk_dqblk)))
+
+/* Structure of quota on disk */
+struct v1_disk_dqblk {
+	u_int32_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
+	u_int32_t dqb_bsoftlimit;	/* preferred limit on disk blks */
+	u_int32_t dqb_curblocks;	/* current block count */
+	u_int32_t dqb_ihardlimit;	/* maximum # allocated inodes */
+	u_int32_t dqb_isoftlimit;	/* preferred limit on inodes */
+	u_int32_t dqb_curinodes;	/* current # allocated inodes */
+	time_t dqb_btime;	/* time limit for excessive disk use */
+	time_t dqb_itime;	/* time limit for excessive files */
+} __attribute__ ((packed));
+
+/* Structure used for communication with kernel */
+struct v1_kern_dqblk {
+	u_int32_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
+	u_int32_t dqb_bsoftlimit;	/* preferred limit on disk blks */
+	u_int32_t dqb_curblocks;	/* current block count */
+	u_int32_t dqb_ihardlimit;	/* maximum # allocated inodes */
+	u_int32_t dqb_isoftlimit;	/* preferred inode limit */
+	u_int32_t dqb_curinodes;	/* current # allocated inodes */
+	time_t dqb_btime;	/* time limit for excessive disk use */
+	time_t dqb_itime;	/* time limit for excessive files */
+};
+
+struct v1_dqstats {
+	u_int32_t lookups;
+	u_int32_t drops;
+	u_int32_t reads;
+	u_int32_t writes;
+	u_int32_t cache_hits;
+	u_int32_t allocated_dquots;
+	u_int32_t free_dquots;
+	u_int32_t syncs;
+};                                                                               
+
+#ifndef Q_V1_GETQUOTA
+#define Q_V1_GETQUOTA  0x300
+#endif
+#ifndef Q_V1_SETQUOTA
+#define Q_V1_SETQUOTA  0x400
+#endif
+
+#endif /* _QUOTAIO_LINUX_V1 */
+
+/*
+ *
+ *	Header file for disk format of new quotafile format
+ *
+ */
+
+#ifndef _QUOTAIO_LINUX_V2
+#define _QUOTAIO_LINUX_V2
+
+#include <sys/types.h>
+
+#ifndef _QUOTA_LINUX
+#define _QUOTA_LINUX
+
+#include <sys/types.h>
+
+typedef u_int32_t qid_t;	/* Type in which we store ids in memory */
+typedef u_int64_t qsize_t;	/* Type in which we store size limitations */
+
+#define MAXQUOTAS 2
+#define USRQUOTA  0		/* element used for user quotas */
+#define GRPQUOTA  1		/* element used for group quotas */
+
+/*
+ * Definitions for the default names of the quotas files.
+ */
+#define INITQFNAMES { \
+	"user",    /* USRQUOTA */ \
+	"group",   /* GRPQUOTA */ \
+	"undefined", \
+}
+
+/*
+ * Definitions of magics and versions of current quota files
+ */
+#define INITQMAGICS {\
+	0xd9c01f11,	/* USRQUOTA */\
+	0xd9c01927	/* GRPQUOTA */\
+}
+
+/* Size of blocks in which are counted size limits in generic utility parts */
+#define QUOTABLOCK_BITS 10
+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
+
+/* Conversion routines from and to quota blocks */
+#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
+#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
+#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
+
+/*
+ * Command definitions for the 'quotactl' system call.
+ * The commands are broken into a main command defined below
+ * and a subcommand that is used to convey the type of
+ * quota that is being manipulated (see above).
+ */
+#define SUBCMDMASK  0x00ff
+#define SUBCMDSHIFT 8
+#define QCMD(cmd, type)  (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
+
+#define Q_6_5_QUOTAON  0x0100	/* enable quotas */
+#define Q_6_5_QUOTAOFF 0x0200	/* disable quotas */
+#define Q_6_5_SYNC     0x0600	/* sync disk copy of a filesystems quotas */
+
+#define Q_SYNC     0x800001	/* sync disk copy of a filesystems quotas */
+#define Q_QUOTAON  0x800002	/* turn quotas on */
+#define Q_QUOTAOFF 0x800003	/* turn quotas off */
+#define Q_GETFMT   0x800004	/* get quota format used on given filesystem */
+#define Q_GETINFO  0x800005	/* get information about quota files */
+#define Q_SETINFO  0x800006	/* set information about quota files */
+#define Q_GETQUOTA 0x800007	/* get user quota structure */
+#define Q_SETQUOTA 0x800008	/* set user quota structure */
+
+/*
+ * Quota structure used for communication with userspace via quotactl
+ * Following flags are used to specify which fields are valid
+ */
+#define QIF_BLIMITS	1
+#define QIF_SPACE	2
+#define QIF_ILIMITS	4
+#define QIF_INODES	8
+#define QIF_BTIME	16
+#define QIF_ITIME	32
+#define QIF_LIMITS	(QIF_BLIMITS | QIF_ILIMITS)
+#define QIF_USAGE	(QIF_SPACE | QIF_INODES)
+#define QIF_TIMES	(QIF_BTIME | QIF_ITIME)
+#define QIF_ALL		(QIF_LIMITS | QIF_USAGE | QIF_TIMES)
+
+struct if_dqblk {
+	u_int64_t dqb_bhardlimit;
+	u_int64_t dqb_bsoftlimit;
+	u_int64_t dqb_curspace;
+	u_int64_t dqb_ihardlimit;
+	u_int64_t dqb_isoftlimit;
+	u_int64_t dqb_curinodes;
+	u_int64_t dqb_btime;
+	u_int64_t dqb_itime;
+	u_int32_t dqb_valid;
+};
+
+/*
+ * Structure used for setting quota information about file via quotactl
+ * Following flags are used to specify which fields are valid
+ */
+#define IIF_BGRACE	1
+#define IIF_IGRACE	2
+#define IIF_FLAGS	4
+#define IIF_ALL		(IIF_BGRACE | IIF_IGRACE | IIF_FLAGS)
+
+struct if_dqinfo {
+	u_int64_t dqi_bgrace;
+	u_int64_t dqi_igrace;
+	u_int32_t dqi_flags;
+	u_int32_t dqi_valid;
+};
+
+/* Quota format identifiers */
+#define QFMT_VFS_OLD 1
+#define QFMT_VFS_V0  2
+
+/* Flags supported by kernel */
+#define V1_DQF_RSQUASH 1
+
+/* Ioctl for getting quota size */
+#include <sys/ioctl.h>
+#ifndef FIOQSIZE
+	#if defined(__alpha__) || defined(__powerpc__) || defined(__sh__) || defined(__sparc__) || defined(__sparc64__)
+		#define FIOQSIZE _IOR('f', 128, loff_t)
+	#elif defined(__arm__) || defined(__mc68000__) || defined(__s390__)
+		#define FIOQSIZE 0x545E
+        #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__ia64__) || defined(__parisc__) || defined(__cris__) || defined(__hppa__)
+		#define FIOQSIZE 0x5460
+	#elif defined(__mips__) || defined(__mips64__)
+		#define FIOQSIZE 0x6667
+	#endif
+#endif
+
+long quotactl __P((int, const char *, qid_t, caddr_t));
+
+#endif /* _QUOTA_LINUX */
+
+#define V2_DQINFOOFF	sizeof(struct v2_disk_dqheader)	/* Offset of info header in file */
+#define V2_DQBLKSIZE_BITS	10
+#define V2_DQBLKSIZE	(1 << V2_DQBLKSIZE_BITS)	/* Size of block with quota structures */
+#define V2_DQTREEOFF	1	/* Offset of tree in file in blOcks */
+#define V2_DQTREEDEPTH	4	/* Depth of quota tree */
+#define V2_DQSTRINBLK	((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))	/* Number of entries in one blocks */
+#define V2_GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
+#define V2_GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)(buf)) + sizeof(struct v2_disk_dqdbheader)))
+#define INIT_V2_VERSIONS { 0, 0}
+
+struct v2_disk_dqheader {
+	u_int32_t dqh_magic;	/* Magic number identifying file */
+	u_int32_t dqh_version;	/* File version */
+} __attribute__ ((packed));
+
+/* Flags for version specific files */
+#define V2_DQF_MASK  0x0000	/* Mask for all valid ondisk flags */
+
+/* Header with type and version specific information */
+struct v2_disk_dqinfo {
+	u_int32_t dqi_bgrace;	/* Time before block soft limit becomes hard limit */
+	u_int32_t dqi_igrace;	/* Time before inode soft limit becomes hard limit */
+	u_int32_t dqi_flags;	/* Flags for quotafile (DQF_*) */
+	u_int32_t dqi_blocks;	/* Number of blocks in file */
+	u_int32_t dqi_free_blk;	/* Number of first free block in the list */
+	u_int32_t dqi_free_entry;	/* Number of block with at least one free entry */
+} __attribute__ ((packed));
+
+/*
+ *  Structure of header of block with quota structures. It is padded to 16 bytes so
+ *  there will be space for exactly 18 quota-entries in a block
+ */
+struct v2_disk_dqdbheader {
+	u_int32_t dqdh_next_free;	/* Number of next block with free entry */
+	u_int32_t dqdh_prev_free;	/* Number of previous block with free entry */
+	u_int16_t dqdh_entries;	/* Number of valid entries in block */
+	u_int16_t dqdh_pad1;
+	u_int32_t dqdh_pad2;
+} __attribute__ ((packed));
+
+/* Structure of quota for one user on disk */
+struct v2_disk_dqblk {
+	u_int32_t dqb_id;	/* id this quota applies to */
+	u_int32_t dqb_ihardlimit;	/* absolute limit on allocated inodes */
+	u_int32_t dqb_isoftlimit;	/* preferred inode limit */
+	u_int32_t dqb_curinodes;	/* current # allocated inodes */
+	u_int32_t dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+	u_int32_t dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+	u_int64_t dqb_curspace;	/* current space occupied (in bytes) */
+	u_int64_t dqb_btime;	/* time limit for excessive disk use */
+	u_int64_t dqb_itime;	/* time limit for excessive inode use */
+} __attribute__ ((packed));
+
+/* Structure of quota for communication with kernel */
+struct v2_kern_dqblk {
+	unsigned int dqb_ihardlimit;
+	unsigned int dqb_isoftlimit;
+	unsigned int dqb_curinodes;
+	unsigned int dqb_bhardlimit;
+	unsigned int dqb_bsoftlimit;
+	qsize_t dqb_curspace;
+	time_t dqb_btime;
+	time_t dqb_itime;
+};
+
+/* Structure of quotafile info for communication with kernel */
+struct v2_kern_dqinfo {
+	unsigned int dqi_bgrace;
+	unsigned int dqi_igrace;
+	unsigned int dqi_flags;
+	unsigned int dqi_blocks;
+	unsigned int dqi_free_blk;
+	unsigned int dqi_free_entry;
+};
+
+/* Structure with gathered statistics from kernel */
+struct v2_dqstats {
+	u_int32_t lookups;
+	u_int32_t drops;
+	u_int32_t reads;
+	u_int32_t writes;
+	u_int32_t cache_hits;
+	u_int32_t allocated_dquots;
+	u_int32_t free_dquots;
+	u_int32_t syncs;
+	u_int32_t version;
+};
+
+#ifndef Q_V2_GETQUOTA
+#define Q_V2_GETQUOTA  0x0D00
+#endif
+#ifndef Q_V2_SETQUOTA
+#define Q_V2_SETQUOTA  0x0E00
+#endif
+
+#endif /* _QUOTAIO_LINUX_V2 */
+
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE        1024
+#endif
+
+#endif /* _SAMBA_LINUX_QUOTA_H_ */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/include/samba_xfs_quota.h 3_0-ioctl/source/include/samba_xfs_quota.h
--- 3_0/source/include/samba_xfs_quota.h	Thu Jan  1 01:00:00 1970
+++ 3_0-ioctl/source/include/samba_xfs_quota.h	Tue Dec  2 09:42:12 2003
@@ -0,0 +1,165 @@
+#ifndef _SAMBA_LINUX_XFS_H_
+#define _SAMBA_LINUX_XFS_H_
+
+#ifndef _QUOTAIO_LINUX_XFS
+#define _QUOTAIO_LINUX_XFS
+
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <linux/types.h>
+
+#define XQM_CMD(cmd)	( ('X'<<8)+(cmd) )
+#define IS_XQM_CMD(cmd)	( ((int)(cmd)>>8) == 'X' )
+
+/*
+ * Disk quota - quotactl(2) commands for XFS Quota Manager (XQM).
+ */
+#define Q_XQUOTAON   XQM_CMD(0x1)	/* enable quota accounting/enforcement */
+#define Q_XQUOTAOFF  XQM_CMD(0x2)	/* disable quota accounting/enforcement */
+#define Q_XGETQUOTA  XQM_CMD(0x3)	/* get disk limits & usage */
+#define Q_XSETQLIM   XQM_CMD(0x4)	/* set disk limits only */
+#define Q_XGETQSTAT  XQM_CMD(0x5)	/* returns fs_quota_stat_t struct */
+#define Q_XQUOTARM   XQM_CMD(0x6)	/* free quota files' space */
+
+/*
+ * fs_disk_quota structure:
+ *
+ * This contains the current quota information regarding a user/proj/group.
+ * It is 64-bit aligned, and all the blk units are in BBs (Basic Blocks) of
+ * 512 bytes.
+ */
+#define FS_DQUOT_VERSION	1	/* fs_disk_quota.d_version */
+typedef struct fs_disk_quota {
+	u_int8_t d_version;		/* version of this structure */
+	u_int8_t d_flags;		/* XFS_{USER,PROJ,GROUP}_QUOTA */
+	u_int16_t d_fieldmask;	/* field specifier */
+	u_int32_t d_id;		/* user, project, or group ID */
+	u_int64_t d_blk_hardlimit;	/* absolute limit on disk blks */
+	u_int64_t d_blk_softlimit;	/* preferred limit on disk blks */
+	u_int64_t d_ino_hardlimit;	/* maximum # allocated inodes */
+	u_int64_t d_ino_softlimit;	/* preferred inode limit */
+	u_int64_t d_bcount;		/* # disk blocks owned by the user */
+	u_int64_t d_icount;		/* # inodes owned by the user */
+	int32_t d_itimer;		/* zero if within inode limits */
+	/* if not, we refuse service */
+	int32_t d_btimer;		/* similar to above; for disk blocks */
+	u_int16_t d_iwarns;		/* # warnings issued wrt num inodes */
+	u_int16_t d_bwarns;		/* # warnings issued wrt disk blocks */
+	int32_t d_padding2;	/* padding2 - for future use */
+	u_int64_t d_rtb_hardlimit;	/* absolute limit on realtime blks */
+	u_int64_t d_rtb_softlimit;	/* preferred limit on RT disk blks */
+	u_int64_t d_rtbcount;	/* # realtime blocks owned */
+	int32_t d_rtbtimer;	/* similar to above; for RT disk blks */
+	u_int16_t d_rtbwarns;	/* # warnings issued wrt RT disk blks */
+	int16_t d_padding3;	/* padding3 - for future use */
+	char d_padding4[8];	/* yet more padding */
+} fs_disk_quota_t;
+
+/*
+ * These fields are sent to Q_XSETQLIM to specify fields that need to change.
+ */
+#define FS_DQ_ISOFT	(1<<0)
+#define FS_DQ_IHARD	(1<<1)
+#define FS_DQ_BSOFT	(1<<2)
+#define FS_DQ_BHARD 	(1<<3)
+#define FS_DQ_RTBSOFT	(1<<4)
+#define FS_DQ_RTBHARD	(1<<5)
+#define FS_DQ_LIMIT_MASK	(FS_DQ_ISOFT | FS_DQ_IHARD | FS_DQ_BSOFT | \
+				 FS_DQ_BHARD | FS_DQ_RTBSOFT | FS_DQ_RTBHARD)
+/*
+ * These timers can only be set in super user's dquot. For others, timers are
+ * automatically started and stopped. Superusers timer values set the limits
+ * for the rest.  In case these values are zero, the DQ_{F,B}TIMELIMIT values
+ * defined below are used. 
+ * These values also apply only to the d_fieldmask field for Q_XSETQLIM.
+ */
+#define FS_DQ_BTIMER	(1<<6)
+#define FS_DQ_ITIMER	(1<<7)
+#define FS_DQ_RTBTIMER 	(1<<8)
+#define FS_DQ_TIMER_MASK	(FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
+
+/*
+ * The following constants define the default amount of time given a user
+ * before the soft limits are treated as hard limits (usually resulting
+ * in an allocation failure).  These may be modified by the quotactl(2)
+ * system call with the Q_XSETQLIM command.
+ */
+#define	DQ_FTIMELIMIT	(7 * 24*60*60)	/* 1 week */
+#define	DQ_BTIMELIMIT	(7 * 24*60*60)	/* 1 week */
+
+/*
+ * Various flags related to quotactl(2).  Only relevant to XFS filesystems.
+ */
+#define XFS_QUOTA_UDQ_ACCT	(1<<0)	/* user quota accounting */
+#define XFS_QUOTA_UDQ_ENFD	(1<<1)	/* user quota limits enforcement */
+#define XFS_QUOTA_GDQ_ACCT	(1<<2)	/* group quota accounting */
+#define XFS_QUOTA_GDQ_ENFD	(1<<3)	/* group quota limits enforcement */
+
+#define XFS_USER_QUOTA		(1<<0)	/* user quota type */
+#define XFS_PROJ_QUOTA		(1<<1)	/* (IRIX) project quota type */
+#define XFS_GROUP_QUOTA		(1<<2)	/* group quota type */
+
+/*
+ * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system.
+ * Provides a centralized way to get meta infomation about the quota subsystem.
+ * eg. space taken up for user and group quotas, number of dquots currently
+ * incore.
+ */
+#define FS_QSTAT_VERSION	1	/* fs_quota_stat.qs_version */
+
+/*
+ * Some basic infomation about 'quota files'.
+ */
+typedef struct fs_qfilestat {
+	u_int64_t qfs_ino;		/* inode number */
+	u_int64_t qfs_nblks;	/* number of BBs 512-byte-blks */
+	u_int32_t qfs_nextents;	/* number of extents */
+} fs_qfilestat_t;
+
+typedef struct fs_quota_stat {
+	u_int8_t qs_version;	/* version number for future changes */
+	u_int16_t qs_flags;		/* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
+	u_int8_t qs_pad;		/* unused */
+	fs_qfilestat_t qs_uquota;	/* user quota storage information */
+	fs_qfilestat_t qs_gquota;	/* group quota storage information */
+	u_int32_t qs_incoredqs;	/* number of dquots incore */
+	int32_t qs_btimelimit;	/* limit for blks timer */
+	int32_t qs_itimelimit;	/* limit for inodes timer */
+	int32_t qs_rtbtimelimit;	/* limit for rt blks timer */
+	u_int16_t qs_bwarnlimit;	/* limit for num warnings */
+	u_int16_t qs_iwarnlimit;	/* limit for num warnings */
+} fs_quota_stat_t;
+
+#endif /* _QUOTAIO_LINUX_XFS */
+
+#endif /* _SAMBA_LINUX_XFS_H_ */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/include/sysquotas.h 3_0-ioctl/source/include/sysquotas.h
--- 3_0/source/include/sysquotas.h	Wed Jul 30 07:32:58 2003
+++ 3_0-ioctl/source/include/sysquotas.h	Fri Dec 12 14:09:11 2003
@@ -23,150 +23,6 @@
  
 #ifdef HAVE_SYS_QUOTAS
 
-/* Sometimes we need this on linux for linux/quota.h */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-
-/*
- * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
- */
-#ifdef HAVE_LINUX_QUOTA_H
-#include <linux/quota.h>
-#elif defined(HAVE_SYS_QUOTA_H)
-#include <sys/quota.h>
-#endif
-
-#if defined(HAVE_STRUCT_IF_DQBLK)
-# define SYS_DQBLK if_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#elif defined(HAVE_STRUCT_MEM_DQBLK)
-# define SYS_DQBLK mem_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#else /* STRUCT_DQBLK */
-# define SYS_DQBLK dqblk
-#endif
-
-#ifndef Q_SETQLIM
-#define Q_SETQLIM Q_SETQUOTA
-#endif
-
-/*********************************************
- check for XFS QUOTA MANAGER 
- *********************************************/
-/* on linux */
-#ifdef HAVE_LINUX_XQM_H
-# include <linux/xqm.h>
-# define HAVE_XFS_QUOTA
-#else
-# ifdef HAVE_XFS_XQM_H
-#  include <xfs/xqm.h>
-#  define HAVE_XFS_QUOTA
-# else
-#  ifdef HAVE_LINUX_DQBLK_XFS_H
-#   include <linux/dqblk_xfs.h>
-#   define HAVE_XFS_QUOTA
-#  endif 
-# endif
-#endif
-/* on IRIX */
-#ifdef Q_XGETQUOTA
-# ifndef HAVE_XFS_QUOTA
-#  define HAVE_XFS_QUOTA
-#  ifndef Q_XQUOTAON
-#   define Q_XQUOTAON Q_QUOTAON
-#  endif /* Q_XQUOTAON */
-#  ifndef Q_XQUOTAOFF
-#   define Q_XQUOTAOFF Q_QUOTAOFF
-#  endif /* Q_XQUOTAOFF */
-#  ifndef Q_XGETQSTAT
-#   define Q_XGETQSTAT Q_GETQSTAT
-#  endif /* Q_XGETQSTAT */
-# endif /* HAVE_XFS_QUOTA */
-#endif /* Q_XGETQUOTA */
-
-#ifdef HAVE_XFS_QUOTA
-/* Linux has BBSIZE in <linux/xfs_fs.h>
- * or <xfs/xfs_fs.h>
- * IRIX has BBSIZE in <sys/param.h>
- */
-#ifdef HAVE_LINUX_XFS_FS_H
-#include <linux/xfs_fs.h>
-#elif defined(HAVE_XFS_XFS_FS_H)
-#include <xfs/xfs_fs.h>
-#endif /* *_XFS_FS_H */
-
-#ifndef BBSHIFT
-#define	BBSHIFT		9
-#endif /* BBSHIFT */
-#ifndef BBSIZE
-#define	BBSIZE		(1<<BBSHIFT)
-#endif /* BBSIZE */
-
-#endif /* HAVE_XFS_QUOTA */
-
-#ifdef LINUX
-# ifndef QUOTABLOCK_SIZE
-#  define QUOTABLOCK_SIZE 1024
-# endif
-/* end LINUX */
-#elif defined(IRIX6)
-# ifndef QUOTABLOCK_SIZE
-#  define QUOTABLOCK_SIZE BBSIZE
-# endif
-/* end IRIX6 */
-#else /* HPUP,... */
-# ifndef QUOTABLOCK_SIZE
-#  define QUOTABLOCK_SIZE DEV_BSIZE
-# endif
-#endif /* HPUP,... */
-
-#if !defined(QUOTAFILENAME) && defined(QFILENAME)
-#define QUOTAFILENAME QFILENAME
-#endif
-
-#ifdef INITQFNAMES
-#define USERQUOTAFILE_EXTENSION ".user"
-#else
-#define USERQUOTAFILE_EXTENSION ""
-#endif
-
-/* this check should be before the QCMD fake! */
-#if defined(QCMD)&&defined(GRPQUOTA)
-#define HAVE_GROUP_QUOTA
-#endif
-
-/* on some systems we have to fake this up ...*/
-#ifndef QCMD
-#define QCMD(cmd,type)	(cmd)
-#endif /* QCMD */
-
-
-#ifdef HAVE_DQB_FSOFTLIMIT
-#define dqb_isoftlimit	dqb_fsoftlimit
-#define dqb_ihardlimit	dqb_fhardlimit
-#define dqb_curinodes	dqb_curfiles
-#endif
-
-/* maybe we can add a configure test for HAVE_CADDR_T,
- * but it's not needed
- */
-#ifdef HAVE_CADDR_T
-#define CADDR_T caddr_t
-#else /* CADDR_T */
-#define CADDR_T void*
-#endif /* CADDR_T */
-
 #if defined(HAVE_MNTENT_H)&&defined(HAVE_SETMNTENT)&&defined(HAVE_GETMNTENT)&&defined(HAVE_ENDMNTENT)
 #include <mntent.h>
 #define HAVE_MNTENT 1
@@ -178,10 +34,6 @@
 #endif /* HAVE_SYS_QUOTAS */
 
 
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE	1024
-#endif
-
 /**************************************************
  Some stuff for the sys_quota api.
  **************************************************/ 
@@ -216,5 +68,9 @@ typedef struct _SMB_DISK_QUOTA {
 	SMB_BIG_UINT curinodes; /* Current used inodes. */
 	uint32       qflags;
 } SMB_DISK_QUOTA;
+
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE 1024
+#endif
 
 #endif /*_SYSQUOTAS_H */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/lib/sysquotas.c 3_0-ioctl/source/lib/sysquotas.c
--- 3_0/source/lib/sysquotas.c	Sat Oct 11 16:17:56 2003
+++ 3_0-ioctl/source/lib/sysquotas.c	Mon Dec 15 10:11:55 2003
@@ -24,255 +24,6 @@
 #ifdef HAVE_SYS_QUOTAS
 
 #if defined(HAVE_QUOTACTL_4A) 
-/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
-/* this is used by: linux,HPUX,IRIX */
-
-/****************************************************************************
- Abstract out the old and new Linux quota get calls.
-****************************************************************************/
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	uint32 qflags = 0;
-	struct SYS_DQBLK D;
-	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
-	if (!path||!bdev||!dp)
-		smb_panic("sys_get_vfs_quota: called with NULL pointer");
-
-	ZERO_STRUCT(D);
-	ZERO_STRUCT(*dp);
-	dp->qtype = qtype;
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) {
-				return ret;
-			}
-
-			if ((D.dqb_curblocks==0)&&
-				(D.dqb_bsoftlimit==0)&&
-				(D.dqb_bhardlimit==0)) {
-				/* the upper layer functions don't want empty quota records...*/
-				return -1;
-			}
-
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_QUOTA_TYPE:
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) {
-				return ret;
-			}
-
-			if ((D.dqb_curblocks==0)&&
-				(D.dqb_bsoftlimit==0)&&
-				(D.dqb_bhardlimit==0)) {
-				/* the upper layer functions don't want empty quota records...*/
-				return -1;
-			}
-
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		case SMB_USER_FS_QUOTA_TYPE:
-			id.uid = getuid();
-
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-
-			ret = 0;
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			id.gid = getgid();
-
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-
-			ret = 0;
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	dp->bsize = bsize;
-	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
-	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
-	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
-	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
-	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
-	dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-
-
-	dp->qflags = qflags;
-
-	return ret;
-}
-
-/****************************************************************************
- Abstract out the old and new Linux quota set calls.
-****************************************************************************/
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	uint32 qflags = 0;
-	uint32 oldqflags = 0;
-	struct SYS_DQBLK D;
-	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
-	if (!path||!bdev||!dp)
-		smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
-	ZERO_STRUCT(D);
-
-	if (bsize == dp->bsize) {
-		D.dqb_bsoftlimit = dp->softlimit;
-		D.dqb_bhardlimit = dp->hardlimit;
-		D.dqb_ihardlimit = dp->ihardlimit;
-		D.dqb_isoftlimit = dp->isoftlimit;
-	} else {
-		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
-		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
-		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
-		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
-	}
-
-	qflags = dp->qflags;
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_QUOTA_TYPE:
-			ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		case SMB_USER_FS_QUOTA_TYPE:
-			/* this stuff didn't work as it should:
-			 * switching on/off quota via quotactl()
-			 * didn't work!
-			 * So we just return 0
-			 * --metze
-			 * 
-			 * On HPUX we didn't have the mount path,
-			 * we need to fix sys_path_to_bdev()
-			 *
-			 */
-#if 0
-			id.uid = getuid();
-
-			ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-
-			if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
-				if (ret == 0) {
-					char *quota_file = NULL;
-					
-					asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
-					if (quota_file == NULL) {
-						DEBUG(0,("asprintf() failed!\n"));
-						errno = ENOMEM;
-						return -1;
-					}
-					
-					ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file);
-				} else {
-					ret = 0;	
-				}
-			} else {
-				if (ret != 0) {
-					/* turn off */
-					ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0);	
-				} else {
-					ret = 0;
-				}		
-			}
-
-			DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
-				ret,errno,strerror(errno),id.uid,bdev));
-#else
-			id.uid = getuid();
-
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
-				oldqflags |= QUOTAS_DENY_DISK;
-			}
-
-			if (oldqflags == qflags) {
-				ret = 0;
-			} else {
-				ret = -1;
-			}
-#endif
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			/* this stuff didn't work as it should:
-			 * switching on/off quota via quotactl()
-			 * didn't work!
-			 * So we just return 0
-			 * --metze
-			 * 
-			 * On HPUX we didn't have the mount path,
-			 * we need to fix sys_path_to_bdev()
-			 *
-			 */
-#if 0
-			id.gid = getgid();
-
-			ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (CADDR_T)&D);
-
-			if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
-				if (ret == 0) {
-					char *quota_file = NULL;
-					
-					asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
-					if (quota_file == NULL) {
-						DEBUG(0,("asprintf() failed!\n"));
-						errno = ENOMEM;
-						return -1;
-					}
-					
-					ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(CADDR_T)quota_file);
-				} else {
-					ret = 0;	
-				}
-			} else {
-				if (ret != 0) {
-					/* turn off */
-					ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (CADDR_T)0);	
-				} else {
-					ret = 0;
-				}		
-			}
-
-			DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
-				ret,errno,strerror(errno),id.gid,bdev));
-#else
-			id.gid = getgid();
-
-			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
-				oldqflags |= QUOTAS_DENY_DISK;
-			}
-
-			if (oldqflags == qflags) {
-				ret = 0;
-			} else {
-				ret = -1;
-			}
-#endif
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	return ret;
-}
 
 /*#endif HAVE_QUOTACTL_4A */
 #elif defined(HAVE_QUOTACTL_4B)
@@ -287,30 +38,6 @@ static int sys_set_vfs_quota(const char 
 /* #endif  HAVE_QUOTACTL_3 */
 #else /* NO_QUOTACTL_USED */
 
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-
-	if (!path||!bdev||!dp)
-		smb_panic("sys_get_vfs_quota: called with NULL pointer");
-		
-	errno = ENOSYS;
-
-	return ret;
-}
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-
-	if (!path||!bdev||!dp)
-		smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
-	errno = ENOSYS;
-
-	return ret;
-}
-
 #endif /* NO_QUOTACTL_USED */
 
 #ifdef HAVE_MNTENT
@@ -433,262 +160,6 @@ static int sys_path_to_bdev(const char *
 	return ret;
 }
 #endif
-
-
-/*********************************************************
- if we have XFS QUOTAS we should use them
- *********************************************************/
-#ifdef HAVE_XFS_QUOTA
-/****************************************************************************
- Abstract out the XFS Quota Manager quota get call.
-****************************************************************************/
-static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	uint32 qflags = 0;
-	SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
-	struct fs_disk_quota D;
-	struct fs_quota_stat F;
-	ZERO_STRUCT(D);
-	ZERO_STRUCT(F);
-
-	if (!bdev||!dp)
-		smb_panic("sys_get_xfs_quota: called with NULL pointer");
-		
-	ZERO_STRUCT(*dp);
-	dp->qtype = qtype;
-		
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D)))
-				return ret;
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_QUOTA_TYPE:
-			if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D)))
-				return ret;
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		case SMB_USER_FS_QUOTA_TYPE:	
-			quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-
-			if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-			else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
-				qflags |= QUOTAS_ENABLED;
-			}
-
-			ret = 0;
-
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_FS_QUOTA_TYPE:	
-			quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-
-			if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
-				qflags |= QUOTAS_DENY_DISK;
-			}
-			else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
-				qflags |= QUOTAS_ENABLED;
-			}
-
-			ret = 0;
-
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	dp->bsize = bsize;
-	dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
-	dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
-	dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
-	dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
-	dp->curinodes = (SMB_BIG_UINT)D.d_icount;
-	dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
-	dp->qflags = qflags;
-
-	return ret;
-}
-
-/****************************************************************************
- Abstract out the XFS Quota Manager quota set call.
-****************************************************************************/
-static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-	int ret = -1;
-	uint32 qflags = 0;
-	SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
-	struct fs_disk_quota D;
-	struct fs_quota_stat F;
-	int q_on = 0;
-	int q_off = 0;
-	ZERO_STRUCT(D);
-	ZERO_STRUCT(F);
-
-	if (!bdev||!dp)
-		smb_panic("sys_set_xfs_quota: called with NULL pointer");
-	
-	if (bsize == dp->bsize) {
-		D.d_blk_softlimit = dp->softlimit;
-		D.d_blk_hardlimit = dp->hardlimit;
-		D.d_ino_hardlimit = dp->ihardlimit;
-		D.d_ino_softlimit = dp->isoftlimit;
-	} else {
-		D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
-		D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
-		D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
-		D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;		
-	}
-
-	qflags = dp->qflags;
-
-	switch (qtype) {
-		case SMB_USER_QUOTA_TYPE:
-			D.d_fieldmask |= FS_DQ_LIMIT_MASK;
-			ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_QUOTA_TYPE:
-			D.d_fieldmask |= FS_DQ_LIMIT_MASK;
-			ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		case SMB_USER_FS_QUOTA_TYPE:
-			quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-			
-			if (qflags & QUOTAS_DENY_DISK) {
-				if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
-					q_on |= XFS_QUOTA_UDQ_ENFD;
-				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-					q_on |= XFS_QUOTA_UDQ_ACCT;
-				
-				if (q_on != 0) {
-					ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
-				} else {
-					ret = 0;
-				}
-
-			} else if (qflags & QUOTAS_ENABLED) {
-				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-					q_off |= XFS_QUOTA_UDQ_ENFD;
-
-				if (q_off != 0) {
-					ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
-				} else {
-					ret = 0;
-				}
-
-				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-					q_on |= XFS_QUOTA_UDQ_ACCT;
-
-				if (q_on != 0) {
-					ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
-				} else {
-					ret = 0;
-				}
-			} else {
-#if 0
-			/* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
-			 * only swittching off XFS_QUOTA_UDQ_ACCT work
-			 */
-				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-					q_off |= XFS_QUOTA_UDQ_ENFD;
-				if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
-					q_off |= XFS_QUOTA_UDQ_ACCT;
-
-				if (q_off !=0) {
-					ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
-				} else {
-					ret = 0;
-				}
-#else
-				ret = -1;
-#endif
-			}
-
-			break;
-#ifdef HAVE_GROUP_QUOTA
-		case SMB_GROUP_FS_QUOTA_TYPE:
-			quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-			
-			if (qflags & QUOTAS_DENY_DISK) {
-				if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
-					q_on |= XFS_QUOTA_UDQ_ENFD;
-				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-					q_on |= XFS_QUOTA_UDQ_ACCT;
-				
-				if (q_on != 0) {
-					ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
-				} else {
-					ret = 0;
-				}
-
-			} else if (qflags & QUOTAS_ENABLED) {
-				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-					q_off |= XFS_QUOTA_UDQ_ENFD;
-
-				if (q_off != 0) {
-					ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
-				} else {
-					ret = 0;
-				}
-
-				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-					q_on |= XFS_QUOTA_UDQ_ACCT;
-
-				if (q_on != 0) {
-					ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
-				} else {
-					ret = 0;
-				}
-			} else {
-#if 0
-			/* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
-			 * only swittching off XFS_QUOTA_UDQ_ACCT work
-			 */
-				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-					q_off |= XFS_QUOTA_UDQ_ENFD;
-				if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
-					q_off |= XFS_QUOTA_UDQ_ACCT;
-
-				if (q_off !=0) {
-					ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
-				} else {
-					ret = 0;
-				}
-#else
-				ret = -1;
-#endif
-			}
-
-			break;
-#endif /* HAVE_GROUP_QUOTA */
-		default:
-			errno = ENOSYS;
-			return -1;
-	}
-
-	return ret;
-}
-#endif /* HAVE_XFS_QUOTA */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 /*********************************************************************
  Now the list of all filesystem specific quota systems we have found
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/lib/sysquotas_4A.c 3_0-ioctl/source/lib/sysquotas_4A.c
--- 3_0/source/lib/sysquotas_4A.c	Thu Jan  1 01:00:00 1970
+++ 3_0-ioctl/source/lib/sysquotas_4A.c	Mon Jan  5 08:09:10 2004
@@ -0,0 +1,308 @@
+/* 
+   Unix SMB/CIFS implementation.
+   System QUOTA function wrappers for LINUX
+   Copyright (C) Stefan (metze) Metzmacher	2003
+   
+   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"
+
+#ifdef HAVE_QUOTACTL_4A
+/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
+/* this is used by: HPUX,IRIX */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
+#ifdef HAVE_SYS_QUOTA_H
+#include <sys/quota.h>
+#endif
+
+#ifndef Q_SETQLIM
+#define Q_SETQLIM Q_SETQUOTA
+#endif
+
+#ifdef GRPQUOTA
+#define HAVE_GROUP_QUOTA
+#endif
+
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE DEV_BSIZE
+#endif
+
+#ifdef HAVE_DQB_FSOFTLIMIT
+#define dqb_isoftlimit	dqb_fsoftlimit
+#define dqb_ihardlimit	dqb_fhardlimit
+#define dqb_curinodes	dqb_curfiles
+#endif
+
+#ifdef INITQFNAMES
+#define USERQUOTAFILE_EXTENSION ".user"
+#else
+#define USERQUOTAFILE_EXTENSION ""
+#endif
+
+#if !defined(QUOTAFILENAME) && defined(QFILENAME)
+#define QUOTAFILENAME QFILENAME
+#endif
+
+/****************************************************************************
+ Abstract out the quotactl_4A get calls.
+****************************************************************************/
+int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	struct dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	ZERO_STRUCT(D);
+	ZERO_STRUCT(*dp);
+	dp->qtype = qtype;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			if ((D.dqb_curblocks==0)&&
+				(D.dqb_bsoftlimit==0)&&
+				(D.dqb_bhardlimit==0)) {
+				/* the upper layer functions don't want empty quota records...*/
+				return -1;
+			}
+
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			if ((D.dqb_curblocks==0)&&
+				(D.dqb_bsoftlimit==0)&&
+				(D.dqb_bhardlimit==0)) {
+				/* the upper layer functions don't want empty quota records...*/
+				return -1;
+			}
+
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		case SMB_USER_FS_QUOTA_TYPE:
+			id.uid = getuid();
+
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			ret = 0;
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			id.gid = getgid();
+
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			ret = 0;
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	dp->bsize = bsize;
+	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+	dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+
+	dp->qflags = qflags;
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the quotactl_4A set calls.
+****************************************************************************/
+int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	uint32 oldqflags = 0;
+	struct dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	ZERO_STRUCT(D);
+
+	if (bsize == dp->bsize) {
+		D.dqb_bsoftlimit = dp->softlimit;
+		D.dqb_bhardlimit = dp->hardlimit;
+		D.dqb_ihardlimit = dp->ihardlimit;
+		D.dqb_isoftlimit = dp->isoftlimit;
+	} else {
+		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+	}
+
+	qflags = dp->qflags;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (void *)&D);
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (void *)&D);
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		case SMB_USER_FS_QUOTA_TYPE:
+			/* this stuff didn't work as it should:
+			 * switching on/off quota via quotactl()
+			 * didn't work!
+			 * So we just return 0
+			 * --metze
+			 * 
+			 * On HPUX we didn't have the mount path,
+			 * we need to fix sys_path_to_bdev()
+			 *
+			 */
+#if 0
+			id.uid = getuid();
+
+			ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D);
+
+			if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
+				if (ret == 0) {
+					char *quota_file = NULL;
+					
+					asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
+					if (quota_file == NULL) {
+						DEBUG(0,("asprintf() failed!\n"));
+						errno = ENOMEM;
+						return -1;
+					}
+					
+					ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(void *)quota_file);
+				} else {
+					ret = 0;	
+				}
+			} else {
+				if (ret != 0) {
+					/* turn off */
+					ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (void *)0);	
+				} else {
+					ret = 0;
+				}		
+			}
+
+			DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
+				ret,errno,strerror(errno),id.uid,bdev));
+#else
+			id.uid = getuid();
+
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			if (oldqflags == qflags) {
+				ret = 0;
+			} else {
+				ret = -1;
+			}
+#endif
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			/* this stuff didn't work as it should:
+			 * switching on/off quota via quotactl()
+			 * didn't work!
+			 * So we just return 0
+			 * --metze
+			 * 
+			 * On HPUX we didn't have the mount path,
+			 * we need to fix sys_path_to_bdev()
+			 *
+			 */
+#if 0
+			id.gid = getgid();
+
+			ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (void *)&D);
+
+			if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
+				if (ret == 0) {
+					char *quota_file = NULL;
+					
+					asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
+					if (quota_file == NULL) {
+						DEBUG(0,("asprintf() failed!\n"));
+						errno = ENOMEM;
+						return -1;
+					}
+					
+					ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(void *)quota_file);
+				} else {
+					ret = 0;	
+				}
+			} else {
+				if (ret != 0) {
+					/* turn off */
+					ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (void *)0);	
+				} else {
+					ret = 0;
+				}		
+			}
+
+			DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
+				ret,errno,strerror(errno),id.gid,bdev));
+#else
+			id.gid = getgid();
+
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			if (oldqflags == qflags) {
+				ret = 0;
+			} else {
+				ret = -1;
+			}
+#endif
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	return ret;
+}
+
+#endif /* HAVE_QUOTACTL_4A */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/lib/sysquotas_linux.c 3_0-ioctl/source/lib/sysquotas_linux.c
--- 3_0/source/lib/sysquotas_linux.c	Thu Jan  1 01:00:00 1970
+++ 3_0-ioctl/source/lib/sysquotas_linux.c	Mon Jan  5 08:11:44 2004
@@ -0,0 +1,486 @@
+/* 
+   Unix SMB/CIFS implementation.
+   System QUOTA function wrappers for LINUX
+   Copyright (C) Stefan (metze) Metzmacher	2003
+   
+   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"
+
+#ifdef HAVE_QUOTACTL_LINUX 
+
+#include "samba_linux_quota.h"
+
+/****************************************************************************
+ Abstract out the v1 Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	struct v1_kern_dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	ZERO_STRUCT(D);
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			break;
+		case SMB_GROUP_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	dp->bsize = bsize;
+	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+	dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+
+	dp->qflags = qflags;
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the v1 Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	uint32 oldqflags = 0;
+	struct v1_kern_dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	ZERO_STRUCT(D);
+
+	if (bsize == dp->bsize) {
+		D.dqb_bsoftlimit = dp->softlimit;
+		D.dqb_bhardlimit = dp->hardlimit;
+		D.dqb_ihardlimit = dp->ihardlimit;
+		D.dqb_isoftlimit = dp->isoftlimit;
+	} else {
+		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+	}
+
+	qflags = dp->qflags;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+			break;
+		case SMB_GROUP_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the v2 Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	struct v2_kern_dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	ZERO_STRUCT(D);
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			break;
+		case SMB_GROUP_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	dp->bsize = bsize;
+	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+	dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
+
+
+	dp->qflags = qflags;
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the v2 Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	uint32 oldqflags = 0;
+	struct v2_kern_dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	ZERO_STRUCT(D);
+
+	if (bsize == dp->bsize) {
+		D.dqb_bsoftlimit = dp->softlimit;
+		D.dqb_bhardlimit = dp->hardlimit;
+		D.dqb_ihardlimit = dp->ihardlimit;
+		D.dqb_isoftlimit = dp->isoftlimit;
+	} else {
+		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+	}
+
+	qflags = dp->qflags;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+			break;
+		case SMB_GROUP_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the generic Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	struct if_dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	ZERO_STRUCT(D);
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			break;
+		case SMB_GROUP_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+				return ret;
+			}
+
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	dp->bsize = bsize;
+	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+	dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
+
+
+	dp->qflags = qflags;
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the gen Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	uint32 oldqflags = 0;
+	struct if_dqblk D;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+	if (!path||!bdev||!dp)
+		smb_panic("sys_set_linux_gen_quota: called with NULL pointer");
+
+	ZERO_STRUCT(D);
+
+	if (bsize == dp->bsize) {
+		D.dqb_bsoftlimit = dp->softlimit;
+		D.dqb_bhardlimit = dp->hardlimit;
+		D.dqb_ihardlimit = dp->ihardlimit;
+		D.dqb_isoftlimit = dp->isoftlimit;
+	} else {
+		D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+		D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+		D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+		D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+	}
+
+	qflags = dp->qflags;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+			break;
+		case SMB_GROUP_QUOTA_TYPE:
+			ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+				oldqflags |= QUOTAS_DENY_DISK;
+			}
+
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the Linux quota get calls.
+****************************************************************************/
+int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+
+	if (!path||!bdev||!dp)
+		smb_panic("sys_get_linux_quota: called with NULL pointer");
+
+	ZERO_STRUCT(*dp);
+	dp->qtype = qtype;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+		case SMB_GROUP_QUOTA_TYPE:
+			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+					if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+						return ret;
+					}
+				}
+			}
+
+			if ((dp->curblocks==0)&&
+				(dp->softlimit==0)&&
+				(dp->hardlimit==0)) {
+				/* the upper layer functions don't want empty quota records...*/
+				return -1;
+			}
+
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			id.uid = getuid();
+
+			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+				}
+			}
+
+			ret = 0;
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			id.gid = getgid();
+
+			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+				}
+			}
+
+			ret = 0;
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the Linux quota set calls.
+****************************************************************************/
+int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 oldqflags = 0;
+
+	if (!path||!bdev||!dp)
+		smb_panic("sys_set_linux_v1_quota: called with NULL pointer");
+
+	oldqflags = dp->qflags;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+		case SMB_GROUP_QUOTA_TYPE:
+			if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
+				if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
+					if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
+						return ret;
+					}
+				}
+			}
+			break;
+		case SMB_USER_FS_QUOTA_TYPE:
+			id.uid = getuid();
+
+			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
+				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
+					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+				}
+			}
+
+			if (oldqflags == dp->qflags) {
+				ret = 0;
+			} else {
+				ret = -1;
+			}
+			break;
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			id.gid = getgid();
+
+			if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
+				if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
+					ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+				}
+			}
+
+			if (oldqflags == dp->qflags) {
+				ret = 0;
+			} else {
+				ret = -1;
+			}
+
+			break;
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	return ret;
+}
+
+#endif /* HAVE_QUOTACTL_LINUX */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/lib/sysquotas_xfs.c 3_0-ioctl/source/lib/sysquotas_xfs.c
--- 3_0/source/lib/sysquotas_xfs.c	Thu Jan  1 01:00:00 1970
+++ 3_0-ioctl/source/lib/sysquotas_xfs.c	Fri Dec 12 14:12:30 2003
@@ -0,0 +1,300 @@
+/* 
+   Unix SMB/CIFS implementation.
+   System QUOTA function wrappers for XFS
+   Copyright (C) Stefan (metze) Metzmacher	2003
+   
+   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"
+
+#ifdef HAVE_XFS_QUOTA
+#include "samba_xfs_quota.h"
+#define HAVE_LINUX_XFS_QUOTA
+#endif
+
+#ifdef HAVE_LINUX_XFS_QUOTA
+
+/* Linux has BBSIZE in <linux/xfs_fs.h>
+ * or <xfs/xfs_fs.h>
+ * IRIX has BBSIZE in <sys/param.h>
+ */
+#ifdef HAVE_XFS_FS_HEADER
+#include HAVE_XFS_FS_HEADER
+#endif
+
+/* on IRIX */
+#ifndef Q_XQUOTAON
+#define Q_XQUOTAON Q_QUOTAON
+#endif /* Q_XQUOTAON */
+#ifndef Q_XQUOTAOFF
+#define Q_XQUOTAOFF Q_QUOTAOFF
+#endif /* Q_XQUOTAOFF */
+#ifndef Q_XGETQSTAT
+#define Q_XGETQSTAT Q_GETQSTAT
+#endif /* Q_XGETQSTAT */
+
+
+#ifndef BBSHIFT
+#define	BBSHIFT		9
+#endif /* BBSHIFT */
+#ifndef BBSIZE
+#define	BBSIZE		(1<<BBSHIFT)
+#endif /* BBSIZE */
+
+#ifdef IRIX6
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE BBSIZE
+#endif
+#endif
+
+/****************************************************************************
+ Abstract out the XFS Quota Manager quota get call.
+****************************************************************************/
+int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
+	struct fs_disk_quota D;
+	struct fs_quota_stat F;
+	ZERO_STRUCT(D);
+	ZERO_STRUCT(F);
+
+	if (!bdev||!dp)
+		smb_panic("sys_get_xfs_quota: called with NULL pointer");
+		
+	ZERO_STRUCT(*dp);
+	dp->qtype = qtype;
+		
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			if ((ret=quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), bdev, id.uid, (caddr_t)&D)))
+				return ret;
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_QUOTA_TYPE:
+			if ((ret=quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), bdev, id.gid, (caddr_t)&D)))
+				return ret;
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		case SMB_USER_FS_QUOTA_TYPE:	
+			quotactl(QCMD(Q_XGETQSTAT,XFS_USER_QUOTA), bdev, -1, (caddr_t)&F);
+
+			if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+			else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
+				qflags |= QUOTAS_ENABLED;
+			}
+
+			ret = 0;
+
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_FS_QUOTA_TYPE:	
+			quotactl(QCMD(Q_XGETQSTAT,XFS_GROUP_QUOTA), bdev, -1, (caddr_t)&F);
+
+			if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
+				qflags |= QUOTAS_DENY_DISK;
+			}
+			else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
+				qflags |= QUOTAS_ENABLED;
+			}
+
+			ret = 0;
+
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	dp->bsize = bsize;
+	dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
+	dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
+	dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
+	dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
+	dp->curinodes = (SMB_BIG_UINT)D.d_icount;
+	dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
+	dp->qflags = qflags;
+
+	return ret;
+}
+
+/****************************************************************************
+ Abstract out the XFS Quota Manager quota set call.
+****************************************************************************/
+int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+	int ret = -1;
+	uint32 qflags = 0;
+	SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
+	struct fs_disk_quota D;
+	struct fs_quota_stat F;
+	int q_on = 0;
+	int q_off = 0;
+	ZERO_STRUCT(D);
+	ZERO_STRUCT(F);
+
+	if (!bdev||!dp)
+		smb_panic("sys_set_xfs_quota: called with NULL pointer");
+	
+	if (bsize == dp->bsize) {
+		D.d_blk_softlimit = dp->softlimit;
+		D.d_blk_hardlimit = dp->hardlimit;
+		D.d_ino_hardlimit = dp->ihardlimit;
+		D.d_ino_softlimit = dp->isoftlimit;
+	} else {
+		D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
+		D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
+		D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+		D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;		
+	}
+
+	qflags = dp->qflags;
+
+	switch (qtype) {
+		case SMB_USER_QUOTA_TYPE:
+			D.d_fieldmask |= FS_DQ_LIMIT_MASK;
+			ret = quotactl(QCMD(Q_XSETQLIM,XFS_USER_QUOTA), bdev, id.uid, (caddr_t)&D);
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_QUOTA_TYPE:
+			D.d_fieldmask |= FS_DQ_LIMIT_MASK;
+			ret = quotactl(QCMD(Q_XSETQLIM,XFS_GROUP_QUOTA), bdev, id.gid, (caddr_t)&D);
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		case SMB_USER_FS_QUOTA_TYPE:
+			quotactl(QCMD(Q_XGETQSTAT,XFS_USER_QUOTA), bdev, -1, (caddr_t)&F);
+			
+			if (qflags & QUOTAS_DENY_DISK) {
+				if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
+					q_on |= XFS_QUOTA_UDQ_ENFD;
+				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+					q_on |= XFS_QUOTA_UDQ_ACCT;
+				
+				if (q_on != 0) {
+					ret = quotactl(QCMD(Q_XQUOTAON,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_on);
+				} else {
+					ret = 0;
+				}
+
+			} else if (qflags & QUOTAS_ENABLED) {
+				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+					q_off |= XFS_QUOTA_UDQ_ENFD;
+
+				if (q_off != 0) {
+					ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_off);
+				} else {
+					ret = 0;
+				}
+
+				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+					q_on |= XFS_QUOTA_UDQ_ACCT;
+
+				if (q_on != 0) {
+					ret = quotactl(QCMD(Q_XQUOTAON,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_on);
+				} else {
+					ret = 0;
+				}
+			} else {
+#if 0
+			/* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
+			 * only swittching off XFS_QUOTA_UDQ_ACCT work
+			 */
+				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+					q_off |= XFS_QUOTA_UDQ_ENFD;
+				if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
+					q_off |= XFS_QUOTA_UDQ_ACCT;
+
+				if (q_off !=0) {
+					ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_off);
+				} else {
+					ret = 0;
+				}
+#else
+				ret = -1;
+#endif
+			}
+
+			break;
+#ifdef HAVE_GROUP_QUOTA
+		case SMB_GROUP_FS_QUOTA_TYPE:
+			quotactl(QCMD(Q_XGETQSTAT,XFS_GROUP_QUOTA), bdev, -1, (caddr_t)&F);
+			
+			if (qflags & QUOTAS_DENY_DISK) {
+				if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
+					q_on |= XFS_QUOTA_UDQ_ENFD;
+				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+					q_on |= XFS_QUOTA_UDQ_ACCT;
+				
+				if (q_on != 0) {
+					ret = quotactl(QCMD(Q_XQUOTAON,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_on);
+				} else {
+					ret = 0;
+				}
+
+			} else if (qflags & QUOTAS_ENABLED) {
+				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+					q_off |= XFS_QUOTA_UDQ_ENFD;
+
+				if (q_off != 0) {
+					ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_off);
+				} else {
+					ret = 0;
+				}
+
+				if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+					q_on |= XFS_QUOTA_UDQ_ACCT;
+
+				if (q_on != 0) {
+					ret = quotactl(QCMD(Q_XQUOTAON,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_on);
+				} else {
+					ret = 0;
+				}
+			} else {
+#if 0
+			/* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
+			 * only swittching off XFS_QUOTA_UDQ_ACCT work
+			 */
+				if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+					q_off |= XFS_QUOTA_UDQ_ENFD;
+				if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
+					q_off |= XFS_QUOTA_UDQ_ACCT;
+
+				if (q_off !=0) {
+					ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_off);
+				} else {
+					ret = 0;
+				}
+#else
+				ret = -1;
+#endif
+			}
+
+			break;
+#endif /* HAVE_GROUP_QUOTA */
+		default:
+			errno = ENOSYS;
+			return -1;
+	}
+
+	return ret;
+}
+
+#endif /* HAVE_LINUX_XFS_QUOTA */
diff -Npur --exclude=CVS --exclude=*.bak --exclude=*.o --exclude=*.po --exclude=*.so --exclude=.#* --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude=*proto*.h --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude=config.* --exclude=bin --exclude=*.configure --exclude=autom4te.cache --exclude=build_options.c* 3_0/source/smbd/quotas.c 3_0-ioctl/source/smbd/quotas.c
--- 3_0/source/smbd/quotas.c	Tue Nov 25 08:32:16 2003
+++ 3_0-ioctl/source/smbd/quotas.c	Mon Jan  5 08:04:32 2004
@@ -50,33 +50,16 @@ BOOL disk_quotas_vxfs(const pstring name
 #ifdef LINUX
 
 #include <sys/types.h>
-#include <asm/types.h>
+#include <mntent.h>
 
 /*
  * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
+ * So we include all the files has *should* be in the system into a large,
+ * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
  */
 
-#include <linux/quota.h>
-#ifdef HAVE_LINUX_XQM_H
-#include <linux/xqm.h>
-#else
-#ifdef HAVE_XFS_XQM_H
-#include <xfs/xqm.h>
-#define HAVE_LINUX_XQM_H
-#endif
-#endif
-
-#include <mntent.h>
-#include <linux/unistd.h>
-
-
-#define LINUX_QUOTAS_2
+#include "samba_linux_quota.h"
+#include "samba_xfs_quota.h"
 
 typedef struct _LINUX_SMB_DISK_QUOTA {
 	SMB_BIG_UINT bsize;
@@ -92,22 +75,20 @@ typedef struct _LINUX_SMB_DISK_QUOTA {
  Abstract out the XFS Quota Manager quota get call.
 ****************************************************************************/
 
-static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
 {
-	int ret = -1;
-#ifdef HAVE_LINUX_XQM_H
 	struct fs_disk_quota D;
+	int ret;
 
 	ZERO_STRUCT(D);
 
-	ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+	ret = quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), path, euser_id, (caddr_t)&D);
 
-	/* As XFS has group quotas, if getting the user quota fails, try getting the group instead. */
-	if (ret) {
-		ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
-		if (ret)
-			return ret;
-	}
+	if (ret)
+		ret = quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), path, egrp_id, (caddr_t)&D);
+
+	if (ret)
+		return ret;
 
 	dp->bsize = (SMB_BIG_UINT)512;
 	dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
@@ -116,7 +97,7 @@ static int get_smb_linux_xfs_quota(char 
 	dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
 	dp->curinodes = (SMB_BIG_UINT)D.d_icount;
 	dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
-#endif
+
 	return ret;
 }
 
@@ -124,48 +105,90 @@ static int get_smb_linux_xfs_quota(char 
  Abstract out the old and new Linux quota get calls.
 ****************************************************************************/
 
-static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
 {
-	int ret = 0;
-#ifdef LINUX_QUOTAS_1
-	struct dqblk D;
+	struct v1_kern_dqblk D;
+	int ret;
+
 	ZERO_STRUCT(D);
-	dp->bsize = (SMB_BIG_UINT)1024;
-#else /* LINUX_QUOTAS_2 */
-	struct mem_dqblk D;
+
+	ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+	if (ret && errno != EDQUOT)
+		ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+	if (ret && errno != EDQUOT)
+		return ret;
+
+	dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+	dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+	return ret;
+}
+
+static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+	struct v2_kern_dqblk D;
+	int ret;
+
 	ZERO_STRUCT(D);
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE 1024
-#endif
+
+	ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+	if (ret && errno != EDQUOT)
+		ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+	if (ret && errno != EDQUOT)
+		return ret;
+
 	dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-#endif
+	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+	dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
+
+	return ret;
+}
+
+/****************************************************************************
+ Brand-new generic quota interface.
+****************************************************************************/
+
+static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+	struct if_dqblk D;
+	int ret;
+
+	ZERO_STRUCT(D);
 
 	ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
 
-	/* Linux can have group quotas, if getting the user quota fails, try getting the group instead. */
-	if (ret) {
-		ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
-		if (ret)
-			return ret;
-	}
+	if (ret && errno != EDQUOT)
+		ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
 
+	if (ret && errno != EDQUOT)
+		return ret;
+
+	dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
 	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
 	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
 	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
 	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
 	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
-
-#ifdef LINUX_QUOTAS_1
-	dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-#else /* LINUX_QUOTAS_2 */
-	dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
-#endif
+	dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
 
 	return ret;
 }
 
 /****************************************************************************
-try to get the disk space from disk quotas (LINUX version)
+ Try to get the disk space from disk quotas (LINUX version).
 ****************************************************************************/
 
 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
@@ -178,9 +201,11 @@ BOOL disk_quotas(const char *path, SMB_B
 	SMB_DEV_T devno;
 	int found;
 	uid_t euser_id;
+	gid_t egrp_id;
 
 	euser_id = geteuid();
-  
+	egrp_id = getegid();
+
 	/* find the block device file */
   
 	if ( sys_stat(path, &S) == -1 )
@@ -208,10 +233,18 @@ BOOL disk_quotas(const char *path, SMB_B
 
 	save_re_uid();
 	set_effective_uid(0);  
-	if (strcmp(mnt->mnt_type, "xfs") == 0)
-		r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D);
-	else
-		r=get_smb_linux_vfs_quota(mnt->mnt_fsname, euser_id, &D);
+
+	if (strcmp(mnt->mnt_type, "xfs")==0) {
+		r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+	} else {
+		r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+		if (r == -1 && errno != EDQUOT) {
+			r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+			if (r == -1 && errno != EDQUOT)
+				r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+		}
+	}
+
 	restore_re_uid();
 
 	/* Use softlimit to determine disk space, except when it has been exceeded */
@@ -920,8 +953,8 @@ BOOL disk_quotas(const char *path, SMB_B
   if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
 #else
   if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) 
-#endif /* ifdef HPUX */
 	return (False);
+#endif /* ifdef HPUX */
 
 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */
 


More information about the samba-technical mailing list