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 @@ -2274,7 +2276,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); @@ -2358,15 +2360,25 @@ 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 | + FILE_UNICODE_ON_DISK; #if defined(HAVE_SYS_QUOTAS) - quota_flag = FILE_VOLUME_QUOTAS; + fs_attribute_flags |= FILE_VOLUME_QUOTAS; #endif - SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| - FILE_UNICODE_ON_DISK| - quota_flag); /* FS ATTRIBUTES */ + 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, 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 @@ -2727,7 +2739,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; @@ -3191,6 +3204,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). @@ -3749,26 +3860,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: