s4:torture: s/private/private_data
[samba.git] / source4 / torture / raw / qfileinfo.c
index 26c94b6a09be387e05871ee8e019e6478ada9e7b..c7673be52633121714f4f81b3c420de56d9d26c1 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/raw/raw_proto.h"
+#include "libcli/libcli.h"
+#include "torture/util.h"
+#include "librpc/rpc/dcerpc.h"
+#include "torture/rpc/rpc.h"
+#include "torture/raw/proto.h"
+#include "param/param.h"
 
 static struct {
        const char *name;
-       enum fileinfo_level level;
-       unsigned only_paths:1;
-       unsigned only_handles:1;
+       enum smb_fileinfo_level level;
+       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 +142,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 +166,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 && 
@@ -112,16 +188,16 @@ static union smb_fileinfo *fname_find(const char *name)
                #n1, #v1, (uint_t)s1->n1.out.v1, \
                #n2, #v2, (uint_t)s2->n2.out.v2, \
               __FILE__, __LINE__); \
-        ret = False; \
+        ret = false; \
 }} while(0)
 
-#define STR_EQUAL(n1, v1, n2, v2) do {if (strcmp(s1->n1.out.v1.s, s2->n2.out.v2.s) || \
+#define STR_EQUAL(n1, v1, n2, v2) do {if (strcmp_safe(s1->n1.out.v1.s, s2->n2.out.v2.s) || \
                                          s1->n1.out.v1.private_length != s2->n2.out.v2.private_length) { \
         printf("%s/%s [%s/%d] != %s/%s [%s/%d] at %s(%d)\n", \
                #n1, #v1, s1->n1.out.v1.s, s1->n1.out.v1.private_length, \
                #n2, #v2, s2->n2.out.v2.s, s2->n2.out.v2.private_length, \
               __FILE__, __LINE__); \
-        ret = False; \
+        ret = false; \
 }} while(0)
 
 #define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
@@ -129,106 +205,111 @@ static union smb_fileinfo *fname_find(const char *name)
                #n1, #v1, \
                #n2, #v2, \
               __FILE__, __LINE__); \
-        ret = False; \
+        ret = false; \
 }} while(0)
 
 /* 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, \
               (uint_t)s1->n1.out.v1, \
               (uint_t)s1->n1.out.v1, \
               __FILE__, __LINE__); \
-        ret = False; \
+        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(int dummy)
+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 cli_state *cli;
        int i;
-       BOOL ret = True;
+       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;
+       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, cli_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) {
-               ret = False;
+               ret = false;
                printf("%d levels failed\n", count);
                if (count > 35) {
-                       printf("too many level failures - giving up\n");
-                       goto done;
+                       torture_fail(torture, "too many level failures - giving up");
                }
        }
 
        /* 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);
-               skip_streams = True;
+               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 +325,9 @@ BOOL torture_raw_qfileinfo(int dummy)
        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)
 
@@ -322,14 +403,14 @@ BOOL torture_raw_qfileinfo(int dummy)
                printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield,  \
                       nt_time_string(mem_ctx, s1->stype.out.tfield), \
                       nt_time_string(mem_ctx, correct_time)); \
-               ret = False; \
+               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), \
                       nt_time_string(mem_ctx, correct_time)); \
-               ret = False; \
+               ret = false; \
        }} while (0)
 
 #define TIME_CHECK_DOS(sname, stype, tfield) do { \
@@ -338,36 +419,38 @@ BOOL torture_raw_qfileinfo(int dummy)
                printf("(%d) handle %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; \
+               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), \
                       nt_time_string(mem_ctx, correct_time)); \
-               ret = False; \
+               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) { \
                printf("(%d) handle %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; \
+               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; \
+               ret = false; \
        }} while (0)
+#endif
 
        /* now check that all the times that are supposed to be equal are correct */
        s1 = fnum_find("BASIC_INFO");
        correct_time = s1->basic_info.out.create_time;
-       printf("create_time: %s\n", nt_time_string(mem_ctx, correct_time));
+       torture_comment(torture, "create_time: %s\n", nt_time_string(mem_ctx, correct_time));
 
        TIME_CHECK_NT ("BASIC_INFO",               basic_info, create_time);
        TIME_CHECK_NT ("BASIC_INFORMATION",        basic_info, create_time);
@@ -379,7 +462,7 @@ BOOL torture_raw_qfileinfo(int dummy)
 
        s1 = fnum_find("BASIC_INFO");
        correct_time = s1->basic_info.out.access_time;
-       printf("access_time: %s\n", nt_time_string(mem_ctx, correct_time));
+       torture_comment(torture, "access_time: %s\n", nt_time_string(mem_ctx, correct_time));
 
        TIME_CHECK_NT ("BASIC_INFO",               basic_info, access_time);
        TIME_CHECK_NT ("BASIC_INFORMATION",        basic_info, access_time);
@@ -391,7 +474,7 @@ BOOL torture_raw_qfileinfo(int dummy)
 
        s1 = fnum_find("BASIC_INFO");
        correct_time = s1->basic_info.out.write_time;
-       printf("write_time : %s\n", nt_time_string(mem_ctx, correct_time));
+       torture_comment(torture, "write_time : %s\n", nt_time_string(mem_ctx, correct_time));
 
        TIME_CHECK_NT ("BASIC_INFO",               basic_info, write_time);
        TIME_CHECK_NT ("BASIC_INFORMATION",        basic_info, write_time);
@@ -404,7 +487,7 @@ BOOL torture_raw_qfileinfo(int dummy)
 
        s1 = fnum_find("BASIC_INFO");
        correct_time = s1->basic_info.out.change_time;
-       printf("change_time: %s\n", nt_time_string(mem_ctx, correct_time));
+       torture_comment(torture, "change_time: %s\n", nt_time_string(mem_ctx, correct_time));
 
        TIME_CHECK_NT ("BASIC_INFO",               basic_info, change_time);
        TIME_CHECK_NT ("BASIC_INFORMATION",        basic_info, change_time);
@@ -416,21 +499,21 @@ BOOL torture_raw_qfileinfo(int dummy)
        s1 = fnum_find(sname); \
        if (s1 && s1->stype.out.tfield != correct_size) { \
                printf("(%d) handle %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield,  \
-                      (unsigned)s1->stype.out.tfield, \
-                      (unsigned)correct_size); \
-               ret = False; \
+                      (uint_t)s1->stype.out.tfield, \
+                      (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,  \
-                      (unsigned)s1->stype.out.tfield, \
-                      (unsigned)correct_size); \
-               ret = False; \
+                      (uint_t)s1->stype.out.tfield, \
+                      (uint_t)correct_size); \
+               ret = false; \
        }} while (0)
 
        s1 = fnum_find("STANDARD_INFO");
        correct_size = s1->standard_info.out.size;
-       printf("size: %u\n", (unsigned)correct_size);
+       torture_comment(torture, "size: %u\n", (uint_t)correct_size);
        
        SIZE_CHECK("GETATTR",                  getattr,                  size);
        SIZE_CHECK("GETATTRE",                 getattre,                 size);
@@ -451,7 +534,7 @@ BOOL torture_raw_qfileinfo(int dummy)
 
        s1 = fnum_find("STANDARD_INFO");
        correct_size = s1->standard_info.out.alloc_size;
-       printf("alloc_size: %u\n", (unsigned)correct_size);
+       torture_comment(torture, "alloc_size: %u\n", (uint_t)correct_size);
        
        SIZE_CHECK("GETATTRE",                 getattre,                 alloc_size);
        SIZE_CHECK("STANDARD",                 standard,                 alloc_size);
@@ -470,50 +553,52 @@ BOOL torture_raw_qfileinfo(int dummy)
        s1 = fnum_find(sname); \
        if (s1 && s1->stype.out.tfield != correct_attrib) { \
                printf("(%d) handle %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield,  \
-                      (unsigned)s1->stype.out.tfield, \
-                      (unsigned)correct_attrib); \
-               ret = False; \
+                      (uint_t)s1->stype.out.tfield, \
+                      (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,  \
-                      (unsigned)s1->stype.out.tfield, \
-                      (unsigned)correct_attrib); \
-               ret = False; \
+                      (uint_t)s1->stype.out.tfield, \
+                      (uint_t)correct_attrib); \
+               ret = false; \
        }} while (0)
 
        s1 = fnum_find("BASIC_INFO");
        correct_attrib = s1->basic_info.out.attrib;
-       printf("attrib: 0x%x\n", (unsigned)correct_attrib);
+       torture_comment(torture, "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);
        ATTRIB_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
 
        correct_name = fname;
-       printf("name: %s\n", correct_name);
+       torture_comment(torture, "name: %s\n", correct_name);
 
 #define NAME_CHECK(sname, stype, tfield, flags) do { \
        s1 = fnum_find(sname); \
-       if (s1 && (strcmp(s1->stype.out.tfield.s, correct_name) != 0 || \
-                       wire_bad_flags(&s1->stype.out.tfield, flags))) { \
+       if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
+                       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; \
+               ret = false; \
        } \
-       s1 = fname_find(sname); \
-       if (s1 && (strcmp(s1->stype.out.tfield.s, correct_name) != 0 || \
-                       wire_bad_flags(&s1->stype.out.tfield, flags))) { \
+       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, 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; \
+               ret = false; \
        }} while (0)
 
        NAME_CHECK("NAME_INFO",        name_info, fname, STR_UNICODE);
@@ -522,57 +607,59 @@ BOOL torture_raw_qfileinfo(int dummy)
        /* the ALL_INFO file name is the full path on the filesystem */
        s1 = fnum_find("ALL_INFO");
        if (s1 && !s1->all_info.out.fname.s) {
-               printf("ALL_INFO didn't give a filename\n");
-               ret = False;
+               torture_fail(torture, "ALL_INFO didn't give a filename");
        }
        if (s1 && s1->all_info.out.fname.s) {
                char *p = strrchr(s1->all_info.out.fname.s, '\\');
                if (!p) {
                        printf("Not a full path in all_info/fname? - '%s'\n", 
                               s1->all_info.out.fname.s);
-                       ret = False;
+                       ret = false;
                } else {
-                       if (strcmp(correct_name, p) != 0) {
+                       if (strcmp_safe(correct_name, p) != 0) {
                                printf("incorrect basename in all_info/fname - '%s'\n",
                                       s1->all_info.out.fname.s);
-                               ret = False;
+                               ret = false;
                        }
                }
-               if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE)) {
+               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;
+                       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 */
-       cli_close(cli->tree, fnum);
-       fnum = cli_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", cli_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;
+               torture_comment(torture, "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";
+                       torture_comment(torture, "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 +668,8 @@ BOOL torture_raw_qfileinfo(int dummy)
                        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 +683,12 @@ BOOL torture_raw_qfileinfo(int dummy)
                        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++) {
@@ -617,28 +704,28 @@ BOOL torture_raw_qfileinfo(int dummy)
                printf("(%d) handle %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; \
+               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; \
+               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; \
+               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,  \
                       s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
-               ret = False; \
+               ret = false; \
        }} while (0)
 
        VAL_CHECK("STANDARD_INFO", standard_info, delete_pending, 
@@ -647,14 +734,33 @@ BOOL torture_raw_qfileinfo(int dummy)
                  "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); \
        } \
@@ -663,7 +769,7 @@ BOOL torture_raw_qfileinfo(int dummy)
 
        s1 = fnum_find("INTERNAL_INFORMATION");
        if (s1) {
-               printf("file_id=%.0f\n", (double)s1->internal_information.out.file_id);
+               torture_comment(torture, "file_id=%.0f\n", (double)s1->internal_information.out.file_id);
        }
 
        NAME_PATH_CHECK("INTERNAL_INFORMATION", internal_information, file_id);
@@ -683,31 +789,77 @@ BOOL torture_raw_qfileinfo(int dummy)
        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) { \
                printf("(%d) handle %s/%s unknown != 0 (0x%x)\n", __LINE__, \
                        #stype, #tfield, \
-                      (unsigned)s1->stype.out.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, \
-                      (unsigned)s1->stype.out.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
           to 0 and delete_pending should be 1 */
        
+       return ret;
+}
 
-done:
-       cli_close(cli->tree, fnum);
-       cli_unlink(cli->tree, fname);
+/* 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)
+{
+       int fnum;
+       bool ret;
+       const char *fname = "\\torture_qfileinfo.txt";
+
+       fnum = create_complex_file(cli, torture, fname);
+       if (fnum == -1) {
+               printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
+               return false;
+       }
+
+       ret = torture_raw_qfileinfo_internals(torture, torture, cli->tree, fnum, fname, false /* is_ipc */);
+       
+       smbcli_close(cli->tree, fnum);
+       smbcli_unlink(cli->tree, fname);
+
+       return ret;
+}
+
+bool torture_raw_qfileinfo_pipe(struct torture_context *torture, 
+                               struct smbcli_state *cli)
+{
+       bool ret = true;
+       int fnum;
+       const char *fname = "\\lsass";
+       struct dcerpc_pipe *p;
+       struct smbcli_tree *ipc_tree;
+       NTSTATUS status;
+
+       if (!(p = dcerpc_pipe_init(torture, cli->tree->session->transport->socket->event.ctx,
+                                  lp_iconv_convenience(torture->lp_ctx)))) {
+               return false;
+       }
+
+       status = dcerpc_pipe_open_smb(p, cli->tree, fname);
+       torture_assert_ntstatus_ok(torture, status, "dcerpc_pipe_open_smb failed");
 
-       torture_close_connection(cli);
-       talloc_destroy(mem_ctx);
+       ipc_tree = dcerpc_smb_tree(p->conn);
+       fnum = dcerpc_smb_fnum(p->conn);
+
+       ret = torture_raw_qfileinfo_internals(torture, torture, ipc_tree, fnum, fname, true /* is_ipc */);
+       
+       talloc_free(p);
        return ret;
 }