s4:torture:basic: add more delete test - variants of deltest16 and deltest17
authorMichael Adam <obnox@samba.org>
Wed, 8 Aug 2012 21:43:05 +0000 (23:43 +0200)
committerStefan Metzmacher <metze@samba.org>
Fri, 17 Aug 2012 19:44:24 +0000 (21:44 +0200)
There seems to be a difference if the initial delete_on_close flag
was set on a handle that created the file or if the handle if was
for a file that already existed.

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Fri Aug 17 21:44:24 CEST 2012 on sn-devel-104

selftest/knownfail
source4/torture/basic/delete.c

index 9376264a3cdffd337183c41e84251858ac0b9c54..1c72718e0473de540c166d442d1d42b63a4ebe3a 100644 (file)
@@ -46,6 +46,8 @@
 ^samba3.raw.samba3checkfsp.samba3checkfsp\(s3dc\) # This test fails against an smbd environment with NT ACLs enabled
 ^samba3.raw.samba3closeerr.samba3closeerr\(s3dc\) # This test fails against an smbd environment with NT ACLs enabled
 ^samba3.raw.acls.generic\(s3dc\) # This fails against smbd
+^samba3.base.delete.deltest16a
+^samba3.base.delete.deltest17a
 ^samba3.unix.whoami anonymous connection.whoami\(plugin_s4_dc\) # We need to resolve if we should be including SID_NT_WORLD and SID_NT_NETWORK in this token
 ^samba3.unix.whoami anonymous connection.whoami\(s3member\) # smbd maps anonymous logins to domain guest in the local domain, not SID_NT_ANONYMOUS
 # these show that we still have some differences between our system
 ^samba.vfstest.acl.vfstest\(s3dc:local\) #until we get the fake_acls module into selftest
 ^samba4.local.convert_string_handle.system.iconv.gd_ascii
 ^samba4.local.convert_string_handle.system.iconv.gd_iso8859_cp850
-^samba4..*base.delete.*.deltest17
+^samba4..*base.delete.*.deltest17\(
+^samba4..*base.delete.*.deltest17b
+^samba4..*base.delete.*.deltest17c
+^samba4..*base.delete.*.deltest17e
+^samba4..*base.delete.*.deltest17f
 ^samba4..*base.delete.*.deltest20a
 ^samba4..*base.delete.*.deltest20b
 ^samba4.raw.session.reauth
index 7fb93456a52438b4a8e5ccc0dc4d1e4563de076e..e3d830da627b7a96b8a23c9dc12a16d9dea2bad8 100644 (file)
@@ -883,6 +883,95 @@ static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, s
        return correct;
 }
 
+/* Test 16 ... */
+static bool deltest16a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       int fnum1 = -1;
+       int fnum2 = -1;
+       bool correct = true;
+
+       del_clean_area(cli1, cli2);
+
+       /* Test 16. */
+
+       /* Ensure the file doesn't already exist. */
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_close(cli1->tree, fnum2);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       /* Firstly open and create with all access */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_CREATE,
+                                     0, 0);
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* And close - just to create the file. */
+       smbcli_close(cli1->tree, fnum1);
+
+       /* Firstly create with all access, but delete on close. */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
+
+       /* Now try opening again for read-only. */
+       fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_READ,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     0, 0);
+
+       /* Should work. */
+       torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                     fname, smbcli_errstr(cli1->tree)));
+
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum1);
+
+       correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
+
+       smbcli_close(cli2->tree, fnum2);
+
+       /* And the file should be deleted ! */
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       return correct;
+}
+
 /* Test 17 ... */
 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 {
@@ -967,6 +1056,532 @@ static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, s
        return correct;
 }
 
+/* Test 17a - like 17, but the delete on close handle is closed last */
+static bool deltest17a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       int fnum1 = -1;
+       int fnum2 = -1;
+       bool correct = true;
+
+       del_clean_area(cli1, cli2);
+
+       /* Ensure the file doesn't already exist. */
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_close(cli1->tree, fnum2);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       /* Firstly open and create with all access */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_CREATE,
+                                     0, 0);
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* And close - just to create the file. */
+       smbcli_close(cli1->tree, fnum1);
+
+       /* Next open with all access, but add delete on close. */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       /* Now try opening again for read-only. */
+       fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_READ|
+                                     SEC_STD_DELETE,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     0, 0);
+
+       /* Should work. */
+       torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* still not reported as being set on either */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum2);
+
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum1);
+
+       /*
+        * The file is still there:
+        * The second open seems to have removed the initial
+        * delete on close flag from the first handle
+        */
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       return correct;
+}
+
+/* Test 17b - like 17a, but the initial delete on close is set on the second handle */
+static bool deltest17b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       int fnum1 = -1;
+       int fnum2 = -1;
+       bool correct = true;
+
+       del_clean_area(cli1, cli2);
+
+       /* Ensure the file doesn't already exist. */
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_close(cli1->tree, fnum2);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       /* Firstly open and create with all access */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_CREATE,
+                                     0, 0);
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* And close - just to create the file. */
+       smbcli_close(cli1->tree, fnum1);
+
+       /* Next open with all access, but add delete on close. */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     0, 0);
+
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       /* Now try opening again for read-only. */
+       fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_READ|
+                                     SEC_STD_DELETE,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       /* Should work. */
+       torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* still not reported as being set on either */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum1);
+
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum2);
+
+       /* Make sure the file has been deleted */
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+       return correct;
+}
+
+/* Test 17c - like 17, but the initial delete on close is set on the second handle */
+static bool deltest17c(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       int fnum1 = -1;
+       int fnum2 = -1;
+       bool correct = true;
+
+       del_clean_area(cli1, cli2);
+
+       /* Ensure the file doesn't already exist. */
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_close(cli1->tree, fnum2);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       /* Firstly open and create with all access */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_CREATE,
+                                     0, 0);
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* And close - just to create the file. */
+       smbcli_close(cli1->tree, fnum1);
+
+       /* Next open with all access, but add delete on close. */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     0, 0);
+
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       /* Now try opening again for read-only. */
+       fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_READ|
+                                     SEC_STD_DELETE,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       /* Should work. */
+       torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* still not reported as being set on either */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum2);
+
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
+
+       fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum2 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
+
+       smbcli_close(cli1->tree, fnum1);
+
+       /* Make sure the file has been deleted */
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+       return correct;
+}
+
+/* Test 17d - like 17a, but the first delete-on-close opener creates the file */
+static bool deltest17d(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       int fnum1 = -1;
+       int fnum2 = -1;
+       bool correct = true;
+
+       del_clean_area(cli1, cli2);
+
+       /* Ensure the file doesn't already exist. */
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_close(cli1->tree, fnum2);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+
+       /* Create the file with delete on close. */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_CREATE,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       /* Now try opening again for read-only. */
+       fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_READ|
+                                     SEC_STD_DELETE,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     0, 0);
+
+       /* Should work. */
+       torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* still not reported as being set on either */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum2);
+
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum1);
+
+       /*
+        * The file is still there:
+        * The second open seems to have removed the initial
+        * delete on close flag from the first handle
+        */
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeed (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+       return correct;
+}
+
+static bool deltest17e(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       int fnum1 = -1;
+       int fnum2 = -1;
+       int fnum3 = -1;
+       bool correct = true;
+
+       del_clean_area(cli1, cli2);
+
+       /* Ensure the file doesn't already exist. */
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_close(cli1->tree, fnum2);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       /* Firstly open and create with all access */
+       fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_CREATE,
+                                     0, 0);
+       torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* Next open with all access, but add delete on close. */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
+
+       /* Now try opening again for read-only. */
+       fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_READ|
+                                     SEC_STD_DELETE,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     0, 0);
+
+       /* Should work. */
+       torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* still not reported as being set on either */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum1);
+
+       /*
+        * closing the handle that has delete_on_close set
+        * inherits the flag to the global context
+        */
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
+
+       smbcli_close(cli1->tree, fnum2);
+
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
+
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
+
+       smbcli_close(cli1->tree, fnum3);
+
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+       return correct;
+}
+
+static bool deltest17f(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
+{
+       int fnum1 = -1;
+       int fnum2 = -1;
+       int fnum3 = -1;
+       bool correct = true;
+       NTSTATUS status;
+
+       del_clean_area(cli1, cli2);
+
+       /* Ensure the file doesn't already exist. */
+       smbcli_close(cli1->tree, fnum1);
+       smbcli_close(cli1->tree, fnum2);
+       smbcli_setatr(cli1->tree, fname, 0, 0);
+       smbcli_unlink(cli1->tree, fname);
+
+       /* Firstly open and create with all access */
+       fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_CREATE,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+       torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* The delete on close bit is *not* reported as being set. */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+
+       /* Next open with all access, but add delete on close. */
+       fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_ALL,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* still not reported as being set on either */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+
+       /* Now try opening again for read-only. */
+       fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
+                                     SEC_RIGHTS_FILE_READ|
+                                     SEC_STD_DELETE,
+                                     FILE_ATTRIBUTE_NORMAL,
+                                     NTCREATEX_SHARE_ACCESS_READ|
+                                     NTCREATEX_SHARE_ACCESS_WRITE|
+                                     NTCREATEX_SHARE_ACCESS_DELETE,
+                                     NTCREATEX_DISP_OPEN,
+                                     NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
+
+       /* Should work. */
+       torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
+                      fname, smbcli_errstr(cli1->tree)));
+
+       /* still not reported as being set on either */
+       correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum1);
+
+       /*
+        * closing the handle that has delete_on_close set
+        * inherits the flag to the global context
+        */
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
+
+
+       status = smbcli_nt_delete_on_close(cli1->tree, fnum2, false);
+       torture_assert_ntstatus_ok(tctx, status,
+                                       "clearing delete_on_close on file failed !");
+
+       correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
+
+       smbcli_close(cli1->tree, fnum2);
+
+       correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
+
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
+
+       smbcli_close(cli1->tree, fnum3);
+
+       fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
+       torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
+                      fname));
+
+       CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
+       return correct;
+}
+
 /* Test 18 ... */
 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 {
@@ -1607,7 +2222,14 @@ struct torture_suite *torture_test_delete(void)
        torture_suite_add_2smb_test(suite, "deltest14", deltest14);
        torture_suite_add_2smb_test(suite, "deltest15", deltest15);
        torture_suite_add_2smb_test(suite, "deltest16", deltest16);
+       torture_suite_add_2smb_test(suite, "deltest16a", deltest16a);
        torture_suite_add_2smb_test(suite, "deltest17", deltest17);
+       torture_suite_add_2smb_test(suite, "deltest17a", deltest17a);
+       torture_suite_add_2smb_test(suite, "deltest17b", deltest17b);
+       torture_suite_add_2smb_test(suite, "deltest17c", deltest17c);
+       torture_suite_add_2smb_test(suite, "deltest17d", deltest17d);
+       torture_suite_add_2smb_test(suite, "deltest17e", deltest17e);
+       torture_suite_add_2smb_test(suite, "deltest17f", deltest17f);
        torture_suite_add_2smb_test(suite, "deltest18", deltest18);
        torture_suite_add_2smb_test(suite, "deltest19", deltest19);
        torture_suite_add_2smb_test(suite, "deltest20", deltest20);