[SCM] Samba Shared Repository - branch master updated - d38bffd4126062b92384f0930196059441a2d765

Tim Prouty tprouty at samba.org
Wed Nov 12 17:50:54 GMT 2008


The branch, master has been updated
       via  d38bffd4126062b92384f0930196059441a2d765 (commit)
      from  7f36d3b55051150b9d4fa75af424898f48c48771 (commit)

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


- Log -----------------------------------------------------------------
commit d38bffd4126062b92384f0930196059441a2d765
Author: Tim Prouty <tprouty at samba.org>
Date:   Wed Nov 5 13:40:03 2008 -0800

    s3: Add support for storing dos attributes as st_flags in the stat struct.
    
    Some filesystems have support for storing dos attributes directly in
    the inode's st_flags and accessing them through the stat struct.  This
    patch:
    
    - Adds a configure check to see if the special flags are available.
    - Implements getting and setting dos attributes in the stat struct and
      inode, respectively.
    
    This will not change the existing functionality of any system that
    doesn't have the special flags available.

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

Summary of changes:
 source3/configure.in   |   19 ++++++
 source3/smbd/dosmode.c |  160 ++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 166 insertions(+), 13 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/configure.in b/source3/configure.in
index 5e3eac5..24341e0 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -1433,6 +1433,25 @@ if test x"$samba_cv_stat_st_birthtime" = x"yes" ; then
     AC_DEFINE(HAVE_STAT_ST_BIRTHTIME, 1, [whether struct stat contains st_birthtime])
 fi
 
+AC_CACHE_CHECK([whether there is DOS flags support in the stat struct], samba_cv_stat_dos_flags,
+    [
+	AC_TRY_COMPILE(
+	    [#include <sys/stat.h>],
+	    [
+		int a = UF_DOS_ARCHIVE;
+		int h = UF_DOS_HIDDEN;
+		int r = UF_DOS_RO;
+		int s = UF_DOS_SYSTEM;
+		int i = UF_DOS_NOINDEX;
+		int f = UF_DOS_FLAGS;
+	    ],
+	    samba_cv_stat_dos_flags=yes, samba_cv_stat_dos_flags=no)
+    ])
+
+if test x"$samba_cv_stat_dos_flags" = x"yes" ; then
+    AC_DEFINE(HAVE_STAT_DOS_FLAGS, 1, [whether there is DOS flags support in the stat struct])
+fi
+
 #####################################
 # needed for SRV lookups
 AC_CHECK_LIB(resolv, dn_expand)
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 784b36d..954cd5a 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -30,6 +30,17 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
 	return 0;
 }
 
+static int set_link_read_only_flag(const SMB_STRUCT_STAT *const sbuf)
+{
+#ifdef S_ISLNK
+#if LINKS_READ_ONLY
+	if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
+		return aRONLY;
+#endif
+#endif
+	return 0;
+}
+
 /****************************************************************************
  Change a dos mode to a unix mode.
     Base permission for files:
@@ -159,13 +170,7 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_
 		result = aDIR | (result & aRONLY);
 
 	result |= set_sparse_flag(sbuf);
- 
-#ifdef S_ISLNK
-#if LINKS_READ_ONLY
-	if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
-		result |= aRONLY;
-#endif
-#endif
+	result |= set_link_read_only_flag(sbuf);
 
 	DEBUG(8,("dos_mode_from_sbuf returning "));
 
@@ -343,6 +348,113 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT
 	return(result);
 }
 
+#ifdef HAVE_STAT_DOS_FLAGS
+/****************************************************************************
+ Convert dos attributes (FILE_ATTRIBUTE_*) to dos stat flags (UF_*)
+****************************************************************************/
+
+static int dos_attributes_to_stat_dos_flags(uint32_t dosmode)
+{
+	uint32_t dos_stat_flags = 0;
+
+	if (dosmode & aARCH)
+		dos_stat_flags |= UF_DOS_ARCHIVE;
+	if (dosmode & aHIDDEN)
+		dos_stat_flags |= UF_DOS_HIDDEN;
+	if (dosmode & aRONLY)
+		dos_stat_flags |= UF_DOS_RO;
+	if (dosmode & aSYSTEM)
+		dos_stat_flags |= UF_DOS_SYSTEM;
+	if (dosmode & FILE_ATTRIBUTE_NONINDEXED)
+		dos_stat_flags |= UF_DOS_NOINDEX;
+
+	return dos_stat_flags;
+}
+
+/****************************************************************************
+ Gets DOS attributes, accessed via st_flags in the stat struct.
+****************************************************************************/
+
+static bool get_stat_dos_flags(connection_struct *conn,
+			       const char *fname,
+			       const SMB_STRUCT_STAT *sbuf,
+			       uint32_t *dosmode)
+{
+	SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
+	SMB_ASSERT(dosmode);
+
+	if (!lp_store_dos_attributes(SNUM(conn))) {
+		return false;
+	}
+
+	DEBUG(5, ("Getting stat dos attributes for %s.\n", fname));
+
+	if (sbuf->st_flags & UF_DOS_ARCHIVE)
+		*dosmode |= aARCH;
+	if (sbuf->st_flags & UF_DOS_HIDDEN)
+		*dosmode |= aHIDDEN;
+	if (sbuf->st_flags & UF_DOS_RO)
+		*dosmode |= aRONLY;
+	if (sbuf->st_flags & UF_DOS_SYSTEM)
+		*dosmode |= aSYSTEM;
+	if (sbuf->st_flags & UF_DOS_NOINDEX)
+		*dosmode |= FILE_ATTRIBUTE_NONINDEXED;
+	if (S_ISDIR(sbuf->st_mode))
+		*dosmode |= aDIR;
+
+	*dosmode |= set_sparse_flag(sbuf);
+	*dosmode |= set_link_read_only_flag(sbuf);
+
+	return true;
+}
+
+/****************************************************************************
+ Sets DOS attributes, stored in st_flags of the inode.
+****************************************************************************/
+
+static bool set_stat_dos_flags(connection_struct *conn,
+				const char *fname,
+				SMB_STRUCT_STAT *sbuf,
+				uint32_t dosmode,
+				bool *attributes_changed)
+{
+	uint32_t new_flags = 0;
+	int error = 0;
+
+	SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
+	SMB_ASSERT(attributes_changed);
+
+	*attributes_changed = false;
+
+	if (!lp_store_dos_attributes(SNUM(conn))) {
+		return false;
+	}
+
+	DEBUG(5, ("Setting stat dos attributes for %s.\n", fname));
+
+	new_flags = (sbuf->st_flags & ~UF_DOS_FLAGS) |
+		     dos_attributes_to_stat_dos_flags(dosmode);
+
+	/* Return early if no flags changed. */
+	if (new_flags == sbuf->st_flags)
+		return true;
+
+	DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags,
+		  sbuf->st_flags));
+
+	/* Set new flags with chflags. */
+	error = SMB_VFS_CHFLAGS(conn, fname, new_flags);
+	if (error) {
+		DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
+			  "file %s! errno=%d\n", new_flags, fname, errno));
+		return false;
+	}
+
+	*attributes_changed = true;
+	return true;
+}
+#endif /* HAVE_STAT_DOS_FLAGS */
+
 /****************************************************************************
  Change a unix mode to a dos mode.
 ****************************************************************************/
@@ -350,7 +462,7 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT
 uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
 {
 	uint32 result = 0;
-	bool offline;
+	bool offline, used_stat_dos_flags = false;
 
 	DEBUG(8,("dos_mode: %s\n", path));
 
@@ -373,11 +485,16 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
 		}
 	}
 	
-	/* Get the DOS attributes from an EA by preference. */
-	if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
-		result |= set_sparse_flag(sbuf);
-	} else {
-		result |= dos_mode_from_sbuf(conn, path, sbuf);
+#ifdef HAVE_STAT_DOS_FLAGS
+	used_stat_dos_flags = get_stat_dos_flags(conn, path, sbuf, &result);
+#endif
+	if (!used_stat_dos_flags) {
+		/* Get the DOS attributes from an EA by preference. */
+		if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
+			result |= set_sparse_flag(sbuf);
+		} else {
+			result |= dos_mode_from_sbuf(conn, path, sbuf);
+		}
 	}
 
 	
@@ -468,6 +585,23 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 		return(0);
 	}
 
+#ifdef HAVE_STAT_DOS_FLAGS
+	{
+		bool attributes_changed;
+
+		if (set_stat_dos_flags(conn, fname, st, dosmode,
+				       &attributes_changed))
+		{
+			if (!newfile && attributes_changed) {
+				notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+				    FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
+			}
+			st->st_mode = unixmode;
+			return 0;
+		}
+	}
+#endif
+
 	/* Store the DOS attributes in an EA by preference. */
 	if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
 		if (!newfile) {


-- 
Samba Shared Repository


More information about the samba-cvs mailing list