[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Dec 17 13:57:01 MST 2010


The branch, master has been updated
       via  16d6da8 Move checks inside file_set_sparse() to allow it to be called from anywhere.
       via  fe50632 file_set_sparse needs to be a handle based call.
       via  192c4a1 s3:smbd: implement FSCTL_SET_SPARSE more correctly
       via  2c10c34 Update our attribute flags.
       via  5c27dd6 s3:smbd: add file_set_sparse() function
       via  9634d03 s3/vfs_gpfs: map SPARSE attribute to/from WINATTRs, too
       via  480042d s3: remove set_sparse_flag
       via  ebe5600 s3: add FILE_ATTRIBUTE_SPARSE to get_stat_dos_flags
      from  c4a8875 heimdal_build: Add version-script for krb5.

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


- Log -----------------------------------------------------------------
commit 16d6da8a9bc87a43e4d31a7c220969bd0eaefa3e
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 16 16:50:31 2010 -0800

    Move checks inside file_set_sparse() to allow it to be called from anywhere.
    
    Autobuild-User: Jeremy Allison <jra at samba.org>
    Autobuild-Date: Fri Dec 17 21:56:38 CET 2010 on sn-devel-104

commit fe50632d54b7946bf7d7ca776d41aaaf657c895a
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Dec 16 16:42:33 2010 -0800

    file_set_sparse needs to be a handle based call.

commit 192c4a145f22d5d08586476793980c21db7793fe
Author: Björn Jacke <bj at sernet.de>
Date:   Thu Nov 18 17:24:00 2010 +0100

    s3:smbd: implement FSCTL_SET_SPARSE more correctly
    
    this is a port of a patch from metze for 3.3:
    
    We don't do the "strict allocation" when the sparse bit isn't
    set, but that shouldn't matter.
    
    We now allow windows applications to set and unset the sparse
    bit.
    
    Note that in order to implement this 100% like described
    in [MS-FSA], we'd have to change our data model and support
    the sparse flag per stream.

commit 2c10c3496876892eb4a89b57c909c3ca397a7440
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Dec 17 10:22:58 2010 -0800

    Update our attribute flags.

commit 5c27dd67c8eb454deffa611971778984381d6db8
Author: Björn Jacke <bj at sernet.de>
Date:   Tue Dec 14 10:03:07 2010 +0100

    s3:smbd: add file_set_sparse() function
    
    this is based on a patch for 3.3 from metze

commit 9634d03339073a094ad5d4a7c33b0c63a131c442
Author: Björn Jacke <bj at sernet.de>
Date:   Thu Nov 18 17:22:31 2010 +0100

    s3/vfs_gpfs: map SPARSE attribute to/from WINATTRs, too

commit 480042ddf9f68bd89368c7373f71044b64b0f494
Author: Björn Jacke <bj at sernet.de>
Date:   Thu Nov 18 17:03:01 2010 +0100

    s3: remove set_sparse_flag
    
    we need to determine sparseness from the sparse flag we store not from the
    allocation size on the POSIX filesystem. This is how Windows works - in the
    first place sparseness is a file flag, not the allocation state of the file
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>

commit ebe56006155b49a4a21a909a7bbdf7b9debc35b0
Author: Björn Jacke <bj at sernet.de>
Date:   Thu Nov 18 16:04:03 2010 +0100

    s3: add FILE_ATTRIBUTE_SPARSE to get_stat_dos_flags

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

Summary of changes:
 source3/include/proto.h    |    3 ++
 source3/include/smb.h      |    7 +++-
 source3/modules/vfs_gpfs.c |   10 ++++-
 source3/smbd/dosmode.c     |   85 ++++++++++++++++++++++++++++++++++++--------
 source3/smbd/nttrans.c     |   30 +++++++++++++---
 5 files changed, 112 insertions(+), 23 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 9b41321..9583388 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -4620,6 +4620,9 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode);
 uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname);
 int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
 		     uint32 dosmode, const char *parent_dir, bool newfile);
+NTSTATUS file_set_sparse(connection_struct *conn,
+			 struct files_struct *fsp,
+			 bool sparse);
 int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
 		struct smb_file_time *ft);
 bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 07a53de..b87caf2 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1207,7 +1207,12 @@ struct bitmap {
 #define FILE_ATTRIBUTE_OFFLINE          0x1000L
 #define FILE_ATTRIBUTE_NONINDEXED	0x2000L
 #define FILE_ATTRIBUTE_ENCRYPTED        0x4000L
-#define SAMBA_ATTRIBUTES_MASK		0x7F
+#define SAMBA_ATTRIBUTES_MASK		(FILE_ATTRIBUTE_READONLY|\
+					FILE_ATTRIBUTE_HIDDEN|\
+					FILE_ATTRIBUTE_SYSTEM|\
+					FILE_ATTRIBUTE_DIRECTORY|\
+					FILE_ATTRIBUTE_ARCHIVE|\
+					FILE_ATTRIBUTE_SPARSE)
 
 /* Flags - combined with attributes. */
 #define FILE_FLAG_WRITE_THROUGH    0x80000000L
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 694bde7..ffe51c3 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -970,7 +970,7 @@ static int gpfs_set_xattr(struct vfs_handle_struct *handle,  const char *path,
 	dosmode = dosattrib.info.info3.attrib;
 
         attrs.winAttrs = 0;
-        /*Just map RD_ONLY, ARCHIVE, SYSTEM and HIDDEN. Ignore the others*/
+        /*Just map RD_ONLY, ARCHIVE, SYSTEM HIDDEN and SPARSE. Ignore the others*/
         if (dosmode & FILE_ATTRIBUTE_ARCHIVE){
                 attrs.winAttrs |= GPFS_WINATTR_ARCHIVE;
         }
@@ -983,6 +983,9 @@ static int gpfs_set_xattr(struct vfs_handle_struct *handle,  const char *path,
         if (dosmode & FILE_ATTRIBUTE_READONLY){
                         attrs.winAttrs |= GPFS_WINATTR_READONLY;
         }
+        if (dosmode & FILE_ATTRIBUTE_SPARSE) {
+		attrs.winAttrs |= GPFS_WINATTR_SPARSE_FILE;
+	}
 
 
         ret = set_gpfs_winattrs(CONST_DISCARD(char *, path),
@@ -1019,7 +1022,7 @@ static ssize_t gpfs_get_xattr(struct vfs_handle_struct *handle,  const char *pat
 
         DEBUG(10, ("gpfs_get_xattr:Got attributes: 0x%x\n",attrs.winAttrs));
 
-        /*Just map RD_ONLY, ARCHIVE, SYSTEM and HIDDEN. Ignore the others*/
+        /*Just map RD_ONLY, ARCHIVE, SYSTEM, HIDDEN and SPARSE. Ignore the others*/
         if (attrs.winAttrs & GPFS_WINATTR_ARCHIVE){
                 dosmode |= FILE_ATTRIBUTE_ARCHIVE;
         }
@@ -1032,6 +1035,9 @@ static ssize_t gpfs_get_xattr(struct vfs_handle_struct *handle,  const char *pat
         if (attrs.winAttrs & GPFS_WINATTR_READONLY){
                 dosmode |= FILE_ATTRIBUTE_READONLY;
         }
+        if (attrs.winAttrs & GPFS_WINATTR_SPARSE_FILE) {
+		dosmode |= FILE_ATTRIBUTE_SPARSE;
+	}
 
         snprintf(attrstr, size, "0x%2.2x", dosmode & SAMBA_ATTRIBUTES_MASK);
         DEBUG(10, ("gpfs_get_xattr: returning %s\n",attrstr));
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 7faeb44..628f887 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -20,6 +20,7 @@
 
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_xattr.h"
+#include "../libcli/security/security.h"
 
 static uint32_t filter_mode_by_protocol(uint32_t mode)
 {
@@ -33,16 +34,6 @@ static uint32_t filter_mode_by_protocol(uint32_t mode)
 	return mode;
 }
 
-static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
-{
-#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
-	if (sbuf->st_ex_size > sbuf->st_ex_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
-		return FILE_ATTRIBUTE_SPARSE;
-	}
-#endif
-	return 0;
-}
-
 static int set_link_read_only_flag(const SMB_STRUCT_STAT *const sbuf)
 {
 #ifdef S_ISLNK
@@ -201,7 +192,6 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn,
 	if (S_ISDIR(smb_fname->st.st_ex_mode))
 		result = aDIR | (result & aRONLY);
 
-	result |= set_sparse_flag(&smb_fname->st);
 	result |= set_link_read_only_flag(&smb_fname->st);
 
 	DEBUG(8,("dos_mode_from_sbuf returning "));
@@ -555,10 +545,11 @@ static bool get_stat_dos_flags(connection_struct *conn,
 		*dosmode |= aSYSTEM;
 	if (smb_fname->st.st_ex_flags & UF_DOS_NOINDEX)
 		*dosmode |= FILE_ATTRIBUTE_NONINDEXED;
+	if (smb_fname->st.st_ex_flags & FILE_ATTRIBUTE_SPARSE)
+		*dosmode |= FILE_ATTRIBUTE_SPARSE;
 	if (S_ISDIR(smb_fname->st.st_ex_mode))
 		*dosmode |= aDIR;
 
-	*dosmode |= set_sparse_flag(&smb_fname->st);
 	*dosmode |= set_link_read_only_flag(&smb_fname->st);
 
 	return true;
@@ -651,9 +642,7 @@ uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
 #endif
 	if (!used_stat_dos_flags) {
 		/* Get the DOS attributes from an EA by preference. */
-		if (get_ea_dos_attribute(conn, smb_fname, &result)) {
-			result |= set_sparse_flag(&smb_fname->st);
-		} else {
+		if (!get_ea_dos_attribute(conn, smb_fname, &result)) {
 			result |= dos_mode_from_sbuf(conn, smb_fname);
 		}
 	}
@@ -858,6 +847,72 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
 	return( ret );
 }
 
+
+NTSTATUS file_set_sparse(connection_struct *conn,
+			 files_struct *fsp,
+			 bool sparse)
+{
+	uint32_t old_dosmode;
+	uint32_t new_dosmode;
+	NTSTATUS status;
+
+	if (!CAN_WRITE(conn)) {
+		DEBUG(9,("file_set_sparse: fname[%s] set[%u] "
+			"on readonly share[%s]\n",
+			smb_fname_str_dbg(fsp->fsp_name),
+			sparse,
+			lp_servicename(SNUM(conn))));
+		return NT_STATUS_MEDIA_WRITE_PROTECTED;
+	}
+
+	if (!(fsp->access_mask & FILE_WRITE_DATA) &&
+			!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
+		DEBUG(9,("file_set_sparse: fname[%s] set[%u] "
+			"access_mask[0x%08X] - access denied\n",
+			smb_fname_str_dbg(fsp->fsp_name),
+			sparse,
+			fsp->access_mask));
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	DEBUG(10,("file_set_sparse: setting sparse bit %u on file %s\n",
+		  sparse, smb_fname_str_dbg(fsp->fsp_name)));
+
+	if (!lp_store_dos_attributes(SNUM(conn))) {
+		return NT_STATUS_INVALID_DEVICE_REQUEST;
+	}
+
+	status = vfs_stat_fsp(fsp);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	old_dosmode = dos_mode(conn, fsp->fsp_name);
+
+	if (sparse && !(old_dosmode & FILE_ATTRIBUTE_SPARSE)) {
+		new_dosmode = old_dosmode | FILE_ATTRIBUTE_SPARSE;
+	} else if (!sparse && (old_dosmode & FILE_ATTRIBUTE_SPARSE)) {
+		new_dosmode = old_dosmode & ~FILE_ATTRIBUTE_SPARSE;
+	} else {
+		return NT_STATUS_OK;
+	}
+
+	/* Store the DOS attributes in an EA. */
+	if (!set_ea_dos_attribute(conn, fsp->fsp_name,
+				  new_dosmode)) {
+		if (errno == 0) {
+			errno = EIO;
+		}
+		return map_nt_error_from_unix(errno);
+	}
+
+	notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+		     FILE_NOTIFY_CHANGE_ATTRIBUTES,
+		     fsp->fsp_name->base_name);
+
+	return NT_STATUS_OK;
+}
+
 /*******************************************************************
  Wrapper around the VFS ntimes that possibly allows DOS semantics rather
  than POSIX.
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index ad58533..cccb47a 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -2107,14 +2107,34 @@ static void call_nt_transact_ioctl(connection_struct *conn,
 
 	switch (function) {
 	case FSCTL_SET_SPARSE:
-		/* pretend this succeeded - tho strictly we should
-		   mark the file sparse (if the local fs supports it)
-		   so we can know if we need to pre-allocate or not */
+	{
+		bool set_sparse = true;
+		NTSTATUS status;
+
+		if (data_count >= 1 && pdata[0] == 0) {
+			set_sparse = false;
+		}
+
+		DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X]set[%u]\n",
+			 fidnum, set_sparse));
+
+		if (!check_fsp_open(conn, req, fsp)) {
+			return;
+		}
+
+		status = file_set_sparse(conn, fsp, set_sparse);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(9,("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
+				 smb_fname_str_dbg(fsp->fsp_name), set_sparse, nt_errstr(status)));
+			reply_nterror(req, status);
+			return;
+		}
 
-		DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
+		DEBUG(10,("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
+			 smb_fname_str_dbg(fsp->fsp_name), set_sparse, nt_errstr(status)));
 		send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
 		return;
-
+	}
 	case FSCTL_CREATE_OR_GET_OBJECT_ID:
 	{
 		unsigned char objid[16];


-- 
Samba Shared Repository


More information about the samba-cvs mailing list