Finish removal of iconv_convenience in public API's.
[bbaumbach/samba-autobuild/.git] / source4 / torture / raw / qfileinfo.c
index b1f508cae81f6208befa0b156cd617fdd881f762..12897ef499abfed2b25a44c2cf20c4cfa9e95cf1 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 "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "libcli/libcli.h"
+#include "torture/util.h"
+#include "torture/rpc/torture_rpc.h"
+#include "param/param.h"
 
 static struct {
        const char *name;
-       enum fileinfo_level level;
-       unsigned only_paths:1;
-       unsigned only_handles:1;
-       uint32 capability_mask;
+       enum smb_fileinfo_level level;
+       unsigned int only_paths:1;
+       unsigned int only_handles:1;
+       uint32_t capability_mask;
+       unsigned int 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 }
 };
 
 /*
   compare a dos time (2 second resolution) to a nt time
 */
-static int dos_nt_time_cmp(time_t t, const NTTIME *nt)
+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;
-       return t2 - t;
+       if (abs(t2 - t) <= 2) return 0;
+       return t2 > t ? 1 : -1;
 }
 
 
@@ -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 && 
@@ -109,19 +182,19 @@ static union smb_fileinfo *fname_find(const char *name)
 /* local macros to make the code below more readable */
 #define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
         printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
-               #n1, #v1, (uint_t)s1->n1.out.v1, \
-               #n2, #v2, (uint_t)s2->n2.out.v2, \
+               #n1, #v1, (unsigned int)s1->n1.out.v1, \
+               #n2, #v2, (unsigned int)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 +202,144 @@ 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, \
+              (unsigned int)s1->n1.out.v1, \
+              (unsigned int)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;
-       large_t correct_size;
-       uint32 correct_attrib;
+       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");
+       bool skip_streams = false;
 
-       fnum = create_complex_file(cli, mem_ctx, fname);
-       if (fnum == -1) {
-               printf("ERROR: open of %s failed (%s)\n", fname, cli_errstr(cli));
-               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 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(levels[i].fname_status,
+                                  NT_STATUS_NOT_SUPPORTED)) {
+                               torture_warning(torture, "fname level %s %s",
+                                       levels[i].name,
+                                       nt_errstr(levels[i].fname_status));
+                               continue;
+                       } 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].fnum_status,
+                           NT_STATUS_NOT_SUPPORTED)) {
+                               torture_warning(torture, "fnum level %s %s",
+                                       levels[i].name,
+                                       nt_errstr(levels[i].fnum_status));
+                               continue;
+                       }
+                       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_EQUAL(levels[i].fnum_status,
+                           NT_STATUS_NOT_SUPPORTED)) {
+                               torture_warning(torture, "fnum level %s %s",
+                                       levels[i].name,
+                                       nt_errstr(levels[i].fnum_status));
+                               continue;
+                       }
+
+                       if (!levels[i].only_handles &&
+                           NT_STATUS_EQUAL(levels[i].fname_status,
+                           NT_STATUS_NOT_SUPPORTED)) {
+                                torture_warning(torture, "fname level %s %s",
+                                       levels[i].name,
+                                       nt_errstr(levels[i].fname_status));
+                               continue;
+                       }
+
+                       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 > 32) {
-                       printf("too many level failures - giving up\n");
-                       goto done;
+               if (count > 35) {
+                       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 +355,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)
 
@@ -320,54 +431,56 @@ BOOL torture_raw_qfileinfo(int dummy)
        s1 = fnum_find(sname); \
        if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
                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; \
+                      nt_time_string(mem_ctx, s1->stype.out.tfield), \
+                      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), \
-                      nt_time_string(mem_ctx, &correct_time)); \
-               ret = False; \
+                      nt_time_string(mem_ctx, s1->stype.out.tfield), \
+                      nt_time_string(mem_ctx, correct_time)); \
+               ret = false; \
        }} while (0)
 
 #define TIME_CHECK_DOS(sname, stype, tfield) do { \
        s1 = fnum_find(sname); \
-       if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, &correct_time) != 0) { \
+       if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
                printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield,  \
-                      time_string(mem_ctx, s1->stype.out.tfield), \
-                      nt_time_string(mem_ctx, &correct_time)); \
-               ret = False; \
+                      timestring(mem_ctx, s1->stype.out.tfield), \
+                      nt_time_string(mem_ctx, correct_time)); \
+               ret = false; \
        } \
-       s1 = fname_find(sname); \
-       if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, &correct_time) != 0) { \
+       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,  \
-                      time_string(mem_ctx, s1->stype.out.tfield), \
-                      nt_time_string(mem_ctx, &correct_time)); \
-               ret = False; \
+                      timestring(mem_ctx, s1->stype.out.tfield), \
+                      nt_time_string(mem_ctx, correct_time)); \
+               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) { \
+       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,  \
-                      time_string(mem_ctx, s1->stype.out.tfield), \
-                      nt_time_string(mem_ctx, &correct_time)); \
-               ret = False; \
+                      timestring(mem_ctx, s1->stype.out.tfield), \
+                      nt_time_string(mem_ctx, correct_time)); \
+               ret = false; \
        } \
-       s1 = fname_find(sname); \
-       if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, &correct_time) != 0) { \
+       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,  \
-                      time_string(mem_ctx, s1->stype.out.tfield), \
-                      nt_time_string(mem_ctx, &correct_time)); \
-               ret = False; \
+                      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");
        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 +492,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 +504,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 +517,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 +529,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; \
+                      (unsigned int)s1->stype.out.tfield, \
+                      (unsigned int)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; \
+                      (unsigned int)s1->stype.out.tfield, \
+                      (unsigned int)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", (unsigned int)correct_size);
        
        SIZE_CHECK("GETATTR",                  getattr,                  size);
        SIZE_CHECK("GETATTRE",                 getattre,                 size);
@@ -451,7 +564,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", (unsigned int)correct_size);
        
        SIZE_CHECK("GETATTRE",                 getattre,                 alloc_size);
        SIZE_CHECK("STANDARD",                 standard,                 alloc_size);
@@ -470,50 +583,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; \
+                      (unsigned int)s1->stype.out.tfield, \
+                      (unsigned int)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; \
+                      (unsigned int)s1->stype.out.tfield, \
+                      (unsigned int)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", (unsigned int)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 +637,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, fnum);
-       fnum = cli_nt_create_full(cli, 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));
-               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 +698,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 +713,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 +734,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,20 +764,51 @@ 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); \
-       VAL_EQUAL(stype, field, stype, field); \
+       s1 = fname_find(is_ipc, sname); s2 = fnum_find(sname); \
+        if (s1 && s2) { \
+               VAL_EQUAL(stype, field, stype, field); \
+       } \
 } while (0)
 
-       NAME_PATH_CHECK("INTERNAL_INFORMATION", internal_information, device);
-       NAME_PATH_CHECK("INTERNAL_INFORMATION", internal_information, inode);
+
+       s1 = fnum_find("INTERNAL_INFORMATION");
+       if (s1) {
+               torture_comment(torture, "file_id=%.0f\n", (double)s1->internal_information.out.file_id);
+       }
+
+       NAME_PATH_CHECK("INTERNAL_INFORMATION", internal_information, file_id);
        NAME_PATH_CHECK("POSITION_INFORMATION", position_information, position);
+       if (s1 && s2) {
+               printf("fnum pos = %.0f, fname pos = %.0f\n",
+                      (double)s2->position_information.out.position,
+                      (double)s1->position_information.out.position );
+       }
        NAME_PATH_CHECK("MODE_INFORMATION", mode_information, mode);
        NAME_PATH_CHECK("ALIGNMENT_INFORMATION", alignment_information, alignment_requirement);
        NAME_PATH_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
@@ -671,31 +819,76 @@ 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); \
+                      (unsigned int)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); \
+                      (unsigned int)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, fnum);
-       cli_unlink(cli, 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);
 
-       torture_close_connection(cli);
-       talloc_destroy(mem_ctx);
+       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))) {
+               return false;
+       }
+
+       status = dcerpc_pipe_open_smb(p, cli->tree, fname);
+       torture_assert_ntstatus_ok(torture, status, "dcerpc_pipe_open_smb failed");
+
+       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;
 }