r23792: convert Samba4 to GPLv3
[samba.git] / source4 / torture / raw / qfileinfo.c
index 99f1dd7a38402654b48231e03aee0875f9810850..6bcfdcfe098ebe7244feafa54f87416212abc561 100644 (file)
@@ -2,10 +2,11 @@
    Unix SMB/CIFS implementation.
    RAW_FILEINFO_* individual test suite
    Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "torture/torture.h"
+#include "libcli/raw/libcliraw.h"
+#include "libcli/libcli.h"
+#include "torture/util.h"
+#include "librpc/rpc/dcerpc.h"
+#include "torture/rpc/rpc.h"
 
 static struct {
        const char *name;
@@ -26,41 +32,105 @@ static struct {
        uint_t only_paths:1;
        uint_t only_handles:1;
        uint32_t capability_mask;
+       uint_t expected_ipc_access_denied:1;
+       NTSTATUS expected_ipc_fnum_status;
        NTSTATUS fnum_status, fname_status;
        union smb_fileinfo fnum_finfo, fname_finfo;
 } levels[] = {
-       { "GETATTR",                   RAW_FILEINFO_GETATTR,           1, 0, },
-       { "GETATTRE",                  RAW_FILEINFO_GETATTRE,          0, 1, },
-       { "STANDARD",                  RAW_FILEINFO_STANDARD, },
-       { "EA_SIZE",                   RAW_FILEINFO_EA_SIZE, },
-       { "ALL_EAS",                   RAW_FILEINFO_ALL_EAS, },
-       { "IS_NAME_VALID",             RAW_FILEINFO_IS_NAME_VALID,     1, 0, },
-       { "BASIC_INFO",                RAW_FILEINFO_BASIC_INFO, },
-       { "STANDARD_INFO",             RAW_FILEINFO_STANDARD_INFO, },
-       { "EA_INFO",                   RAW_FILEINFO_EA_INFO, },
-       { "NAME_INFO",                 RAW_FILEINFO_NAME_INFO, },
-       { "ALL_INFO",                  RAW_FILEINFO_ALL_INFO, },
-       { "ALT_NAME_INFO",             RAW_FILEINFO_ALT_NAME_INFO, },
-       { "STREAM_INFO",               RAW_FILEINFO_STREAM_INFO, },
-       { "COMPRESSION_INFO",          RAW_FILEINFO_COMPRESSION_INFO, },
-       { "UNIX_BASIC_INFO",           RAW_FILEINFO_UNIX_BASIC, 0, 0, CAP_UNIX},
-       { "UNIX_LINK_INFO",            RAW_FILEINFO_UNIX_LINK, 0, 0, CAP_UNIX},
-       { "BASIC_INFORMATION",         RAW_FILEINFO_BASIC_INFORMATION, },
-       { "STANDARD_INFORMATION",      RAW_FILEINFO_STANDARD_INFORMATION, },
-       { "INTERNAL_INFORMATION",      RAW_FILEINFO_INTERNAL_INFORMATION, },
-       { "EA_INFORMATION",            RAW_FILEINFO_EA_INFORMATION, },
-       { "ACCESS_INFORMATION",        RAW_FILEINFO_ACCESS_INFORMATION, },
-       { "NAME_INFORMATION",          RAW_FILEINFO_NAME_INFORMATION, },
-       { "POSITION_INFORMATION",      RAW_FILEINFO_POSITION_INFORMATION, },
-       { "MODE_INFORMATION",          RAW_FILEINFO_MODE_INFORMATION, },
-       { "ALIGNMENT_INFORMATION",     RAW_FILEINFO_ALIGNMENT_INFORMATION, },
-       { "ALL_INFORMATION",           RAW_FILEINFO_ALL_INFORMATION, },
-       { "ALT_NAME_INFORMATION",      RAW_FILEINFO_ALT_NAME_INFORMATION, },
-       { "STREAM_INFORMATION",        RAW_FILEINFO_STREAM_INFORMATION, },
-       { "COMPRESSION_INFORMATION",   RAW_FILEINFO_COMPRESSION_INFORMATION, },
-       { "NETWORK_OPEN_INFORMATION",  RAW_FILEINFO_NETWORK_OPEN_INFORMATION, },
-       { "ATTRIBUTE_TAG_INFORMATION", RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION, },
-       { NULL, }
+       { .name = "GETATTR",
+         .level = RAW_FILEINFO_GETATTR,         
+         .only_paths = 1,
+         .only_handles = 0,
+         .expected_ipc_access_denied = 1},
+       {  .name ="GETATTRE",                  
+          .level = RAW_FILEINFO_GETATTRE,         
+          .only_paths = 0, 
+          .only_handles = 1 },
+       {  .name ="STANDARD",                  
+          .level = RAW_FILEINFO_STANDARD, },
+       {  .name ="EA_SIZE",                 
+          .level = RAW_FILEINFO_EA_SIZE },
+       {  .name ="ALL_EAS",                 
+          .level = RAW_FILEINFO_ALL_EAS,
+          .expected_ipc_fnum_status = NT_STATUS_ACCESS_DENIED,
+       },
+       {  .name ="IS_NAME_VALID",          
+          .level =  RAW_FILEINFO_IS_NAME_VALID,
+          .only_paths =  1,
+          .only_handles =  0 },
+       {  .name ="BASIC_INFO",            
+          .level =  RAW_FILEINFO_BASIC_INFO },
+       {  .name ="STANDARD_INFO",         
+          .level =  RAW_FILEINFO_STANDARD_INFO },
+       {  .name ="EA_INFO",               
+          .level =  RAW_FILEINFO_EA_INFO },
+       {  .name ="NAME_INFO",           
+          .level =  RAW_FILEINFO_NAME_INFO },
+       {  .name ="ALL_INFO",              
+          .level =  RAW_FILEINFO_ALL_INFO },
+       {  .name ="ALT_NAME_INFO",        
+          .level =  RAW_FILEINFO_ALT_NAME_INFO,
+          .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       {  .name ="STREAM_INFO",           
+          .level =  RAW_FILEINFO_STREAM_INFO,
+          .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       {  .name ="COMPRESSION_INFO",        
+          .level =  RAW_FILEINFO_COMPRESSION_INFO,
+          .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       {  .name ="UNIX_BASIC_INFO",         
+          .level =  RAW_FILEINFO_UNIX_BASIC,
+          .only_paths =  0, 
+          .only_handles = 0, 
+          .capability_mask = CAP_UNIX},
+       {  .name ="UNIX_LINK_INFO",          
+          .level =  RAW_FILEINFO_UNIX_LINK, 
+          .only_paths = 0, 
+          .only_handles = 0, 
+          .capability_mask = CAP_UNIX},
+       {  .name ="BASIC_INFORMATION",      
+          .level =  RAW_FILEINFO_BASIC_INFORMATION },
+       {  .name ="STANDARD_INFORMATION",   
+          .level =  RAW_FILEINFO_STANDARD_INFORMATION },
+       {  .name ="INTERNAL_INFORMATION",   
+          .level =  RAW_FILEINFO_INTERNAL_INFORMATION },
+       {  .name ="EA_INFORMATION",        
+          .level =  RAW_FILEINFO_EA_INFORMATION },
+       { .name = "ACCESS_INFORMATION",    
+         .level =  RAW_FILEINFO_ACCESS_INFORMATION },
+       { .name = "NAME_INFORMATION",      
+         .level =  RAW_FILEINFO_NAME_INFORMATION },
+       {  .name ="POSITION_INFORMATION",  
+          .level =  RAW_FILEINFO_POSITION_INFORMATION },
+       {  .name ="MODE_INFORMATION",       
+          .level =  RAW_FILEINFO_MODE_INFORMATION },
+       {  .name ="ALIGNMENT_INFORMATION",  
+          .level =  RAW_FILEINFO_ALIGNMENT_INFORMATION },
+       {  .name ="ALL_INFORMATION",       
+          .level =  RAW_FILEINFO_ALL_INFORMATION },
+       {  .name ="ALT_NAME_INFORMATION",  
+          .level =  RAW_FILEINFO_ALT_NAME_INFORMATION,
+          .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       {  .name ="STREAM_INFORMATION",    
+          .level =  RAW_FILEINFO_STREAM_INFORMATION,
+          .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       { .name = "COMPRESSION_INFORMATION", 
+         .level =  RAW_FILEINFO_COMPRESSION_INFORMATION,
+         .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       {  .name ="NETWORK_OPEN_INFORMATION",
+          .level =  RAW_FILEINFO_NETWORK_OPEN_INFORMATION,
+          .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       { .name = "ATTRIBUTE_TAG_INFORMATION",
+         .level =  RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION,
+         .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
+       },
+       { NULL }
 };
 
 /*
@@ -69,7 +139,7 @@ static struct {
 static int dos_nt_time_cmp(time_t t, NTTIME nt)
 {
        time_t t2 = nt_time_to_unix(nt);
-       if (ABS(t2 - t) <= 2) return 0;
+       if (abs(t2 - t) <= 2) return 0;
        return t2 - t;
 }
 
@@ -93,9 +163,12 @@ static union smb_fileinfo *fnum_find(const char *name)
 /*
   find a level in the levels[] table
 */
-static union smb_fileinfo *fname_find(const char *name)
+static union smb_fileinfo *fname_find(bool is_ipc, const char *name)
 {
        int i;
+       if (is_ipc) {
+               return NULL;
+       }
        for (i=0; levels[i].name; i++) {
                if (NT_STATUS_IS_OK(levels[i].fname_status) &&
                    strcmp(name, levels[i].name) == 0 && 
@@ -134,6 +207,7 @@ static union smb_fileinfo *fname_find(const char *name)
 
 /* used to find hints on unknown values - and to make sure 
    we zero-fill */
+#if 0 /* unused */
 #define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
         printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
                #n1, #v1, \
@@ -142,76 +216,77 @@ static union smb_fileinfo *fname_find(const char *name)
               __FILE__, __LINE__); \
         ret = False; \
 }} while(0)
+#endif
 
 /* basic testing of all RAW_FILEINFO_* calls 
    for each call we test that it succeeds, and where possible test 
    for consistency between the calls. 
 */
-BOOL torture_raw_qfileinfo(void)
+static BOOL torture_raw_qfileinfo_internals(struct torture_context *torture, TALLOC_CTX *mem_ctx,      
+                                           struct smbcli_tree *tree, int fnum, const char *fname,
+       bool is_ipc)
 {
-       struct smbcli_state *cli;
        int i;
        BOOL ret = True;
        int count;
        union smb_fileinfo *s1, *s2;    
-       TALLOC_CTX *mem_ctx;
-       int fnum;
-       const char *fname = "\\torture_qfileinfo.txt";
        NTTIME correct_time;
        uint64_t correct_size;
        uint32_t correct_attrib;
        const char *correct_name;
        BOOL skip_streams = False;
 
-       if (!torture_open_connection(&cli)) {
-               return False;
-       }
-
-       mem_ctx = talloc_init("torture_qfileinfo");
-
-       fnum = create_complex_file(cli, mem_ctx, fname);
-       if (fnum == -1) {
-               printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
-               ret = False;
-               goto done;
-       }
-       
-       
        /* scan all the fileinfo and pathinfo levels */
        for (i=0; levels[i].name; i++) {
                if (!levels[i].only_paths) {
                        levels[i].fnum_finfo.generic.level = levels[i].level;
-                       levels[i].fnum_finfo.generic.in.fnum = fnum;
-                       levels[i].fnum_status = smb_raw_fileinfo(cli->tree, mem_ctx, 
+                       levels[i].fnum_finfo.generic.in.file.fnum = fnum;
+                       levels[i].fnum_status = smb_raw_fileinfo(tree, mem_ctx, 
                                                                 &levels[i].fnum_finfo);
                }
 
                if (!levels[i].only_handles) {
                        levels[i].fname_finfo.generic.level = levels[i].level;
-                       levels[i].fname_finfo.generic.in.fname = talloc_strdup(mem_ctx, fname);
-                       levels[i].fname_status = smb_raw_pathinfo(cli->tree, mem_ctx, 
+                       levels[i].fname_finfo.generic.in.file.path = talloc_strdup(mem_ctx, fname);
+                       levels[i].fname_status = smb_raw_pathinfo(tree, mem_ctx, 
                                                                  &levels[i].fname_finfo);
                }
        }
 
        /* check for completely broken levels */
        for (count=i=0; levels[i].name; i++) {
-               uint32_t cap = cli->transport->negotiate.capabilities;
+               uint32_t cap = tree->session->transport->negotiate.capabilities;
                /* see if this server claims to support this level */
                if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
                        continue;
                }
 
-               if (!levels[i].only_paths && !NT_STATUS_IS_OK(levels[i].fnum_status)) {
-                       printf("ERROR: level %s failed - %s\n", 
-                              levels[i].name, nt_errstr(levels[i].fnum_status));
-                       count++;
-               }
-               if (!levels[i].only_handles && !NT_STATUS_IS_OK(levels[i].fname_status)) {
-                       printf("ERROR: level %s failed - %s\n", 
-                              levels[i].name, nt_errstr(levels[i].fname_status));
-                       count++;
+               if (is_ipc) {
+                       if (levels[i].expected_ipc_access_denied && NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, levels[i].fname_status)) {
+                       } else if (!levels[i].only_handles && !NT_STATUS_EQUAL(NT_STATUS_INVALID_DEVICE_REQUEST, levels[i].fname_status)) {
+                               printf("ERROR: fname level %s failed, expected NT_STATUS_INVALID_DEVICE_REQUEST - %s\n", 
+                                      levels[i].name, nt_errstr(levels[i].fname_status));
+                               count++;
+                       }
+                       if (!levels[i].only_paths && !NT_STATUS_EQUAL(levels[i].expected_ipc_fnum_status, levels[i].fnum_status)) {
+                               printf("ERROR: fnum level %s failed, expected %s - %s\n", 
+                                      levels[i].name, nt_errstr(levels[i].expected_ipc_fnum_status), 
+                                      nt_errstr(levels[i].fnum_status));
+                               count++;
+                       }
+               } else {
+                       if (!levels[i].only_paths && !NT_STATUS_IS_OK(levels[i].fnum_status)) {
+                               printf("ERROR: fnum level %s failed - %s\n", 
+                                      levels[i].name, nt_errstr(levels[i].fnum_status));
+                               count++;
+                       }
+                       if (!levels[i].only_handles && !NT_STATUS_IS_OK(levels[i].fname_status)) {
+                               printf("ERROR: fname level %s failed - %s\n", 
+                                      levels[i].name, nt_errstr(levels[i].fname_status));
+                               count++;
+                       }
                }
+               
        }
 
        if (count != 0) {
@@ -226,8 +301,10 @@ BOOL torture_raw_qfileinfo(void)
        /* see if we can do streams */
        s1 = fnum_find("STREAM_INFO");
        if (!s1 || s1->stream_info.out.num_streams == 0) {
-               printf("STREAM_INFO broken (%d) - skipping streams checks\n",
-                      s1 ? s1->stream_info.out.num_streams : -1);
+               if (!is_ipc) {
+                       printf("STREAM_INFO broken (%d) - skipping streams checks\n",
+                              s1 ? s1->stream_info.out.num_streams : -1);
+               }
                skip_streams = True;
        }       
 
@@ -244,9 +321,9 @@ BOOL torture_raw_qfileinfo(void)
        do { \
                s1 = fnum_find(sname1);  s2 = fnum_find(sname2); \
                if (s1 && s2) { INFO_CHECK } \
-               s1 = fname_find(sname1); s2 = fname_find(sname2); \
+               s1 = fname_find(is_ipc, sname1); s2 = fname_find(is_ipc, sname2); \
                if (s1 && s2) { INFO_CHECK } \
-               s1 = fnum_find(sname1);  s2 = fname_find(sname2); \
+               s1 = fnum_find(sname1);  s2 = fname_find(is_ipc, sname2); \
                if (s1 && s2) { INFO_CHECK } \
        } while (0)
 
@@ -324,7 +401,7 @@ BOOL torture_raw_qfileinfo(void)
                       nt_time_string(mem_ctx, correct_time)); \
                ret = False; \
        } \
-       s1 = fname_find(sname); \
+       s1 = fname_find(is_ipc, sname); \
        if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
                printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield,  \
                       nt_time_string(mem_ctx, s1->stype.out.tfield), \
@@ -340,7 +417,7 @@ BOOL torture_raw_qfileinfo(void)
                       nt_time_string(mem_ctx, correct_time)); \
                ret = False; \
        } \
-       s1 = fname_find(sname); \
+       s1 = fname_find(is_ipc, sname); \
        if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
                printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield,  \
                       timestring(mem_ctx, s1->stype.out.tfield), \
@@ -348,6 +425,7 @@ BOOL torture_raw_qfileinfo(void)
                ret = False; \
        }} while (0)
 
+#if 0 /* unused */
 #define TIME_CHECK_UNX(sname, stype, tfield) do { \
        s1 = fnum_find(sname); \
        if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
@@ -356,13 +434,14 @@ BOOL torture_raw_qfileinfo(void)
                       nt_time_string(mem_ctx, correct_time)); \
                ret = False; \
        } \
-       s1 = fname_find(sname); \
+       s1 = fname_find(is_ipc, sname); \
        if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
                printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield,  \
                       timestring(mem_ctx, s1->stype.out.tfield), \
                       nt_time_string(mem_ctx, correct_time)); \
                ret = False; \
        }} while (0)
+#endif
 
        /* now check that all the times that are supposed to be equal are correct */
        s1 = fnum_find("BASIC_INFO");
@@ -420,7 +499,7 @@ BOOL torture_raw_qfileinfo(void)
                       (uint_t)correct_size); \
                ret = False; \
        } \
-       s1 = fname_find(sname); \
+       s1 = fname_find(is_ipc, sname); \
        if (s1 && s1->stype.out.tfield != correct_size) { \
                printf("(%d) path %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield,  \
                       (uint_t)s1->stype.out.tfield, \
@@ -474,7 +553,7 @@ BOOL torture_raw_qfileinfo(void)
                       (uint_t)correct_attrib); \
                ret = False; \
        } \
-       s1 = fname_find(sname); \
+       s1 = fname_find(is_ipc, sname); \
        if (s1 && s1->stype.out.tfield != correct_attrib) { \
                printf("(%d) path %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield,  \
                       (uint_t)s1->stype.out.tfield, \
@@ -487,11 +566,13 @@ BOOL torture_raw_qfileinfo(void)
        printf("attrib: 0x%x\n", (uint_t)correct_attrib);
        
        ATTRIB_CHECK("GETATTR",                   getattr,                   attrib);
-       ATTRIB_CHECK("GETATTRE",                  getattre,                  attrib);
-       ATTRIB_CHECK("STANDARD",                  standard,                  attrib);
+       if (!is_ipc) {
+               ATTRIB_CHECK("GETATTRE",                  getattre,                  attrib);
+               ATTRIB_CHECK("STANDARD",                  standard,                  attrib);
+               ATTRIB_CHECK("EA_SIZE",                   ea_size,                   attrib);
+       }
        ATTRIB_CHECK("BASIC_INFO",                basic_info,                attrib);
        ATTRIB_CHECK("BASIC_INFORMATION",         basic_info,                attrib);
-       ATTRIB_CHECK("EA_SIZE",                   ea_size,                   attrib);
        ATTRIB_CHECK("ALL_INFO",                  all_info,                  attrib);
        ATTRIB_CHECK("ALL_INFORMATION",           all_info,                  attrib);
        ATTRIB_CHECK("NETWORK_OPEN_INFORMATION",  network_open_information,  attrib);
@@ -503,14 +584,14 @@ BOOL torture_raw_qfileinfo(void)
 #define NAME_CHECK(sname, stype, tfield, flags) do { \
        s1 = fnum_find(sname); \
        if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
-                       wire_bad_flags(&s1->stype.out.tfield, flags, cli))) { \
+                       wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
                printf("(%d) handle %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield,  \
                       s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
                ret = False; \
        } \
-       s1 = fname_find(sname); \
+       s1 = fname_find(is_ipc, sname); \
        if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
-                       wire_bad_flags(&s1->stype.out.tfield, flags, cli))) { \
+                       wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
                printf("(%d) path %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield,  \
                       s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
                ret = False; \
@@ -538,41 +619,44 @@ BOOL torture_raw_qfileinfo(void)
                                ret = False;
                        }
                }
-               if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE, cli)) {
+               if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE, tree->session->transport)) {
                        printf("Should not null terminate all_info/fname\n");
                        ret = False;
                }
        }
 
        s1 = fnum_find("ALT_NAME_INFO");
-       correct_name = s1->alt_name_info.out.fname.s;
-       printf("alt_name: %s\n", correct_name);
-
-       NAME_CHECK("ALT_NAME_INFO",        alt_name_info, fname, STR_UNICODE);
-       NAME_CHECK("ALT_NAME_INFORMATION", alt_name_info, fname, STR_UNICODE);
-
-       /* and make sure we can open by alternate name */
-       smbcli_close(cli->tree, fnum);
-       fnum = smbcli_nt_create_full(cli->tree, correct_name, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, 
-                                 FILE_ATTRIBUTE_NORMAL,
-                                 NTCREATEX_SHARE_ACCESS_DELETE|
-                                 NTCREATEX_SHARE_ACCESS_READ|
-                                 NTCREATEX_SHARE_ACCESS_WRITE, 
-                                 NTCREATEX_DISP_OVERWRITE_IF, 
-                                 0, 0);
-       if (fnum == -1) {
-               printf("Unable to open by alt_name - %s\n", smbcli_errstr(cli->tree));
-               ret = False;
-       }
-
-       if (!skip_streams) {
-               correct_name = "::$DATA";
-               printf("stream_name: %s\n", correct_name);
-
-               NAME_CHECK("STREAM_INFO",        stream_info, streams[0].stream_name, STR_UNICODE);
-               NAME_CHECK("STREAM_INFORMATION", stream_info, streams[0].stream_name, STR_UNICODE);
+       if (s1) {
+               correct_name = s1->alt_name_info.out.fname.s;
+               printf("alt_name: %s\n", correct_name);
+               
+               NAME_CHECK("ALT_NAME_INFO",        alt_name_info, fname, STR_UNICODE);
+               NAME_CHECK("ALT_NAME_INFORMATION", alt_name_info, fname, STR_UNICODE);
+               
+               /* and make sure we can open by alternate name */
+               smbcli_close(tree, fnum);
+               fnum = smbcli_nt_create_full(tree, correct_name, 0, 
+                                            SEC_RIGHTS_FILE_ALL,
+                                            FILE_ATTRIBUTE_NORMAL,
+                                            NTCREATEX_SHARE_ACCESS_DELETE|
+                                            NTCREATEX_SHARE_ACCESS_READ|
+                                            NTCREATEX_SHARE_ACCESS_WRITE, 
+                                            NTCREATEX_DISP_OVERWRITE_IF, 
+                                            0, 0);
+               if (fnum == -1) {
+                       printf("Unable to open by alt_name - %s\n", smbcli_errstr(tree));
+                       ret = False;
+               }
+               
+               if (!skip_streams) {
+                       correct_name = "::$DATA";
+                       printf("stream_name: %s\n", correct_name);
+                       
+                       NAME_CHECK("STREAM_INFO",        stream_info, streams[0].stream_name, STR_UNICODE);
+                       NAME_CHECK("STREAM_INFORMATION", stream_info, streams[0].stream_name, STR_UNICODE);
+               }
        }
-
+               
        /* make sure the EAs look right */
        s1 = fnum_find("ALL_EAS");
        s2 = fnum_find("ALL_INFO");
@@ -581,8 +665,8 @@ BOOL torture_raw_qfileinfo(void)
                        printf("  flags=%d %s=%*.*s\n", 
                               s1->all_eas.out.eas[i].flags,
                               s1->all_eas.out.eas[i].name.s,
-                              s1->all_eas.out.eas[i].value.length,
-                              s1->all_eas.out.eas[i].value.length,
+                              (int)s1->all_eas.out.eas[i].value.length,
+                              (int)s1->all_eas.out.eas[i].value.length,
                               s1->all_eas.out.eas[i].value.data);
                }
        }
@@ -596,12 +680,12 @@ BOOL torture_raw_qfileinfo(void)
                        if (s2->all_info.out.ea_size != 
                            ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas)) {
                                printf("ERROR: ea_list_size=%d != fnum all_info.out.ea_size=%d\n",
-                                      ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas),
-                                      s2->all_info.out.ea_size);
+                                      (int)ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas),
+                                      (int)s2->all_info.out.ea_size);
                        }
                }
        }
-       s2 = fname_find("ALL_EAS");
+       s2 = fname_find(is_ipc, "ALL_EAS");
        if (s2) {
                VAL_EQUAL(all_eas, num_eas, all_eas, num_eas);
                for (i=0;i<s1->all_eas.out.num_eas;i++) {
@@ -619,21 +703,21 @@ BOOL torture_raw_qfileinfo(void)
                       s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
                ret = False; \
        } \
-       s1 = fname_find(sname1); s2 = fname_find(sname2); \
+       s1 = fname_find(is_ipc, sname1); s2 = fname_find(is_ipc, sname2); \
        if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
                printf("(%d) path %s/%s != %s/%s - 0x%x vs 0x%x\n", __LINE__, \
                        #stype1, #tfield1, #stype2, #tfield2,  \
                       s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
                ret = False; \
        } \
-       s1 = fnum_find(sname1); s2 = fname_find(sname2); \
+       s1 = fnum_find(sname1); s2 = fname_find(is_ipc, sname2); \
        if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
                printf("(%d) handle %s/%s != path %s/%s - 0x%x vs 0x%x\n", __LINE__, \
                        #stype1, #tfield1, #stype2, #tfield2,  \
                       s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
                ret = False; \
        } \
-       s1 = fname_find(sname1); s2 = fnum_find(sname2); \
+       s1 = fname_find(is_ipc, sname1); s2 = fnum_find(sname2); \
        if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
                printf("(%d) path %s/%s != handle %s/%s - 0x%x vs 0x%x\n", __LINE__, \
                        #stype1, #tfield1, #stype2, #tfield2,  \
@@ -647,14 +731,33 @@ BOOL torture_raw_qfileinfo(void)
                  "ALL_INFO",      all_info,      directory);
        VAL_CHECK("STANDARD_INFO", standard_info, nlink, 
                  "ALL_INFO",      all_info,      nlink);
+       s1 = fnum_find("BASIC_INFO");
+       if (s1 && is_ipc) {
+               if (s1->basic_info.out.attrib != FILE_ATTRIBUTE_NORMAL) {
+                       printf("(%d) attrib basic_info/nlink incorrect - %d should be %d\n", __LINE__, s1->basic_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
+                       ret = False;
+               }
+       }
+       s1 = fnum_find("STANDARD_INFO");
+       if (s1 && is_ipc) {
+               if (s1->standard_info.out.nlink != 1) {
+                       printf("(%d) nlinks standard_info/nlink incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.nlink);
+                       ret = False;
+               }
+               if (s1->standard_info.out.delete_pending != 1) {
+                       printf("(%d) nlinks standard_info/delete_pending incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.delete_pending);
+                       ret = False;
+               }
+       }
        VAL_CHECK("EA_INFO",       ea_info,       ea_size, 
                  "ALL_INFO",      all_info,      ea_size);
-       VAL_CHECK("EA_SIZE",       ea_size,       ea_size, 
-                 "ALL_INFO",      all_info,      ea_size);
-
+       if (!is_ipc) {
+               VAL_CHECK("EA_SIZE",       ea_size,       ea_size, 
+                         "ALL_INFO",      all_info,      ea_size);
+       }
 
 #define NAME_PATH_CHECK(sname, stype, field) do { \
-       s1 = fname_find(sname); s2 = fnum_find(sname); \
+       s1 = fname_find(is_ipc, sname); s2 = fnum_find(sname); \
         if (s1 && s2) { \
                VAL_EQUAL(stype, field, stype, field); \
        } \
@@ -683,6 +786,7 @@ BOOL torture_raw_qfileinfo(void)
        NAME_PATH_CHECK("ACCESS_INFORMATION", access_information, access_flags);
 #endif
 
+#if 0 /* unused */
 #define UNKNOWN_CHECK(sname, stype, tfield) do { \
        s1 = fnum_find(sname); \
        if (s1 && s1->stype.out.tfield != 0) { \
@@ -690,13 +794,13 @@ BOOL torture_raw_qfileinfo(void)
                        #stype, #tfield, \
                       (uint_t)s1->stype.out.tfield); \
        } \
-       s1 = fname_find(sname); \
+       s1 = fname_find(is_ipc, sname); \
        if (s1 && s1->stype.out.tfield != 0) { \
                printf("(%d) path %s/%s unknown != 0 (0x%x)\n", __LINE__, \
                        #stype, #tfield, \
                       (uint_t)s1->stype.out.tfield); \
        }} while (0)
-
+#endif
        /* now get a bit fancier .... */
        
        /* when we set the delete disposition then the link count should drop
@@ -704,10 +808,81 @@ BOOL torture_raw_qfileinfo(void)
        
 
 done:
+
+       return ret;
+}
+
+/* basic testing of all RAW_FILEINFO_* calls 
+   for each call we test that it succeeds, and where possible test 
+   for consistency between the calls. 
+*/
+BOOL torture_raw_qfileinfo(struct torture_context *torture)
+{
+       struct smbcli_state *cli;
+       BOOL ret = True;
+       TALLOC_CTX *mem_ctx;
+       int fnum;
+       const char *fname = "\\torture_qfileinfo.txt";
+
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
+
+       mem_ctx = talloc_init("torture_qfileinfo");
+
+       fnum = create_complex_file(cli, mem_ctx, fname);
+       if (fnum == -1) {
+               printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
+               ret = False;
+               goto done;
+       }
+
+       ret = torture_raw_qfileinfo_internals(torture, mem_ctx, cli->tree, fnum, fname, False /* is_ipc */);
+       
        smbcli_close(cli->tree, fnum);
        smbcli_unlink(cli->tree, fname);
 
+done:
        torture_close_connection(cli);
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
+       return ret;
+}
+
+BOOL torture_raw_qfileinfo_pipe(struct torture_context *torture)
+{
+       TALLOC_CTX *mem_ctx;
+       BOOL ret = True;
+       int fnum;
+       const char *fname = "\\lsass";
+       struct smbcli_state *cli;
+       struct dcerpc_pipe *p;
+       struct smbcli_tree *ipc_tree;
+       NTSTATUS status;
+
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
+
+       mem_ctx = talloc_init("torture_qfileinfo_pipe");
+
+       if (!(p = dcerpc_pipe_init(mem_ctx, 
+                                  cli->tree->session->transport->socket->event.ctx))) {
+               return False;
+       }
+
+       status = dcerpc_pipe_open_smb(p, cli->tree, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("dcerpc_pipe_open_smb failed: %s\n",
+                        nt_errstr(status));
+               talloc_free(p);
+               return False;
+       }
+
+       ipc_tree = dcerpc_smb_tree(p->conn);
+       fnum = dcerpc_smb_fnum(p->conn);
+
+       ret = torture_raw_qfileinfo_internals(torture, mem_ctx, ipc_tree, fnum, fname, True /* is_ipc */);
+       
+       talloc_free(p);
        return ret;
 }