--- /home/stevef/samba-3-trunk/source/include/vfs.h	2005-07-12 17:21:33.000000000 -0500
+++ source/include/vfs.h	2005-08-01 12:02:17.000000000 -0500
@@ -3,7 +3,7 @@
    VFS structures and parameters
    Copyright (C) Jeremy Allison                         1999-2005
    Copyright (C) Tim Potter				1999
-   Copyright (C) Alexander Bokovoy			2002
+   Copyright (C) Alexander Bokovoy			2002-2005
    Copyright (C) Stefan (metze) Metzmacher		2003
    
    This program is free software; you can redistribute it and/or modify
@@ -81,6 +81,7 @@
 struct connection_struct;
 struct files_struct;
 struct security_descriptor_info;
+struct vfs_statvfs_struct;
 
 /*
     Available VFS operations. These values must be in sync with vfs_ops struct
@@ -100,7 +101,7 @@
 	SMB_VFS_OP_GET_QUOTA,
 	SMB_VFS_OP_SET_QUOTA,
 	SMB_VFS_OP_GET_SHADOW_COPY_DATA,
-
+	SMB_VFS_OP_STATVFS,
 
 	/* Directory operations */
 
@@ -221,6 +222,7 @@
 		int (*get_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
 		int (*set_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt);
 		int (*get_shadow_copy_data)(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels);
+		int (*statvfs)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct vfs_statvfs_struct *statbuf);
 		
 		/* Directory operations */
 		
@@ -333,6 +335,7 @@
 		struct vfs_handle_struct *get_quota;
 		struct vfs_handle_struct *set_quota;
 		struct vfs_handle_struct *get_shadow_copy_data;
+		struct vfs_handle_struct *statvfs;
 
 		/* Directory operations */
 
@@ -494,6 +497,29 @@
 } vfs_handle_struct;
 
 
+typedef struct _vfs_statvfs_struct {
+	/* For undefined recommended transfer size return -1 in that field */
+	uint32 OptimalTransferSize;  /* bsize on some os, iosize on other os */
+	uint32 BlockSize; 
+    /* The next three fields are in terms of the block size.
+	(above). If block size is unknown, 4096 would be a
+	reasonable block size for a server to report. 
+	Note that returning the blocks/blocksavail removes need
+	to make a second call (to QFSInfo level 0x103 to get this info.
+	UserBlockAvail is typically less than or equal to BlocksAvail,
+	if no distinction is made return the same value in each */
+	SMB_BIG_UINT TotalBlocks;
+	SMB_BIG_UINT BlocksAvail;       /* bfree */
+	SMB_BIG_UINT UserBlocksAvail;   /* bavail */
+    /* For undefined Node fields or FSID return -1 */
+	SMB_BIG_UINT TotalFileNodes;
+	SMB_BIG_UINT FreeFileNodes;
+	SMB_BIG_UINT FsIdentifier;   /* fsid */
+	/* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
+	/* NB flags can come from FILE_SYSTEM_DEVICE_INFO call   */
+} vfs_statvfs_struct;
+
+
 #define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \
 	if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \
 		DEBUG(0,("%s() failed to get vfs_handle->data!\n",FUNCTION_MACRO)); \
--- /home/stevef/samba-3-trunk/source/include/vfs_macros.h	2005-07-12 17:21:33.000000000 -0500
+++ source/include/vfs_macros.h	2005-08-01 12:06:32.000000000 -0500
@@ -34,6 +34,7 @@
 #define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (conn), (qtype), (id), (qt)))
 #define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (conn), (qtype), (id), (qt)))
 #define SMB_VFS_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs.ops.get_shadow_copy_data((fsp)->conn->vfs.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
+#define SMB_VFS_STATVFS(conn, path, statbuf) ((conn)->vfs.ops.statvfs((conn)->vfs.handles.statvfs, (conn), (path), (statbuf)))
 
 /* Directory operations */
 #define SMB_VFS_OPENDIR(conn, fname, mask, attr) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (conn), (fname), (mask), (attr)))
@@ -144,6 +145,7 @@
 #define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (conn), (qtype), (id), (qt)))
 #define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (conn), (qtype), (id), (qt)))
 #define SMB_VFS_OPAQUE_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs_opaque.ops.get_shadow_copy_data((fsp)->conn->vfs_opaque.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
+#define SMB_VFS_OPAQUE_STATVFS(conn, path, statbuf) ((conn)->vfs_opaque.ops.statvfs((conn)->vfs_opaque.handles.statvfs, (conn), (path), (statbuf)))
 
 /* Directory operations */
 #define SMB_VFS_OPAQUE_OPENDIR(conn, fname, mask, attr) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (conn), (fname), (mask), (attr)))
@@ -254,6 +256,7 @@
 #define SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (conn), (qtype), (id), (qt)))
 #define SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (conn), (qtype), (id), (qt)))
 #define SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data ,labels) ((handle)->vfs_next.ops.get_shadow_copy_data((handle)->vfs_next.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels)))
+#define SMB_VFS_NEXT_STATVFS(conn, path, statbuf) ((conn)->vfs_next.ops.statvfs((conn)->vfs_next.handles.statvfs, (conn), (path), (statbuf)))
 
 /* Directory operations */
 #define SMB_VFS_NEXT_OPENDIR(handle, conn, fname, mask, attr) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (conn), (fname), (mask), (attr)))
Index: source/Makefile.in
===================================================================
--- source/Makefile.in  (revision 8175)
+++ source/Makefile.in  (working copy)
@@ -387,7 +387,7 @@
               lib/sysquotas_xfs.o lib/sysquotas_4A.o \
               smbd/change_trust_pw.o smbd/fake_file.o \
               smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \
-              $(AFS_SETTOKEN_OBJ) smbd/aio.o \
+              $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \
               $(MANGLE_OBJ) @VFS_STATIC@

 SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \

--- /home/stevef/samba-3-trunk/source/smbd/vfs.c	2005-07-12 17:21:30.000000000 -0500
+++ source/smbd/vfs.c	2005-07-18 11:39:57.000000000 -0500
@@ -57,6 +57,7 @@
 		vfswrap_get_quota,
 		vfswrap_set_quota,
 		vfswrap_get_shadow_copy_data,
+		vfswrap_statvfs,
 	
 		/* Directory operations */
 	
--- /home/stevef/samba-3-trunk/source/smbd/vfs-wrap.c	2005-07-12 17:21:30.000000000 -0500
+++ source/smbd/vfs-wrap.c	2005-07-18 11:39:57.000000000 -0500
@@ -86,6 +86,11 @@
 	return -1;  /* Not implemented. */
 }
     
+int vfswrap_statvfs(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, vfs_statvfs_struct *statbuf)
+{
+	return sys_statvfs(path, statbuf);
+}
+
 /* Directory operations */
 
 DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname, const char *mask, uint32 attr)
--- /home/stevef/samba-3-trunk/source/smbd/statvfs.c	1969-12-31 18:00:00.000000000 -0600
+++ smbd/statvfs.c	2005-08-01 15:47:16.000000000 -0500
@@ -0,0 +1,65 @@
+/* 
+   Unix SMB/CIFS implementation.
+   VFS API's statvfs abstraction
+   Copyright (C) Alexander Bokovoy			2005
+   Copyright (C) Steve French				2005
+   
+   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"
+
+#if defined(LINUX)
+static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf)
+{
+	struct statvfs statvfs_buf;
+	int result;
+
+	result = statvfs(path, &statvfs_buf);
+
+	if (!result) {
+		statbuf->OptimalTransferSize = statvfs_buf.f_frsize;
+		statbuf->BlockSize = statvfs_buf.f_bsize;
+		statbuf->TotalBlocks = statvfs_buf.f_blocks;
+		statbuf->BlocksAvail = statvfs_buf.f_bfree;
+		statbuf->UserBlocksAvail = statvfs_buf.f_bavail;
+		statbuf->TotalFileNodes = statvfs_buf.f_files;
+		statbuf->FreeFileNodes = statvfs_buf.f_ffree;
+		statbuf->FsIdentifier = statvfs_buf.f_fsid;
+	}
+	return result;
+}
+#endif
+
+/* 
+ sys_statvfs() is an abstraction layer over system-dependent statvfs()/statfs()
+ for particular POSIX systems. Due to controversy of what is considered more important
+ between LSB and FreeBSD/POSIX.1 (IEEE Std 1003.1-2001) we need to abstract the interface
+ so that particular OS would use its preffered interface.
+*/
+int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf)
+{
+#if defined(LINUX)
+	return linux_statvfs(path, statbuf);
+#else
+	/* BB change this to return invalid level */
+#ifdef EOPNOTSUPP
+	return EOPNOTSUPP;
+#else
+	return -1;
+#endif /* EOPNOTSUPP */
+#endif /* LINUX */
+
+}
--- /home/stevef/samba-3-trunk/source/smbd/trans2.c	2005-07-12 17:21:30.000000000 -0500
+++ smbd/trans2.c	2005-08-01 15:56:30.000000000 -0500
@@ -4,6 +4,7 @@
    Copyright (C) Jeremy Allison			1994-2003
    Copyright (C) Stefan (metze) Metzmacher	2003
    Copyright (C) Volker Lendecke		2005
+   Copyright (C) Steve French			2005
 
    Extensively modified by Andrew Tridgell, 1995
 
@@ -2404,6 +2405,38 @@
 					CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
 			break;
 
+		case SMB_QUERY_POSIX_FS_INFO:
+		{
+			int rc;
+			vfs_statvfs_struct svfs;
+
+			if (!lp_unix_extensions())
+				return ERROR_DOS(ERRDOS,ERRunknownlevel);
+			
+			rc = SMB_VFS_STATVFS(conn, ".", &svfs);
+
+			if (!rc) {
+				data_len = 56;
+				SIVAL(pdata,0,svfs.OptimalTransferSize);
+				SIVAL(pdata,4,svfs.BlockSize);
+				SBIG_UINT(pdata,8,svfs.TotalBlocks);
+				SBIG_UINT(pdata,16,svfs.BlocksAvail);
+				SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
+				SBIG_UINT(pdata,32,svfs.TotalFileNodes);
+				SBIG_UINT(pdata,40,svfs.FreeFileNodes);
+				SBIG_UINT(pdata,48,svfs.FsIdentifier);
+				DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
+#ifdef EOPNOTSUPP
+			} else if (rc == EOPNOTSUPP) {
+				return ERROR_DOS(ERRDOS, ERRunknownlevel);
+#endif /* EOPNOTSUPP */
+			} else {
+				DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
+				return ERROR_DOS(ERRSRV,ERRerror);
+			}
+			break;
+		}
+
 		case SMB_MAC_QUERY_FS_INFO:
 			/*
 			 * Thursby MAC extension... ONLY on NTFS filesystems
