[SCM] Samba Shared Repository - branch v3-6-test updated

Jeremy Allison jra at samba.org
Fri Dec 17 13:26:07 MST 2010


The branch, v3-6-test has been updated
       via  17baec6 Move checks inside file_set_sparse() to allow it to be called from anywhere.
       via  485b8b4 file_set_sparse needs to be a handle based call.
       via  659e627 s3:smbd: implement FSCTL_SET_SPARSE more correctly
       via  f00383b Update our attribute flags.
       via  27f543a s3:smbd: add file_set_sparse() function
       via  43df00a s3/vfs_gpfs: map SPARSE attribute to/from WINATTRs, too
       via  669ee9b s3: remove set_sparse_flag
       via  13988e4 s3: add FILE_ATTRIBUTE_SPARSE to get_stat_dos_flags
      from  2e867d9 WHATSNEW: Add information on changed security defaults.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 17baec616fb66c9927902b56513e8b8389792120
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.

commit 485b8b45df0768d846dcd74dddb37136a9b26535
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 659e627424a011bb3cad33e50976036fd55c7010
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 f00383bc3bfc190ed690b0f564a9465d8a1947ea
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Dec 17 10:22:58 2010 -0800

    Update our attribute flags.

commit 27f543a02e6973a3a52200f7d749ca4b7aa6a87e
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 43df00a112b52e5a1e04e2b286b358b6bc319154
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 669ee9b2dd6591ab9bfc137060bdfb9a59dd9742
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 13988e44c3402d03808e096e59c4878cefd56f84
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 0f02dfb..e26f43e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -4622,6 +4622,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