add-server-streams-support   [plain text]


Index: samba/source/smbd/trans2.c
===================================================================
--- samba/source/smbd/trans2.c.orig
+++ samba/source/smbd/trans2.c
@@ -7,6 +7,8 @@
    Copyright (C) Steve French			2005
    Copyright (C) James Peach			2007
 
+   Copyright (C) 2006-2007 Apple Inc. All right reserved.
+
    Extensively modified by Andrew Tridgell, 1995
 
    This program is free software; you can redistribute it and/or modify
@@ -2235,7 +2237,7 @@ static int call_trans2qfsinfo(connection
 	const char *vname = volume_label(SNUM(conn));
 	int snum = SNUM(conn);
 	char *fstype = lp_fstype(SNUM(conn));
-	int quota_flag = 0;
+	int fs_attribute_flags = 0;
 
 	if (total_params < 2) {
 		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@@ -2319,14 +2321,23 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAva
 		case SMB_QUERY_FS_ATTRIBUTE_INFO:
 		case SMB_FS_ATTRIBUTE_INFORMATION:
 
+			fs_attribute_flags =
+				FILE_CASE_SENSITIVE_SEARCH |
+				FILE_CASE_PRESERVED_NAMES;
 
 #if defined(HAVE_SYS_QUOTAS)
-			quota_flag = FILE_VOLUME_QUOTAS;
+			fs_attribute_flags |= FILE_VOLUME_QUOTAS;
 #endif
+			if (lp_stream_support(SNUM(conn)) &&
+			    (conn->fs_capabilities & FILE_NAMED_STREAMS)) {
+				fs_attribute_flags |= FILE_NAMED_STREAMS;
+			}
+
+			if (lp_nt_acl_support(SNUM(conn)) ) {
+				fs_attribute_flags |= FILE_PERSISTENT_ACLS;
+			}
 
-			SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
-				(lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
-				quota_flag); /* FS ATTRIBUTES */
+			SIVAL(pdata, 0, fs_attribute_flags); /* FS ATTRIBUTES */
 
 			SIVAL(pdata,4,255); /* Max filename component length */
 			/* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
@@ -2675,7 +2686,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAva
 			 * Thursby MAC extension... ONLY on NTFS filesystems
 			 * once we do streams then we don't need this
 			 */
-			if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
+			if (!lp_stream_support(SNUM(conn)) &&
+			    strequal(lp_fstype(SNUM(conn)),"NTFS")) {
 				data_len = 88;
 				SIVAL(pdata,84,0x100); /* Don't support mac... */
 				break;
@@ -3139,6 +3151,104 @@ static char *store_file_unix_basic_info2
 	return pdata;
 }
 
+static unsigned int marshall_stream_info(connection_struct *conn,
+			    files_struct *fsp,
+			    const char *fname,
+			    int dosmode,
+			    SMB_BIG_UINT file_data_size,
+			    SMB_BIG_UINT file_data_allocation,
+			    char *pdata)
+{
+	unsigned int data_size = 0;
+	unsigned nextOffset = 0;
+	int count = 0;
+	int curr = 0;
+	char * namelist = NULL;
+	size_t * sizelist = NULL;
+
+	char * name;
+
+	size_t byte_len = 0;
+
+	if (!(dosmode & aDIR)) {
+	    /* Don't show ::$DATA for directories. If we do, the XP copy engine
+	     * tries to copy it, which results in all sorts of interesting
+	     * phenomena.
+	     */
+		byte_len += dos_PutUniCode(pdata + 24,"::$DATA",
+					(size_t)0xE, False);
+		SIVAL(pdata, nextOffset, 0); /* might overwrite this if
+						    more streams */
+		SIVAL(pdata,  4, byte_len); /* Byte length of unicode
+						    string ::$DATA */
+		SOFF_T(pdata, 8, file_data_size);
+		SIVAL(pdata, 16, file_data_allocation);
+		SIVAL(pdata, 20, 0); /* ??? */
+		data_size = 24 + byte_len;
+	}
+
+	count = SMB_VFS_STREAMINFO(conn, fsp, fname,
+			    &namelist, &sizelist);
+	if (count <= 0) {
+		return data_size;
+	}
+
+	DEBUG(4, ("streaminfo on %s gave %d streams\n",
+	    fsp ? fsp->fsp_name : fname, count));
+
+	for (name = namelist, curr = 0; curr < count; ++curr ) {
+		size_t nlen = strlen(name);
+
+/* TDB_ALIGN, renamed to avoid clashes. */
+#define STREAMINFO_ALIGN(x, a) (((x) + (a)-1) & ~((a)-1))
+
+		/* update the previous record's next
+		 * record offset ...
+		 */
+		data_size = STREAMINFO_ALIGN(data_size, 8);
+		SIVAL(pdata, nextOffset, data_size - nextOffset);
+
+#undef STREAMINFO_ALIGN
+
+		DEBUG(4, ("pushing name=%s size=%u\n",
+			name, (unsigned)sizelist[curr]));
+
+		/* remember where the next record offset
+		 * field is for this record ...
+		 */
+		nextOffset = data_size;
+		/* make sure it's clear ... */
+		SIVAL(pdata, nextOffset, 0);
+
+		/* now insert the new record .. */
+
+		byte_len = dos_PutUniCode(pdata + data_size + 24,
+			    name, nlen * 2, False);
+
+		/* add stream name length ... */
+		SIVAL(pdata, 4 + data_size, byte_len);
+
+		/* add stream size ... */
+		SOFF_T(pdata, 8 + data_size, (SMB_OFF_T)sizelist[curr]);
+
+		/* allocation size is the same as the
+		 * stream size ...
+		 */
+		SOFF_T(pdata,16 + data_size, (SMB_OFF_T)sizelist[curr]);
+		SIVAL(pdata, 20 + data_size, 0); /*??*/
+
+		data_size += 24 + byte_len;
+
+		/* Skip to next name. */
+		name += (nlen + 1);
+	}
+
+	SAFE_FREE(namelist);
+	SAFE_FREE(sizelist);
+
+	return data_size;
+}
+
 /****************************************************************************
  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
  file name or file id).
@@ -3698,26 +3808,20 @@ total_data=%u (should be %u)\n", (unsign
 			data_size = 4;
 			break;
 
-#if 0
 		/*
-		 * NT4 server just returns "invalid query" to this - if we try to answer
-		 * it then NTws gets a BSOD! (tridge).
+		 * NT4 server just returns "invalid query" to this - if we
+		 * try to answer it then NTws gets a BSOD! (tridge).
 		 * W2K seems to want this. JRA.
 		 */
+		/* The first statement above is false - verified using Thursby
+		 * client against NT4 -- gcolley.
+		 */
 		case SMB_QUERY_FILE_STREAM_INFO:
-#endif
 		case SMB_FILE_STREAM_INFORMATION:
 			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
-			if (mode & aDIR) {
-				data_size = 0;
-			} else {
-				size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
-				SIVAL(pdata,0,0); /* ??? */
-				SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
-				SOFF_T(pdata,8,file_size);
-				SOFF_T(pdata,16,allocation_size);
-				data_size = 24 + byte_len;
-			}
+			data_size = marshall_stream_info(conn, fsp,
+						fname, mode, file_size,
+						allocation_size, pdata);
 			break;
 
 		case SMB_QUERY_COMPRESSION_INFO: