2 Unix SMB/CIFS implementation.
4 delete on close testing
6 Copyright (C) Andrew Tridgell 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "libcli/libcli.h"
25 #include "torture/torture.h"
26 #include "torture/util.h"
27 #include "system/filesys.h"
28 #include "libcli/raw/libcliraw.h"
30 #include "torture/raw/proto.h"
32 static bool check_delete_on_close(struct torture_context *tctx,
33 struct smbcli_state *cli, int fnum,
34 const char *fname, bool expect_it,
37 union smb_search_data data;
40 time_t c_time, a_time, m_time;
44 status = torture_single_search(cli, tctx,
47 RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
48 FILE_ATTRIBUTE_DIRECTORY,
50 torture_assert_ntstatus_ok(tctx, status,
51 talloc_asprintf(tctx, "single_search failed (%s)", where));
54 union smb_fileinfo io;
55 int nlink = expect_it ? 0 : 1;
57 io.all_info.level = RAW_FILEINFO_ALL_INFO;
58 io.all_info.in.file.fnum = fnum;
60 status = smb_raw_fileinfo(cli->tree, tctx, &io);
61 torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx,
62 "qfileinfo failed (%s)", where));
64 torture_assert(tctx, expect_it == io.all_info.out.delete_pending,
66 "%s - Expected del_on_close flag %d, qfileinfo/all_info gave %d",
67 where, expect_it, io.all_info.out.delete_pending));
69 torture_assert(tctx, nlink == io.all_info.out.nlink,
71 "%s - Expected nlink %d, qfileinfo/all_info gave %d",
72 where, nlink, io.all_info.out.nlink));
74 io.standard_info.level = RAW_FILEINFO_STANDARD_INFO;
75 io.standard_info.in.file.fnum = fnum;
77 status = smb_raw_fileinfo(cli->tree, tctx, &io);
78 torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
80 torture_assert(tctx, expect_it == io.standard_info.out.delete_pending,
81 talloc_asprintf(tctx, "%s - Expected del_on_close flag %d, qfileinfo/standard_info gave %d\n",
82 where, expect_it, io.standard_info.out.delete_pending));
84 torture_assert(tctx, nlink == io.standard_info.out.nlink,
85 talloc_asprintf(tctx, "%s - Expected nlink %d, qfileinfo/standard_info gave %d",
86 where, nlink, io.all_info.out.nlink));
89 status = smbcli_qpathinfo(cli->tree, fname,
90 &c_time, &a_time, &m_time,
94 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
95 "qpathinfo did not give correct error code");
97 torture_assert_ntstatus_ok(tctx, status,
98 talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
104 #define CHECK_STATUS(_cli, _expected) \
105 torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
108 static const char *fname = "\\delete.file";
109 static const char *fname_new = "\\delete.new";
110 static const char *dname = "\\delete.dir";
112 static void del_clean_area(struct smbcli_state *cli1, struct smbcli_state *cli2)
114 smb_raw_exit(cli1->session);
115 smb_raw_exit(cli2->session);
117 smbcli_deltree(cli1->tree, dname);
118 smbcli_setatr(cli1->tree, fname, 0, 0);
119 smbcli_unlink(cli1->tree, fname);
120 smbcli_setatr(cli1->tree, fname_new, 0, 0);
121 smbcli_unlink(cli1->tree, fname_new);
124 /* Test 1 - this should delete the file on close. */
126 static bool deltest1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
130 del_clean_area(cli1, cli2);
132 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
134 FILE_ATTRIBUTE_NORMAL,
135 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
136 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
138 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
139 fname, smbcli_errstr(cli1->tree)));
141 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
142 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli1->tree)));
144 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
145 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
151 /* Test 2 - this should delete the file on close. */
152 static bool deltest2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
156 del_clean_area(cli1, cli2);
158 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
160 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
161 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
163 torture_assert(tctx, fnum1 != -1,
164 talloc_asprintf(tctx, "open of %s failed (%s)",
165 fname, smbcli_errstr(cli1->tree)));
167 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
168 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
169 smbcli_errstr(cli1->tree)));
171 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
172 talloc_asprintf(tctx, "close failed (%s)",
173 smbcli_errstr(cli1->tree)));
175 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
177 printf("(%s) open of %s succeeded should have been deleted on close !\n",
178 __location__, fname);
179 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
180 printf("(%s) close failed (%s)\n",
181 __location__, smbcli_errstr(cli1->tree));
184 smbcli_unlink(cli1->tree, fname);
190 static bool deltest3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
195 del_clean_area(cli1, cli2);
197 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
199 FILE_ATTRIBUTE_NORMAL,
200 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
201 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
203 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
204 fname, smbcli_errstr(cli1->tree)));
206 /* This should fail with a sharing violation - open for delete is only compatible
207 with SHARE_DELETE. */
209 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
210 SEC_RIGHTS_FILE_READ,
211 FILE_ATTRIBUTE_NORMAL,
212 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
213 NTCREATEX_DISP_OPEN, 0, 0);
215 torture_assert(tctx, fnum2 == -1,
216 talloc_asprintf(tctx, "open - 2 of %s succeeded - should have failed.",
219 /* This should succeed. */
221 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
222 SEC_RIGHTS_FILE_READ,
223 FILE_ATTRIBUTE_NORMAL,
224 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
225 NTCREATEX_DISP_OPEN, 0, 0);
227 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
228 fname, smbcli_errstr(cli1->tree)));
230 torture_assert_ntstatus_ok(tctx,
231 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
232 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
233 smbcli_errstr(cli1->tree)));
235 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
236 talloc_asprintf(tctx, "close 1 failed (%s)",
237 smbcli_errstr(cli1->tree)));
239 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum2),
240 talloc_asprintf(tctx, "close 2 failed (%s)",
241 smbcli_errstr(cli1->tree)));
243 /* This should fail - file should no longer be there. */
245 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
247 printf("(%s) open of %s succeeded should have been deleted on close !\n",
248 __location__, fname);
249 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
250 printf("(%s) close failed (%s)\n",
251 __location__, smbcli_errstr(cli1->tree));
253 smbcli_unlink(cli1->tree, fname);
260 static bool deltest4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
266 del_clean_area(cli1, cli2);
268 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
270 SEC_FILE_WRITE_DATA |
272 FILE_ATTRIBUTE_NORMAL,
273 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
274 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
276 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
277 fname, smbcli_errstr(cli1->tree)));
279 /* This should succeed. */
280 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
281 SEC_RIGHTS_FILE_READ,
282 FILE_ATTRIBUTE_NORMAL,
283 NTCREATEX_SHARE_ACCESS_READ |
284 NTCREATEX_SHARE_ACCESS_WRITE |
285 NTCREATEX_SHARE_ACCESS_DELETE,
286 NTCREATEX_DISP_OPEN, 0, 0);
287 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
288 fname, smbcli_errstr(cli1->tree)));
290 torture_assert_ntstatus_ok(tctx,
291 smbcli_close(cli1->tree, fnum2),
292 talloc_asprintf(tctx, "close - 1 failed (%s)",
293 smbcli_errstr(cli1->tree)));
295 torture_assert_ntstatus_ok(tctx,
296 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
297 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
298 smbcli_errstr(cli1->tree)));
300 /* This should fail - no more opens once delete on close set. */
301 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
302 SEC_RIGHTS_FILE_READ,
303 FILE_ATTRIBUTE_NORMAL,
304 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
305 NTCREATEX_DISP_OPEN, 0, 0);
306 torture_assert(tctx, fnum2 == -1,
307 talloc_asprintf(tctx, "open - 3 of %s succeeded ! Should have failed.",
310 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
312 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
313 talloc_asprintf(tctx, "close - 2 failed (%s)",
314 smbcli_errstr(cli1->tree)));
320 static bool deltest5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
324 del_clean_area(cli1, cli2);
326 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
327 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
328 fname, smbcli_errstr(cli1->tree)));
330 /* This should fail - only allowed on NT opens with DELETE access. */
332 torture_assert(tctx, !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True)),
333 "setting delete_on_close on OpenX file succeeded - should fail !");
335 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
336 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
342 static bool deltest6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
346 del_clean_area(cli1, cli2);
348 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
349 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
350 FILE_ATTRIBUTE_NORMAL,
351 NTCREATEX_SHARE_ACCESS_READ |
352 NTCREATEX_SHARE_ACCESS_WRITE |
353 NTCREATEX_SHARE_ACCESS_DELETE,
354 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
356 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
357 fname, smbcli_errstr(cli1->tree)));
359 /* This should fail - only allowed on NT opens with DELETE access. */
362 !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True)),
363 "setting delete_on_close on file with no delete access succeeded - should fail !");
365 torture_assert_ntstatus_ok(tctx,
366 smbcli_close(cli1->tree, fnum1),
367 talloc_asprintf(tctx, "close - 2 failed (%s)",
368 smbcli_errstr(cli1->tree)));
374 static bool deltest7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
379 del_clean_area(cli1, cli2);
381 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
383 SEC_FILE_WRITE_DATA |
385 FILE_ATTRIBUTE_NORMAL, 0,
386 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
388 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
389 fname, smbcli_errstr(cli1->tree)));
391 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
392 "setting delete_on_close on file failed !");
394 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
396 torture_assert_ntstatus_ok(tctx,
397 smbcli_nt_delete_on_close(cli1->tree, fnum1, False),
398 "unsetting delete_on_close on file failed !");
400 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
402 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
403 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
405 /* This next open should succeed - we reset the flag. */
407 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
408 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
409 fname, smbcli_errstr(cli1->tree)));
411 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
412 talloc_asprintf(tctx, "close - 2 failed (%s)",
413 smbcli_errstr(cli1->tree)));
419 static bool deltest8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
425 del_clean_area(cli1, cli2);
427 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
431 FILE_ATTRIBUTE_NORMAL,
432 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
433 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
435 torture_assert(tctx, fnum1 != -1,
436 talloc_asprintf(tctx, "open of %s failed (%s)",
437 fname, smbcli_errstr(cli1->tree)));
439 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
443 FILE_ATTRIBUTE_NORMAL,
444 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
445 NTCREATEX_DISP_OPEN, 0, 0);
447 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
448 fname, smbcli_errstr(cli1->tree)));
450 torture_assert_ntstatus_ok(tctx,
451 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
452 "setting delete_on_close on file failed !");
454 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
455 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
457 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
458 talloc_asprintf(tctx, "close - 1 failed (%s)",
459 smbcli_errstr(cli1->tree)));
461 correct &= check_delete_on_close(tctx, cli1, -1, fname, True, __location__);
462 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
464 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
465 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli2->tree)));
467 /* This should fail.. */
468 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
469 torture_assert(tctx, fnum1 == -1,
470 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !\n", fname));
476 static bool deltest9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
480 del_clean_area(cli1, cli2);
482 /* This should fail - we need to set DELETE_ACCESS. */
483 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
484 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
485 FILE_ATTRIBUTE_NORMAL,
486 NTCREATEX_SHARE_ACCESS_NONE,
487 NTCREATEX_DISP_OVERWRITE_IF,
488 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
490 torture_assert(tctx, fnum1 == -1,
491 talloc_asprintf(tctx, "open of %s succeeded should have failed!",
498 static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
502 del_clean_area(cli1, cli2);
504 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
508 FILE_ATTRIBUTE_NORMAL,
509 NTCREATEX_SHARE_ACCESS_NONE,
510 NTCREATEX_DISP_OVERWRITE_IF,
511 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
512 torture_assert(tctx, fnum1 != -1,
513 talloc_asprintf(tctx, "open of %s failed (%s)",
514 fname, smbcli_errstr(cli1->tree)));
516 /* This should delete the file. */
517 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
518 talloc_asprintf(tctx, "close failed (%s)",
519 smbcli_errstr(cli1->tree)));
521 /* This should fail.. */
522 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
523 torture_assert(tctx, fnum1 == -1,
524 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
530 static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
535 del_clean_area(cli1, cli2);
537 /* test 11 - does having read only attribute still allow delete on close. */
539 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
541 FILE_ATTRIBUTE_READONLY,
542 NTCREATEX_SHARE_ACCESS_NONE,
543 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
545 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
546 fname, smbcli_errstr(cli1->tree)));
548 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, True);
550 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
551 talloc_asprintf(tctx, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1->tree)));
553 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
554 talloc_asprintf(tctx, "close failed (%s)",
555 smbcli_errstr(cli1->tree)));
561 static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
566 del_clean_area(cli1, cli2);
568 /* test 12 - does having read only attribute still allow delete on
569 * close at time of open. */
571 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
573 FILE_ATTRIBUTE_READONLY,
574 NTCREATEX_SHARE_ACCESS_DELETE,
575 NTCREATEX_DISP_OVERWRITE_IF,
576 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
578 torture_assert(tctx, fnum1 == -1,
579 talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
580 "NT_STATUS_CANNOT_DELETE.\n", fname));
582 status = smbcli_nt_error(cli1->tree);
583 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
584 talloc_asprintf(tctx, "setting delete_on_close on open should "
585 "fail with NT_STATUS_CANNOT_DELETE. Got %s "
587 smbcli_errstr(cli1->tree)));
593 static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
599 del_clean_area(cli1, cli2);
601 /* Test 13: Does resetting the delete on close flag affect a second
604 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
608 FILE_ATTRIBUTE_NORMAL,
609 NTCREATEX_SHARE_ACCESS_READ|
610 NTCREATEX_SHARE_ACCESS_WRITE|
611 NTCREATEX_SHARE_ACCESS_DELETE,
612 NTCREATEX_DISP_OVERWRITE_IF,
615 torture_assert(tctx, fnum1 != -1,
616 talloc_asprintf(tctx, "open of %s failed (%s)",
617 fname, smbcli_errstr(cli1->tree)));
619 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
623 FILE_ATTRIBUTE_NORMAL,
624 NTCREATEX_SHARE_ACCESS_READ|
625 NTCREATEX_SHARE_ACCESS_WRITE|
626 NTCREATEX_SHARE_ACCESS_DELETE,
627 NTCREATEX_DISP_OPEN, 0, 0);
629 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
630 "open of %s failed (%s)",
631 fname, smbcli_errstr(cli2->tree)));
633 torture_assert_ntstatus_ok(tctx,
634 smbcli_nt_delete_on_close(cli1->tree, fnum1,
636 "setting delete_on_close on file failed !");
638 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
639 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
641 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
643 "setting delete_on_close on file failed !");
645 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
646 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
648 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
649 talloc_asprintf(tctx, "close - 1 failed (%s)",
650 smbcli_errstr(cli1->tree)));
652 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
653 talloc_asprintf(tctx, "close - 2 failed (%s)",
654 smbcli_errstr(cli2->tree)));
656 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
658 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!",
661 smbcli_close(cli1->tree, fnum1);
667 static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
672 del_clean_area(cli1, cli2);
674 /* Test 14 -- directory */
676 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
680 FILE_ATTRIBUTE_DIRECTORY,
681 NTCREATEX_SHARE_ACCESS_READ|
682 NTCREATEX_SHARE_ACCESS_WRITE|
683 NTCREATEX_SHARE_ACCESS_DELETE,
684 NTCREATEX_DISP_CREATE, 0, 0);
685 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
686 dname, smbcli_errstr(cli1->tree)));
688 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, False, __location__);
689 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, True),
690 "setting delete_on_close on file failed !");
691 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, True, __location__);
692 smbcli_close(cli1->tree, dnum1);
694 /* Now it should be gone... */
696 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
700 FILE_ATTRIBUTE_DIRECTORY,
701 NTCREATEX_SHARE_ACCESS_READ|
702 NTCREATEX_SHARE_ACCESS_WRITE|
703 NTCREATEX_SHARE_ACCESS_DELETE,
704 NTCREATEX_DISP_OPEN, 0, 0);
705 torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
711 static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
718 del_clean_area(cli1, cli2);
720 /* Test 15: delete on close under rename */
722 smbcli_setatr(cli1->tree, fname, 0, 0);
723 smbcli_unlink(cli1->tree, fname);
724 smbcli_unlink(cli1->tree, fname_new);
726 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
728 FILE_ATTRIBUTE_NORMAL,
729 NTCREATEX_SHARE_ACCESS_READ|
730 NTCREATEX_SHARE_ACCESS_WRITE|
731 NTCREATEX_SHARE_ACCESS_DELETE,
732 NTCREATEX_DISP_OVERWRITE_IF,
735 torture_assert(tctx, fnum1 != -1,
736 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
738 status = smbcli_rename(cli2->tree, fname, fname_new);
740 torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
742 fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
744 FILE_ATTRIBUTE_NORMAL,
745 NTCREATEX_SHARE_ACCESS_READ|
746 NTCREATEX_SHARE_ACCESS_WRITE|
747 NTCREATEX_SHARE_ACCESS_DELETE,
748 NTCREATEX_DISP_OVERWRITE_IF,
751 torture_assert(tctx, fnum2 != -1,
752 talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
753 fname_new, smbcli_errstr(cli1->tree)));
755 status = smbcli_nt_delete_on_close(cli2->tree, fnum2, True);
757 torture_assert_ntstatus_ok(tctx, status,
758 "setting delete_on_close on file failed !");
760 smbcli_close(cli2->tree, fnum2);
762 /* The file should be around under the new name, there's a second
765 correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, True, __location__);
767 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
769 FILE_ATTRIBUTE_NORMAL,
770 NTCREATEX_SHARE_ACCESS_READ|
771 NTCREATEX_SHARE_ACCESS_WRITE|
772 NTCREATEX_SHARE_ACCESS_DELETE,
773 NTCREATEX_DISP_OVERWRITE_IF,
776 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
777 fname, smbcli_errstr(cli1->tree)));
779 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
781 smbcli_close(cli2->tree, fnum2);
782 smbcli_close(cli1->tree, fnum1);
784 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
786 FILE_ATTRIBUTE_NORMAL,
787 NTCREATEX_SHARE_ACCESS_READ|
788 NTCREATEX_SHARE_ACCESS_WRITE|
789 NTCREATEX_SHARE_ACCESS_DELETE,
793 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
794 fname, smbcli_errstr(cli1->tree)));
796 smbcli_close(cli1->tree, fnum1);
798 fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
800 FILE_ATTRIBUTE_NORMAL,
801 NTCREATEX_SHARE_ACCESS_READ|
802 NTCREATEX_SHARE_ACCESS_WRITE|
803 NTCREATEX_SHARE_ACCESS_DELETE,
807 torture_assert(tctx, fnum1 == -1,
808 "smbcli_open succeeded, should have "
815 static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
821 del_clean_area(cli1, cli2);
825 /* Ensure the file doesn't already exist. */
826 smbcli_close(cli1->tree, fnum1);
827 smbcli_close(cli1->tree, fnum2);
828 smbcli_setatr(cli1->tree, fname, 0, 0);
829 smbcli_unlink(cli1->tree, fname);
831 /* Firstly create with all access, but delete on close. */
832 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
834 FILE_ATTRIBUTE_NORMAL,
835 NTCREATEX_SHARE_ACCESS_READ|
836 NTCREATEX_SHARE_ACCESS_WRITE|
837 NTCREATEX_SHARE_ACCESS_DELETE,
838 NTCREATEX_DISP_CREATE,
839 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
841 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
843 /* The delete on close bit is *not* reported as being set. */
844 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
846 /* The delete on close bit is *not* reported as being set. */
847 correct &= check_delete_on_close(tctx, cli1, -1, fname, False, __location__);
848 correct &= check_delete_on_close(tctx, cli2, -1, fname, False, __location__);
850 /* Now try opening again for read-only. */
851 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
852 SEC_RIGHTS_FILE_READ,
853 FILE_ATTRIBUTE_NORMAL,
854 NTCREATEX_SHARE_ACCESS_READ|
855 NTCREATEX_SHARE_ACCESS_WRITE|
856 NTCREATEX_SHARE_ACCESS_DELETE,
861 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
862 fname, smbcli_errstr(cli1->tree)));
864 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
865 correct &= check_delete_on_close(tctx, cli1, -1, fname, False, __location__);
866 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
867 correct &= check_delete_on_close(tctx, cli2, -1, fname, False, __location__);
869 smbcli_close(cli1->tree, fnum1);
871 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
872 correct &= check_delete_on_close(tctx, cli2, -1, fname, True, __location__);
874 smbcli_close(cli2->tree, fnum2);
876 /* And the file should be deleted ! */
877 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
878 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
885 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
891 del_clean_area(cli1, cli2);
895 /* Ensure the file doesn't already exist. */
896 smbcli_close(cli1->tree, fnum1);
897 smbcli_close(cli1->tree, fnum2);
898 smbcli_setatr(cli1->tree, fname, 0, 0);
899 smbcli_unlink(cli1->tree, fname);
901 /* Firstly open and create with all access */
902 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
904 FILE_ATTRIBUTE_NORMAL,
905 NTCREATEX_SHARE_ACCESS_READ|
906 NTCREATEX_SHARE_ACCESS_WRITE|
907 NTCREATEX_SHARE_ACCESS_DELETE,
908 NTCREATEX_DISP_CREATE,
910 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
911 fname, smbcli_errstr(cli1->tree)));
913 /* And close - just to create the file. */
914 smbcli_close(cli1->tree, fnum1);
916 /* Next open with all access, but add delete on close. */
917 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
919 FILE_ATTRIBUTE_NORMAL,
920 NTCREATEX_SHARE_ACCESS_READ|
921 NTCREATEX_SHARE_ACCESS_WRITE|
922 NTCREATEX_SHARE_ACCESS_DELETE,
924 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
926 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
927 fname, smbcli_errstr(cli1->tree)));
929 /* The delete on close bit is *not* reported as being set. */
930 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
932 /* Now try opening again for read-only. */
933 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
934 SEC_RIGHTS_FILE_READ|
936 FILE_ATTRIBUTE_NORMAL,
937 NTCREATEX_SHARE_ACCESS_READ|
938 NTCREATEX_SHARE_ACCESS_WRITE|
939 NTCREATEX_SHARE_ACCESS_DELETE,
944 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
945 fname, smbcli_errstr(cli1->tree)));
947 /* still not reported as being set on either */
948 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
949 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, False, __location__);
951 smbcli_close(cli1->tree, fnum1);
953 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, False, __location__);
955 smbcli_close(cli1->tree, fnum2);
957 /* See if the file is deleted - shouldn't be.... */
958 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
959 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
960 fname, smbcli_errstr(cli1->tree)));
966 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
972 del_clean_area(cli1, cli2);
974 /* Test 18. With directories. */
976 /* Ensure the file doesn't already exist. */
977 smbcli_close(cli1->tree, fnum1);
978 smbcli_close(cli1->tree, fnum2);
980 smbcli_deltree(cli1->tree, dname);
982 /* Firstly create with all access, but delete on close. */
983 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
987 FILE_ATTRIBUTE_DIRECTORY,
988 NTCREATEX_SHARE_ACCESS_READ|
989 NTCREATEX_SHARE_ACCESS_WRITE|
990 NTCREATEX_SHARE_ACCESS_DELETE,
991 NTCREATEX_DISP_CREATE,
992 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
994 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
995 dname, smbcli_errstr(cli1->tree)));
997 /* The delete on close bit is *not* reported as being set. */
998 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, False, __location__);
1000 /* Now try opening again for read-only. */
1001 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1002 SEC_RIGHTS_FILE_READ,
1003 FILE_ATTRIBUTE_DIRECTORY,
1004 NTCREATEX_SHARE_ACCESS_READ|
1005 NTCREATEX_SHARE_ACCESS_WRITE|
1006 NTCREATEX_SHARE_ACCESS_DELETE,
1007 NTCREATEX_DISP_OPEN,
1008 NTCREATEX_OPTIONS_DIRECTORY, 0);
1012 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1013 dname, smbcli_errstr(cli1->tree)));
1015 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, False, __location__);
1016 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, False, __location__);
1018 smbcli_close(cli1->tree, fnum1);
1020 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, True, __location__);
1022 smbcli_close(cli1->tree, fnum2);
1024 /* And the directory should be deleted ! */
1025 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1026 SEC_RIGHTS_FILE_READ,
1027 FILE_ATTRIBUTE_DIRECTORY,
1028 NTCREATEX_SHARE_ACCESS_READ|
1029 NTCREATEX_SHARE_ACCESS_WRITE|
1030 NTCREATEX_SHARE_ACCESS_DELETE,
1031 NTCREATEX_DISP_OPEN,
1032 NTCREATEX_OPTIONS_DIRECTORY, 0);
1033 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
1040 static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1044 bool correct = True;
1046 del_clean_area(cli1, cli2);
1050 smbcli_deltree(cli1->tree, dname);
1052 /* Firstly open and create with all access */
1053 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1055 SEC_FILE_WRITE_DATA|
1057 FILE_ATTRIBUTE_DIRECTORY,
1058 NTCREATEX_SHARE_ACCESS_READ|
1059 NTCREATEX_SHARE_ACCESS_WRITE|
1060 NTCREATEX_SHARE_ACCESS_DELETE,
1061 NTCREATEX_DISP_CREATE,
1062 NTCREATEX_OPTIONS_DIRECTORY, 0);
1064 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1065 dname, smbcli_errstr(cli1->tree)));
1067 /* And close - just to create the directory. */
1068 smbcli_close(cli1->tree, fnum1);
1070 /* Next open with all access, but add delete on close. */
1071 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1073 SEC_FILE_WRITE_DATA|
1075 FILE_ATTRIBUTE_DIRECTORY,
1076 NTCREATEX_SHARE_ACCESS_READ|
1077 NTCREATEX_SHARE_ACCESS_WRITE|
1078 NTCREATEX_SHARE_ACCESS_DELETE,
1079 NTCREATEX_DISP_OPEN,
1080 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1082 torture_assert(tctx, fnum1 != -1,
1083 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1085 /* The delete on close bit is *not* reported as being set. */
1086 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, False, __location__);
1088 /* Now try opening again for read-only. */
1089 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1090 SEC_RIGHTS_FILE_READ,
1091 FILE_ATTRIBUTE_DIRECTORY,
1092 NTCREATEX_SHARE_ACCESS_READ|
1093 NTCREATEX_SHARE_ACCESS_WRITE|
1094 NTCREATEX_SHARE_ACCESS_DELETE,
1095 NTCREATEX_DISP_OPEN,
1096 NTCREATEX_OPTIONS_DIRECTORY, 0);
1099 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1100 dname, smbcli_errstr(cli1->tree)));
1102 smbcli_close(cli1->tree, fnum1);
1104 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, True, __location__);
1106 smbcli_close(cli1->tree, fnum2);
1108 /* See if the file is deleted - for a directory this seems to be true ! */
1109 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1110 SEC_RIGHTS_FILE_READ,
1111 FILE_ATTRIBUTE_DIRECTORY,
1112 NTCREATEX_SHARE_ACCESS_READ|
1113 NTCREATEX_SHARE_ACCESS_WRITE|
1114 NTCREATEX_SHARE_ACCESS_DELETE,
1115 NTCREATEX_DISP_OPEN,
1116 NTCREATEX_OPTIONS_DIRECTORY, 0);
1118 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1120 torture_assert(tctx, fnum1 == -1,
1121 talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1127 static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1131 bool correct = True;
1134 del_clean_area(cli1, cli2);
1136 /* Test 20 -- non-empty directory hardest to get right... */
1138 if (torture_setting_bool(tctx, "samba3", False)) {
1142 smbcli_deltree(cli1->tree, dname);
1144 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1146 SEC_FILE_WRITE_DATA|
1148 FILE_ATTRIBUTE_DIRECTORY,
1149 NTCREATEX_SHARE_ACCESS_READ|
1150 NTCREATEX_SHARE_ACCESS_WRITE|
1151 NTCREATEX_SHARE_ACCESS_DELETE,
1152 NTCREATEX_DISP_CREATE,
1153 NTCREATEX_OPTIONS_DIRECTORY, 0);
1154 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
1155 dname, smbcli_errstr(cli1->tree)));
1157 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, False, __location__);
1158 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
1162 asprintf(&fullname, "\\%s%s", dname, fname);
1163 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1165 torture_assert(tctx, fnum1 == -1,
1166 "smbcli_open succeeded, should have "
1167 "failed with NT_STATUS_DELETE_PENDING"
1170 torture_assert_ntstatus_equal(tctx,
1171 smbcli_nt_error(cli1->tree),
1172 NT_STATUS_DELETE_PENDING,
1173 "smbcli_open failed");
1176 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, False);
1177 torture_assert_ntstatus_ok(tctx, status,
1178 "setting delete_on_close on file failed !");
1182 asprintf(&fullname, "\\%s%s", dname, fname);
1183 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1185 torture_assert(tctx, fnum1 != -1,
1186 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1187 smbcli_errstr(cli1->tree)));
1188 smbcli_close(cli1->tree, fnum1);
1191 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
1193 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1194 "setting delete_on_close failed");
1195 smbcli_close(cli1->tree, dnum1);
1201 static bool deltest21(struct torture_context *tctx)
1204 struct smbcli_state *cli1;
1205 struct smbcli_state *cli2;
1206 bool correct = True;
1208 if (!torture_open_connection(&cli1, 0))
1211 if (!torture_open_connection(&cli2, 1))
1214 del_clean_area(cli1, cli2);
1216 /* Test 21 -- Test removal of file after socket close. */
1218 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1219 SEC_RIGHTS_FILE_ALL,
1220 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
1221 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1223 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
1224 fname, smbcli_errstr(cli1->tree)));
1226 torture_assert_ntstatus_ok(tctx,
1227 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
1228 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
1229 smbcli_errstr(cli1->tree)));
1231 /* Ensure delete on close is set. */
1232 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
1234 /* Now yank the rug from under cli1. */
1235 smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
1239 if (!torture_open_connection(&cli1, 0)) {
1243 /* On slow build farm machines it might happen that they are not fast
1244 * enogh to delete the file for this test */
1247 /* File should not be there. */
1248 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1249 SEC_RIGHTS_FILE_READ,
1250 FILE_ATTRIBUTE_NORMAL,
1251 NTCREATEX_SHARE_ACCESS_READ|
1252 NTCREATEX_SHARE_ACCESS_WRITE|
1253 NTCREATEX_SHARE_ACCESS_DELETE,
1254 NTCREATEX_DISP_OPEN,
1257 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1265 * Test whether a second *directory* handle inhibits delete if the first has
1266 * del-on-close set and is closed
1268 static bool deltest22(struct torture_context *tctx)
1272 struct smbcli_state *cli1;
1273 bool correct = True;
1275 if (!torture_open_connection(&cli1, 0))
1278 smbcli_deltree(cli1->tree, dname);
1280 torture_assert_ntstatus_ok(
1281 tctx, smbcli_mkdir(cli1->tree, dname),
1282 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
1283 smbcli_errstr(cli1->tree)));
1285 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1287 SEC_FILE_WRITE_DATA|
1289 FILE_ATTRIBUTE_DIRECTORY,
1290 NTCREATEX_SHARE_ACCESS_READ|
1291 NTCREATEX_SHARE_ACCESS_WRITE|
1292 NTCREATEX_SHARE_ACCESS_DELETE,
1293 NTCREATEX_DISP_OPEN,
1294 NTCREATEX_OPTIONS_DIRECTORY, 0);
1296 torture_assert(tctx, dnum1 != -1,
1297 talloc_asprintf(tctx, "open of %s failed: %s!",
1298 dname, smbcli_errstr(cli1->tree)));
1300 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1302 SEC_FILE_WRITE_DATA,
1303 FILE_ATTRIBUTE_DIRECTORY,
1304 NTCREATEX_SHARE_ACCESS_READ|
1305 NTCREATEX_SHARE_ACCESS_WRITE|
1306 NTCREATEX_SHARE_ACCESS_DELETE,
1307 NTCREATEX_DISP_OPEN,
1308 NTCREATEX_OPTIONS_DIRECTORY, 0);
1310 torture_assert(tctx, dnum2 != -1,
1311 talloc_asprintf(tctx, "open of %s failed: %s!",
1312 dname, smbcli_errstr(cli1->tree)));
1314 torture_assert_ntstatus_ok(
1315 tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, True),
1316 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
1317 smbcli_errstr(cli1->tree)));
1319 smbcli_close(cli1->tree, dnum1);
1321 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1323 SEC_FILE_WRITE_DATA|
1325 FILE_ATTRIBUTE_DIRECTORY,
1326 NTCREATEX_SHARE_ACCESS_READ|
1327 NTCREATEX_SHARE_ACCESS_WRITE|
1328 NTCREATEX_SHARE_ACCESS_DELETE,
1329 NTCREATEX_DISP_OPEN,
1330 NTCREATEX_OPTIONS_DIRECTORY, 0);
1332 torture_assert(tctx, dnum1 == -1,
1333 talloc_asprintf(tctx, "open of %s succeeded!\n",
1336 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1342 Test delete on close semantics.
1344 struct torture_suite *torture_test_delete(void)
1346 struct torture_suite *suite = torture_suite_create(
1347 talloc_autofree_context(),
1350 torture_suite_add_2smb_test(suite, "deltest1", deltest1);
1351 torture_suite_add_2smb_test(suite, "deltest2", deltest2);
1352 torture_suite_add_2smb_test(suite, "deltest3", deltest3);
1353 torture_suite_add_2smb_test(suite, "deltest4", deltest4);
1354 torture_suite_add_2smb_test(suite, "deltest5", deltest5);
1355 torture_suite_add_2smb_test(suite, "deltest6", deltest6);
1356 torture_suite_add_2smb_test(suite, "deltest7", deltest7);
1357 torture_suite_add_2smb_test(suite, "deltest8", deltest8);
1358 torture_suite_add_2smb_test(suite, "deltest9", deltest9);
1359 torture_suite_add_2smb_test(suite, "deltest10", deltest10);
1360 torture_suite_add_2smb_test(suite, "deltest11", deltest11);
1361 torture_suite_add_2smb_test(suite, "deltest12", deltest12);
1362 torture_suite_add_2smb_test(suite, "deltest13", deltest13);
1363 torture_suite_add_2smb_test(suite, "deltest14", deltest14);
1364 torture_suite_add_2smb_test(suite, "deltest15", deltest15);
1365 torture_suite_add_2smb_test(suite, "deltest16", deltest16);
1366 torture_suite_add_2smb_test(suite, "deltest17", deltest17);
1367 torture_suite_add_2smb_test(suite, "deltest18", deltest18);
1368 torture_suite_add_2smb_test(suite, "deltest19", deltest19);
1369 torture_suite_add_2smb_test(suite, "deltest20", deltest20);
1370 torture_suite_add_simple_test(suite, "deltest21", deltest21);
1371 torture_suite_add_simple_test(suite, "deltest22", deltest22);