torture3: Add test for smbd crash
[samba.git] / source3 / torture / torture.c
index dcaa905ed753c2fed17ae5e98c41598b2996f705..2c10ae87e8e3e4a8735dd2bec94e8f5bd4c9538e 100644 (file)
@@ -26,7 +26,7 @@
 #include "tldap.h"
 #include "tldap_util.h"
 #include "../librpc/gen_ndr/svcctl.h"
-#include "memcache.h"
+#include "../lib/util/memcache.h"
 #include "nsswitch/winbind_client.h"
 #include "dbwrap/dbwrap.h"
 #include "dbwrap/dbwrap_open.h"
 #include "util_tdb.h"
 #include "../libcli/smb/read_smb.h"
 #include "../libcli/smb/smbXcli_base.h"
+#include "lib/util/sys_rw_data.h"
+#include "lib/util/base64.h"
 
 extern char *optarg;
 extern int optind;
 
 fstring host, workgroup, share, password, username, myname;
-static int max_protocol = PROTOCOL_NT1;
+struct cli_credentials *torture_creds;
 static const char *sockops="TCP_NODELAY";
 int torture_nprocs=1;
 static int port_to_use=0;
@@ -65,7 +67,7 @@ static fstring multishare_conn_fname;
 static bool use_multishare_conn = False;
 static bool do_encrypt;
 static const char *local_path = NULL;
-static int signing_state = SMB_SIGNING_DEFAULT;
+static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
 char *test_filename;
 
 bool torture_showall = False;
@@ -79,8 +81,8 @@ static double create_procs(bool (*fn)(int), bool *result);
 static bool force_cli_encryption(struct cli_state *c,
                        const char *sharename)
 {
-       uint16 major, minor;
-       uint32 caplow, caphigh;
+       uint16_t major, minor;
+       uint32_t caplow, caphigh;
        NTSTATUS status;
 
        if (!SERVER_HAS_UNIX_CIFS(c)) {
@@ -106,15 +108,7 @@ static bool force_cli_encryption(struct cli_state *c,
                return false;
        }
 
-       if (c->use_kerberos) {
-               status = cli_gss_smb_encryption_start(c);
-       } else {
-               status = cli_raw_ntlm_smb_encryption_start(c,
-                                               username,
-                                               password,
-                                               workgroup);
-       }
-
+       status = cli_smb1_setup_encryption(c, torture_creds);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("Encryption required and "
                        "setup failed with error %s.\n",
@@ -180,7 +174,7 @@ static bool cli_bad_session_request(int fd,
        bool ret = false;
        uint8_t message_type;
        uint8_t error;
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct tevent_req *req;
 
        frame = talloc_stackframe();
@@ -228,7 +222,7 @@ static bool cli_bad_session_request(int fd,
                goto fail;
        }
 
-       ev = event_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
@@ -337,18 +331,21 @@ static bool torture_open_connection_share(struct cli_state **c,
        int flags = 0;
        NTSTATUS status;
 
-       if (use_kerberos)
-               flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
        if (use_oplocks)
                flags |= CLI_FULL_CONNECTION_OPLOCKS;
        if (use_level_II_oplocks)
                flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
 
-       status = cli_full_connection(c, myname,
-                                    hostname, NULL, port_to_use, 
-                                    sharename, "?????", 
-                                    username, workgroup, 
-                                    password, flags, signing_state);
+       status = cli_full_connection_creds(c,
+                                          myname,
+                                          hostname,
+                                          NULL, /* dest_ss */
+                                          port_to_use,
+                                          sharename,
+                                          "?????",
+                                          torture_creds,
+                                          flags,
+                                          signing_state);
        if (!NT_STATUS_IS_OK(status)) {
                printf("failed to open share connection: //%s/%s port:%d - %s\n",
                        hostname, sharename, port_to_use, nt_errstr(status));
@@ -409,26 +406,17 @@ bool torture_init_connection(struct cli_state **pcli)
        return true;
 }
 
-bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
+bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
 {
        uint16_t old_vuid = cli_state_get_uid(cli);
-       fstring old_user_name;
-       size_t passlen = strlen(password);
        NTSTATUS status;
        bool ret;
 
-       fstrcpy(old_user_name, cli->user_name);
        cli_state_set_uid(cli, 0);
-       ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
-                                               password, passlen,
-                                               password, passlen,
-                                               workgroup));
+       status = cli_session_setup_creds(cli, torture_creds);
+       ret = NT_STATUS_IS_OK(status);
        *new_vuid = cli_state_get_uid(cli);
        cli_state_set_uid(cli, old_vuid);
-       status = cli_set_username(cli, old_user_name);
-       if (!NT_STATUS_IS_OK(status)) {
-               return false;
-       }
        return ret;
 }
 
@@ -452,11 +440,11 @@ bool torture_close_connection(struct cli_state *c)
 
 /* check if the server produced the expected dos or nt error code */
 static bool check_both_error(int line, NTSTATUS status,
-                            uint8 eclass, uint32 ecode, NTSTATUS nterr)
+                            uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
 {
        if (NT_STATUS_IS_DOS(status)) {
-               uint8 cclass;
-               uint32 num;
+               uint8_t cclass;
+               uint32_t num;
 
                /* Check DOS error */
                cclass = NT_STATUS_DOS_CLASS(status);
@@ -486,11 +474,11 @@ static bool check_both_error(int line, NTSTATUS status,
 
 /* check if the server produced the expected error code */
 static bool check_error(int line, NTSTATUS status,
-                       uint8 eclass, uint32 ecode, NTSTATUS nterr)
+                       uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
 {
        if (NT_STATUS_IS_DOS(status)) {
-                uint8 cclass;
-                uint32 num;
+                uint8_t cclass;
+                uint32_t num;
 
                 /* Check DOS error */
 
@@ -522,7 +510,7 @@ static bool check_error(int line, NTSTATUS status,
 }
 
 
-static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
+static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
 {
        NTSTATUS status;
 
@@ -682,7 +670,7 @@ static bool rw_torture3(struct cli_state *c, char *lockfname)
        NTSTATUS status = NT_STATUS_OK;
 
        srandom(1);
-       for (i = 0; i < sizeof(buf); i += sizeof(uint32))
+       for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
        {
                SIVAL(buf, i, sys_random());
        }
@@ -711,7 +699,7 @@ static bool rw_torture3(struct cli_state *c, char *lockfname)
                {
                        status = cli_openx(c, lockfname, O_RDONLY, 
                                         DENY_NONE, &fnum);
-                       if (!NT_STATUS_IS_OK(status)) {
+                       if (NT_STATUS_IS_OK(status)) {
                                break;
                        }
                        smb_msleep(10);
@@ -1312,9 +1300,9 @@ static bool run_tcon_test(int dummy)
 {
        static struct cli_state *cli;
        const char *fname = "\\tcontest.tmp";
-       uint16 fnum1;
-       uint16 cnum1, cnum2, cnum3;
-       uint16 vuid1, vuid2;
+       uint16_t fnum1;
+       uint16_t cnum1, cnum2, cnum3;
+       uint16_t vuid1, vuid2;
        char buf[4];
        bool ret = True;
        NTSTATUS status;
@@ -1345,8 +1333,7 @@ static bool run_tcon_test(int dummy)
                return False;
        }
 
-       status = cli_tree_connect(cli, share, "?????",
-                                 password, strlen(password)+1);
+       status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
        if (!NT_STATUS_IS_OK(status)) {
                printf("%s refused 2nd tree connect (%s)\n", host,
                       nt_errstr(status));
@@ -1429,7 +1416,7 @@ static bool run_tcon_test(int dummy)
 static bool run_tcon2_test(int dummy)
 {
        static struct cli_state *cli;
-       uint16 cnum, max_xmit;
+       uint16_t cnum, max_xmit;
        char *service;
        NTSTATUS status;
 
@@ -1471,8 +1458,7 @@ static bool tcon_devtest(struct cli_state *cli,
        NTSTATUS status;
        bool ret;
 
-       status = cli_tree_connect(cli, myshare, devtype,
-                                 password, strlen(password)+1);
+       status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
 
        if (NT_STATUS_IS_OK(expected_error)) {
                if (NT_STATUS_IS_OK(status)) {
@@ -1520,11 +1506,16 @@ static bool run_tcon_devtype_test(int dummy)
        NTSTATUS status;
        bool ret = True;
 
-       status = cli_full_connection(&cli1, myname,
-                                    host, NULL, port_to_use,
-                                    NULL, NULL,
-                                    username, workgroup,
-                                    password, flags, signing_state);
+       status = cli_full_connection_creds(&cli1,
+                                          myname,
+                                          host,
+                                          NULL, /* dest_ss */
+                                          port_to_use,
+                                          NULL, /* service */
+                                          NULL, /* service_type */
+                                          torture_creds,
+                                          flags,
+                                          signing_state);
 
        if (!NT_STATUS_IS_OK(status)) {
                printf("could not open connection\n");
@@ -1746,11 +1737,11 @@ static bool run_locktest3(int dummy)
        const char *fname = "\\lockt3.lck";
        uint16_t fnum1, fnum2;
        int i;
-       uint32 offset;
+       uint32_t offset;
        bool correct = True;
        NTSTATUS status;
 
-#define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
+#define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
 
        if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
                return False;
@@ -2771,10 +2762,10 @@ static bool run_fdpasstest(int dummy)
 static bool run_fdsesstest(int dummy)
 {
        struct cli_state *cli;
-       uint16 new_vuid;
-       uint16 saved_vuid;
-       uint16 new_cnum;
-       uint16 saved_cnum;
+       uint16_t new_vuid;
+       uint16_t saved_vuid;
+       uint16_t new_cnum;
+       uint16_t saved_cnum;
        const char *fname = "\\fdsess.tst";
        const char *fname1 = "\\fdsess1.tst";
        uint16_t fnum1;
@@ -2791,7 +2782,7 @@ static bool run_fdsesstest(int dummy)
                return False;
 
        saved_cnum = cli_state_get_tid(cli);
-       if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", "", 1)))
+       if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
                return False;
        new_cnum = cli_state_get_tid(cli);
        cli_state_set_tid(cli, saved_cnum);
@@ -2985,7 +2976,7 @@ static bool run_negprot_nowait(int dummy)
 
        printf("starting negprot nowait test\n");
 
-       ev = tevent_context_init(talloc_tos());
+       ev = samba_tevent_context_init(talloc_tos());
        if (ev == NULL) {
                return false;
        }
@@ -3088,7 +3079,7 @@ static bool run_randomipc(int dummy)
 
                cli_api(cli, 
                        param, param_len, 8,  
-                       NULL, 0, BUFFER_SIZE, 
+                       NULL, 0, CLI_BUFFER_SIZE,
                        &rparam, &rprcnt,     
                        &rdata, &rdrcnt);
                if (i % 100 == 0) {
@@ -3101,6 +3092,9 @@ static bool run_randomipc(int dummy)
                correct = False;
        }
 
+       SAFE_FREE(rparam);
+       SAFE_FREE(rdata);
+
        printf("finished random ipc test\n");
 
        return correct;
@@ -3108,7 +3102,7 @@ static bool run_randomipc(int dummy)
 
 
 
-static void browse_callback(const char *sname, uint32 stype, 
+static void browse_callback(const char *sname, uint32_t stype,
                            const char *comment, void *state)
 {
        printf("\t%20.20s %08x %s\n", sname, stype, comment);
@@ -3266,8 +3260,7 @@ static bool run_trans2test(int dummy)
                printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
                correct = False;
        }
-
-       if (strcmp(pname, fname)) {
+       else if (strcmp(pname, fname)) {
                printf("qfilename gave different name? [%s] [%s]\n",
                       fname, pname);
                correct = False;
@@ -3382,7 +3375,7 @@ static bool run_trans2test(int dummy)
 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
 {
        uint8_t *buf = NULL;
-       uint32 len;
+       uint32_t len;
        NTSTATUS status;
 
        status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
@@ -3392,7 +3385,7 @@ static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
                       nt_errstr(status));
        } else {
                printf("qfileinfo: level %d, len = %u\n", level, len);
-               dump_data(0, (uint8 *)buf, len);
+               dump_data(0, (uint8_t *)buf, len);
                printf("\n");
        }
        TALLOC_FREE(buf);
@@ -3723,7 +3716,7 @@ static bool run_oplock4(int dummy)
                return false;
        }
 
-       ev = tevent_context_init(talloc_tos());
+       ev = samba_tevent_context_init(talloc_tos());
        if (ev == NULL) {
                printf("tevent_context_init failed\n");
                return false;
@@ -3853,7 +3846,7 @@ static bool run_deletetest(int dummy)
        const char *fname = "\\delete.file";
        uint16_t fnum1 = (uint16_t)-1;
        uint16_t fnum2 = (uint16_t)-1;
-       bool correct = True;
+       bool correct = false;
        NTSTATUS status;
 
        printf("starting delete test\n");
@@ -3871,24 +3864,21 @@ static bool run_deletetest(int dummy)
 
        status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
                              FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
-                             FILE_DELETE_ON_CLOSE, 0, &fnum1);
+                             FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[1] close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
        if (NT_STATUS_IS_OK(status)) {
                printf("[1] open of %s succeeded (should fail)\n", fname);
-               correct = False;
                goto fail;
        }
 
@@ -3901,24 +3891,21 @@ static bool run_deletetest(int dummy)
 
        status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_nt_delete_on_close(cli1, fnum1, true);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[2] close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -3930,7 +3917,6 @@ static bool run_deletetest(int dummy)
                        printf("[2] close failed (%s)\n", nt_errstr(status));
                }
                cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-               correct = False;
                goto fail;
        }
 
@@ -3943,10 +3929,9 @@ static bool run_deletetest(int dummy)
        status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
                              FILE_ATTRIBUTE_NORMAL,
                              FILE_SHARE_READ|FILE_SHARE_WRITE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -3956,10 +3941,9 @@ static bool run_deletetest(int dummy)
        status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
                              FILE_ATTRIBUTE_NORMAL,
                              FILE_SHARE_READ|FILE_SHARE_WRITE,
-                             FILE_OPEN, 0, 0, &fnum2);
+                             FILE_OPEN, 0, 0, &fnum2, NULL);
        if (NT_STATUS_IS_OK(status)) {
                printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
-               correct = False;
                goto fail;
        }
 
@@ -3967,31 +3951,27 @@ static bool run_deletetest(int dummy)
        status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
                             FILE_ATTRIBUTE_NORMAL,
                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                            FILE_OPEN, 0, 0, &fnum2);
+                            FILE_OPEN, 0, 0, &fnum2, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[3] open  - 3 of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_nt_delete_on_close(cli1, fnum1, true);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[3] close 1 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum2);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[3] close 2 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4005,7 +3985,6 @@ static bool run_deletetest(int dummy)
                        printf("[3] close failed (%s)\n", nt_errstr(status));
                }
                cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-               correct = False;
                goto fail;
        }
 
@@ -4019,10 +3998,9 @@ static bool run_deletetest(int dummy)
                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
                              FILE_ATTRIBUTE_NORMAL,
                              FILE_SHARE_READ|FILE_SHARE_WRITE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4030,24 +4008,21 @@ static bool run_deletetest(int dummy)
        status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
                             FILE_ATTRIBUTE_NORMAL,
                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                            FILE_OPEN, 0, 0, &fnum2);
+                            FILE_OPEN, 0, 0, &fnum2, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum2);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_nt_delete_on_close(cli1, fnum1, true);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4055,17 +4030,15 @@ static bool run_deletetest(int dummy)
        status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
                              FILE_ATTRIBUTE_NORMAL,
                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                             FILE_OPEN, 0, 0, &fnum2);
+                             FILE_OPEN, 0, 0, &fnum2, NULL);
        if (NT_STATUS_IS_OK(status)) {
                printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4078,7 +4051,6 @@ static bool run_deletetest(int dummy)
        status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4087,14 +4059,12 @@ static bool run_deletetest(int dummy)
        status = cli_nt_delete_on_close(cli1, fnum1, true);
        if (NT_STATUS_IS_OK(status)) {
                printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[5] close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4107,11 +4077,10 @@ static bool run_deletetest(int dummy)
        status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
                             FILE_ATTRIBUTE_NORMAL,
                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                            FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                            FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[6] open of %s failed (%s)\n", fname,
                       nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4120,14 +4089,12 @@ static bool run_deletetest(int dummy)
        status = cli_nt_delete_on_close(cli1, fnum1, true);
        if (NT_STATUS_IS_OK(status)) {
                printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[6] close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4140,31 +4107,27 @@ static bool run_deletetest(int dummy)
        status = cli_ntcreate(cli1, fname, 0,
                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
                              FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
-                             0, 0, &fnum1);
+                             0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_nt_delete_on_close(cli1, fnum1, true);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[7] setting delete_on_close on file failed !\n");
-               correct = False;
                goto fail;
        }
 
        status = cli_nt_delete_on_close(cli1, fnum1, false);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[7] unsetting delete_on_close on file failed !\n");
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4172,14 +4135,12 @@ static bool run_deletetest(int dummy)
        status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4191,7 +4152,6 @@ static bool run_deletetest(int dummy)
 
        if (!torture_open_connection(&cli2, 1)) {
                printf("[8] failed to open second connection.\n");
-               correct = False;
                goto fail;
        }
 
@@ -4201,10 +4161,9 @@ static bool run_deletetest(int dummy)
                             FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
                             FILE_ATTRIBUTE_NORMAL,
                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                            FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                            FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4212,31 +4171,27 @@ static bool run_deletetest(int dummy)
                             FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
                             FILE_ATTRIBUTE_NORMAL,
                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                            FILE_OPEN, 0, 0, &fnum2);
+                            FILE_OPEN, 0, 0, &fnum2, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_nt_delete_on_close(cli1, fnum1, true);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[8] setting delete_on_close on file failed !\n");
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli2, fnum2);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4245,7 +4200,6 @@ static bool run_deletetest(int dummy)
        if (NT_STATUS_IS_OK(status)) {
                printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
                goto fail;
-               correct = False;
        }
 
        printf("eighth delete on close test succeeded.\n");
@@ -4257,10 +4211,9 @@ static bool run_deletetest(int dummy)
                              FILE_ATTRIBUTE_NORMAL,
                              FILE_SHARE_NONE,
                              FILE_OVERWRITE_IF,
-                             FILE_DELETE_ON_CLOSE, 0, &fnum1);
+                             FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
        if (NT_STATUS_IS_OK(status)) {
                printf("[9] open of %s succeeded should have failed!\n", fname);
-               correct = False;
                goto fail;
        }
 
@@ -4272,10 +4225,9 @@ static bool run_deletetest(int dummy)
                             FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
                             FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
-                            0, &fnum1);
+                            0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4283,7 +4235,6 @@ static bool run_deletetest(int dummy)
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[10] close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4292,7 +4243,6 @@ static bool run_deletetest(int dummy)
        if (NT_STATUS_IS_OK(status)) {
                printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
                goto fail;
-               correct = False;
        }
 
        printf("tenth delete on close test succeeded.\n");
@@ -4302,23 +4252,20 @@ static bool run_deletetest(int dummy)
        cli_setatr(cli1, fname, 0, 0);
        cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       /* What error do we get when attempting to open a read-only file with
-          delete access ? */
+       /* Can we open a read-only file with delete access? */
 
        /* Create a readonly file. */
        status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
                              FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
                printf("[11] close failed (%s)\n", nt_errstr(status));
-               correct = False;
                goto fail;
        }
 
@@ -4327,24 +4274,118 @@ static bool run_deletetest(int dummy)
                             FILE_READ_ATTRIBUTES|DELETE_ACCESS,
                             0,
                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                            FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                            FILE_OPEN, 0, 0, &fnum1, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
+               goto fail;
+       }
+
+       cli_close(cli1, fnum1);
+
+       printf("eleventh delete on close test succeeded.\n");
+
+       /*
+        * Test 12
+        * like test 4 but with initial delete on close
+        */
+
+       cli_setatr(cli1, fname, 0, 0);
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       status = cli_ntcreate(cli1, fname, 0,
+                             FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ|FILE_SHARE_WRITE,
+                             FILE_OVERWRITE_IF,
+                             FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               goto fail;
+       }
+
+       status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                             FILE_OPEN, 0, 0, &fnum2, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
+               goto fail;
+       }
+
+       status = cli_close(cli1, fnum2);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] close 1 failed (%s)\n", nt_errstr(status));
+               goto fail;
+       }
+
+       status = cli_nt_delete_on_close(cli1, fnum1, true);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
+               goto fail;
+       }
+
+       /* This should fail - no more opens once delete on close set. */
+       status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                             FILE_OPEN, 0, 0, &fnum2, NULL);
        if (NT_STATUS_IS_OK(status)) {
-               printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
-               cli_close(cli1, fnum1);
+               printf("[12] open 3 of %s succeeded - should fail).\n", fname);
+               goto fail;
+       }
+
+       status = cli_nt_delete_on_close(cli1, fnum1, false);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
+               goto fail;
+       }
+
+       status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                             FILE_OPEN, 0, 0, &fnum2, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
+               goto fail;
+       }
+
+       status = cli_close(cli1, fnum2);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] close 2 failed (%s)\n", nt_errstr(status));
+               goto fail;
+       }
+
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("[12] close 3 failed (%s)\n", nt_errstr(status));
+               goto fail;
+       }
+
+       /*
+        * setting delete on close on the handle does
+        * not unset the initial delete on close...
+        */
+       status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                             FILE_OPEN, 0, 0, &fnum2, NULL);
+       if (NT_STATUS_IS_OK(status)) {
+               printf("[12] open 5 of %s succeeded - should fail).\n", fname);
+               goto fail;
+       } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               printf("ntcreate returned %s, expected "
+                      "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
+                      nt_errstr(status));
                goto fail;
-               correct = False;
-       } else {
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
-                       printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(status));
-                       goto fail;
-                       correct = False;
-               } else {
-                       printf("eleventh delete on close test succeeded.\n");
-               }
        }
 
+       printf("twelfth delete on close test succeeded.\n");
+
+
        printf("finished delete test\n");
 
+       correct = true;
+
   fail:
        /* FIXME: This will crash if we aborted before cli2 got
         * intialized, because these functions don't handle
@@ -4364,6 +4405,72 @@ static bool run_deletetest(int dummy)
        return correct;
 }
 
+
+/*
+  Test wildcard delete.
+ */
+static bool run_wild_deletetest(int dummy)
+{
+       struct cli_state *cli = NULL;
+       const char *dname = "\\WTEST";
+       const char *fname = "\\WTEST\\A";
+       const char *wunlink_name = "\\WTEST\\*";
+       uint16_t fnum1 = (uint16_t)-1;
+       bool correct = false;
+       NTSTATUS status;
+
+       printf("starting wildcard delete test\n");
+
+       if (!torture_open_connection(&cli, 0)) {
+               return false;
+       }
+
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+       cli_unlink(cli, fname, 0);
+       cli_rmdir(cli, dname);
+       status = cli_mkdir(cli, dname);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
+               goto fail;
+       }
+       status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("open of %s failed %s!\n", fname, nt_errstr(status));
+               goto fail;
+       }
+       status = cli_close(cli, fnum1);
+       fnum1 = -1;
+
+       /*
+        * Note the unlink attribute-type of zero. This should
+        * map into FILE_ATTRIBUTE_NORMAL at the server even
+        * on a wildcard delete.
+        */
+
+       status = cli_unlink(cli, wunlink_name, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("unlink of %s failed %s!\n",
+                       wunlink_name, nt_errstr(status));
+               goto fail;
+       }
+
+       printf("finished wildcard delete test\n");
+
+       correct = true;
+
+  fail:
+
+       if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
+       cli_unlink(cli, fname, 0);
+       cli_rmdir(cli, dname);
+
+       if (cli && !torture_close_connection(cli)) {
+               correct = false;
+       }
+       return correct;
+}
+
 static bool run_deletetest_ln(int dummy)
 {
        struct cli_state *cli;
@@ -4410,7 +4517,7 @@ static bool run_deletetest_ln(int dummy)
        status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
                        FILE_ATTRIBUTE_NORMAL,
                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                       FILE_OPEN_IF, 0, 0, &fnum);
+                       FILE_OPEN_IF, 0, 0, &fnum, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
                return false;
@@ -4420,7 +4527,7 @@ static bool run_deletetest_ln(int dummy)
        status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
                        FILE_ATTRIBUTE_NORMAL,
                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                       FILE_OPEN_IF, 0, 0, &fnum1);
+                       FILE_OPEN_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
                return false;
@@ -4545,7 +4652,7 @@ static bool run_xcopy(int dummy)
 
        status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
                              FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("First open failed - %s\n", nt_errstr(status));
                return False;
@@ -4553,7 +4660,7 @@ static bool run_xcopy(int dummy)
 
        status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
                             FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                            FILE_OPEN, 0x200000, 0, &fnum2);
+                            FILE_OPEN, 0x200000, 0, &fnum2, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("second open failed - %s\n", nt_errstr(status));
                return False;
@@ -4590,7 +4697,7 @@ static bool run_rename(int dummy)
 
        status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("First open failed - %s\n", nt_errstr(status));
                return False;
@@ -4618,7 +4725,7 @@ static bool run_rename(int dummy)
 #else
                              FILE_SHARE_DELETE|FILE_SHARE_READ,
 #endif
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Second open failed - %s\n", nt_errstr(status));
                return False;
@@ -4643,7 +4750,7 @@ static bool run_rename(int dummy)
 
        status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Third open failed - %s\n", nt_errstr(status));
                return False;
@@ -4655,7 +4762,7 @@ static bool run_rename(int dummy)
        uint16_t fnum2;
 
        if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
-                                  FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
+                                  FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
                printf("Fourth open failed - %s\n", cli_errstr(cli1));
                return False;
        }
@@ -4693,7 +4800,7 @@ static bool run_rename(int dummy)
        status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
                              FILE_ATTRIBUTE_NORMAL,
                              FILE_SHARE_READ | FILE_SHARE_WRITE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Fourth open failed - %s\n", nt_errstr(status));
                return False;
@@ -4721,7 +4828,7 @@ static bool run_rename(int dummy)
        status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
                         FILE_ATTRIBUTE_NORMAL,
                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                        FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Fifth open failed - %s\n", nt_errstr(status));
                return False;
@@ -4740,7 +4847,8 @@ static bool run_rename(int dummy)
          */
 
         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
-                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
+                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                  FILE_OVERWRITE_IF, 0, 0, &fnum2, NULL))) {
           printf("Opening original file after rename of open file fails: %s\n",
               cli_errstr(cli1));
         }
@@ -4785,461 +4893,1037 @@ static bool run_rename(int dummy)
        return correct;
 }
 
-static bool run_pipe_number(int dummy)
-{
-       struct cli_state *cli1;
-       const char *pipe_name = "\\SPOOLSS";
-       uint16_t fnum;
-       int num_pipes = 0;
+/*
+  Test rename into a directory with an ACL denying it.
+ */
+static bool run_rename_access(int dummy)
+{
+       static struct cli_state *cli = NULL;
+       static struct cli_state *posix_cli = NULL;
+       const char *src = "test.txt";
+       const char *dname = "dir";
+       const char *dst = "dir\\test.txt";
+       const char *dsrc = "test.dir";
+       const char *ddst = "dir\\test.dir";
+       uint16_t fnum = (uint16_t)-1;
+       struct security_descriptor *sd = NULL;
+       struct security_descriptor *newsd = NULL;
        NTSTATUS status;
+       TALLOC_CTX *frame = NULL;
 
-       printf("starting pipenumber test\n");
-       if (!torture_open_connection(&cli1, 0)) {
-               return False;
-       }
+       frame = talloc_stackframe();
+       printf("starting rename access test\n");
 
-       smbXcli_conn_set_sockopt(cli1->conn, sockops);
-       while(1) {
-               status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
-                                     FILE_ATTRIBUTE_NORMAL,
-                                     FILE_SHARE_READ|FILE_SHARE_WRITE,
-                                     FILE_OPEN_IF, 0, 0, &fnum);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
-                       break;
-               }
-               num_pipes++;
-               printf("\r%6d", num_pipes);
+       /* Windows connection. */
+       if (!torture_open_connection(&cli, 0)) {
+               goto fail;
        }
 
-       printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
-       torture_close_connection(cli1);
-       return True;
-}
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
 
-/*
-  Test open mode returns on read-only files.
- */
-static bool run_opentest(int dummy)
-{
-       static struct cli_state *cli1;
-       static struct cli_state *cli2;
-       const char *fname = "\\readonly.file";
-       uint16_t fnum1, fnum2;
-       char buf[20];
-       off_t fsize;
-       bool correct = True;
-       char *tmp_path;
-       NTSTATUS status;
+       /* Posix connection. */
+       if (!torture_open_connection(&posix_cli, 0)) {
+               goto fail;
+       }
 
-       printf("starting open test\n");
+       smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
 
-       if (!torture_open_connection(&cli1, 0)) {
-               return False;
+       status = torture_setup_unix_extensions(posix_cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto fail;
        }
 
-       cli_setatr(cli1, fname, 0, 0);
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       /* Start with a clean slate. */
+       cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       cli_rmdir(cli, dsrc);
+       cli_rmdir(cli, ddst);
+       cli_rmdir(cli, dname);
 
-       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+       /*
+        * Setup the destination directory with a DENY ACE to
+        * prevent new files within it.
+        */
+       status = cli_ntcreate(cli,
+                               dname,
+                               0,
+                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
+                                       WRITE_DAC_ACCESS|FILE_READ_DATA|
+                                       WRITE_OWNER_ACCESS,
+                               FILE_ATTRIBUTE_DIRECTORY,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                               FILE_CREATE,
+                               FILE_DIRECTORY_FILE,
+                               0,
+                               &fnum,
+                               NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Create of %s - %s\n", dname, nt_errstr(status));
+               goto fail;
+       }
 
-       status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
+       status = cli_query_secdesc(cli,
+                               fnum,
+                               frame,
+                               &sd);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("cli_query_secdesc failed for %s (%s)\n",
+                       dname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_close(cli1, fnum1);
+       newsd = security_descriptor_dacl_create(frame,
+                                       0,
+                                       NULL,
+                                       NULL,
+                                       SID_WORLD,
+                                       SEC_ACE_TYPE_ACCESS_DENIED,
+                                       SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
+                                       0,
+                                       NULL);
+       if (newsd == NULL) {
+               goto fail;
+       }
+       sd->dacl = security_acl_concatenate(frame,
+                                       newsd->dacl,
+                                       sd->dacl);
+       if (sd->dacl == NULL) {
+               goto fail;
+       }
+       status = cli_set_secdesc(cli, fnum, sd);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("close2 failed (%s)\n", nt_errstr(status));
-               return False;
+               printf("cli_set_secdesc failed for %s (%s)\n",
+                       dname, nt_errstr(status));
+               goto fail;
        }
-
-       status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
+       status = cli_close(cli, fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("cli_setatr failed (%s)\n", nt_errstr(status));
-               return False;
+               printf("close failed for %s (%s)\n",
+                       dname, nt_errstr(status));
+               goto fail;
        }
-
-       status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
+       /* Now go around the back and chmod to 777 via POSIX. */
+       status = cli_posix_chmod(posix_cli, dname, 0777);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("cli_posix_chmod failed for %s (%s)\n",
+                       dname, nt_errstr(status));
+               goto fail;
        }
 
-       /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
-       status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
+       /* Check we can't create a file within dname via Windows. */
+       status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               cli_close(posix_cli, fnum);
+               printf("Create of %s should be ACCESS denied, was %s\n",
+                       dst, nt_errstr(status));
+               goto fail;
+       }
 
-        if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
-                       NT_STATUS_ACCESS_DENIED)) {
-               printf("correct error code ERRDOS/ERRnoaccess returned\n");
+       /* Make the sample file/directory. */
+       status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("open of %s failed (%s)\n", src, nt_errstr(status));
+               goto fail;
+       }
+       status = cli_close(cli, fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_close failed (%s)\n", nt_errstr(status));
+               goto fail;
        }
 
-       printf("finished open test 1\n");
+       status = cli_mkdir(cli, dsrc);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_mkdir of %s failed (%s)\n",
+                       dsrc, nt_errstr(status));
+               goto fail;
+       }
 
-       cli_close(cli1, fnum1);
+       /*
+        * OK - renames of the new file and directory into the
+        * dst directory should fail.
+        */
 
-       /* Now try not readonly and ensure ERRbadshare is returned. */
+       status = cli_rename(cli, src, dst);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("rename of %s -> %s should be ACCESS denied, was %s\n",
+                       src, dst, nt_errstr(status));
+               goto fail;
+       }
+       status = cli_rename(cli, dsrc, ddst);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("rename of %s -> %s should be ACCESS denied, was %s\n",
+                       src, dst, nt_errstr(status));
+               goto fail;
+       }
 
-       cli_setatr(cli1, fname, 0, 0);
+       TALLOC_FREE(frame);
+       return true;
 
-       status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+  fail:
+
+       if (posix_cli) {
+               torture_close_connection(posix_cli);
        }
 
-       /* This will fail - but the error should be ERRshare. */
-       status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
+       if (cli) {
+               if (fnum != (uint64_t)-1) {
+                       cli_close(cli, fnum);
+               }
+               cli_unlink(cli, src,
+                       FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+               cli_unlink(cli, dst,
+                       FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+               cli_rmdir(cli, dsrc);
+               cli_rmdir(cli, ddst);
+               cli_rmdir(cli, dname);
 
-       if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
-                       NT_STATUS_SHARING_VIOLATION)) {
-               printf("correct error code ERRDOS/ERRbadshare returned\n");
+               torture_close_connection(cli);
        }
 
-       status = cli_close(cli1, fnum1);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("close2 failed (%s)\n", nt_errstr(status));
-               return False;
-       }
+       TALLOC_FREE(frame);
+       return false;
+}
 
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+/*
+  Test owner rights ACE.
+ */
+static bool run_owner_rights(int dummy)
+{
+       static struct cli_state *cli = NULL;
+       const char *fname = "owner_rights.txt";
+       uint16_t fnum = (uint16_t)-1;
+       struct security_descriptor *sd = NULL;
+       struct security_descriptor *newsd = NULL;
+       NTSTATUS status;
+       TALLOC_CTX *frame = NULL;
 
-       printf("finished open test 2\n");
+       frame = talloc_stackframe();
+       printf("starting owner rights test\n");
 
-       /* Test truncate open disposition on file opened for read. */
-       status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+       /* Windows connection. */
+       if (!torture_open_connection(&cli, 0)) {
+               goto fail;
        }
 
-       /* write 20 bytes. */
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
 
-       memset(buf, '\0', 20);
+       /* Start with a clean slate. */
+       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
+       /* Create the test file. */
+       /* Now try and open for read and write-dac. */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               GENERIC_ALL_ACCESS,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_CREATE,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("write failed (%s)\n", nt_errstr(status));
-               correct = False;
+               printf("Create of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_close(cli1, fnum1);
+       /* Get the original SD. */
+       status = cli_query_secdesc(cli,
+                               fnum,
+                               frame,
+                               &sd);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("(3) close1 failed (%s)\n", nt_errstr(status));
-               return False;
+               printf("cli_query_secdesc failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
 
-       /* Ensure size == 20. */
-       status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("(3) getatr failed (%s)\n", nt_errstr(status));
-               return False;
-       }
+       /*
+        * Add an "owner-rights" ACE denying WRITE_DATA,
+        * and an "owner-rights" ACE allowing READ_DATA.
+        */
 
-       if (fsize != 20) {
-               printf("(3) file size != 20\n");
-               return False;
+       newsd = security_descriptor_dacl_create(frame,
+                                       0,
+                                       NULL,
+                                       NULL,
+                                       SID_OWNER_RIGHTS,
+                                       SEC_ACE_TYPE_ACCESS_DENIED,
+                                       FILE_WRITE_DATA,
+                                       0,
+                                       SID_OWNER_RIGHTS,
+                                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                                       FILE_READ_DATA,
+                                       0,
+                                       NULL);
+       if (newsd == NULL) {
+               goto fail;
        }
-
-       /* Now test if we can truncate a file opened for readonly. */
-       status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+       sd->dacl = security_acl_concatenate(frame,
+                                       newsd->dacl,
+                                       sd->dacl);
+       if (sd->dacl == NULL) {
+               goto fail;
        }
-
-       status = cli_close(cli1, fnum1);
+       status = cli_set_secdesc(cli, fnum, sd);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("close2 failed (%s)\n", nt_errstr(status));
-               return False;
+               printf("cli_set_secdesc failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
-
-       /* Ensure size == 0. */
-       status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
+       status = cli_close(cli, fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("(3) getatr failed (%s)\n", nt_errstr(status));
-               return False;
+               printf("close failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
-
-       if (fsize != 0) {
-               printf("(3) file size != 0\n");
-               return False;
+       fnum = (uint16_t)-1;
+
+       /* Try and open for FILE_WRITE_DATA */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               FILE_WRITE_DATA,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_OPEN,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("Open of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
-       printf("finished open test 3\n");
-
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       printf("Do ctemp tests\n");
-       status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
+       /* Now try and open for FILE_READ_DATA */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               FILE_READ_DATA,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_OPEN,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("ctemp failed (%s)\n", nt_errstr(status));
-               return False;
+               printf("Open of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
 
-       printf("ctemp gave path %s\n", tmp_path);
-       status = cli_close(cli1, fnum1);
+       status = cli_close(cli, fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("close of temp failed (%s)\n", nt_errstr(status));
+               printf("close failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       /* Restore clean slate. */
+       TALLOC_FREE(sd);
+       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       /* Create the test file. */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               GENERIC_ALL_ACCESS,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_CREATE,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("unlink of temp failed (%s)\n", nt_errstr(status));
+               printf("Create of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
 
-       /* Test the non-io opens... */
-
-       if (!torture_open_connection(&cli2, 1)) {
-               return False;
+       /* Get the original SD. */
+       status = cli_query_secdesc(cli,
+                               fnum,
+                               frame,
+                               &sd);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_query_secdesc failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
 
-       cli_setatr(cli2, fname, 0, 0);
-       cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-
-       smbXcli_conn_set_sockopt(cli2->conn, sockops);
+       /*
+        * Add an "owner-rights ACE denying WRITE_DATA,
+        * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
+        */
 
-       printf("TEST #1 testing 2 non-io opens (no delete)\n");
-       status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+       newsd = security_descriptor_dacl_create(frame,
+                                       0,
+                                       NULL,
+                                       NULL,
+                                       SID_OWNER_RIGHTS,
+                                       SEC_ACE_TYPE_ACCESS_DENIED,
+                                       FILE_WRITE_DATA,
+                                       0,
+                                       SID_OWNER_RIGHTS,
+                                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                                       FILE_READ_DATA|FILE_WRITE_DATA,
+                                       0,
+                                       NULL);
+       if (newsd == NULL) {
+               goto fail;
+       }
+       sd->dacl = security_acl_concatenate(frame,
+                                       newsd->dacl,
+                                       sd->dacl);
+       if (sd->dacl == NULL) {
+               goto fail;
+       }
+       status = cli_set_secdesc(cli, fnum, sd);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("cli_set_secdesc failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
-
-       status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OPEN_IF, 0, 0, &fnum2);
+       status = cli_close(cli, fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("close failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
+       }
+       fnum = (uint16_t)-1;
+
+       /* Try and open for FILE_WRITE_DATA */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               FILE_WRITE_DATA,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_OPEN,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("Open of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_close(cli1, fnum1);
+       /* Now try and open for FILE_READ_DATA */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               FILE_READ_DATA,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_OPEN,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("Open of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_close(cli2, fnum2);
+       status = cli_close(cli, fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("close failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
 
-       printf("non-io open test #1 passed.\n");
-
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       /* Restore clean slate. */
+       TALLOC_FREE(sd);
+       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       printf("TEST #2 testing 2 non-io opens (first with delete)\n");
 
-       status = cli_ntcreate(cli1, fname, 0,
-                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+       /* Create the test file. */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               GENERIC_ALL_ACCESS,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_CREATE,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("Create of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OPEN_IF, 0, 0, &fnum2);
+       /* Get the original SD. */
+       status = cli_query_secdesc(cli,
+                               fnum,
+                               frame,
+                               &sd);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("cli_query_secdesc failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_close(cli1, fnum1);
+       /*
+        * Add an "authenticated users" ACE allowing READ_DATA,
+        * add an "owner-rights" denying READ_DATA,
+        * and an "authenticated users" ACE allowing WRITE_DATA.
+        */
+
+       newsd = security_descriptor_dacl_create(frame,
+                                       0,
+                                       NULL,
+                                       NULL,
+                                       SID_NT_AUTHENTICATED_USERS,
+                                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                                       FILE_READ_DATA,
+                                       0,
+                                       SID_OWNER_RIGHTS,
+                                       SEC_ACE_TYPE_ACCESS_DENIED,
+                                       FILE_READ_DATA,
+                                       0,
+                                       SID_NT_AUTHENTICATED_USERS,
+                                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                                       FILE_WRITE_DATA,
+                                       0,
+                                       NULL);
+       if (newsd == NULL) {
+               printf("newsd == NULL\n");
+               goto fail;
+       }
+       sd->dacl = security_acl_concatenate(frame,
+                                       newsd->dacl,
+                                       sd->dacl);
+       if (sd->dacl == NULL) {
+               printf("sd->dacl == NULL\n");
+               goto fail;
+       }
+       status = cli_set_secdesc(cli, fnum, sd);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("cli_set_secdesc failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
+       }
+       status = cli_close(cli, fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("close failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
+       }
+       fnum = (uint16_t)-1;
+
+       /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               FILE_READ_DATA|FILE_WRITE_DATA,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_OPEN,
+                               0,
+                               0,
+                               &fnum,
+                               NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Open of %s - %s\n", fname, nt_errstr(status));
+               goto fail;
        }
 
-       status = cli_close(cli2, fnum2);
+       status = cli_close(cli, fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+               printf("close failed for %s (%s)\n",
+                       fname, nt_errstr(status));
+               goto fail;
        }
 
-       printf("non-io open test #2 passed.\n");
+       cli_unlink(cli, fname,
+               FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       TALLOC_FREE(frame);
+       return true;
 
-       printf("TEST #3 testing 2 non-io opens (second with delete)\n");
+  fail:
 
-       status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+       if (cli) {
+               if (fnum != (uint16_t)-1) {
+                       cli_close(cli, fnum);
+               }
+               cli_unlink(cli, fname,
+                       FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+               torture_close_connection(cli);
+       }
+
+       TALLOC_FREE(frame);
+       return false;
+}
+
+static bool run_pipe_number(int dummy)
+{
+       struct cli_state *cli1;
+       const char *pipe_name = "\\SPOOLSS";
+       uint16_t fnum;
+       int num_pipes = 0;
+       NTSTATUS status;
+
+       printf("starting pipenumber test\n");
+       if (!torture_open_connection(&cli1, 0)) {
                return False;
        }
 
-       status = cli_ntcreate(cli2, fname, 0,
-                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OPEN_IF, 0, 0, &fnum2);
+       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+       while(1) {
+               status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                     FILE_OPEN_IF, 0, 0, &fnum, NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
+                       break;
+               }
+               num_pipes++;
+               printf("\r%6d", num_pipes);
+       }
+
+       printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
+       torture_close_connection(cli1);
+       return True;
+}
+
+/*
+  Test open mode returns on read-only files.
+ */
+static bool run_opentest(int dummy)
+{
+       static struct cli_state *cli1;
+       static struct cli_state *cli2;
+       const char *fname = "\\readonly.file";
+       uint16_t fnum1, fnum2;
+       char buf[20];
+       off_t fsize;
+       bool correct = True;
+       char *tmp_path;
+       NTSTATUS status;
+
+       printf("starting open test\n");
+
+       if (!torture_open_connection(&cli1, 0)) {
+               return False;
+       }
+
+       cli_setatr(cli1, fname, 0, 0);
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+
+       status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("close2 failed (%s)\n", nt_errstr(status));
                return False;
        }
 
-       status = cli_close(cli2, fnum2);
+       status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("cli_setatr failed (%s)\n", nt_errstr(status));
                return False;
        }
 
-       printf("non-io open test #3 passed.\n");
+       status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
 
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
+       status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
 
-       printf("TEST #4 testing 2 non-io opens (both with delete)\n");
+        if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
+                       NT_STATUS_ACCESS_DENIED)) {
+               printf("correct error code ERRDOS/ERRnoaccess returned\n");
+       }
 
-       status = cli_ntcreate(cli1, fname, 0,
-                              DELETE_ACCESS|FILE_READ_ATTRIBUTES,
-                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
+       printf("finished open test 1\n");
+
+       cli_close(cli1, fnum1);
+
+       /* Now try not readonly and ensure ERRbadshare is returned. */
+
+       cli_setatr(cli1, fname, 0, 0);
+
+       status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
-       status = cli_ntcreate(cli2, fname, 0,
-                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OPEN_IF, 0, 0, &fnum2);
-       if (NT_STATUS_IS_OK(status)) {
-               printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
+       /* This will fail - but the error should be ERRshare. */
+       status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
+
+       if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
+                       NT_STATUS_SHARING_VIOLATION)) {
+               printf("correct error code ERRDOS/ERRbadshare returned\n");
+       }
+
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("close2 failed (%s)\n", nt_errstr(status));
                return False;
        }
 
-       printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       status = cli_close(cli1, fnum1);
+       printf("finished open test 2\n");
+
+       /* Test truncate open disposition on file opened for read. */
+       status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
-       printf("non-io open test #4 passed.\n");
+       /* write 20 bytes. */
 
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       memset(buf, '\0', 20);
 
-       printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
+       status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("write failed (%s)\n", nt_errstr(status));
+               correct = False;
+       }
 
-       status = cli_ntcreate(cli1, fname, 0,
-                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+       status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("(3) close1 failed (%s)\n", nt_errstr(status));
                return False;
        }
 
-       status = cli_ntcreate(cli2, fname, 0,
-                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
-                             FILE_OPEN_IF, 0, 0, &fnum2);
+       /* Ensure size == 20. */
+       status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("(3) getatr failed (%s)\n", nt_errstr(status));
                return False;
        }
 
-       status = cli_close(cli1, fnum1);
+       if (fsize != 20) {
+               printf("(3) file size != 20\n");
+               return False;
+       }
+
+       /* Now test if we can truncate a file opened for readonly. */
+       status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
-       status = cli_close(cli2, fnum2);
+       status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("close2 failed (%s)\n", nt_errstr(status));
                return False;
        }
 
-       printf("non-io open test #5 passed.\n");
+       /* Ensure size == 0. */
+       status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("(3) getatr failed (%s)\n", nt_errstr(status));
+               return False;
+       }
 
-       printf("TEST #6 testing 1 non-io open, one io open\n");
+       if (fsize != 0) {
+               printf("(3) file size != 0\n");
+               return False;
+       }
+       printf("finished open test 3\n");
 
        cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
+       printf("Do ctemp tests\n");
+       status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("ctemp failed (%s)\n", nt_errstr(status));
+               return False;
+       }
+
+       printf("ctemp gave path %s\n", tmp_path);
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("close of temp failed (%s)\n", nt_errstr(status));
+       }
+
+       status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("unlink of temp failed (%s)\n", nt_errstr(status));
+       }
+
+       /* Test the non-io opens... */
+
+       if (!torture_open_connection(&cli2, 1)) {
+               return False;
+       }
+
+       cli_setatr(cli2, fname, 0, 0);
+       cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       smbXcli_conn_set_sockopt(cli2->conn, sockops);
+
+       printf("TEST #1 testing 2 non-io opens (no delete)\n");
+       status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
        status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
-                             FILE_OPEN_IF, 0, 0, &fnum2);
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                             FILE_OPEN_IF, 0, 0, &fnum2, NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
        status = cli_close(cli2, fnum2);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
-       printf("non-io open test #6 passed.\n");
-
-       printf("TEST #7 testing 1 non-io open, one io open with delete\n");
+       printf("non-io open test #1 passed.\n");
 
        cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
+       printf("TEST #2 testing 2 non-io opens (first with delete)\n");
+
+       status = cli_ntcreate(cli1, fname, 0,
+                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
-                             FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
-       status = cli_ntcreate(cli2, fname, 0,
-                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
-                             FILE_ATTRIBUTE_NORMAL,
-                             FILE_SHARE_READ|FILE_SHARE_DELETE,
-                             FILE_OPEN_IF, 0, 0, &fnum2);
-       if (NT_STATUS_IS_OK(status)) {
-               printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
+       status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                             FILE_OPEN_IF, 0, 0, &fnum2, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
-       printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
-
        status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
                return False;
        }
 
-       printf("non-io open test #7 passed.\n");
+       status = cli_close(cli2, fnum2);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("non-io open test #2 passed.\n");
+
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       printf("TEST #3 testing 2 non-io opens (second with delete)\n");
+
+       status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_ntcreate(cli2, fname, 0,
+                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                             FILE_OPEN_IF, 0, 0, &fnum2, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_close(cli2, fnum2);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("non-io open test #3 passed.\n");
+
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       printf("TEST #4 testing 2 non-io opens (both with delete)\n");
+
+       status = cli_ntcreate(cli1, fname, 0,
+                              DELETE_ACCESS|FILE_READ_ATTRIBUTES,
+                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                              FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_ntcreate(cli2, fname, 0,
+                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                             FILE_OPEN_IF, 0, 0, &fnum2, NULL);
+       if (NT_STATUS_IS_OK(status)) {
+               printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
+
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("non-io open test #4 passed.\n");
+
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
+
+       status = cli_ntcreate(cli1, fname, 0,
+                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_ntcreate(cli2, fname, 0,
+                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
+                             FILE_OPEN_IF, 0, 0, &fnum2, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_close(cli2, fnum2);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("non-io open test #5 passed.\n");
+
+       printf("TEST #6 testing 1 non-io open, one io open\n");
+
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
+                             FILE_OPEN_IF, 0, 0, &fnum2, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_close(cli2, fnum2);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("non-io open test #6 passed.\n");
+
+       printf("TEST #7 testing 1 non-io open, one io open with delete\n");
+
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
+                             FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_ntcreate(cli2, fname, 0,
+                             DELETE_ACCESS|FILE_READ_ATTRIBUTES,
+                             FILE_ATTRIBUTE_NORMAL,
+                             FILE_SHARE_READ|FILE_SHARE_DELETE,
+                             FILE_OPEN_IF, 0, 0, &fnum2, NULL);
+       if (NT_STATUS_IS_OK(status)) {
+               printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
+
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       printf("non-io open test #7 passed.\n");
 
        cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
        printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
        status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
+                               FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
                correct = false;
@@ -5275,8 +5959,8 @@ static bool run_opentest(int dummy)
 
 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
 {
-       uint16 major, minor;
-       uint32 caplow, caphigh;
+       uint16_t major, minor;
+       uint32_t caplow, caphigh;
        NTSTATUS status;
 
        if (!SERVER_HAS_UNIX_CIFS(cli)) {
@@ -5320,6 +6004,8 @@ static bool run_simple_posix_open_test(int dummy)
        bool correct = false;
        NTSTATUS status;
        size_t nread;
+       const char *fname_windows = "windows_file";
+       uint16_t fnum2 = (uint16_t)-1;
 
        printf("Starting simple POSIX open test\n");
 
@@ -5342,6 +6028,8 @@ static bool run_simple_posix_open_test(int dummy)
        cli_posix_unlink(cli1, hname);
        cli_setatr(cli1, sname, 0, 0);
        cli_posix_unlink(cli1, sname);
+       cli_setatr(cli1, fname_windows, 0, 0);
+       cli_posix_unlink(cli1, fname_windows);
 
        /* Create a directory. */
        status = cli_posix_mkdir(cli1, dname, 0777);
@@ -5633,6 +6321,39 @@ static bool run_simple_posix_open_test(int dummy)
                goto out;
        }
 
+       /*
+        * Now create a Windows file, and attempt a POSIX unlink.
+        * This should fail with a sharing violation but due to:
+        *
+        * [Bug 9571] Unlink after open causes smbd to panic
+        *
+        * ensure we've fixed the lock ordering violation.
+        */
+
+       status = cli_ntcreate(cli1, fname_windows, 0,
+                       FILE_READ_DATA|FILE_WRITE_DATA, 0,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                       FILE_CREATE,
+                       0x0, 0x0, &fnum2, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Windows create of %s failed (%s)\n", fname_windows,
+                       nt_errstr(status));
+               goto out;
+       }
+
+       /* Now try posix_unlink. */
+       status = cli_posix_unlink(cli1, fname_windows);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+               printf("POSIX unlink of %s should fail "
+                       "with NT_STATUS_SHARING_VIOLATION "
+                       "got %s instead !\n",
+                       fname_windows,
+                       nt_errstr(status));
+               goto out;
+       }
+
+       cli_close(cli1, fnum2);
+
        printf("Simple POSIX open test passed\n");
        correct = true;
 
@@ -5643,6 +6364,11 @@ static bool run_simple_posix_open_test(int dummy)
                fnum1 = (uint16_t)-1;
        }
 
+       if (fnum2 != (uint16_t)-1) {
+               cli_close(cli1, fnum2);
+               fnum2 = (uint16_t)-1;
+       }
+
        cli_setatr(cli1, sname, 0, 0);
        cli_posix_unlink(cli1, sname);
        cli_setatr(cli1, hname, 0, 0);
@@ -5651,6 +6377,8 @@ static bool run_simple_posix_open_test(int dummy)
        cli_posix_unlink(cli1, fname);
        cli_setatr(cli1, dname, 0, 0);
        cli_posix_rmdir(cli1, dname);
+       cli_setatr(cli1, fname_windows, 0, 0);
+       cli_posix_unlink(cli1, fname_windows);
 
        if (!torture_close_connection(cli1)) {
                correct = false;
@@ -5659,1489 +6387,2609 @@ static bool run_simple_posix_open_test(int dummy)
        return correct;
 }
 
+/*
+  Test POSIX and Windows ACLs are rejected on symlinks.
+ */
+static bool run_acl_symlink_test(int dummy)
+{
+       static struct cli_state *cli;
+       const char *fname = "posix_file";
+       const char *sname = "posix_symlink";
+       uint16_t fnum = (uint16_t)-1;
+       bool correct = false;
+       NTSTATUS status;
+       char *posix_acl = NULL;
+       size_t posix_acl_len = 0;
+       char *posix_acl_sym = NULL;
+       size_t posix_acl_len_sym = 0;
+       struct security_descriptor *sd = NULL;
+       struct security_descriptor *sd_sym = NULL;
+       TALLOC_CTX *frame = NULL;
 
-static uint32 open_attrs_table[] = {
-               FILE_ATTRIBUTE_NORMAL,
-               FILE_ATTRIBUTE_ARCHIVE,
-               FILE_ATTRIBUTE_READONLY,
-               FILE_ATTRIBUTE_HIDDEN,
-               FILE_ATTRIBUTE_SYSTEM,
-
-               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
-               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
-               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
-               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
-               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
-               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
-
-               FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
-               FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
-               FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
-               FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
-};
-
-struct trunc_open_results {
-       unsigned int num;
-       uint32 init_attr;
-       uint32 trunc_attr;
-       uint32 result_attr;
-};
+       frame = talloc_stackframe();
 
-static struct trunc_open_results attr_results[] = {
-       { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
-       { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
-       { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
-       { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
-       { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
-       { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
-       { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
-       { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
-       { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
-       { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
-       { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
-       { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
-       { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
-       { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
-       { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
-       { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
-       { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
-       { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
-       { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
-       { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
-       { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
-       { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
-       { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
-       { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
-       { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
-       { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
-};
+       printf("Starting acl symlink test\n");
 
-static bool run_openattrtest(int dummy)
-{
-       static struct cli_state *cli1;
-       const char *fname = "\\openattr.file";
-       uint16_t fnum1;
-       bool correct = True;
-       uint16 attr;
-       unsigned int i, j, k, l;
-       NTSTATUS status;
+       if (!torture_open_connection(&cli, 0)) {
+               TALLOC_FREE(frame);
+               return false;
+       }
 
-       printf("starting open attr test\n");
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
 
-       if (!torture_open_connection(&cli1, 0)) {
-               return False;
+       status = torture_setup_unix_extensions(cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return false;
        }
 
-       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
+       cli_setatr(cli, sname, 0, 0);
+       cli_posix_unlink(cli, sname);
 
-       for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
-               cli_setatr(cli1, fname, 0, 0);
-               cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-
-               status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
-                                      open_attrs_table[i], FILE_SHARE_NONE,
-                                      FILE_OVERWRITE_IF, 0, 0, &fnum1);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
-                       return False;
-               }
-
-               status = cli_close(cli1, fnum1);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
-                       return False;
-               }
-
-               for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
-                       status = cli_ntcreate(cli1, fname, 0,
-                                             FILE_READ_DATA|FILE_WRITE_DATA,
-                                             open_attrs_table[j],
-                                             FILE_SHARE_NONE, FILE_OVERWRITE,
-                                             0, 0, &fnum1);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
-                                       if (attr_results[l].num == k) {
-                                               printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
-                                                               k, open_attrs_table[i],
-                                                               open_attrs_table[j],
-                                                               fname, NT_STATUS_V(status), nt_errstr(status));
-                                               correct = False;
-                                       }
-                               }
+       status = cli_ntcreate(cli,
+                       fname,
+                       0,
+                       READ_CONTROL_ACCESS,
+                       0,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                       FILE_CREATE,
+                       0x0,
+                       0x0,
+                       &fnum,
+                       NULL);
 
-                               if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
-                                       printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
-                                                       k, open_attrs_table[i], open_attrs_table[j],
-                                                       nt_errstr(status));
-                                       correct = False;
-                               }
-#if 0
-                               printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
-#endif
-                               k++;
-                               continue;
-                       }
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_ntcreate of %s failed (%s)\n",
+                       fname,
+                       nt_errstr(status));
+               goto out;
+       }
 
-                       status = cli_close(cli1, fnum1);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
-                               return False;
-                       }
+       /* Get the Windows ACL on the file. */
+       status = cli_query_secdesc(cli,
+                               fnum,
+                               frame,
+                               &sd);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_query_secdesc failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
+       }
 
-                       status = cli_getatr(cli1, fname, &attr, NULL, NULL);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               printf("getatr(2) failed (%s)\n", nt_errstr(status));
-                               return False;
-                       }
+       /* Get the POSIX ACL on the file. */
+       status = cli_posix_getacl(cli,
+                               fname,
+                               frame,
+                               &posix_acl_len,
+                               &posix_acl);
 
-#if 0
-                       printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
-                                       k,  open_attrs_table[i],  open_attrs_table[j], attr );
-#endif
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_posix_getacl failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
+       }
 
-                       for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
-                               if (attr_results[l].num == k) {
-                                       if (attr != attr_results[l].result_attr ||
-                                                       open_attrs_table[i] != attr_results[l].init_attr ||
-                                                       open_attrs_table[j] != attr_results[l].trunc_attr) {
-                                               printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
-                                               open_attrs_table[i],
-                                               open_attrs_table[j],
-                                               (unsigned int)attr,
-                                               attr_results[l].result_attr);
-                                               correct = False;
-                                       }
-                                       break;
-                               }
-                       }
-                       k++;
-               }
+       status = cli_close(cli, fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("close failed (%s)\n", nt_errstr(status));
+               goto out;
        }
+       fnum = (uint16_t)-1;
 
-       cli_setatr(cli1, fname, 0, 0);
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       /* Now create a symlink. */
+       status = cli_posix_symlink(cli, fname, sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_posix_symlink of %s -> %s failed (%s)\n",
+                       sname,
+                       fname,
+                       nt_errstr(status));
+               goto out;
+       }
 
-       printf("open attr test %s.\n", correct ? "passed" : "failed");
+       /* Open a handle on the symlink. */
+       status = cli_ntcreate(cli,
+                       sname,
+                       0,
+                       READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
+                       0,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                       FILE_OPEN,
+                       0x0,
+                       0x0,
+                       &fnum,
+                       NULL);
 
-       if (!torture_close_connection(cli1)) {
-               correct = False;
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_posix_open of %s failed (%s)\n",
+                       sname,
+                       nt_errstr(status));
+               goto out;
        }
-       return correct;
-}
 
-static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
-                   const char *name, void *state)
-{
-       int *matched = (int *)state;
-       if (matched != NULL) {
-               *matched += 1;
-       }
-       return NT_STATUS_OK;
-}
+       /* Get the Windows ACL on the symlink handle. Should fail */
+       status = cli_query_secdesc(cli,
+                               fnum,
+                               frame,
+                               &sd_sym);
 
-/*
-  test directory listing speed
- */
-static bool run_dirtest(int dummy)
-{
-       int i;
-       static struct cli_state *cli;
-       uint16_t fnum;
-       struct timeval core_start;
-       bool correct = True;
-       int matched;
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("cli_query_secdesc on a symlink gave %s. "
+                       "Should be NT_STATUS_ACCESS_DENIED.\n",
+                       nt_errstr(status));
+               goto out;
+       }
 
-       printf("starting directory test\n");
+       /* Get the POSIX ACL on the symlink pathname. Should fail. */
+       status = cli_posix_getacl(cli,
+                               sname,
+                               frame,
+                               &posix_acl_len_sym,
+                               &posix_acl_sym);
 
-       if (!torture_open_connection(&cli, 0)) {
-               return False;
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("cli_posix_getacl on a symlink gave %s. "
+                       "Should be NT_STATUS_ACCESS_DENIED.\n",
+                       nt_errstr(status));
+               goto out;
        }
 
-       smbXcli_conn_set_sockopt(cli->conn, sockops);
+       /* Set the Windows ACL on the symlink handle. Should fail */
+       status = cli_set_security_descriptor(cli,
+                               fnum,
+                               SECINFO_DACL,
+                               sd);
 
-       srandom(0);
-       for (i=0;i<torture_numops;i++) {
-               fstring fname;
-               slprintf(fname, sizeof(fname), "\\%x", (int)random());
-               if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
-                       fprintf(stderr,"Failed to open %s\n", fname);
-                       return False;
-               }
-               cli_close(cli, fnum);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("cli_query_secdesc on a symlink gave %s. "
+                       "Should be NT_STATUS_ACCESS_DENIED.\n",
+                       nt_errstr(status));
+               goto out;
        }
 
-       core_start = timeval_current();
-
-       matched = 0;
-       cli_list(cli, "a*.*", 0, list_fn, &matched);
-       printf("Matched %d\n", matched);
+       /* Set the POSIX ACL on the symlink pathname. Should fail. */
+       status = cli_posix_setacl(cli,
+                               sname,
+                               posix_acl,
+                               posix_acl_len);
 
-       matched = 0;
-       cli_list(cli, "b*.*", 0, list_fn, &matched);
-       printf("Matched %d\n", matched);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("cli_posix_getacl on a symlink gave %s. "
+                       "Should be NT_STATUS_ACCESS_DENIED.\n",
+                       nt_errstr(status));
+               goto out;
+       }
 
-       matched = 0;
-       cli_list(cli, "xyzabc", 0, list_fn, &matched);
-       printf("Matched %d\n", matched);
+       printf("ACL symlink test passed\n");
+       correct = true;
 
-       printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
+  out:
 
-       srandom(0);
-       for (i=0;i<torture_numops;i++) {
-               fstring fname;
-               slprintf(fname, sizeof(fname), "\\%x", (int)random());
-               cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       if (fnum != (uint16_t)-1) {
+               cli_close(cli, fnum);
+               fnum = (uint16_t)-1;
        }
 
+       cli_setatr(cli, sname, 0, 0);
+       cli_posix_unlink(cli, sname);
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
+
        if (!torture_close_connection(cli)) {
-               correct = False;
+               correct = false;
        }
 
-       printf("finished dirtest\n");
-
+       TALLOC_FREE(frame);
        return correct;
 }
 
-static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
-                  void *state)
-{
-       struct cli_state *pcli = (struct cli_state *)state;
-       fstring fname;
-       slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
-
-       if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
-               return NT_STATUS_OK;
-
-       if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
-               if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
-                       printf("del_fn: failed to rmdir %s\n,", fname );
-       } else {
-               if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
-                       printf("del_fn: failed to unlink %s\n,", fname );
-       }
-       return NT_STATUS_OK;
-}
-
-
 /*
-  sees what IOCTLs are supported
+  Test POSIX can delete a file containing streams.
  */
-bool torture_ioctl_test(int dummy)
+static bool run_posix_stream_delete(int dummy)
 {
-       static struct cli_state *cli;
-       uint16_t device, function;
-       uint16_t fnum;
-       const char *fname = "\\ioctl.dat";
-       DATA_BLOB blob;
+       struct cli_state *cli1 = NULL;
+       struct cli_state *cli2 = NULL;
+       const char *fname = "streamfile";
+       const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
+       uint16_t fnum1 = (uint16_t)-1;
+       bool correct = false;
        NTSTATUS status;
+       TALLOC_CTX *frame = NULL;
 
-       if (!torture_open_connection(&cli, 0)) {
-               return False;
-       }
-
-       printf("starting ioctl test\n");
+       frame = talloc_stackframe();
 
-       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       printf("Starting POSIX stream delete test\n");
 
-       status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
-               return False;
+       if (!torture_open_connection(&cli1, 0) ||
+                       !torture_open_connection(&cli2, 1)) {
+               TALLOC_FREE(frame);
+               return false;
        }
 
-       status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
-       printf("ioctl device info: %s\n", nt_errstr(status));
+       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+       smbXcli_conn_set_sockopt(cli2->conn, sockops);
 
-       status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
-       printf("ioctl job info: %s\n", nt_errstr(status));
+       status = torture_setup_unix_extensions(cli2);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
 
-       for (device=0;device<0x100;device++) {
-               printf("ioctl test with device = 0x%x\n", device);
-               for (function=0;function<0x100;function++) {
-                       uint32 code = (device<<16) | function;
+       cli_setatr(cli1, fname, 0, 0);
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-                       status = cli_raw_ioctl(cli, fnum, code, &blob);
+       /* Create the file. */
+       status = cli_ntcreate(cli1,
+                       fname,
+                       0,
+                       READ_CONTROL_ACCESS,
+                       0,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                       FILE_CREATE,
+                       0x0,
+                       0x0,
+                       &fnum1,
+                       NULL);
 
-                       if (NT_STATUS_IS_OK(status)) {
-                               printf("ioctl 0x%x OK : %d bytes\n", (int)code,
-                                      (int)blob.length);
-                               data_blob_free(&blob);
-                       }
-               }
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_ntcreate of %s failed (%s)\n",
+                       fname,
+                       nt_errstr(status));
+               goto out;
        }
 
-       if (!torture_close_connection(cli)) {
-               return False;
+       status = cli_close(cli1, fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_close of %s failed (%s)\n",
+                       fname,
+                       nt_errstr(status));
+               goto out;
        }
+       fnum1 = (uint16_t)-1;
 
-       return True;
-}
-
-
-/*
-  tries varients of chkpath
- */
-bool torture_chkpath_test(int dummy)
-{
-       static struct cli_state *cli;
-       uint16_t fnum;
-       bool ret;
-       NTSTATUS status;
-
-       if (!torture_open_connection(&cli, 0)) {
-               return False;
-       }
-
-       printf("starting chkpath test\n");
-
-       /* cleanup from an old run */
-       cli_rmdir(cli, "\\chkpath.dir\\dir2");
-       cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-       cli_rmdir(cli, "\\chkpath.dir");
+       /* Now create the stream. */
+       status = cli_ntcreate(cli1,
+                       stream_fname,
+                       0,
+                       FILE_WRITE_DATA,
+                       0,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE,
+                       FILE_CREATE,
+                       0x0,
+                       0x0,
+                       &fnum1,
+                       NULL);
 
-       status = cli_mkdir(cli, "\\chkpath.dir");
        if (!NT_STATUS_IS_OK(status)) {
-               printf("mkdir1 failed : %s\n", nt_errstr(status));
-               return False;
+               printf("cli_ntcreate of %s failed (%s)\n",
+                       stream_fname,
+                       nt_errstr(status));
+               goto out;
        }
 
-       status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("mkdir2 failed : %s\n", nt_errstr(status));
-               return False;
-       }
+       /* Leave the stream handle open... */
 
-       status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
-                         DENY_NONE, &fnum);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("open1 failed (%s)\n", nt_errstr(status));
-               return False;
+       /* POSIX unlink should fail. */
+       status = cli_posix_unlink(cli2, fname);
+       if (NT_STATUS_IS_OK(status)) {
+               printf("cli_posix_unlink of %s succeeded, should have failed\n",
+                       fname);
+               goto out;
        }
-       cli_close(cli, fnum);
 
-       status = cli_chkpath(cli, "\\chkpath.dir");
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("chkpath1 failed: %s\n", nt_errstr(status));
-               ret = False;
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+               printf("cli_posix_unlink of %s failed with (%s) "
+                       "should have been NT_STATUS_SHARING_VIOLATION\n",
+                       fname,
+                       nt_errstr(status));
+               goto out;
        }
 
-       status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
+       /* Close the stream handle. */
+       status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("chkpath2 failed: %s\n", nt_errstr(status));
-               ret = False;
+               printf("cli_close of %s failed (%s)\n",
+                       stream_fname,
+                       nt_errstr(status));
+               goto out;
        }
+       fnum1 = (uint16_t)-1;
 
-       status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
+       /* POSIX unlink after stream handle closed should succeed. */
+       status = cli_posix_unlink(cli2, fname);
        if (!NT_STATUS_IS_OK(status)) {
-               ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
-                                 NT_STATUS_NOT_A_DIRECTORY);
-       } else {
-               printf("* chkpath on a file should fail\n");
-               ret = False;
+               printf("cli_posix_unlink of %s failed (%s)\n",
+                       fname,
+                       nt_errstr(status));
+               goto out;
        }
 
-       status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
-       if (!NT_STATUS_IS_OK(status)) {
-               ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
-                                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
-       } else {
-               printf("* chkpath on a non existent file should fail\n");
-               ret = False;
-       }
+       printf("POSIX stream delete test passed\n");
+       correct = true;
 
-       status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
-       if (!NT_STATUS_IS_OK(status)) {
-               ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
-                                 NT_STATUS_OBJECT_PATH_NOT_FOUND);
-       } else {
-               printf("* chkpath on a non existent component should fail\n");
-               ret = False;
+  out:
+
+       if (fnum1 != (uint16_t)-1) {
+               cli_close(cli1, fnum1);
+               fnum1 = (uint16_t)-1;
        }
 
-       cli_rmdir(cli, "\\chkpath.dir\\dir2");
-       cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-       cli_rmdir(cli, "\\chkpath.dir");
+       cli_setatr(cli1, fname, 0, 0);
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
-       if (!torture_close_connection(cli)) {
-               return False;
+       if (!torture_close_connection(cli1)) {
+               correct = false;
+       }
+       if (!torture_close_connection(cli2)) {
+               correct = false;
        }
 
-       return ret;
+       TALLOC_FREE(frame);
+       return correct;
 }
 
-static bool run_eatest(int dummy)
+/*
+  Test setting EA's are rejected on symlinks.
+ */
+static bool run_ea_symlink_test(int dummy)
 {
        static struct cli_state *cli;
-       const char *fname = "\\eatest.txt";
-       bool correct = True;
-       uint16_t fnum;
-       int i;
-       size_t num_eas;
-       struct ea_struct *ea_list = NULL;
-       TALLOC_CTX *mem_ctx = talloc_init("eatest");
+       const char *fname = "posix_file_ea";
+       const char *sname = "posix_symlink_ea";
+       const char *ea_name = "testea_name";
+       const char *ea_value = "testea_value";
+       uint16_t fnum = (uint16_t)-1;
+       bool correct = false;
        NTSTATUS status;
+       size_t i, num_eas;
+       struct ea_struct *eas = NULL;
+       TALLOC_CTX *frame = NULL;
 
-       printf("starting eatest\n");
+       frame = talloc_stackframe();
+
+       printf("Starting EA symlink test\n");
 
        if (!torture_open_connection(&cli, 0)) {
-               talloc_destroy(mem_ctx);
-               return False;
+               TALLOC_FREE(frame);
+               return false;
        }
 
-       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
 
-       status = cli_ntcreate(cli, fname, 0,
-                              FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
-                              FILE_SHARE_NONE, FILE_OVERWRITE_IF,
-                              0x4044, 0, &fnum);
+       status = torture_setup_unix_extensions(cli);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("open failed - %s\n", nt_errstr(status));
-               talloc_destroy(mem_ctx);
-               return False;
+               TALLOC_FREE(frame);
+               return false;
        }
 
-       for (i = 0; i < 10; i++) {
-               fstring ea_name, ea_val;
-
-               slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
-               memset(ea_val, (char)i+1, i+1);
-               status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("ea_set of name %s failed - %s\n", ea_name,
-                              nt_errstr(status));
-                       talloc_destroy(mem_ctx);
-                       return False;
-               }
-       }
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
+       cli_setatr(cli, sname, 0, 0);
+       cli_posix_unlink(cli, sname);
 
-       cli_close(cli, fnum);
-       for (i = 0; i < 10; i++) {
-               fstring ea_name, ea_val;
+       status = cli_ntcreate(cli,
+                       fname,
+                       0,
+                       READ_CONTROL_ACCESS,
+                       0,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                       FILE_CREATE,
+                       0x0,
+                       0x0,
+                       &fnum,
+                       NULL);
 
-               slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
-               memset(ea_val, (char)i+1, i+1);
-               status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("ea_set of name %s failed - %s\n", ea_name,
-                              nt_errstr(status));
-                       talloc_destroy(mem_ctx);
-                       return False;
-               }
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_ntcreate of %s failed (%s)\n",
+                       fname,
+                       nt_errstr(status));
+               goto out;
        }
 
-       status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
+       status = cli_close(cli, fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("ea_get list failed - %s\n", nt_errstr(status));
-               correct = False;
+               printf("close failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
        }
+       fnum = (uint16_t)-1;
 
-       printf("num_eas = %d\n", (int)num_eas);
+       /* Set an EA on the path. */
+       status = cli_set_ea_path(cli,
+                               fname,
+                               ea_name,
+                               ea_value,
+                               strlen(ea_value)+1);
 
-       if (num_eas != 20) {
-               printf("Should be 20 EA's stored... failing.\n");
-               correct = False;
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_set_ea_path failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
        }
 
-       for (i = 0; i < num_eas; i++) {
-               printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
-               dump_data(0, ea_list[i].value.data,
-                         ea_list[i].value.length);
+       /* Now create a symlink. */
+       status = cli_posix_symlink(cli, fname, sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_posix_symlink of %s -> %s failed (%s)\n",
+                       sname,
+                       fname,
+                       nt_errstr(status));
+               goto out;
        }
 
-       /* Setting EA's to zero length deletes them. Test this */
-       printf("Now deleting all EA's - case indepenent....\n");
+       /* Get the EA list on the path. Should return value set. */
+       status = cli_get_ea_list_path(cli,
+                               fname,
+                               frame,
+                               &num_eas,
+                               &eas);
 
-#if 1
-       cli_set_ea_path(cli, fname, "", "", 0);
-#else
-       for (i = 0; i < 20; i++) {
-               fstring ea_name;
-               slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
-               status = cli_set_ea_path(cli, fname, ea_name, "", 0);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("ea_set of name %s failed - %s\n", ea_name,
-                              nt_errstr(status));
-                       talloc_destroy(mem_ctx);
-                       return False;
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_get_ea_list_path failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
+       }
+
+       /* Ensure the EA we set is there. */
+       for (i=0; i<num_eas; i++) {
+               if (strcmp(eas[i].name, ea_name) == 0 &&
+                               eas[i].value.length == strlen(ea_value)+1 &&
+                               memcmp(eas[i].value.data,
+                                       ea_value,
+                                       eas[i].value.length) == 0) {
+                       break;
                }
        }
-#endif
 
-       status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("ea_get list failed - %s\n", nt_errstr(status));
-               correct = False;
+       if (i == num_eas) {
+               printf("Didn't find EA on pathname %s\n",
+                       fname);
+               goto out;
        }
 
-       printf("num_eas = %d\n", (int)num_eas);
-       for (i = 0; i < num_eas; i++) {
-               printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
-               dump_data(0, ea_list[i].value.data,
-                         ea_list[i].value.length);
+       num_eas = 0;
+       TALLOC_FREE(eas);
+
+       /* Get the EA list on the symlink. Should return empty list. */
+       status = cli_get_ea_list_path(cli,
+                               sname,
+                               frame,
+                               &num_eas,
+                               &eas);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_get_ea_list_path failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
        }
 
        if (num_eas != 0) {
-               printf("deleting EA's failed.\n");
-               correct = False;
+               printf("cli_get_ea_list_path failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
        }
 
-       /* Try and delete a non existent EA. */
-       status = cli_set_ea_path(cli, fname, "foo", "", 0);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("deleting non-existent EA 'foo' should succeed. %s\n",
-                      nt_errstr(status));
-               correct = False;
+       /* Set an EA on the symlink. Should fail. */
+       status = cli_set_ea_path(cli,
+                               sname,
+                               ea_name,
+                               ea_value,
+                               strlen(ea_value)+1);
+
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               printf("cli_set_ea_path on a symlink gave %s. "
+                       "Should be NT_STATUS_ACCESS_DENIED.\n",
+                       nt_errstr(status));
+               goto out;
        }
 
-       talloc_destroy(mem_ctx);
+       printf("EA symlink test passed\n");
+       correct = true;
+
+  out:
+
+       if (fnum != (uint16_t)-1) {
+               cli_close(cli, fnum);
+               fnum = (uint16_t)-1;
+       }
+
+       cli_setatr(cli, sname, 0, 0);
+       cli_posix_unlink(cli, sname);
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
+
        if (!torture_close_connection(cli)) {
-               correct = False;
+               correct = false;
        }
 
+       TALLOC_FREE(frame);
        return correct;
 }
 
-static bool run_dirtest1(int dummy)
+/*
+  Test POSIX locks are OFD-locks.
+ */
+static bool run_posix_ofd_lock_test(int dummy)
 {
-       int i;
        static struct cli_state *cli;
-       uint16_t fnum;
-       int num_seen;
-       bool correct = True;
+       const char *fname = "posix_file";
+       uint16_t fnum1 = (uint16_t)-1;
+       uint16_t fnum2 = (uint16_t)-1;
+       bool correct = false;
+       NTSTATUS status;
+       TALLOC_CTX *frame = NULL;
 
-       printf("starting directory test\n");
+       frame = talloc_stackframe();
+
+       printf("Starting POSIX ofd-lock test\n");
 
        if (!torture_open_connection(&cli, 0)) {
-               return False;
+               TALLOC_FREE(frame);
+               return false;
        }
 
        smbXcli_conn_set_sockopt(cli->conn, sockops);
 
-       cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
-       cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
-       cli_rmdir(cli, "\\LISTDIR");
-       cli_mkdir(cli, "\\LISTDIR");
-
-       /* Create 1000 files and 1000 directories. */
-       for (i=0;i<1000;i++) {
-               fstring fname;
-               slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
-               if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
-                                  FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
-                       fprintf(stderr,"Failed to open %s\n", fname);
-                       return False;
-               }
-               cli_close(cli, fnum);
-       }
-       for (i=0;i<1000;i++) {
-               fstring fname;
-               slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
-               if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
-                       fprintf(stderr,"Failed to open %s\n", fname);
-                       return False;
-               }
-       }
-
-       /* Now ensure that doing an old list sees both files and directories. */
-       num_seen = 0;
-       cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
-       printf("num_seen = %d\n", num_seen );
-       /* We should see 100 files + 1000 directories + . and .. */
-       if (num_seen != 2002)
-               correct = False;
-
-       /* Ensure if we have the "must have" bits we only see the
-        * relevent entries.
-        */
-       num_seen = 0;
-       cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
-       printf("num_seen = %d\n", num_seen );
-       if (num_seen != 1002)
-               correct = False;
-
-       num_seen = 0;
-       cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
-       printf("num_seen = %d\n", num_seen );
-       if (num_seen != 1000)
-               correct = False;
-
-       /* Delete everything. */
-       cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
-       cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
-       cli_rmdir(cli, "\\LISTDIR");
-
-#if 0
-       printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
-       printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
-       printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
-#endif
-
-       if (!torture_close_connection(cli)) {
-               correct = False;
-       }
-
-       printf("finished dirtest1\n");
-
-       return correct;
-}
-
-static bool run_error_map_extract(int dummy) {
-
-       static struct cli_state *c_dos;
-       static struct cli_state *c_nt;
-       NTSTATUS status;
-
-       uint32 error;
-
-       uint32 errnum;
-        uint8 errclass;
-
-       NTSTATUS nt_status;
-
-       fstring user;
-
-       /* NT-Error connection */
-
-       disable_spnego = true;
-       if (!(c_nt = open_nbt_connection())) {
-               disable_spnego = false;
-               return False;
+       status = torture_setup_unix_extensions(cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return false;
        }
-       disable_spnego = false;
 
-       status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
-                                PROTOCOL_NT1);
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
 
+       /* Open the file twice. */
+       status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
+                               0600, &fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("%s rejected the NT-error negprot (%s)\n", host,
-                      nt_errstr(status));
-               cli_shutdown(c_nt);
-               return False;
+               printf("First POSIX open of %s failed\n", fname);
+               goto out;
        }
 
-       status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
+       status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
-               return False;
+               printf("First POSIX open of %s failed\n", fname);
+               goto out;
        }
 
-       /* DOS-Error connection */
-
-       disable_spnego = true;
-       force_dos_errors = true;
-       if (!(c_dos = open_nbt_connection())) {
-               disable_spnego = false;
-               force_dos_errors = false;
-               return False;
+       /* Set a 0-50 lock on fnum1. */
+       status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("POSIX lock (1) failed %s\n", nt_errstr(status));
+               goto out;
        }
-       disable_spnego = false;
-       force_dos_errors = false;
 
-       status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
-                                PROTOCOL_NT1);
+       /* Set a 60-100 lock on fnum2. */
+       status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("%s rejected the DOS-error negprot (%s)\n", host,
-                      nt_errstr(status));
-               cli_shutdown(c_dos);
-               return False;
+               printf("POSIX lock (2) failed %s\n", nt_errstr(status));
+               goto out;
        }
 
-       status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
+       /* close fnum1 - 0-50 lock should go away. */
+       status = cli_close(cli, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("%s rejected the DOS-error initial session setup (%s)\n",
-                       host, nt_errstr(status));
-               return False;
+               printf("close failed (%s)\n",
+                       nt_errstr(status));
+               goto out;
        }
+       fnum1 = (uint16_t)-1;
 
-       c_nt->map_dos_errors = false;
-       c_dos->map_dos_errors = false;
-
-       for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
-               fstr_sprintf(user, "%X", error);
-
-               status = cli_session_setup(c_nt, user,
-                                          password, strlen(password),
-                                          password, strlen(password),
-                                          workgroup);
-               if (NT_STATUS_IS_OK(status)) {
-                       printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
-               }
-
-               /* Case #1: 32-bit NT errors */
-               if (!NT_STATUS_IS_DOS(status)) {
-                       nt_status = status;
-               } else {
-                       printf("/** Dos error on NT connection! (%s) */\n", 
-                              nt_errstr(status));
-                       nt_status = NT_STATUS(0xc0000000);
-               }
-
-               status = cli_session_setup(c_dos, user,
-                                          password, strlen(password),
-                                          password, strlen(password),
-                                          workgroup);
-               if (NT_STATUS_IS_OK(status)) {
-                       printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
-               }
-
-               /* Case #1: 32-bit NT errors */
-               if (NT_STATUS_IS_DOS(status)) {
-                       printf("/** NT error on DOS connection! (%s) */\n", 
-                              nt_errstr(status));
-                       errnum = errclass = 0;
-               } else {
-                       errclass = NT_STATUS_DOS_CLASS(status);
-                       errnum = NT_STATUS_DOS_CODE(status);
-               }
-
-               if (NT_STATUS_V(nt_status) != error) { 
-                       printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
-                              get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
-                              get_nt_error_c_code(talloc_tos(), nt_status));
-               }
+       /* Change the lock context. */
+       cli_setpid(cli, cli_getpid(cli) + 1);
 
-               printf("\t{%s,\t%s,\t%s},\n", 
-                      smb_dos_err_class(errclass), 
-                      smb_dos_err_name(errclass, errnum), 
-                      get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
+       /* Re-open fnum1. */
+       status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Third POSIX open of %s failed\n", fname);
+               goto out;
        }
-       return True;
-}
-
-static bool run_sesssetup_bench(int dummy)
-{
-       static struct cli_state *c;
-       const char *fname = "\\file.dat";
-       uint16_t fnum;
-       NTSTATUS status;
-       int i;
 
-       if (!torture_open_connection(&c, 0)) {
-               return false;
+       /* 60-100 lock should still be there. */
+       status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
+               printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
+               goto out;
        }
 
-       status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
-                             FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
-                             FILE_DELETE_ON_CLOSE, 0, &fnum);
+       /* 0-50 lock should be gone. */
+       status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
        if (!NT_STATUS_IS_OK(status)) {
-               d_printf("open %s failed: %s\n", fname, nt_errstr(status));
-               return false;
+               printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
+               goto out;
        }
 
-       for (i=0; i<torture_numops; i++) {
-               status = cli_session_setup(
-                       c, username,
-                       password, strlen(password),
-                       password, strlen(password),
-                       workgroup);
-               if (!NT_STATUS_IS_OK(status)) {
-                       d_printf("(%s) cli_session_setup failed: %s\n",
-                                __location__, nt_errstr(status));
-                       return false;
-               }
+       printf("POSIX OFD lock test passed\n");
+       correct = true;
 
-               d_printf("\r%d   ", (int)cli_state_get_uid(c));
+  out:
 
-               status = cli_ulogoff(c);
-               if (!NT_STATUS_IS_OK(status)) {
-                       d_printf("(%s) cli_ulogoff failed: %s\n",
-                                __location__, nt_errstr(status));
-                       return false;
-               }
+       if (fnum1 != (uint16_t)-1) {
+               cli_close(cli, fnum1);
+               fnum1 = (uint16_t)-1;
+       }
+       if (fnum2 != (uint16_t)-1) {
+               cli_close(cli, fnum2);
+               fnum2 = (uint16_t)-1;
        }
 
-       return true;
-}
-
-static bool subst_test(const char *str, const char *user, const char *domain,
-                      uid_t uid, gid_t gid, const char *expected)
-{
-       char *subst;
-       bool result = true;
-
-       subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
 
-       if (strcmp(subst, expected) != 0) {
-               printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
-                      "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
-                      expected);
-               result = false;
+       if (!torture_close_connection(cli)) {
+               correct = false;
        }
 
-       TALLOC_FREE(subst);
-       return result;
+       TALLOC_FREE(frame);
+       return correct;
 }
 
-static void chain1_open_completion(struct tevent_req *req)
-{
-       uint16_t fnum;
-       NTSTATUS status;
-       status = cli_openx_recv(req, &fnum);
-       TALLOC_FREE(req);
-
-       d_printf("cli_openx_recv returned %s: %d\n",
-                nt_errstr(status),
-                NT_STATUS_IS_OK(status) ? fnum : -1);
-}
+static uint32_t open_attrs_table[] = {
+               FILE_ATTRIBUTE_NORMAL,
+               FILE_ATTRIBUTE_ARCHIVE,
+               FILE_ATTRIBUTE_READONLY,
+               FILE_ATTRIBUTE_HIDDEN,
+               FILE_ATTRIBUTE_SYSTEM,
 
-static void chain1_write_completion(struct tevent_req *req)
-{
-       size_t written;
-       NTSTATUS status;
-       status = cli_write_andx_recv(req, &written);
-       TALLOC_FREE(req);
+               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
+               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
+               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
+               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
+               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
+               FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
 
-       d_printf("cli_write_andx_recv returned %s: %d\n",
-                nt_errstr(status),
+               FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
+               FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
+               FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
+               FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
+};
+
+struct trunc_open_results {
+       unsigned int num;
+       uint32_t init_attr;
+       uint32_t trunc_attr;
+       uint32_t result_attr;
+};
+
+static struct trunc_open_results attr_results[] = {
+       { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
+       { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
+       { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
+       { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
+       { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
+       { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
+       { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
+       { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
+       { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
+       { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
+       { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
+       { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
+       { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
+       { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
+       { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
+       { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
+       { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
+       { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
+       { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
+       { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
+       { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
+       { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
+       { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
+       { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
+       { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
+       { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
+};
+
+static bool run_openattrtest(int dummy)
+{
+       static struct cli_state *cli1;
+       const char *fname = "\\openattr.file";
+       uint16_t fnum1;
+       bool correct = True;
+       uint16_t attr;
+       unsigned int i, j, k, l;
+       NTSTATUS status;
+
+       printf("starting open attr test\n");
+
+       if (!torture_open_connection(&cli1, 0)) {
+               return False;
+       }
+
+       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+
+       for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
+               cli_setatr(cli1, fname, 0, 0);
+               cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+               status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
+                                      open_attrs_table[i], FILE_SHARE_NONE,
+                                      FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
+                       return False;
+               }
+
+               status = cli_close(cli1, fnum1);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
+                       return False;
+               }
+
+               for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
+                       status = cli_ntcreate(cli1, fname, 0,
+                                             FILE_READ_DATA|FILE_WRITE_DATA,
+                                             open_attrs_table[j],
+                                             FILE_SHARE_NONE, FILE_OVERWRITE,
+                                             0, 0, &fnum1, NULL);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
+                                       if (attr_results[l].num == k) {
+                                               printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
+                                                               k, open_attrs_table[i],
+                                                               open_attrs_table[j],
+                                                               fname, NT_STATUS_V(status), nt_errstr(status));
+                                               correct = False;
+                                       }
+                               }
+
+                               if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+                                       printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
+                                                       k, open_attrs_table[i], open_attrs_table[j],
+                                                       nt_errstr(status));
+                                       correct = False;
+                               }
+#if 0
+                               printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
+#endif
+                               k++;
+                               continue;
+                       }
+
+                       status = cli_close(cli1, fnum1);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
+                               return False;
+                       }
+
+                       status = cli_getatr(cli1, fname, &attr, NULL, NULL);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               printf("getatr(2) failed (%s)\n", nt_errstr(status));
+                               return False;
+                       }
+
+#if 0
+                       printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
+                                       k,  open_attrs_table[i],  open_attrs_table[j], attr );
+#endif
+
+                       for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
+                               if (attr_results[l].num == k) {
+                                       if (attr != attr_results[l].result_attr ||
+                                                       open_attrs_table[i] != attr_results[l].init_attr ||
+                                                       open_attrs_table[j] != attr_results[l].trunc_attr) {
+                                               printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
+                                               open_attrs_table[i],
+                                               open_attrs_table[j],
+                                               (unsigned int)attr,
+                                               attr_results[l].result_attr);
+                                               correct = False;
+                                       }
+                                       break;
+                               }
+                       }
+                       k++;
+               }
+       }
+
+       cli_setatr(cli1, fname, 0, 0);
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       printf("open attr test %s.\n", correct ? "passed" : "failed");
+
+       if (!torture_close_connection(cli1)) {
+               correct = False;
+       }
+       return correct;
+}
+
+static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
+                   const char *name, void *state)
+{
+       int *matched = (int *)state;
+       if (matched != NULL) {
+               *matched += 1;
+       }
+       return NT_STATUS_OK;
+}
+
+/*
+  test directory listing speed
+ */
+static bool run_dirtest(int dummy)
+{
+       int i;
+       static struct cli_state *cli;
+       uint16_t fnum;
+       struct timeval core_start;
+       bool correct = True;
+       int matched;
+
+       printf("starting directory test\n");
+
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
+
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+       srandom(0);
+       for (i=0;i<torture_numops;i++) {
+               fstring fname;
+               slprintf(fname, sizeof(fname), "\\%x", (int)random());
+               if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
+                       fprintf(stderr,"Failed to open %s\n", fname);
+                       return False;
+               }
+               cli_close(cli, fnum);
+       }
+
+       core_start = timeval_current();
+
+       matched = 0;
+       cli_list(cli, "a*.*", 0, list_fn, &matched);
+       printf("Matched %d\n", matched);
+
+       matched = 0;
+       cli_list(cli, "b*.*", 0, list_fn, &matched);
+       printf("Matched %d\n", matched);
+
+       matched = 0;
+       cli_list(cli, "xyzabc", 0, list_fn, &matched);
+       printf("Matched %d\n", matched);
+
+       printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
+
+       srandom(0);
+       for (i=0;i<torture_numops;i++) {
+               fstring fname;
+               slprintf(fname, sizeof(fname), "\\%x", (int)random());
+               cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       }
+
+       if (!torture_close_connection(cli)) {
+               correct = False;
+       }
+
+       printf("finished dirtest\n");
+
+       return correct;
+}
+
+static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
+                  void *state)
+{
+       struct cli_state *pcli = (struct cli_state *)state;
+       fstring fname;
+       slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
+
+       if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
+               return NT_STATUS_OK;
+
+       if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
+               if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
+                       printf("del_fn: failed to rmdir %s\n,", fname );
+       } else {
+               if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
+                       printf("del_fn: failed to unlink %s\n,", fname );
+       }
+       return NT_STATUS_OK;
+}
+
+
+/*
+  sees what IOCTLs are supported
+ */
+bool torture_ioctl_test(int dummy)
+{
+       static struct cli_state *cli;
+       uint16_t device, function;
+       uint16_t fnum;
+       const char *fname = "\\ioctl.dat";
+       DATA_BLOB blob;
+       NTSTATUS status;
+
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
+
+       printf("starting ioctl test\n");
+
+       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("open of %s failed (%s)\n", fname, nt_errstr(status));
+               return False;
+       }
+
+       status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
+       printf("ioctl device info: %s\n", nt_errstr(status));
+
+       status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
+       printf("ioctl job info: %s\n", nt_errstr(status));
+
+       for (device=0;device<0x100;device++) {
+               printf("ioctl test with device = 0x%x\n", device);
+               for (function=0;function<0x100;function++) {
+                       uint32_t code = (device<<16) | function;
+
+                       status = cli_raw_ioctl(cli, fnum, code, &blob);
+
+                       if (NT_STATUS_IS_OK(status)) {
+                               printf("ioctl 0x%x OK : %d bytes\n", (int)code,
+                                      (int)blob.length);
+                               data_blob_free(&blob);
+                       }
+               }
+       }
+
+       if (!torture_close_connection(cli)) {
+               return False;
+       }
+
+       return True;
+}
+
+
+/*
+  tries varients of chkpath
+ */
+bool torture_chkpath_test(int dummy)
+{
+       static struct cli_state *cli;
+       uint16_t fnum;
+       bool ret;
+       NTSTATUS status;
+
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
+
+       printf("starting chkpath test\n");
+
+       /* cleanup from an old run */
+       cli_rmdir(cli, "\\chkpath.dir\\dir2");
+       cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       cli_rmdir(cli, "\\chkpath.dir");
+
+       status = cli_mkdir(cli, "\\chkpath.dir");
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("mkdir1 failed : %s\n", nt_errstr(status));
+               return False;
+       }
+
+       status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("mkdir2 failed : %s\n", nt_errstr(status));
+               return False;
+       }
+
+       status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
+                         DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("open1 failed (%s)\n", nt_errstr(status));
+               return False;
+       }
+       cli_close(cli, fnum);
+
+       status = cli_chkpath(cli, "\\chkpath.dir");
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("chkpath1 failed: %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("chkpath2 failed: %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
+                                 NT_STATUS_NOT_A_DIRECTORY);
+       } else {
+               printf("* chkpath on a file should fail\n");
+               ret = False;
+       }
+
+       status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
+                                 NT_STATUS_OBJECT_NAME_NOT_FOUND);
+       } else {
+               printf("* chkpath on a non existent file should fail\n");
+               ret = False;
+       }
+
+       status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
+                                 NT_STATUS_OBJECT_PATH_NOT_FOUND);
+       } else {
+               printf("* chkpath on a non existent component should fail\n");
+               ret = False;
+       }
+
+       cli_rmdir(cli, "\\chkpath.dir\\dir2");
+       cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       cli_rmdir(cli, "\\chkpath.dir");
+
+       if (!torture_close_connection(cli)) {
+               return False;
+       }
+
+       return ret;
+}
+
+static bool run_eatest(int dummy)
+{
+       static struct cli_state *cli;
+       const char *fname = "\\eatest.txt";
+       bool correct = True;
+       uint16_t fnum;
+       int i;
+       size_t num_eas;
+       struct ea_struct *ea_list = NULL;
+       TALLOC_CTX *mem_ctx = talloc_init("eatest");
+       NTSTATUS status;
+
+       printf("starting eatest\n");
+
+       if (!torture_open_connection(&cli, 0)) {
+               talloc_destroy(mem_ctx);
+               return False;
+       }
+
+       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       status = cli_ntcreate(cli, fname, 0,
+                              FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
+                              FILE_SHARE_NONE, FILE_OVERWRITE_IF,
+                              0x4044, 0, &fnum, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("open failed - %s\n", nt_errstr(status));
+               talloc_destroy(mem_ctx);
+               return False;
+       }
+
+       for (i = 0; i < 10; i++) {
+               fstring ea_name, ea_val;
+
+               slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
+               memset(ea_val, (char)i+1, i+1);
+               status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("ea_set of name %s failed - %s\n", ea_name,
+                              nt_errstr(status));
+                       talloc_destroy(mem_ctx);
+                       return False;
+               }
+       }
+
+       cli_close(cli, fnum);
+       for (i = 0; i < 10; i++) {
+               fstring ea_name, ea_val;
+
+               slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
+               memset(ea_val, (char)i+1, i+1);
+               status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("ea_set of name %s failed - %s\n", ea_name,
+                              nt_errstr(status));
+                       talloc_destroy(mem_ctx);
+                       return False;
+               }
+       }
+
+       status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("ea_get list failed - %s\n", nt_errstr(status));
+               correct = False;
+       }
+
+       printf("num_eas = %d\n", (int)num_eas);
+
+       if (num_eas != 20) {
+               printf("Should be 20 EA's stored... failing.\n");
+               correct = False;
+       }
+
+       for (i = 0; i < num_eas; i++) {
+               printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
+               dump_data(0, ea_list[i].value.data,
+                         ea_list[i].value.length);
+       }
+
+       /* Setting EA's to zero length deletes them. Test this */
+       printf("Now deleting all EA's - case indepenent....\n");
+
+#if 1
+       cli_set_ea_path(cli, fname, "", "", 0);
+#else
+       for (i = 0; i < 20; i++) {
+               fstring ea_name;
+               slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
+               status = cli_set_ea_path(cli, fname, ea_name, "", 0);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("ea_set of name %s failed - %s\n", ea_name,
+                              nt_errstr(status));
+                       talloc_destroy(mem_ctx);
+                       return False;
+               }
+       }
+#endif
+
+       status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("ea_get list failed - %s\n", nt_errstr(status));
+               correct = False;
+       }
+
+       printf("num_eas = %d\n", (int)num_eas);
+       for (i = 0; i < num_eas; i++) {
+               printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
+               dump_data(0, ea_list[i].value.data,
+                         ea_list[i].value.length);
+       }
+
+       if (num_eas != 0) {
+               printf("deleting EA's failed.\n");
+               correct = False;
+       }
+
+       /* Try and delete a non existent EA. */
+       status = cli_set_ea_path(cli, fname, "foo", "", 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("deleting non-existent EA 'foo' should succeed. %s\n",
+                      nt_errstr(status));
+               correct = False;
+       }
+
+       talloc_destroy(mem_ctx);
+       if (!torture_close_connection(cli)) {
+               correct = False;
+       }
+
+       return correct;
+}
+
+static bool run_dirtest1(int dummy)
+{
+       int i;
+       static struct cli_state *cli;
+       uint16_t fnum;
+       int num_seen;
+       bool correct = True;
+
+       printf("starting directory test\n");
+
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
+
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+       cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
+       cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
+       cli_rmdir(cli, "\\LISTDIR");
+       cli_mkdir(cli, "\\LISTDIR");
+
+       /* Create 1000 files and 1000 directories. */
+       for (i=0;i<1000;i++) {
+               fstring fname;
+               slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
+               if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
+                                  FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
+                                  0, 0, &fnum, NULL))) {
+                       fprintf(stderr,"Failed to open %s\n", fname);
+                       return False;
+               }
+               cli_close(cli, fnum);
+       }
+       for (i=0;i<1000;i++) {
+               fstring fname;
+               slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
+               if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
+                       fprintf(stderr,"Failed to open %s\n", fname);
+                       return False;
+               }
+       }
+
+       /* Now ensure that doing an old list sees both files and directories. */
+       num_seen = 0;
+       cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
+       printf("num_seen = %d\n", num_seen );
+       /* We should see 100 files + 1000 directories + . and .. */
+       if (num_seen != 2002)
+               correct = False;
+
+       /* Ensure if we have the "must have" bits we only see the
+        * relevent entries.
+        */
+       num_seen = 0;
+       cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
+       printf("num_seen = %d\n", num_seen );
+       if (num_seen != 1002)
+               correct = False;
+
+       num_seen = 0;
+       cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
+       printf("num_seen = %d\n", num_seen );
+       if (num_seen != 1000)
+               correct = False;
+
+       /* Delete everything. */
+       cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
+       cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
+       cli_rmdir(cli, "\\LISTDIR");
+
+#if 0
+       printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
+       printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
+       printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
+#endif
+
+       if (!torture_close_connection(cli)) {
+               correct = False;
+       }
+
+       printf("finished dirtest1\n");
+
+       return correct;
+}
+
+static bool run_error_map_extract(int dummy) {
+
+       static struct cli_state *c_dos;
+       static struct cli_state *c_nt;
+       NTSTATUS status;
+
+       uint32_t error;
+
+       uint32_t errnum;
+        uint8_t errclass;
+
+       NTSTATUS nt_status;
+
+       fstring user;
+
+       /* NT-Error connection */
+
+       disable_spnego = true;
+       if (!(c_nt = open_nbt_connection())) {
+               disable_spnego = false;
+               return False;
+       }
+       disable_spnego = false;
+
+       status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
+                                PROTOCOL_NT1);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("%s rejected the NT-error negprot (%s)\n", host,
+                      nt_errstr(status));
+               cli_shutdown(c_nt);
+               return False;
+       }
+
+       status = cli_session_setup_anon(c_nt);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
+               return False;
+       }
+
+       /* DOS-Error connection */
+
+       disable_spnego = true;
+       force_dos_errors = true;
+       if (!(c_dos = open_nbt_connection())) {
+               disable_spnego = false;
+               force_dos_errors = false;
+               return False;
+       }
+       disable_spnego = false;
+       force_dos_errors = false;
+
+       status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
+                                PROTOCOL_NT1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("%s rejected the DOS-error negprot (%s)\n", host,
+                      nt_errstr(status));
+               cli_shutdown(c_dos);
+               return False;
+       }
+
+       status = cli_session_setup_anon(c_dos);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("%s rejected the DOS-error initial session setup (%s)\n",
+                       host, nt_errstr(status));
+               return False;
+       }
+
+       c_nt->map_dos_errors = false;
+       c_dos->map_dos_errors = false;
+
+       for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
+               struct cli_credentials *user_creds = NULL;
+
+               fstr_sprintf(user, "%X", error);
+
+               user_creds = cli_session_creds_init(talloc_tos(),
+                                                   user,
+                                                   workgroup,
+                                                   NULL, /* realm */
+                                                   password,
+                                                   false, /* use_kerberos */
+                                                   false, /* fallback_after_kerberos */
+                                                   false, /* use_ccache */
+                                                   false); /* password_is_nt_hash */
+               if (user_creds == NULL) {
+                       printf("cli_session_creds_init(%s) failed\n", user);
+                       return false;
+               }
+
+               status = cli_session_setup_creds(c_nt, user_creds);
+               if (NT_STATUS_IS_OK(status)) {
+                       printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
+               }
+
+               /* Case #1: 32-bit NT errors */
+               if (!NT_STATUS_IS_DOS(status)) {
+                       nt_status = status;
+               } else {
+                       printf("/** Dos error on NT connection! (%s) */\n", 
+                              nt_errstr(status));
+                       nt_status = NT_STATUS(0xc0000000);
+               }
+
+               status = cli_session_setup_creds(c_dos, user_creds);
+               if (NT_STATUS_IS_OK(status)) {
+                       printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
+               }
+
+               /* Case #1: 32-bit NT errors */
+               if (NT_STATUS_IS_DOS(status)) {
+                       printf("/** NT error on DOS connection! (%s) */\n", 
+                              nt_errstr(status));
+                       errnum = errclass = 0;
+               } else {
+                       errclass = NT_STATUS_DOS_CLASS(status);
+                       errnum = NT_STATUS_DOS_CODE(status);
+               }
+
+               if (NT_STATUS_V(nt_status) != error) { 
+                       printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
+                              get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
+                              get_nt_error_c_code(talloc_tos(), nt_status));
+               }
+
+               printf("\t{%s,\t%s,\t%s},\n", 
+                      smb_dos_err_class(errclass), 
+                      smb_dos_err_name(errclass, errnum), 
+                      get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
+
+               TALLOC_FREE(user_creds);
+       }
+       return True;
+}
+
+static bool run_sesssetup_bench(int dummy)
+{
+       static struct cli_state *c;
+       const char *fname = "\\file.dat";
+       uint16_t fnum;
+       NTSTATUS status;
+       int i;
+
+       if (!torture_open_connection(&c, 0)) {
+               return false;
+       }
+
+       status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
+                             FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("open %s failed: %s\n", fname, nt_errstr(status));
+               return false;
+       }
+
+       for (i=0; i<torture_numops; i++) {
+               status = cli_session_setup_creds(c, torture_creds);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("(%s) cli_session_setup_creds failed: %s\n",
+                                __location__, nt_errstr(status));
+                       return false;
+               }
+
+               d_printf("\r%d   ", (int)cli_state_get_uid(c));
+
+               status = cli_ulogoff(c);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("(%s) cli_ulogoff failed: %s\n",
+                                __location__, nt_errstr(status));
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static bool subst_test(const char *str, const char *user, const char *domain,
+                      uid_t uid, gid_t gid, const char *expected)
+{
+       char *subst;
+       bool result = true;
+
+       subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
+
+       if (strcmp(subst, expected) != 0) {
+               printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
+                      "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
+                      expected);
+               result = false;
+       }
+
+       TALLOC_FREE(subst);
+       return result;
+}
+
+static void chain1_open_completion(struct tevent_req *req)
+{
+       uint16_t fnum;
+       NTSTATUS status;
+       status = cli_openx_recv(req, &fnum);
+       TALLOC_FREE(req);
+
+       d_printf("cli_openx_recv returned %s: %d\n",
+                nt_errstr(status),
+                NT_STATUS_IS_OK(status) ? fnum : -1);
+}
+
+static void chain1_write_completion(struct tevent_req *req)
+{
+       size_t written;
+       NTSTATUS status;
+       status = cli_write_andx_recv(req, &written);
+       TALLOC_FREE(req);
+
+       d_printf("cli_write_andx_recv returned %s: %d\n",
+                nt_errstr(status),
                 NT_STATUS_IS_OK(status) ? (int)written : -1);
 }
 
-static void chain1_close_completion(struct tevent_req *req)
+static void chain1_close_completion(struct tevent_req *req)
+{
+       NTSTATUS status;
+       bool *done = (bool *)tevent_req_callback_data_void(req);
+
+       status = cli_close_recv(req);
+       *done = true;
+
+       TALLOC_FREE(req);
+
+       d_printf("cli_close returned %s\n", nt_errstr(status));
+}
+
+static bool run_chain1(int dummy)
+{
+       struct cli_state *cli1;
+       struct tevent_context *evt = samba_tevent_context_init(NULL);
+       struct tevent_req *reqs[3], *smbreqs[3];
+       bool done = false;
+       const char *str = "foobar";
+       NTSTATUS status;
+
+       printf("starting chain1 test\n");
+       if (!torture_open_connection(&cli1, 0)) {
+               return False;
+       }
+
+       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+
+       reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
+                                 O_CREAT|O_RDWR, 0, &smbreqs[0]);
+       if (reqs[0] == NULL) return false;
+       tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
+
+
+       reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
+                                       (const uint8_t *)str, 0, strlen(str)+1,
+                                       smbreqs, 1, &smbreqs[1]);
+       if (reqs[1] == NULL) return false;
+       tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
+
+       reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
+       if (reqs[2] == NULL) return false;
+       tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
+
+       status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       while (!done) {
+               tevent_loop_once(evt);
+       }
+
+       torture_close_connection(cli1);
+       return True;
+}
+
+static void chain2_sesssetup_completion(struct tevent_req *req)
+{
+       NTSTATUS status;
+       status = cli_session_setup_guest_recv(req);
+       d_printf("sesssetup returned %s\n", nt_errstr(status));
+}
+
+static void chain2_tcon_completion(struct tevent_req *req)
+{
+       bool *done = (bool *)tevent_req_callback_data_void(req);
+       NTSTATUS status;
+       status = cli_tcon_andx_recv(req);
+       d_printf("tcon_and_x returned %s\n", nt_errstr(status));
+       *done = true;
+}
+
+static bool run_chain2(int dummy)
+{
+       struct cli_state *cli1;
+       struct tevent_context *evt = samba_tevent_context_init(NULL);
+       struct tevent_req *reqs[2], *smbreqs[2];
+       bool done = false;
+       NTSTATUS status;
+
+       printf("starting chain2 test\n");
+       status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
+                                     port_to_use, SMB_SIGNING_DEFAULT, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               return False;
+       }
+
+       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+
+       reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
+                                                &smbreqs[0]);
+       if (reqs[0] == NULL) return false;
+       tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
+
+       reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
+                                      "?????", NULL, 0, &smbreqs[1]);
+       if (reqs[1] == NULL) return false;
+       tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
+
+       status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
+       }
+
+       while (!done) {
+               tevent_loop_once(evt);
+       }
+
+       torture_close_connection(cli1);
+       return True;
+}
+
+
+struct torture_createdel_state {
+       struct tevent_context *ev;
+       struct cli_state *cli;
+};
+
+static void torture_createdel_created(struct tevent_req *subreq);
+static void torture_createdel_closed(struct tevent_req *subreq);
+
+static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
+                                                struct tevent_context *ev,
+                                                struct cli_state *cli,
+                                                const char *name)
+{
+       struct tevent_req *req, *subreq;
+       struct torture_createdel_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct torture_createdel_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->cli = cli;
+
+       subreq = cli_ntcreate_send(
+               state, ev, cli, name, 0,
+               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
+               FILE_ATTRIBUTE_NORMAL,
+               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+               FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
+
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, torture_createdel_created, req);
+       return req;
+}
+
+static void torture_createdel_created(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct torture_createdel_state *state = tevent_req_data(
+               req, struct torture_createdel_state);
+       NTSTATUS status;
+       uint16_t fnum;
+
+       status = cli_ntcreate_recv(subreq, &fnum, NULL);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               DEBUG(10, ("cli_ntcreate_recv returned %s\n",
+                          nt_errstr(status)));
+               return;
+       }
+
+       subreq = cli_close_send(state, state->ev, state->cli, fnum);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, torture_createdel_closed, req);
+}
+
+static void torture_createdel_closed(struct tevent_req *subreq)
 {
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
        NTSTATUS status;
-       bool *done = (bool *)tevent_req_callback_data_void(req);
 
-       status = cli_close_recv(req);
-       *done = true;
+       status = cli_close_recv(subreq);
+       if (tevent_req_nterror(req, status)) {
+               DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
+               return;
+       }
+       tevent_req_done(req);
+}
 
-       TALLOC_FREE(req);
+static NTSTATUS torture_createdel_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+struct torture_createdels_state {
+       struct tevent_context *ev;
+       struct cli_state *cli;
+       const char *base_name;
+       int sent;
+       int received;
+       int num_files;
+       struct tevent_req **reqs;
+};
+
+static void torture_createdels_done(struct tevent_req *subreq);
+
+static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
+                                                 struct tevent_context *ev,
+                                                 struct cli_state *cli,
+                                                 const char *base_name,
+                                                 int num_parallel,
+                                                 int num_files)
+{
+       struct tevent_req *req;
+       struct torture_createdels_state *state;
+       int i;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct torture_createdels_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->cli = cli;
+       state->base_name = talloc_strdup(state, base_name);
+       if (tevent_req_nomem(state->base_name, req)) {
+               return tevent_req_post(req, ev);
+       }
+       state->num_files = MAX(num_parallel, num_files);
+       state->sent = 0;
+       state->received = 0;
+
+       state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
+       if (tevent_req_nomem(state->reqs, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       for (i=0; i<num_parallel; i++) {
+               char *name;
+
+               name = talloc_asprintf(state, "%s%8.8d", state->base_name,
+                                      state->sent);
+               if (tevent_req_nomem(name, req)) {
+                       return tevent_req_post(req, ev);
+               }
+               state->reqs[i] = torture_createdel_send(
+                       state->reqs, state->ev, state->cli, name);
+               if (tevent_req_nomem(state->reqs[i], req)) {
+                       return tevent_req_post(req, ev);
+               }
+               name = talloc_move(state->reqs[i], &name);
+               tevent_req_set_callback(state->reqs[i],
+                                       torture_createdels_done, req);
+               state->sent += 1;
+       }
+       return req;
+}
+
+static void torture_createdels_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct torture_createdels_state *state = tevent_req_data(
+               req, struct torture_createdels_state);
+       size_t num_parallel = talloc_array_length(state->reqs);
+       NTSTATUS status;
+       char *name;
+       int i;
+
+       status = torture_createdel_recv(subreq);
+       if (!NT_STATUS_IS_OK(status)){
+               DEBUG(10, ("torture_createdel_recv returned %s\n",
+                          nt_errstr(status)));
+               TALLOC_FREE(subreq);
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       for (i=0; i<num_parallel; i++) {
+               if (subreq == state->reqs[i]) {
+                       break;
+               }
+       }
+       if (i == num_parallel) {
+               DEBUG(10, ("received something we did not send\n"));
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+       }
+       TALLOC_FREE(state->reqs[i]);
+
+       if (state->sent >= state->num_files) {
+               tevent_req_done(req);
+               return;
+       }
+
+       name = talloc_asprintf(state, "%s%8.8d", state->base_name,
+                              state->sent);
+       if (tevent_req_nomem(name, req)) {
+               return;
+       }
+       state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
+                                               state->cli, name);
+       if (tevent_req_nomem(state->reqs[i], req)) {
+               return;
+       }
+       name = talloc_move(state->reqs[i], &name);
+       tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
+       state->sent += 1;
+}
+
+static NTSTATUS torture_createdels_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+struct swallow_notify_state {
+       struct tevent_context *ev;
+       struct cli_state *cli;
+       uint16_t fnum;
+       uint32_t completion_filter;
+       bool recursive;
+       bool (*fn)(uint32_t action, const char *name, void *priv);
+       void *priv;
+};
+
+static void swallow_notify_done(struct tevent_req *subreq);
+
+static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
+                                             struct tevent_context *ev,
+                                             struct cli_state *cli,
+                                             uint16_t fnum,
+                                             uint32_t completion_filter,
+                                             bool recursive,
+                                             bool (*fn)(uint32_t action,
+                                                        const char *name,
+                                                        void *priv),
+                                             void *priv)
+{
+       struct tevent_req *req, *subreq;
+       struct swallow_notify_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct swallow_notify_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->cli = cli;
+       state->fnum = fnum;
+       state->completion_filter = completion_filter;
+       state->recursive = recursive;
+       state->fn = fn;
+       state->priv = priv;
 
-       d_printf("cli_close returned %s\n", nt_errstr(status));
+       subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
+                                0xffff, state->completion_filter,
+                                state->recursive);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, swallow_notify_done, req);
+       return req;
 }
 
-static bool run_chain1(int dummy)
+static void swallow_notify_done(struct tevent_req *subreq)
 {
-       struct cli_state *cli1;
-       struct event_context *evt = event_context_init(NULL);
-       struct tevent_req *reqs[3], *smbreqs[3];
-       bool done = false;
-       const char *str = "foobar";
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct swallow_notify_state *state = tevent_req_data(
+               req, struct swallow_notify_state);
        NTSTATUS status;
+       uint32_t i, num_changes;
+       struct notify_change *changes;
 
-       printf("starting chain1 test\n");
-       if (!torture_open_connection(&cli1, 0)) {
-               return False;
-       }
-
-       smbXcli_conn_set_sockopt(cli1->conn, sockops);
-
-       reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
-                                 O_CREAT|O_RDWR, 0, &smbreqs[0]);
-       if (reqs[0] == NULL) return false;
-       tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
-
-
-       reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
-                                       (const uint8_t *)str, 0, strlen(str)+1,
-                                       smbreqs, 1, &smbreqs[1]);
-       if (reqs[1] == NULL) return false;
-       tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
-
-       reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
-       if (reqs[2] == NULL) return false;
-       tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
-
-       status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
+       status = cli_notify_recv(subreq, state, &num_changes, &changes);
+       TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
-               return false;
+               DEBUG(10, ("cli_notify_recv returned %s\n",
+                          nt_errstr(status)));
+               tevent_req_nterror(req, status);
+               return;
        }
 
-       while (!done) {
-               tevent_loop_once(evt);
+       for (i=0; i<num_changes; i++) {
+               state->fn(changes[i].action, changes[i].name, state->priv);
        }
+       TALLOC_FREE(changes);
 
-       torture_close_connection(cli1);
-       return True;
+       subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
+                                0xffff, state->completion_filter,
+                                state->recursive);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, swallow_notify_done, req);
 }
 
-static void chain2_sesssetup_completion(struct tevent_req *req)
+static bool print_notifies(uint32_t action, const char *name, void *priv)
 {
-       NTSTATUS status;
-       status = cli_session_setup_guest_recv(req);
-       d_printf("sesssetup returned %s\n", nt_errstr(status));
+       if (DEBUGLEVEL > 5) {
+               d_printf("%d %s\n", (int)action, name);
+       }
+       return true;
 }
 
-static void chain2_tcon_completion(struct tevent_req *req)
+static void notify_bench_done(struct tevent_req *req)
 {
-       bool *done = (bool *)tevent_req_callback_data_void(req);
-       NTSTATUS status;
-       status = cli_tcon_andx_recv(req);
-       d_printf("tcon_and_x returned %s\n", nt_errstr(status));
-       *done = true;
+       int *num_finished = (int *)tevent_req_callback_data_void(req);
+       *num_finished += 1;
 }
 
-static bool run_chain2(int dummy)
+static bool run_notify_bench(int dummy)
 {
-       struct cli_state *cli1;
-       struct event_context *evt = event_context_init(NULL);
-       struct tevent_req *reqs[2], *smbreqs[2];
-       bool done = false;
+       const char *dname = "\\notify-bench";
+       struct tevent_context *ev;
        NTSTATUS status;
+       uint16_t dnum;
+       struct tevent_req *req1;
+       struct tevent_req *req2 = NULL;
+       int i, num_unc_names;
+       int num_finished = 0;
 
-       printf("starting chain2 test\n");
-       status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
-                                     port_to_use, SMB_SIGNING_DEFAULT, 0);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
-
-       smbXcli_conn_set_sockopt(cli1->conn, sockops);
-
-       reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
-                                                &smbreqs[0]);
-       if (reqs[0] == NULL) return false;
-       tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
+       printf("starting notify-bench test\n");
 
-       reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
-                                      "?????", NULL, 0, &smbreqs[1]);
-       if (reqs[1] == NULL) return false;
-       tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
+       if (use_multishare_conn) {
+               char **unc_list;
+               unc_list = file_lines_load(multishare_conn_fname,
+                                          &num_unc_names, 0, NULL);
+               if (!unc_list || num_unc_names <= 0) {
+                       d_printf("Failed to load unc names list from '%s'\n",
+                                multishare_conn_fname);
+                       return false;
+               }
+               TALLOC_FREE(unc_list);
+       } else {
+               num_unc_names = 1;
+       }
 
-       status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
-       if (!NT_STATUS_IS_OK(status)) {
+       ev = samba_tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               d_printf("tevent_context_init failed\n");
                return false;
        }
 
-       while (!done) {
-               tevent_loop_once(evt);
-       }
+       for (i=0; i<num_unc_names; i++) {
+               struct cli_state *cli;
+               char *base_fname;
 
-       torture_close_connection(cli1);
-       return True;
-}
+               base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
+                                            dname, i);
+               if (base_fname == NULL) {
+                       return false;
+               }
 
+               if (!torture_open_connection(&cli, i)) {
+                       return false;
+               }
 
-struct torture_createdel_state {
-       struct tevent_context *ev;
-       struct cli_state *cli;
-};
+               status = cli_ntcreate(cli, dname, 0,
+                                     MAXIMUM_ALLOWED_ACCESS,
+                                     0, FILE_SHARE_READ|FILE_SHARE_WRITE|
+                                     FILE_SHARE_DELETE,
+                                     FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
+                                     &dnum, NULL);
 
-static void torture_createdel_created(struct tevent_req *subreq);
-static void torture_createdel_closed(struct tevent_req *subreq);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("Could not create %s: %s\n", dname,
+                                nt_errstr(status));
+                       return false;
+               }
 
-static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
-                                                struct tevent_context *ev,
-                                                struct cli_state *cli,
-                                                const char *name)
-{
-       struct tevent_req *req, *subreq;
-       struct torture_createdel_state *state;
+               req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
+                                          FILE_NOTIFY_CHANGE_FILE_NAME |
+                                          FILE_NOTIFY_CHANGE_DIR_NAME |
+                                          FILE_NOTIFY_CHANGE_ATTRIBUTES |
+                                          FILE_NOTIFY_CHANGE_LAST_WRITE,
+                                          false, print_notifies, NULL);
+               if (req1 == NULL) {
+                       d_printf("Could not create notify request\n");
+                       return false;
+               }
 
-       req = tevent_req_create(mem_ctx, &state,
-                               struct torture_createdel_state);
-       if (req == NULL) {
-               return NULL;
+               req2 = torture_createdels_send(talloc_tos(), ev, cli,
+                                              base_fname, 10, torture_numops);
+               if (req2 == NULL) {
+                       d_printf("Could not create createdels request\n");
+                       return false;
+               }
+               TALLOC_FREE(base_fname);
+
+               tevent_req_set_callback(req2, notify_bench_done,
+                                       &num_finished);
        }
-       state->ev = ev;
-       state->cli = cli;
 
-       subreq = cli_ntcreate_send(
-               state, ev, cli, name, 0,
-               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
-               FILE_ATTRIBUTE_NORMAL,
-               FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-               FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
+       while (num_finished < num_unc_names) {
+               int ret;
+               ret = tevent_loop_once(ev);
+               if (ret != 0) {
+                       d_printf("tevent_loop_once failed\n");
+                       return false;
+               }
+       }
 
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
+       if (!tevent_req_poll(req2, ev)) {
+               d_printf("tevent_req_poll failed\n");
        }
-       tevent_req_set_callback(subreq, torture_createdel_created, req);
-       return req;
+
+       status = torture_createdels_recv(req2);
+       d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
+
+       return true;
 }
 
-static void torture_createdel_created(struct tevent_req *subreq)
+static bool run_mangle1(int dummy)
 {
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct torture_createdel_state *state = tevent_req_data(
-               req, struct torture_createdel_state);
-       NTSTATUS status;
+       struct cli_state *cli;
+       const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
        uint16_t fnum;
+       fstring alt_name;
+       NTSTATUS status;
+       time_t change_time, access_time, write_time;
+       off_t size;
+       uint16_t mode;
+
+       printf("starting mangle1 test\n");
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
+
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+       status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
+                             0, 0, &fnum, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("open %s failed: %s\n", fname, nt_errstr(status));
+               return false;
+       }
+       cli_close(cli, fnum);
+
+       status = cli_qpathinfo_alt_name(cli, fname, alt_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("cli_qpathinfo_alt_name failed: %s\n",
+                        nt_errstr(status));
+               return false;
+       }
+       d_printf("alt_name: %s\n", alt_name);
 
-       status = cli_ntcreate_recv(subreq, &fnum);
-       TALLOC_FREE(subreq);
+       status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("cli_ntcreate_recv returned %s\n",
-                          nt_errstr(status)));
-               tevent_req_nterror(req, status);
-               return;
+               d_printf("cli_openx(%s) failed: %s\n", alt_name,
+                        nt_errstr(status));
+               return false;
        }
+       cli_close(cli, fnum);
 
-       subreq = cli_close_send(state, state->ev, state->cli, fnum);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
+       status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
+                               &write_time, &size, &mode);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
+                        nt_errstr(status));
+               return false;
        }
-       tevent_req_set_callback(subreq, torture_createdel_closed, req);
+
+       return true;
 }
 
-static void torture_createdel_closed(struct tevent_req *subreq)
+static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
+                                                struct file_info *f,
+                                                const char *mask,
+                                                void *state)
 {
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       NTSTATUS status;
+       if (f->short_name == NULL) {
+               return NT_STATUS_OK;
+       }
 
-       status = cli_close_recv(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
-               tevent_req_nterror(req, status);
-               return;
+       if (strlen(f->short_name) == 0) {
+               return NT_STATUS_OK;
        }
-       tevent_req_done(req);
+
+       printf("unexpected shortname: %s\n", f->short_name);
+
+       return NT_STATUS_OBJECT_NAME_INVALID;
 }
 
-static NTSTATUS torture_createdel_recv(struct tevent_req *req)
+static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
+                                           struct file_info *f,
+                                           const char *mask,
+                                           void *state)
 {
-       return tevent_req_simple_recv_ntstatus(req);
+       char *name = state;
+
+       printf("name: %s\n", f->name);
+       fstrcpy(name, f->name);
+       return NT_STATUS_OK;
 }
 
-struct torture_createdels_state {
-       struct tevent_context *ev;
-       struct cli_state *cli;
-       const char *base_name;
-       int sent;
-       int received;
-       int num_files;
-       struct tevent_req **reqs;
-};
+static bool run_mangle_illegal(int dummy)
+{
+       struct cli_state *cli = NULL;
+       struct cli_state *cli_posix = NULL;
+       const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
+       const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
+       char *mangled_path = NULL;
+       uint16_t fnum;
+       fstring name;
+       fstring alt_name;
+       NTSTATUS status;
 
-static void torture_createdels_done(struct tevent_req *subreq);
+       printf("starting mangle-illegal test\n");
 
-static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
-                                                 struct tevent_context *ev,
-                                                 struct cli_state *cli,
-                                                 const char *base_name,
-                                                 int num_parallel,
-                                                 int num_files)
-{
-       struct tevent_req *req;
-       struct torture_createdels_state *state;
-       int i;
+       if (!torture_open_connection(&cli, 0)) {
+               return False;
+       }
 
-       req = tevent_req_create(mem_ctx, &state,
-                               struct torture_createdels_state);
-       if (req == NULL) {
-               return NULL;
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+       if (!torture_open_connection(&cli_posix, 0)) {
+               return false;
        }
-       state->ev = ev;
-       state->cli = cli;
-       state->base_name = talloc_strdup(state, base_name);
-       if (tevent_req_nomem(state->base_name, req)) {
-               return tevent_req_post(req, ev);
+
+       smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
+
+       status = torture_setup_unix_extensions(cli_posix);
+       if (!NT_STATUS_IS_OK(status)) {
+               return false;
        }
-       state->num_files = MAX(num_parallel, num_files);
-       state->sent = 0;
-       state->received = 0;
 
-       state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
-       if (tevent_req_nomem(state->reqs, req)) {
-               return tevent_req_post(req, ev);
+       cli_rmdir(cli, "\\MANGLE_ILLEGAL");
+       status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("mkdir1 failed : %s\n", nt_errstr(status));
+               return False;
        }
 
-       for (i=0; i<num_parallel; i++) {
-               char *name;
+       /*
+        * Create a file with illegal NTFS characters and test that we
+        * get a usable mangled name
+        */
 
-               name = talloc_asprintf(state, "%s%8.8d", state->base_name,
-                                      state->sent);
-               if (tevent_req_nomem(name, req)) {
-                       return tevent_req_post(req, ev);
-               }
-               state->reqs[i] = torture_createdel_send(
-                       state->reqs, state->ev, state->cli, name);
-               if (tevent_req_nomem(state->reqs[i], req)) {
-                       return tevent_req_post(req, ev);
-               }
-               name = talloc_move(state->reqs[i], &name);
-               tevent_req_set_callback(state->reqs[i],
-                                       torture_createdels_done, req);
-               state->sent += 1;
+       cli_setatr(cli_posix, illegal_fname, 0, 0);
+       cli_posix_unlink(cli_posix, illegal_fname);
+
+       status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
+                               0600, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("POSIX create of %s failed (%s)\n",
+                      illegal_fname, nt_errstr(status));
+               return false;
        }
-       return req;
-}
 
-static void torture_createdels_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct torture_createdels_state *state = tevent_req_data(
-               req, struct torture_createdels_state);
-       size_t num_parallel = talloc_array_length(state->reqs);
-       NTSTATUS status;
-       char *name;
-       int i;
+       status = cli_close(cli_posix, fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("close failed (%s)\n", nt_errstr(status));
+               return false;
+       }
 
-       status = torture_createdel_recv(subreq);
-       if (!NT_STATUS_IS_OK(status)){
-               DEBUG(10, ("torture_createdel_recv returned %s\n",
-                          nt_errstr(status)));
-               TALLOC_FREE(subreq);
-               tevent_req_nterror(req, status);
-               return;
+       status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("cli_list failed: %s\n", nt_errstr(status));
+               return false;
        }
 
-       for (i=0; i<num_parallel; i++) {
-               if (subreq == state->reqs[i]) {
-                       break;
-               }
+       mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
+       if (mangled_path == NULL) {
+               return false;
        }
-       if (i == num_parallel) {
-               DEBUG(10, ("received something we did not send\n"));
-               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
-               return;
+
+       status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
+               TALLOC_FREE(mangled_path);
+               return false;
        }
-       TALLOC_FREE(state->reqs[i]);
+       TALLOC_FREE(mangled_path);
+       cli_close(cli, fnum);
 
-       if (state->sent >= state->num_files) {
-               tevent_req_done(req);
-               return;
+       cli_setatr(cli_posix, illegal_fname, 0, 0);
+       cli_posix_unlink(cli_posix, illegal_fname);
+
+       /*
+        * Create a file with a long name and check that we got *no* short name.
+        */
+
+       status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
+                             0, 0, &fnum, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("open %s failed: %s\n", fname, nt_errstr(status));
+               return false;
        }
+       cli_close(cli, fnum);
 
-       name = talloc_asprintf(state, "%s%8.8d", state->base_name,
-                              state->sent);
-       if (tevent_req_nomem(name, req)) {
-               return;
+       status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("cli_list failed\n");
+               return false;
        }
-       state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
-                                               state->cli, name);
-       if (tevent_req_nomem(state->reqs[i], req)) {
-               return;
+
+       cli_unlink(cli, fname, 0);
+       cli_rmdir(cli, "\\MANGLE_ILLEGAL");
+
+       if (!torture_close_connection(cli_posix)) {
+               return false;
        }
-       name = talloc_move(state->reqs[i], &name);
-       tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
-       state->sent += 1;
+
+       if (!torture_close_connection(cli)) {
+               return false;
+       }
+
+       return true;
 }
 
-static NTSTATUS torture_createdels_recv(struct tevent_req *req)
+static size_t null_source(uint8_t *buf, size_t n, void *priv)
 {
-       return tevent_req_simple_recv_ntstatus(req);
+       size_t *to_pull = (size_t *)priv;
+       size_t thistime = *to_pull;
+
+       thistime = MIN(thistime, n);
+       if (thistime == 0) {
+               return 0;
+       }
+
+       memset(buf, 0, thistime);
+       *to_pull -= thistime;
+       return thistime;
 }
 
-struct swallow_notify_state {
-       struct tevent_context *ev;
-       struct cli_state *cli;
+static bool run_windows_write(int dummy)
+{
+       struct cli_state *cli1;
        uint16_t fnum;
-       uint32_t completion_filter;
-       bool recursive;
-       bool (*fn)(uint32_t action, const char *name, void *priv);
-       void *priv;
-};
+       int i;
+       bool ret = false;
+       const char *fname = "\\writetest.txt";
+       struct timeval start_time;
+       double seconds;
+       double kbytes;
+       NTSTATUS status;
 
-static void swallow_notify_done(struct tevent_req *subreq);
+       printf("starting windows_write test\n");
+       if (!torture_open_connection(&cli1, 0)) {
+               return False;
+       }
 
-static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
-                                             struct tevent_context *ev,
-                                             struct cli_state *cli,
-                                             uint16_t fnum,
-                                             uint32_t completion_filter,
-                                             bool recursive,
-                                             bool (*fn)(uint32_t action,
-                                                        const char *name,
-                                                        void *priv),
-                                             void *priv)
-{
-       struct tevent_req *req, *subreq;
-       struct swallow_notify_state *state;
+       status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("open failed (%s)\n", nt_errstr(status));
+               return False;
+       }
+
+       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+
+       start_time = timeval_current();
+
+       for (i=0; i<torture_numops; i++) {
+               uint8_t c = 0;
+               off_t start = i * torture_blocksize;
+               size_t to_pull = torture_blocksize - 1;
+
+               status = cli_writeall(cli1, fnum, 0, &c,
+                                     start + torture_blocksize - 1, 1, NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("cli_write failed: %s\n", nt_errstr(status));
+                       goto fail;
+               }
 
-       req = tevent_req_create(mem_ctx, &state,
-                               struct swallow_notify_state);
-       if (req == NULL) {
-               return NULL;
+               status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
+                                 null_source, &to_pull);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("cli_push returned: %s\n", nt_errstr(status));
+                       goto fail;
+               }
        }
-       state->ev = ev;
-       state->cli = cli;
-       state->fnum = fnum;
-       state->completion_filter = completion_filter;
-       state->recursive = recursive;
-       state->fn = fn;
-       state->priv = priv;
 
-       subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
-                                0xffff, state->completion_filter,
-                                state->recursive);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-       tevent_req_set_callback(subreq, swallow_notify_done, req);
-       return req;
+       seconds = timeval_elapsed(&start_time);
+       kbytes = (double)torture_blocksize * torture_numops;
+       kbytes /= 1024;
+
+       printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
+              (double)seconds, (int)(kbytes/seconds));
+
+       ret = true;
+ fail:
+       cli_close(cli1, fnum);
+       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       torture_close_connection(cli1);
+       return ret;
 }
 
-static void swallow_notify_done(struct tevent_req *subreq)
+static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
 {
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct swallow_notify_state *state = tevent_req_data(
-               req, struct swallow_notify_state);
-       NTSTATUS status;
-       uint32_t i, num_changes;
-       struct notify_change *changes;
+       size_t max_pdu = 0x1FFFF;
 
-       status = cli_notify_recv(subreq, state, &num_changes, &changes);
-       TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("cli_notify_recv returned %s\n",
-                          nt_errstr(status)));
-               tevent_req_nterror(req, status);
-               return;
+       if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
+               max_pdu = 0xFFFFFF;
        }
 
-       for (i=0; i<num_changes; i++) {
-               state->fn(changes[i].action, changes[i].name, state->priv);
+       if (smb1cli_conn_signing_is_active(cli->conn)) {
+               max_pdu = 0x1FFFF;
        }
-       TALLOC_FREE(changes);
 
-       subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
-                                0xffff, state->completion_filter,
-                                state->recursive);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
+       if (smb1cli_conn_encryption_on(cli->conn)) {
+               max_pdu = CLI_BUFFER_SIZE;
        }
-       tevent_req_set_callback(subreq, swallow_notify_done, req);
-}
 
-static bool print_notifies(uint32_t action, const char *name, void *priv)
-{
-       if (DEBUGLEVEL > 5) {
-               d_printf("%d %s\n", (int)action, name);
+       if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
+               len_requested &= 0xFFFF;
        }
-       return true;
-}
 
-static void notify_bench_done(struct tevent_req *req)
-{
-       int *num_finished = (int *)tevent_req_callback_data_void(req);
-       *num_finished += 1;
+       return MIN(len_requested,
+                  max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
 }
 
-static bool run_notify_bench(int dummy)
+static bool check_read_call(struct cli_state *cli,
+                           uint16_t fnum,
+                           uint8_t *buf,
+                           size_t len_requested)
 {
-       const char *dname = "\\notify-bench";
-       struct tevent_context *ev;
        NTSTATUS status;
-       uint16_t dnum;
-       struct tevent_req *req1;
-       struct tevent_req *req2 = NULL;
-       int i, num_unc_names;
-       int num_finished = 0;
-
-       printf("starting notify-bench test\n");
-
-       if (use_multishare_conn) {
-               char **unc_list;
-               unc_list = file_lines_load(multishare_conn_fname,
-                                          &num_unc_names, 0, NULL);
-               if (!unc_list || num_unc_names <= 0) {
-                       d_printf("Failed to load unc names list from '%s'\n",
-                                multishare_conn_fname);
-                       return false;
-               }
-               TALLOC_FREE(unc_list);
-       } else {
-               num_unc_names = 1;
-       }
+       struct tevent_req *subreq = NULL;
+       ssize_t len_read = 0;
+       size_t len_expected = 0;
+       struct tevent_context *ev = NULL;
 
-       ev = tevent_context_init(talloc_tos());
+       ev = samba_tevent_context_init(talloc_tos());
        if (ev == NULL) {
-               d_printf("tevent_context_init failed\n");
                return false;
        }
 
-       for (i=0; i<num_unc_names; i++) {
-               struct cli_state *cli;
-               char *base_fname;
-
-               base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
-                                            dname, i);
-               if (base_fname == NULL) {
-                       return false;
-               }
+       subreq = cli_read_andx_send(talloc_tos(),
+                                   ev,
+                                   cli,
+                                   fnum,
+                                   0,
+                                   len_requested);
 
-               if (!torture_open_connection(&cli, i)) {
-                       return false;
-               }
+       if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
+               return false;
+       }
 
-               status = cli_ntcreate(cli, dname, 0,
-                                     MAXIMUM_ALLOWED_ACCESS,
-                                     0, FILE_SHARE_READ|FILE_SHARE_WRITE|
-                                     FILE_SHARE_DELETE,
-                                     FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
-                                     &dnum);
+       status = cli_read_andx_recv(subreq, &len_read, &buf);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
+               return false;
+       }
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       d_printf("Could not create %s: %s\n", dname,
-                                nt_errstr(status));
-                       return false;
-               }
+       TALLOC_FREE(subreq);
+       TALLOC_FREE(ev);
 
-               req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
-                                          FILE_NOTIFY_CHANGE_FILE_NAME |
-                                          FILE_NOTIFY_CHANGE_DIR_NAME |
-                                          FILE_NOTIFY_CHANGE_ATTRIBUTES |
-                                          FILE_NOTIFY_CHANGE_LAST_WRITE,
-                                          false, print_notifies, NULL);
-               if (req1 == NULL) {
-                       d_printf("Could not create notify request\n");
-                       return false;
-               }
+       len_expected = calc_expected_return(cli, len_requested);
+
+       if (len_expected > 0x10000 && len_read == 0x10000) {
+               /* Windows servers only return a max of 0x10000,
+                  doesn't matter if you set CAP_LARGE_READX in
+                  the client sessionsetupX call or not. */
+               d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
+                       (unsigned int)len_requested);
+       } else if (len_read != len_expected) {
+               d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
+                       (unsigned int)len_requested,
+                       (unsigned int)len_read,
+                       (unsigned int)len_expected);
+               return false;
+       } else {
+               d_printf("Correct read reply.\n");
+       }
 
-               req2 = torture_createdels_send(talloc_tos(), ev, cli,
-                                              base_fname, 10, torture_numops);
-               if (req2 == NULL) {
-                       d_printf("Could not create createdels request\n");
-                       return false;
-               }
-               TALLOC_FREE(base_fname);
+       return true;
+}
 
-               tevent_req_set_callback(req2, notify_bench_done,
-                                       &num_finished);
+/* Test large readX variants. */
+static bool large_readx_tests(struct cli_state *cli,
+                               uint16_t fnum,
+                               uint8_t *buf)
+{
+       /* A read of 0xFFFF0001 should *always* return 1 byte. */
+       if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
+               return false;
        }
-
-       while (num_finished < num_unc_names) {
-               int ret;
-               ret = tevent_loop_once(ev);
-               if (ret != 0) {
-                       d_printf("tevent_loop_once failed\n");
-                       return false;
-               }
+       /* A read of 0x10000 should return 0x10000 bytes. */
+       if (check_read_call(cli, fnum, buf,    0x10000) == false) {
+               return false;
        }
-
-       if (!tevent_req_poll(req2, ev)) {
-               d_printf("tevent_req_poll failed\n");
+       /* A read of 0x10000 should return 0x10001 bytes. */
+       if (check_read_call(cli, fnum, buf,    0x10001) == false) {
+               return false;
+       }
+       /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
+          the requested number of bytes. */
+       if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
+               return false;
+       }
+       /* A read of 1MB should return 1MB bytes (on Samba). */
+       if (check_read_call(cli, fnum, buf,   0x100000) == false) {
+               return false;
        }
 
-       status = torture_createdels_recv(req2);
-       d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
-
+       if (check_read_call(cli, fnum, buf,    0x20001) == false) {
+               return false;
+       }
+       if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
+               return false;
+       }
+       if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
+               return false;
+       }
        return true;
 }
 
-static bool run_mangle1(int dummy)
+static bool run_large_readx(int dummy)
 {
-       struct cli_state *cli;
-       const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
-       uint16_t fnum;
-       fstring alt_name;
+       uint8_t *buf = NULL;
+       struct cli_state *cli1 = NULL;
+       struct cli_state *cli2 = NULL;
+       bool correct = false;
+       const char *fname = "\\large_readx.dat";
        NTSTATUS status;
-       time_t change_time, access_time, write_time;
-       off_t size;
-       uint16_t mode;
+       uint16_t fnum1 = UINT16_MAX;
+       uint32_t normal_caps = 0;
+       size_t file_size = 20*1024*1024;
+       TALLOC_CTX *frame = talloc_stackframe();
+       size_t i;
+       struct {
+               const char *name;
+               enum smb_signing_setting signing_setting;
+               enum protocol_types protocol;
+       } runs[] = {
+               {
+                       .name = "NT1",
+                       .signing_setting = SMB_SIGNING_IF_REQUIRED,
+                       .protocol = PROTOCOL_NT1,
+               },{
+                       .name = "NT1 - SIGNING_REQUIRED",
+                       .signing_setting = SMB_SIGNING_REQUIRED,
+                       .protocol = PROTOCOL_NT1,
+               },
+       };
 
-       printf("starting mangle1 test\n");
-       if (!torture_open_connection(&cli, 0)) {
-               return False;
+       printf("starting large_readx test\n");
+
+       if (!torture_open_connection(&cli1, 0)) {
+               goto out;
        }
 
-       smbXcli_conn_set_sockopt(cli->conn, sockops);
+       normal_caps = smb1cli_conn_capabilities(cli1->conn);
+
+       if (!(normal_caps & CAP_LARGE_READX)) {
+               d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
+                       (unsigned int)normal_caps);
+               goto out;
+       }
+
+       /* Create a file of size 4MB. */
+       status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
+                       FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
+                       0, 0, &fnum1, NULL);
 
-       status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
-                             FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
-                             0, 0, &fnum);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("open %s failed: %s\n", fname, nt_errstr(status));
-               return false;
+               goto out;
        }
-       cli_close(cli, fnum);
 
-       status = cli_qpathinfo_alt_name(cli, fname, alt_name);
+       /* Write file_size bytes. */
+       buf = talloc_zero_array(frame, uint8_t, file_size);
+       if (buf == NULL) {
+               goto out;
+       }
+
+       status = cli_writeall(cli1,
+                             fnum1,
+                             0,
+                             buf,
+                             0,
+                             file_size,
+                             NULL);
        if (!NT_STATUS_IS_OK(status)) {
-               d_printf("cli_qpathinfo_alt_name failed: %s\n",
-                        nt_errstr(status));
-               return false;
+               d_printf("cli_writeall failed: %s\n", nt_errstr(status));
+               goto out;
        }
-       d_printf("alt_name: %s\n", alt_name);
 
-       status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
+       status = cli_close(cli1, fnum1);
        if (!NT_STATUS_IS_OK(status)) {
-               d_printf("cli_openx(%s) failed: %s\n", alt_name,
-                        nt_errstr(status));
-               return false;
+               d_printf("cli_close failed: %s\n", nt_errstr(status));
+               goto out;
        }
-       cli_close(cli, fnum);
 
-       status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
-                               &write_time, &size, &mode);
-       if (!NT_STATUS_IS_OK(status)) {
-               d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
-                        nt_errstr(status));
-               return false;
-       }
+       fnum1 = UINT16_MAX;
+
+       for (i=0; i < ARRAY_SIZE(runs); i++) {
+               enum smb_signing_setting saved_signing_setting = signing_state;
+               uint16_t fnum2 = -1;
+
+               if (do_encrypt &&
+                   (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
+               {
+                       d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
+                       continue;
+               }
+
+               d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
+
+               signing_state = runs[i].signing_setting;
+               cli2 = open_nbt_connection();
+               signing_state = saved_signing_setting;
+               if (cli2 == NULL) {
+                       goto out;
+               }
+
+               status = smbXcli_negprot(cli2->conn,
+                                        cli2->timeout,
+                                        runs[i].protocol,
+                                        runs[i].protocol);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto out;
+               }
+
+               status = cli_session_setup_creds(cli2, torture_creds);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto out;
+               }
+
+               status = cli_tree_connect(cli2,
+                                       share,
+                                       "?????",
+                                       password);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto out;
+               }
+
+               cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
 
-       return true;
-}
+               normal_caps = smb1cli_conn_capabilities(cli2->conn);
 
-static size_t null_source(uint8_t *buf, size_t n, void *priv)
-{
-       size_t *to_pull = (size_t *)priv;
-       size_t thistime = *to_pull;
+               if (!(normal_caps & CAP_LARGE_READX)) {
+                       d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
+                               (unsigned int)normal_caps);
+                       goto out;
+               }
 
-       thistime = MIN(thistime, n);
-       if (thistime == 0) {
-               return 0;
-       }
+               if (do_encrypt) {
+                       if (force_cli_encryption(cli2, share) == false) {
+                               goto out;
+                       }
+               } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
+                       uint16_t major, minor;
+                       uint32_t caplow, caphigh;
 
-       memset(buf, 0, thistime);
-       *to_pull -= thistime;
-       return thistime;
-}
+                       status = cli_unix_extensions_version(cli2,
+                                                            &major, &minor,
+                                                            &caplow, &caphigh);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               goto out;
+                       }
+               }
 
-static bool run_windows_write(int dummy)
-{
-       struct cli_state *cli1;
-       uint16_t fnum;
-       int i;
-       bool ret = false;
-       const char *fname = "\\writetest.txt";
-       struct timeval start_time;
-       double seconds;
-       double kbytes;
-       NTSTATUS status;
+               status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
+                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
+                               0, 0, &fnum2, NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
+                       goto out;
+               }
 
-       printf("starting windows_write test\n");
-       if (!torture_open_connection(&cli1, 0)) {
-               return False;
-       }
+               /* All reads must return less than file_size bytes. */
+               if (!large_readx_tests(cli2, fnum2, buf)) {
+                       goto out;
+               }
 
-       status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("open failed (%s)\n", nt_errstr(status));
-               return False;
+               status = cli_close(cli2, fnum2);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("cli_close failed: %s\n", nt_errstr(status));
+                       goto out;
+               }
+               fnum2 = -1;
+
+               if (!torture_close_connection(cli2)) {
+                       goto out;
+               }
+               cli2 = NULL;
        }
 
-       smbXcli_conn_set_sockopt(cli1->conn, sockops);
+       correct = true;
+       printf("Success on large_readx test\n");
 
-       start_time = timeval_current();
+  out:
 
-       for (i=0; i<torture_numops; i++) {
-               uint8_t c = 0;
-               off_t start = i * torture_blocksize;
-               size_t to_pull = torture_blocksize - 1;
+       if (cli2) {
+               if (!torture_close_connection(cli2)) {
+                       correct = false;
+               }
+       }
 
-               status = cli_writeall(cli1, fnum, 0, &c,
-                                     start + torture_blocksize - 1, 1, NULL);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("cli_write failed: %s\n", nt_errstr(status));
-                       goto fail;
+       if (cli1) {
+               if (fnum1 != UINT16_MAX) {
+                       status = cli_close(cli1, fnum1);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               d_printf("cli_close failed: %s\n", nt_errstr(status));
+                       }
+                       fnum1 = UINT16_MAX;
                }
 
-               status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
-                                 null_source, &to_pull);
+               status = cli_unlink(cli1, fname,
+                                   FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("cli_push returned: %s\n", nt_errstr(status));
-                       goto fail;
+                       printf("unlink failed (%s)\n", nt_errstr(status));
                }
-       }
 
-       seconds = timeval_elapsed(&start_time);
-       kbytes = (double)torture_blocksize * torture_numops;
-       kbytes /= 1024;
+               if (!torture_close_connection(cli1)) {
+                       correct = false;
+               }
+       }
 
-       printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
-              (double)seconds, (int)(kbytes/seconds));
+       TALLOC_FREE(frame);
 
-       ret = true;
- fail:
-       cli_close(cli1, fnum);
-       cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-       torture_close_connection(cli1);
-       return ret;
+       printf("finished large_readx test\n");
+       return correct;
 }
 
 static bool run_cli_echo(int dummy)
@@ -7365,7 +9213,8 @@ static bool run_shortname_test(int dummy)
                fname[15] = i;
 
                status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
-                                   FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
+                                   FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                  FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
                if (!NT_STATUS_IS_OK(status)) {
                        d_printf("(%s) cli_nt_create of %s failed: %s\n",
                                __location__, fname, nt_errstr(status));
@@ -7409,14 +9258,14 @@ static bool run_shortname_test(int dummy)
 
 static void pagedsearch_cb(struct tevent_req *req)
 {
-       int rc;
+       TLDAPRC rc;
        struct tldap_message *msg;
        char *dn;
 
        rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
-       if (rc != TLDAP_SUCCESS) {
+       if (!TLDAP_RC_IS_SUCCESS(rc)) {
                d_printf("tldap_search_paged_recv failed: %s\n",
-                        tldap_err2string(rc));
+                        tldap_rc2string(rc));
                return;
        }
        if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
@@ -7434,7 +9283,8 @@ static void pagedsearch_cb(struct tevent_req *req)
 static bool run_tldap(int dummy)
 {
        struct tldap_context *ld;
-       int fd, rc;
+       int fd;
+       TLDAPRC rc;
        NTSTATUS status;
        struct sockaddr_storage addr;
        struct tevent_context *ev;
@@ -7460,7 +9310,7 @@ static bool run_tldap(int dummy)
        }
 
        rc = tldap_fetch_rootdse(ld);
-       if (rc != TLDAP_SUCCESS) {
+       if (!TLDAP_RC_IS_SUCCESS(rc)) {
                d_printf("tldap_fetch_rootdse failed: %s\n",
                         tldap_errstr(talloc_tos(), ld, rc));
                return false;
@@ -7474,7 +9324,7 @@ static bool run_tldap(int dummy)
        }
        d_printf("defaultNamingContext: %s\n", basedn);
 
-       ev = tevent_context_init(talloc_tos());
+       ev = samba_tevent_context_init(talloc_tos());
        if (ev == NULL) {
                d_printf("tevent_context_init failed\n");
                return false;
@@ -7500,8 +9350,8 @@ static bool run_tldap(int dummy)
 
        rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
                          NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
-                         talloc_tos(), NULL, NULL);
-       if (rc != TLDAP_SUCCESS) {
+                         talloc_tos(), NULL);
+       if (!TLDAP_RC_IS_SUCCESS(rc)) {
                d_printf("tldap_search with complex filter failed: %s\n",
                         tldap_errstr(talloc_tos(), ld, rc));
                return false;
@@ -7539,100 +9389,358 @@ static bool run_dir_createtime(int dummy)
                goto out;
        }
 
-       status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
-                               NULL, NULL, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("cli_qpathinfo2 returned %s\n",
-                      nt_errstr(status));
-               goto out;
+       status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
+                               NULL, NULL, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_qpathinfo2 returned %s\n",
+                      nt_errstr(status));
+               goto out;
+       }
+
+       /* Sleep 3 seconds, then create a file. */
+       sleep(3);
+
+       status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
+                         DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_openx failed: %s\n", nt_errstr(status));
+               goto out;
+       }
+
+       status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
+                               NULL, NULL, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_qpathinfo2 (2) returned %s\n",
+                      nt_errstr(status));
+               goto out;
+       }
+
+       if (timespec_compare(&create_time1, &create_time)) {
+               printf("run_dir_createtime: create time was updated (error)\n");
+       } else {
+               printf("run_dir_createtime: create time was not updated (correct)\n");
+               ret = true;
+       }
+
+  out:
+
+       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       cli_rmdir(cli, dname);
+       if (!torture_close_connection(cli)) {
+               ret = false;
+       }
+       return ret;
+}
+
+
+static bool run_streamerror(int dummy)
+{
+       struct cli_state *cli;
+       const char *dname = "\\testdir";
+       const char *streamname =
+               "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
+       NTSTATUS status;
+       time_t change_time, access_time, write_time;
+       off_t size;
+       uint16_t mode, fnum;
+       bool ret = true;
+
+       if (!torture_open_connection(&cli, 0)) {
+               return false;
+       }
+
+       cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       cli_rmdir(cli, dname);
+
+       status = cli_mkdir(cli, dname);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("mkdir failed: %s\n", nt_errstr(status));
+               return false;
+       }
+
+       status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
+                               &write_time, &size, &mode);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               printf("pathinfo returned %s, expected "
+                      "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
+                      nt_errstr(status));
+               ret = false;
+       }
+
+       status = cli_ntcreate(cli, streamname, 0x16,
+                             FILE_READ_DATA|FILE_READ_EA|
+                             FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
+                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
+                             FILE_OPEN, 0, 0, &fnum, NULL);
+
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               printf("ntcreate returned %s, expected "
+                      "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
+                      nt_errstr(status));
+               ret = false;
+       }
+
+
+       cli_rmdir(cli, dname);
+       return ret;
+}
+
+struct pidtest_state {
+       bool success;
+       uint16_t vwv[1];
+       DATA_BLOB data;
+};
+
+static void pid_echo_done(struct tevent_req *subreq);
+
+static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
+                       struct tevent_context *ev,
+                       struct cli_state *cli)
+{
+       struct tevent_req *req, *subreq;
+       struct pidtest_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       SSVAL(state->vwv, 0, 1);
+       state->data = data_blob_const("hello", 5);
+
+       subreq = smb1cli_req_send(state,
+                               ev,
+                               cli->conn,
+                               SMBecho,
+                               0, 0, /* *_flags */
+                               0, 0, /* *_flags2 */
+                               cli->timeout,
+                               0xDEADBEEF, /* pid */
+                               NULL, /* tcon */
+                               NULL, /* session */
+                               ARRAY_SIZE(state->vwv), state->vwv,
+                               state->data.length, state->data.data);
+
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, pid_echo_done, req);
+       return req;
+}
+
+static void pid_echo_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct pidtest_state *state = tevent_req_data(
+               req, struct pidtest_state);
+       NTSTATUS status;
+       uint32_t num_bytes;
+       uint8_t *bytes = NULL;
+       struct iovec *recv_iov = NULL;
+       uint8_t *phdr = NULL;
+       uint16_t pidlow = 0;
+       uint16_t pidhigh = 0;
+       struct smb1cli_req_expected_response expected[] = {
+       {
+               .status = NT_STATUS_OK,
+               .wct    = 1,
+       },
+       };
+
+       status = smb1cli_req_recv(subreq, state,
+                               &recv_iov,
+                               &phdr,
+                               NULL, /* pwct */
+                               NULL, /* pvwv */
+                               NULL, /* pvwv_offset */
+                               &num_bytes,
+                               &bytes,
+                               NULL, /* pbytes_offset */
+                               NULL, /* pinbuf */
+                               expected, ARRAY_SIZE(expected));
+
+       TALLOC_FREE(subreq);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       if (num_bytes != state->data.length) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+               return;
+       }
+
+       if (memcmp(bytes, state->data.data, num_bytes) != 0) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+               return;
+       }
+
+       /* Check pid low/high == DEADBEEF */
+       pidlow = SVAL(phdr, HDR_PID);
+       if (pidlow != 0xBEEF){
+               printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
+                       (unsigned int)pidlow);
+               tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+               return;
+       }
+       pidhigh = SVAL(phdr, HDR_PIDHIGH);
+       if (pidhigh != 0xDEAD){
+               printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
+                       (unsigned int)pidhigh);
+               tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+static NTSTATUS pid_echo_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+static bool run_pidhigh(int dummy)
+{
+       bool success = false;
+       struct cli_state *cli = NULL;
+       NTSTATUS status;
+       struct tevent_context *ev = NULL;
+       struct tevent_req *req = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       printf("starting pid high test\n");
+       if (!torture_open_connection(&cli, 0)) {
+               return false;
+       }
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+       ev = samba_tevent_context_init(frame);
+       if (ev == NULL) {
+                goto fail;
        }
 
-       /* Sleep 3 seconds, then create a file. */
-       sleep(3);
-
-       status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
-                         DENY_NONE, &fnum);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("cli_openx failed: %s\n", nt_errstr(status));
-               goto out;
+       req = pid_echo_send(frame, ev, cli);
+       if (req == NULL) {
+               goto fail;
        }
 
-       status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
-                               NULL, NULL, NULL);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("cli_qpathinfo2 (2) returned %s\n",
-                      nt_errstr(status));
-               goto out;
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+               goto fail;
        }
 
-       if (timespec_compare(&create_time1, &create_time)) {
-               printf("run_dir_createtime: create time was updated (error)\n");
-       } else {
-               printf("run_dir_createtime: create time was not updated (correct)\n");
-               ret = true;
+       status = pid_echo_recv(req);
+       if (NT_STATUS_IS_OK(status)) {
+               printf("pid high test ok\n");
+               success = true;
        }
 
 out:
fail:
 
-       cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-       cli_rmdir(cli, dname);
-       if (!torture_close_connection(cli)) {
-               ret = false;
-       }
-       return ret;
+       TALLOC_FREE(frame);
+       torture_close_connection(cli);
+       return success;
 }
 
-
-static bool run_streamerror(int dummy)
+/*
+  Test Windows open on a bad POSIX symlink.
+ */
+static bool run_symlink_open_test(int dummy)
 {
-       struct cli_state *cli;
-       const char *dname = "\\testdir";
-       const char *streamname =
-               "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
+       static struct cli_state *cli;
+       const char *fname = "non_existant_file";
+       const char *sname = "dangling_symlink";
+       uint16_t fnum = (uint16_t)-1;
+       bool correct = false;
        NTSTATUS status;
-       time_t change_time, access_time, write_time;
-       off_t size;
-       uint16_t mode, fnum;
-       bool ret = true;
+       TALLOC_CTX *frame = NULL;
+
+       frame = talloc_stackframe();
+
+       printf("Starting Windows bad symlink open test\n");
 
        if (!torture_open_connection(&cli, 0)) {
+               TALLOC_FREE(frame);
                return false;
        }
 
-       cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-       cli_rmdir(cli, dname);
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
 
-       status = cli_mkdir(cli, dname);
+       status = torture_setup_unix_extensions(cli);
        if (!NT_STATUS_IS_OK(status)) {
-               printf("mkdir failed: %s\n", nt_errstr(status));
+               TALLOC_FREE(frame);
                return false;
        }
 
-       status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
-                               &write_time, &size, &mode);
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-               printf("pathinfo returned %s, expected "
-                      "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
-                      nt_errstr(status));
-               ret = false;
+       /* Ensure nothing exists. */
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
+       cli_setatr(cli, sname, 0, 0);
+       cli_posix_unlink(cli, sname);
+
+       /* Create a symlink pointing nowhere. */
+       status = cli_posix_symlink(cli, fname, sname);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_posix_symlink of %s -> %s failed (%s)\n",
+                       sname,
+                       fname,
+                       nt_errstr(status));
+               goto out;
        }
 
-       status = cli_ntcreate(cli, streamname, 0x16,
-                             FILE_READ_DATA|FILE_READ_EA|
-                             FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
-                             FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
-                             FILE_OPEN, 0, 0, &fnum);
+       /* Now ensure that a Windows open doesn't hang. */
+       status = cli_ntcreate(cli,
+                       sname,
+                       0,
+                       FILE_READ_DATA|FILE_WRITE_DATA,
+                       0,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+                       FILE_OPEN_IF,
+                       0x0,
+                       0x0,
+                       &fnum,
+                       NULL);
+
+       /*
+        * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
+        * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
+        * we use O_NOFOLLOW on the server or not.
+        */
+       if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
+       {
+               correct = true;
+       } else {
+               printf("cli_ntcreate of %s returned %s - should return"
+                               " either (%s) or (%s)\n",
+                       sname,
+                       nt_errstr(status),
+                       nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
+                       nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
+               goto out;
+       }
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
-               printf("ntcreate returned %s, expected "
-                      "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
-                      nt_errstr(status));
-               ret = false;
+       correct = true;
+
+  out:
+
+       if (fnum != (uint16_t)-1) {
+               cli_close(cli, fnum);
+               fnum = (uint16_t)-1;
        }
 
+       cli_setatr(cli, sname, 0, 0);
+       cli_posix_unlink(cli, sname);
+       cli_setatr(cli, fname, 0, 0);
+       cli_posix_unlink(cli, fname);
 
-       cli_rmdir(cli, dname);
-       return ret;
+       if (!torture_close_connection(cli)) {
+               correct = false;
+       }
+
+       TALLOC_FREE(frame);
+       return correct;
 }
 
 static bool run_local_substitute(int dummy)
@@ -7689,23 +9797,48 @@ static bool run_local_base64(int dummy)
        return ret;
 }
 
+static void parse_fn(time_t timeout, DATA_BLOB blob, void *private_data)
+{
+       return;
+}
+
 static bool run_local_gencache(int dummy)
 {
        char *val;
        time_t tm;
        DATA_BLOB blob;
+       char v;
+       struct memcache *mem;
+       int i;
+
+       mem = memcache_init(NULL, 0);
+       if (mem == NULL) {
+               d_printf("%s: memcache_init failed\n", __location__);
+               return false;
+       }
+       memcache_set_global(mem);
 
        if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
                d_printf("%s: gencache_set() failed\n", __location__);
                return False;
        }
 
-       if (!gencache_get("foo", NULL, NULL)) {
+       if (!gencache_get("foo", NULL, NULL, NULL)) {
                d_printf("%s: gencache_get() failed\n", __location__);
                return False;
        }
 
-       if (!gencache_get("foo", &val, &tm)) {
+       for (i=0; i<1000000; i++) {
+               gencache_parse("foo", parse_fn, NULL);
+       }
+
+       if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
+               d_printf("%s: gencache_get() failed\n", __location__);
+               return False;
+       }
+       TALLOC_FREE(val);
+
+       if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
                d_printf("%s: gencache_get() failed\n", __location__);
                return False;
        }
@@ -7713,11 +9846,11 @@ static bool run_local_gencache(int dummy)
        if (strcmp(val, "bar") != 0) {
                d_printf("%s: gencache_get() returned %s, expected %s\n",
                         __location__, val, "bar");
-               SAFE_FREE(val);
+               TALLOC_FREE(val);
                return False;
        }
 
-       SAFE_FREE(val);
+       TALLOC_FREE(val);
 
        if (!gencache_del("foo")) {
                d_printf("%s: gencache_del() failed\n", __location__);
@@ -7729,7 +9862,7 @@ static bool run_local_gencache(int dummy)
                return False;
        }
 
-       if (gencache_get("foo", &val, &tm)) {
+       if (gencache_get("foo", talloc_tos(), &val, &tm)) {
                d_printf("%s: gencache_get() on deleted entry "
                         "succeeded\n", __location__);
                return False;
@@ -7743,7 +9876,7 @@ static bool run_local_gencache(int dummy)
                return False;
        }
 
-       if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
+       if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
                d_printf("%s: gencache_get_data_blob() failed\n", __location__);
                return False;
        }
@@ -7767,12 +9900,26 @@ static bool run_local_gencache(int dummy)
                return False;
        }
 
-       if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
+       if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
                d_printf("%s: gencache_get_data_blob() on deleted entry "
                         "succeeded\n", __location__);
                return False;
        }
 
+       v = 1;
+       blob.data = (uint8_t *)&v;
+       blob.length = sizeof(v);
+
+       if (!gencache_set_data_blob("blob", &blob, tm)) {
+               d_printf("%s: gencache_set_data_blob() failed\n",
+                        __location__);
+               return false;
+       }
+       if (gencache_get("blob", talloc_tos(), &val, &tm)) {
+               d_printf("%s: gencache_get succeeded\n", __location__);
+               return false;
+       }
+
        return True;
 }
 
@@ -7816,11 +9963,29 @@ static bool rbt_testval(struct db_context *db, const char *key,
        return ret;
 }
 
+static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
+{
+       int *count2 = (int *)private_data;
+       (*count2)++;
+       return 0;
+}
+
+static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
+{
+       int *count2 = (int *)private_data;
+       (*count2)++;
+       dbwrap_record_delete(rec);
+       return 0;
+}
+
 static bool run_local_rbtree(int dummy)
 {
        struct db_context *db;
        bool ret = false;
        int i;
+       NTSTATUS status;
+       int count = 0;
+       int count2 = 0;
 
        db = db_open_rbt(NULL);
 
@@ -7863,6 +10028,27 @@ static bool run_local_rbtree(int dummy)
        }
 
        ret = true;
+       count = 0; count2 = 0;
+       status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
+                                     &count2, &count);
+       printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+       if ((count != count2) || (count != 1000)) {
+               ret = false;
+       }
+       count = 0; count2 = 0;
+       status = dbwrap_traverse(db, local_rbtree_traverse_delete,
+                                &count2, &count);
+       printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+       if ((count != count2) || (count != 1000)) {
+               ret = false;
+       }
+       count = 0; count2 = 0;
+       status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
+                                     &count2, &count);
+       printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
+       if ((count != count2) || (count != 0)) {
+               ret = false;
+       }
 
  done:
        TALLOC_FREE(db);
@@ -8039,6 +10225,22 @@ static bool run_local_string_to_sid(int dummy) {
                printf("allowing S-1-5-32-545-abc\n");
                return false;
        }
+       if (string_to_sid(&sid, "S-300-5-32-545")) {
+               printf("allowing S-300-5-32-545\n");
+               return false;
+       }
+       if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
+               printf("allowing S-1-0xfffffffffffffe-32-545\n");
+               return false;
+       }
+       if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
+               printf("allowing S-1-0xffffffffffff-5294967297-545\n");
+               return false;
+       }
+       if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
+               printf("could not parse S-1-0xfffffffffffe-32-545\n");
+               return false;
+       }
        if (!string_to_sid(&sid, "S-1-5-32-545")) {
                printf("could not parse S-1-5-32-545\n");
                return false;
@@ -8051,9 +10253,38 @@ static bool run_local_string_to_sid(int dummy) {
        return true;
 }
 
+static bool sid_to_string_test(const char *expected) {
+       char *str;
+       bool res = true;
+       struct dom_sid sid;
+
+       if (!string_to_sid(&sid, expected)) {
+               printf("could not parse %s\n", expected);
+               return false;
+       }
+
+       str = dom_sid_string(NULL, &sid);
+       if (strcmp(str, expected)) {
+               printf("Comparison failed (%s != %s)\n", str, expected);
+               res = false;
+       }
+       TALLOC_FREE(str);
+       return res;
+}
+
+static bool run_local_sid_to_string(int dummy) {
+       if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
+               return false;
+       if (!sid_to_string_test("S-1-545"))
+               return false;
+       if (!sid_to_string_test("S-255-3840-1-1-1-1"))
+               return false;
+       return true;
+}
+
 static bool run_local_binary_to_sid(int dummy) {
        struct dom_sid *sid = talloc(NULL, struct dom_sid);
-       static const char good_binary_sid[] = {
+       static const uint8_t good_binary_sid[] = {
                0x1, /* revision number */
                15, /* num auths */
                0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
@@ -8074,7 +10305,7 @@ static bool run_local_binary_to_sid(int dummy) {
                0x1, 0x1, 0x1, 0x1, /* auth[14] */
        };
 
-       static const char long_binary_sid[] = {
+       static const uint8_t long_binary_sid[] = {
                0x1, /* revision number */
                15, /* num auths */
                0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
@@ -8098,7 +10329,7 @@ static bool run_local_binary_to_sid(int dummy) {
                0x1, 0x1, 0x1, 0x1, /* auth[17] */
        };
 
-       static const char long_binary_sid2[] = {
+       static const uint8_t long_binary_sid2[] = {
                0x1, /* revision number */
                32, /* num auths */
                0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
@@ -8168,7 +10399,7 @@ static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
 
        sname = strchr_m(fname, ':');
 
-       if (lp_posix_pathnames() || (sname == NULL)) {
+       if (sname == NULL) {
                if (pbase != NULL) {
                        base = talloc_strdup(mem_ctx, fname);
                        NT_STATUS_HAVE_NO_MEMORY(base);
@@ -8225,7 +10456,7 @@ static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
                /*
                 * upper-case the type field
                 */
-               strupper_m(strchr_m(stream, ':')+1);
+               (void)strupper_m(strchr_m(stream, ':')+1);
        }
 
  done:
@@ -8424,9 +10655,9 @@ static void wbclient_done(struct tevent_req *req)
        d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
 }
 
-static bool run_local_wbclient(int dummy)
+static bool run_wbclient_multi_ping(int dummy)
 {
-       struct event_context *ev;
+       struct tevent_context *ev;
        struct wb_context **wb_ctx;
        struct winbindd_request wb_req;
        bool result = false;
@@ -8434,7 +10665,7 @@ static bool run_local_wbclient(int dummy)
 
        BlockSignals(True, SIGPIPE);
 
-       ev = tevent_context_init_byname(talloc_tos(), "epoll");
+       ev = tevent_context_init(talloc_tos());
        if (ev == NULL) {
                goto fail;
        }
@@ -8503,7 +10734,7 @@ static bool run_getaddrinfo_send(int dummy)
        struct tevent_req *reqs[4];
        int i;
 
-       ev = event_context_init(frame);
+       ev = samba_tevent_context_init(frame);
        if (ev == NULL) {
                goto fail;
        }
@@ -8579,7 +10810,8 @@ static bool run_local_dbtrans(int dummy)
        TDB_DATA value;
 
        db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
-                    O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
+                    O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
+                    DBWRAP_FLAG_NONE);
        if (db == NULL) {
                printf("Could not open transtest.db\n");
                return false;
@@ -8834,6 +11066,178 @@ static bool run_local_remove_duplicate_addrs2(int dummy)
        return true;
 }
 
+static bool run_local_tdb_opener(int dummy)
+{
+       TDB_CONTEXT *t;
+       unsigned v = 0;
+
+       while (1) {
+               t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
+                            O_RDWR|O_CREAT, 0755);
+               if (t == NULL) {
+                       perror("tdb_open failed");
+                       return false;
+               }
+               tdb_close(t);
+
+               v += 1;
+               printf("\r%u", v);
+       }
+       return true;
+}
+
+static bool run_local_tdb_writer(int dummy)
+{
+       TDB_CONTEXT *t;
+       unsigned v = 0;
+       TDB_DATA val;
+
+       t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
+       if (t == 0) {
+               perror("tdb_open failed");
+               return 1;
+       }
+
+       val.dptr = (uint8_t *)&v;
+       val.dsize = sizeof(v);
+
+       while (1) {
+               TDB_DATA data;
+               int ret;
+
+               ret = tdb_store(t, val, val, 0);
+               if (ret != 0) {
+                       printf("%s\n", tdb_errorstr(t));
+               }
+               v += 1;
+               printf("\r%u", v);
+
+               data = tdb_fetch(t, val);
+               if (data.dptr != NULL) {
+                       SAFE_FREE(data.dptr);
+               }
+       }
+       return true;
+}
+
+static bool run_local_canonicalize_path(int dummy)
+{
+       const char *src[] = {
+                       "/foo/..",
+                       "/..",
+                       "/foo/bar/../baz",
+                       "/foo/././",
+                       "/../foo",
+                       ".././././",
+                       ".././././../../../boo",
+                       "./..",
+                       NULL
+                       };
+       const char *dst[] = {
+                       "/",
+                       "/",
+                       "/foo/baz",
+                       "/foo",
+                       "/foo",
+                       "/",
+                       "/boo",
+                       "/",
+                       NULL
+                       };
+       unsigned int i;
+
+       for (i = 0; src[i] != NULL; i++) {
+               char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
+               if (d == NULL) {
+                       perror("talloc fail\n");
+                       return false;
+               }
+               if (strcmp(d, dst[i]) != 0) {
+                       d_fprintf(stderr,
+                               "canonicalize missmatch %s -> %s != %s",
+                               src[i], d, dst[i]);
+                       return false;
+               }
+               talloc_free(d);
+       }
+       return true;
+}
+
+static bool run_ign_bad_negprot(int dummy)
+{
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       struct smbXcli_conn *conn;
+       struct sockaddr_storage ss;
+       NTSTATUS status;
+       int fd;
+       bool ok;
+
+       printf("starting ignore bad negprot\n");
+
+       ok = resolve_name(host, &ss, 0x20, true);
+       if (!ok) {
+               d_fprintf(stderr, "Could not resolve name %s\n", host);
+               return false;
+       }
+
+       status = open_socket_out(&ss, 445, 10000, &fd);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "open_socket_out failed: %s\n",
+                         nt_errstr(status));
+               return false;
+       }
+
+       conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
+                                  NULL, 0);
+       if (conn == NULL) {
+               d_fprintf(stderr, "smbXcli_conn_create failed\n");
+               return false;
+       }
+
+       status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
+       if (NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
+               return false;
+       }
+
+       ev = samba_tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               d_fprintf(stderr, "samba_tevent_context_init failed\n");
+               return false;
+       }
+
+       req = smb1cli_session_setup_nt1_send(
+               ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
+               data_blob_null, data_blob_null, 0x40,
+               "Windows 2000 2195", "Windows 2000 5.0");
+       if (req == NULL) {
+               d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
+               return false;
+       }
+
+       ok = tevent_req_poll_ntstatus(req, ev, &status);
+       if (!ok) {
+               d_fprintf(stderr, "tevent_req_poll failed\n");
+               return false;
+       }
+
+       status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
+                                               NULL, NULL);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
+               d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
+                         "%s, expected NT_STATUS_CONNECTION_RESET\n",
+                         nt_errstr(status));
+               return false;
+       }
+
+       TALLOC_FREE(conn);
+
+       printf("starting ignore bad negprot\n");
+
+       return true;
+}
+
 static double create_procs(bool (*fn)(int), bool *result)
 {
        int i, status;
@@ -8972,6 +11376,11 @@ static struct {
        {"OPEN", run_opentest, 0},
        {"POSIX", run_simple_posix_open_test, 0},
        {"POSIX-APPEND", run_posix_append, 0},
+       {"POSIX-SYMLINK-ACL", run_acl_symlink_test, 0},
+       {"POSIX-SYMLINK-EA", run_ea_symlink_test, 0},
+       {"POSIX-STREAM-DELETE", run_posix_stream_delete, 0},
+       {"POSIX-OFD-LOCK", run_posix_ofd_lock_test, 0},
+       {"WINDOWS-BAD-SYMLINK", run_symlink_open_test, 0},
        {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
        {"ASYNC-ECHO", run_async_echo, 0},
        { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
@@ -8982,11 +11391,15 @@ static struct {
 #endif
        {"XCOPY", run_xcopy, 0},
        {"RENAME", run_rename, 0},
+       {"RENAME-ACCESS", run_rename_access, 0},
+       {"OWNER-RIGHTS", run_owner_rights, 0},
        {"DELETE", run_deletetest, 0},
+       {"WILDDELETE", run_wild_deletetest, 0},
        {"DELETE-LN", run_deletetest_ln, 0},
        {"PROPERTIES", run_properties, 0},
        {"MANGLE", torture_mangle, 0},
        {"MANGLE1", run_mangle1, 0},
+       {"MANGLE-ILLEGAL", run_mangle_illegal, 0},
        {"W2K", run_w2ktest, 0},
        {"TRANS2SCAN", torture_trans2_scan, 0},
        {"NTTRANSSCAN", torture_nttrans_scan, 0},
@@ -9004,6 +11417,7 @@ static struct {
        { "CHAIN2", run_chain2, 0},
        { "CHAIN3", run_chain3, 0},
        { "WINDOWS-WRITE", run_windows_write, 0},
+       { "LARGE_READX", run_large_readx, 0},
        { "NTTRANS-CREATE", run_nttrans_create, 0},
        { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
        { "CLI_ECHO", run_cli_echo, 0},
@@ -9014,6 +11428,7 @@ static struct {
        { "NOTIFY-BENCH2", run_notify_bench2 },
        { "NOTIFY-BENCH3", run_notify_bench3 },
        { "BAD-NBT-SESSION", run_bad_nbt_session },
+       { "IGN-BAD-NEGPROT", run_ign_bad_negprot },
        { "SMB-ANY-CONNECT", run_smb_any_connect },
        { "NOTIFY-ONLINE", run_notify_online },
        { "SMB2-BASIC", run_smb2_basic },
@@ -9022,33 +11437,57 @@ static struct {
        { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
        { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
        { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
+       { "SMB2-FTRUNCATE", run_smb2_ftruncate },
        { "CLEANUP1", run_cleanup1 },
        { "CLEANUP2", run_cleanup2 },
        { "CLEANUP3", run_cleanup3 },
+       { "CLEANUP4", run_cleanup4 },
+       { "OPLOCK-CANCEL", run_oplock_cancel },
+       { "PIDHIGH", run_pidhigh },
        { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
        { "LOCAL-GENCACHE", run_local_gencache, 0},
        { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
-       { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
-       { "LOCAL-MSG", run_msg_test, 0},
        { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
+       { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
+       { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
+       { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
+       { "LOCAL-MESSAGING-READ4", run_messaging_read4, 0 },
+       { "LOCAL-MESSAGING-FDPASS1", run_messaging_fdpass1, 0 },
+       { "LOCAL-MESSAGING-FDPASS2", run_messaging_fdpass2, 0 },
+       { "LOCAL-MESSAGING-FDPASS2a", run_messaging_fdpass2a, 0 },
+       { "LOCAL-MESSAGING-FDPASS2b", run_messaging_fdpass2b, 0 },
        { "LOCAL-BASE64", run_local_base64, 0},
        { "LOCAL-RBTREE", run_local_rbtree, 0},
        { "LOCAL-MEMCACHE", run_local_memcache, 0},
        { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
-       { "LOCAL-WBCLIENT", run_local_wbclient, 0},
+       { "WBCLIENT-MULTI-PING", run_wbclient_multi_ping, 0},
        { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
+       { "LOCAL-sid_to_string", run_local_sid_to_string, 0},
        { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
        { "LOCAL-DBTRANS", run_local_dbtrans, 0},
        { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
        { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
        { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
-       { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
        { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
        { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
        { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
+       { "local-tdb-opener", run_local_tdb_opener, 0 },
+       { "local-tdb-writer", run_local_tdb_writer, 0 },
+       { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 },
+       { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 },
+       { "LOCAL-PTHREADPOOL-TEVENT", run_pthreadpool_tevent, 0 },
+       { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 },
+       { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 },
        {NULL, NULL, 0}};
 
-
+/*
+ * dummy function to satisfy linker dependency
+ */
+struct tevent_context *winbind_event_context(void);
+struct tevent_context *winbind_event_context(void)
+{
+       return NULL;
+}
 
 /****************************************************************************
 run a specified test or "ALL"
@@ -9113,7 +11552,7 @@ static void usage(void)
 
        printf("\t-d debuglevel\n");
        printf("\t-U user%%pass\n");
-       printf("\t-k               use kerberos\n");
+       printf("\t-k                    use kerberos\n");
        printf("\t-N numprocs\n");
        printf("\t-n my_netbios_name\n");
        printf("\t-W workgroup\n");
@@ -9121,12 +11560,13 @@ static void usage(void)
        printf("\t-O socket_options\n");
        printf("\t-m maximum protocol\n");
        printf("\t-L use oplocks\n");
-       printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
+       printf("\t-c CLIENT.TXT         specify client load file for NBENCH\n");
        printf("\t-A showall\n");
        printf("\t-p port\n");
        printf("\t-s seed\n");
        printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
-       printf("\t-f filename   filename to test\n");
+       printf("\t-f filename           filename to test\n");
+       printf("\t-e                    encrypt\n");
        printf("\n\n");
 
        printf("tests are:");
@@ -9159,7 +11599,8 @@ static void usage(void)
 
        setup_logging("smbtorture", DEBUG_STDOUT);
 
-       load_case_tables();
+       smb_init_locale();
+       fault_setup();
 
        if (is_default_dyn_CONFIGFILE()) {
                if(getenv("SMB_CONF_PATH")) {
@@ -9217,7 +11658,7 @@ static void usage(void)
                        fstrcpy(workgroup,optarg);
                        break;
                case 'm':
-                       max_protocol = interpret_protocol(optarg, max_protocol);
+                       lp_set_cmdline("client max protocol", optarg);
                        break;
                case 'N':
                        torture_nprocs = atoi(optarg);
@@ -9290,9 +11731,12 @@ static void usage(void)
        if(use_kerberos && !gotuser) gotpass = True;
 
        while (!gotpass) {
-               p = getpass("Password:");
-               if (p) {
-                       fstrcpy(password, p);
+               char pwd[256] = {0};
+               int rc;
+
+               rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
+               if (rc == 0) {
+                       fstrcpy(password, pwd);
                        gotpass = 1;
                }
        }
@@ -9300,6 +11744,20 @@ static void usage(void)
        printf("host=%s share=%s user=%s myname=%s\n", 
               host, share, username, myname);
 
+       torture_creds = cli_session_creds_init(frame,
+                                              username,
+                                              workgroup,
+                                              NULL, /* realm */
+                                              password,
+                                              use_kerberos,
+                                              false, /* fallback_after_kerberos */
+                                              false, /* use_ccache */
+                                              false); /* password_is_nt_hash */
+       if (torture_creds == NULL) {
+               d_printf("cli_session_creds_init() failed.\n");
+               exit(1);
+       }
+
        if (argc == optind) {
                correct = run_test("ALL");
        } else {