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 "system/filesys.h"
27 #include "libcli/raw/libcliraw.h"
29 static BOOL check_delete_on_close(struct smbcli_state *cli, int fnum,
30 const char *fname, BOOL expect_it)
32 TALLOC_CTX *mem_ctx = talloc_init("single_search");
33 union smb_search_data data;
36 time_t c_time, a_time, m_time;
42 status = torture_single_search(cli, mem_ctx,
43 fname, RAW_SEARCH_FULL_DIRECTORY_INFO,
44 FILE_ATTRIBUTE_DIRECTORY,
46 if (!NT_STATUS_IS_OK(status)) {
47 printf("(%s) single_search failed (%s)\n",
48 __location__, nt_errstr(status));
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.fnum = fnum;
60 status = smb_raw_fileinfo(cli->tree, mem_ctx, &io);
61 if (!NT_STATUS_IS_OK(status)) {
62 printf("(%s) qpathinfo failed (%s)\n", __location__,
68 if (expect_it != io.all_info.out.delete_pending) {
69 printf("Expected del_on_close flag %d, qfileinfo gave %d\n",
70 expect_it, io.all_info.out.delete_pending);
75 if (nlink != io.all_info.out.nlink) {
76 printf("Expected nlink %d, qfileinfo gave %d\n",
77 nlink, io.all_info.out.nlink);
82 io.standard_info.level = RAW_FILEINFO_STANDARD_INFO;
83 io.standard_info.in.fnum = fnum;
85 status = smb_raw_fileinfo(cli->tree, mem_ctx, &io);
86 if (!NT_STATUS_IS_OK(status)) {
87 printf("(%s) qpathinfo failed (%s)\n", __location__,
93 if (expect_it != io.standard_info.out.delete_pending) {
94 printf("Expected del_on_close flag %d, qfileinfo gave %d\n",
95 expect_it, io.standard_info.out.delete_pending);
100 if (nlink != io.standard_info.out.nlink) {
101 printf("Expected nlink %d, qfileinfo gave %d\n",
102 nlink, io.all_info.out.nlink);
109 status = smbcli_qpathinfo(cli->tree, fname,
110 &c_time, &a_time, &m_time,
114 if (!NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
115 printf("(%s) qpathinfo did not give correct error "
116 "code (%s) -- NT_STATUS_DELETE_PENDING "
117 "expected\n", __location__,
123 if (!NT_STATUS_IS_OK(status)) {
124 printf("(%s) qpathinfo failed (%s)\n", __location__,
132 talloc_free(mem_ctx);
136 #define CHECK_STATUS(_cli, _expected) do { \
137 if (!NT_STATUS_EQUAL(_cli->tree->session->transport->error.e.nt_status, _expected)) { \
138 printf("(%d) Incorrect status %s - should be %s\n", \
139 __LINE__, nt_errstr(_cli->tree->session->transport->error.e.nt_status), nt_errstr(_expected)); \
144 const char *fname = "\\delete.file";
145 const char *fname_new = "\\delete.new";
146 const char *dirname = "\\delete.dir";
148 static void del_clean_area(struct smbcli_state *cli1, struct smbcli_state *cli2)
150 smbcli_deltree(cli1->tree, dirname);
151 smbcli_setatr(cli1->tree, fname, 0, 0);
152 smbcli_unlink(cli1->tree, fname);
153 smbcli_setatr(cli1->tree, fname_new, 0, 0);
154 smbcli_unlink(cli1->tree, fname_new);
156 smb_raw_exit(cli1->session);
157 smb_raw_exit(cli2->session);
160 /* Test 1 - this should delete the file on close. */
162 static BOOL deltest1(struct smbcli_state *cli1, struct smbcli_state *cli2)
166 del_clean_area(cli1, cli2);
168 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
170 FILE_ATTRIBUTE_NORMAL,
171 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
172 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
175 printf("(%s) open of %s failed (%s)\n",
176 __location__, fname, smbcli_errstr(cli1->tree));
180 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
181 printf("(%s) close failed (%s)\n",
182 __location__, smbcli_errstr(cli1->tree));
186 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
188 printf("(%s) open of %s succeeded (should fail)\n",
189 __location__, fname);
193 printf("first delete on close test succeeded.\n");
197 /* Test 2 - this should delete the file on close. */
198 static BOOL deltest2(struct smbcli_state *cli1, struct smbcli_state *cli2)
202 del_clean_area(cli1, cli2);
204 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
206 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
207 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
210 printf("(%s) open of %s failed (%s)\n",
211 __location__, fname, smbcli_errstr(cli1->tree));
215 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
216 printf("(%s) setting delete_on_close failed (%s)\n",
217 __location__, smbcli_errstr(cli1->tree));
221 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
222 printf("(%s) close failed (%s)\n",
223 __location__, smbcli_errstr(cli1->tree));
227 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
229 printf("(%s) open of %s succeeded should have been deleted on close !\n",
230 __location__, fname);
231 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
232 printf("(%s) close failed (%s)\n",
233 __location__, smbcli_errstr(cli1->tree));
236 smbcli_unlink(cli1->tree, fname);
238 printf("second delete on close test succeeded.\n");
244 static BOOL deltest3(struct smbcli_state *cli1, struct smbcli_state *cli2)
249 del_clean_area(cli1, cli2);
251 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
253 FILE_ATTRIBUTE_NORMAL,
254 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
255 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
258 printf("(%s) open - 1 of %s failed (%s)\n",
259 __location__, fname, smbcli_errstr(cli1->tree));
263 /* This should fail with a sharing violation - open for delete is only compatible
264 with SHARE_DELETE. */
266 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
267 SEC_RIGHTS_FILE_READ,
268 FILE_ATTRIBUTE_NORMAL,
269 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
270 NTCREATEX_DISP_OPEN, 0, 0);
273 printf("(%s) open - 2 of %s succeeded - should have failed.\n",
274 __location__, fname);
278 /* 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|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
284 NTCREATEX_DISP_OPEN, 0, 0);
287 printf("(%s) open - 2 of %s failed (%s)\n",
288 __location__, fname, smbcli_errstr(cli1->tree));
292 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
293 printf("(%s) setting delete_on_close failed (%s)\n",
294 __location__, smbcli_errstr(cli1->tree));
298 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
299 printf("(%s) close 1 failed (%s)\n",
300 __location__, smbcli_errstr(cli1->tree));
304 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
305 printf("(%s) close 2 failed (%s)\n",
306 __location__, smbcli_errstr(cli1->tree));
310 /* This should fail - file should no longer be there. */
312 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
314 printf("(%s) open of %s succeeded should have been deleted on close !\n",
315 __location__, fname);
316 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
317 printf("(%s) close failed (%s)\n",
318 __location__, smbcli_errstr(cli1->tree));
320 smbcli_unlink(cli1->tree, fname);
323 printf("third delete on close test succeeded.\n");
329 static BOOL deltest4(struct smbcli_state *cli1, struct smbcli_state *cli2)
335 del_clean_area(cli1, cli2);
337 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
339 SEC_FILE_WRITE_DATA |
341 FILE_ATTRIBUTE_NORMAL,
342 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
343 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
346 printf("(%s) open of %s failed (%s)\n",
347 __location__, fname, smbcli_errstr(cli1->tree));
351 /* This should succeed. */
352 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
353 SEC_RIGHTS_FILE_READ,
354 FILE_ATTRIBUTE_NORMAL,
355 NTCREATEX_SHARE_ACCESS_READ |
356 NTCREATEX_SHARE_ACCESS_WRITE |
357 NTCREATEX_SHARE_ACCESS_DELETE,
358 NTCREATEX_DISP_OPEN, 0, 0);
360 printf("(%s) open - 2 of %s failed (%s)\n",
361 __location__, fname, smbcli_errstr(cli1->tree));
365 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
366 printf("(%s) close - 1 failed (%s)\n",
367 __location__, smbcli_errstr(cli1->tree));
371 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
372 printf("(%s) setting delete_on_close failed (%s)\n",
373 __location__, smbcli_errstr(cli1->tree));
377 /* This should fail - no more opens once delete on close set. */
378 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
379 SEC_RIGHTS_FILE_READ,
380 FILE_ATTRIBUTE_NORMAL,
381 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
382 NTCREATEX_DISP_OPEN, 0, 0);
384 printf("(%s) open - 3 of %s succeeded ! Should have failed.\n",
385 __location__, fname );
388 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
390 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
391 printf("(%s) close - 2 failed (%s)\n",
392 __location__, smbcli_errstr(cli1->tree));
396 printf("fourth delete on close test succeeded.\n");
404 static BOOL deltest5(struct smbcli_state *cli1, struct smbcli_state *cli2)
408 del_clean_area(cli1, cli2);
410 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
412 printf("(%s) open of %s failed (%s)\n",
413 __location__, fname, smbcli_errstr(cli1->tree));
417 /* This should fail - only allowed on NT opens with DELETE access. */
419 if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
420 printf("(%s) setting delete_on_close on OpenX file succeeded - should fail !\n",
425 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
426 printf("(%s) close - 2 failed (%s)\n",
427 __location__, smbcli_errstr(cli1->tree));
431 printf("fifth delete on close test succeeded.\n");
436 static BOOL deltest6(struct smbcli_state *cli1, struct smbcli_state *cli2)
440 del_clean_area(cli1, cli2);
442 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
443 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
444 FILE_ATTRIBUTE_NORMAL,
445 NTCREATEX_SHARE_ACCESS_READ |
446 NTCREATEX_SHARE_ACCESS_WRITE |
447 NTCREATEX_SHARE_ACCESS_DELETE,
448 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
451 printf("(%s) open of %s failed (%s)\n",
452 __location__, fname, smbcli_errstr(cli1->tree));
456 /* This should fail - only allowed on NT opens with DELETE access. */
458 if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
459 printf("(%s) setting delete_on_close on file with no delete access succeeded - should fail !\n",
464 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
465 printf("(%s) close - 2 failed (%s)\n",
466 __location__, smbcli_errstr(cli1->tree));
470 printf("sixth delete on close test succeeded.\n");
475 static BOOL deltest7(struct smbcli_state *cli1, struct smbcli_state *cli2)
480 del_clean_area(cli1, cli2);
482 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
484 SEC_FILE_WRITE_DATA |
486 FILE_ATTRIBUTE_NORMAL, 0,
487 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
490 printf("(%s) open of %s failed (%s)\n",
491 __location__, fname, smbcli_errstr(cli1->tree));
496 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
497 printf("(%s) setting delete_on_close on file failed !\n",
503 correct &= check_delete_on_close(cli1, fnum1, fname, True);
505 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, False))) {
506 printf("(%s) unsetting delete_on_close on file failed !\n",
512 correct &= check_delete_on_close(cli1, fnum1, fname, False);
514 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
515 printf("(%s) close - 2 failed (%s)\n",
516 __location__, smbcli_errstr(cli1->tree));
521 /* This next open should succeed - we reset the flag. */
523 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
525 printf("(%s) open of %s failed (%s)\n",
526 __location__, fname, smbcli_errstr(cli1->tree));
531 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
532 printf("(%s) close - 2 failed (%s)\n",
533 __location__, smbcli_errstr(cli1->tree));
538 printf("seventh delete on close test succeeded.\n");
546 static BOOL deltest8(struct smbcli_state *cli1, struct smbcli_state *cli2)
552 del_clean_area(cli1, cli2);
554 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
558 FILE_ATTRIBUTE_NORMAL,
559 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
560 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
563 printf("(%s) open of %s failed (%s)\n",
564 __location__, fname, smbcli_errstr(cli1->tree));
569 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
573 FILE_ATTRIBUTE_NORMAL,
574 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
575 NTCREATEX_DISP_OPEN, 0, 0);
578 printf("(%s) open of %s failed (%s)\n",
579 __location__, fname, smbcli_errstr(cli1->tree));
584 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
585 printf("(%s) setting delete_on_close on file failed !\n",
591 correct &= check_delete_on_close(cli1, fnum1, fname, True);
592 correct &= check_delete_on_close(cli2, fnum2, fname, True);
594 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
595 printf("(%s) close - 1 failed (%s)\n",
596 __location__, smbcli_errstr(cli1->tree));
601 correct &= check_delete_on_close(cli1, -1, fname, True);
602 correct &= check_delete_on_close(cli2, fnum2, fname, True);
604 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
605 printf("(%s) close - 2 failed (%s)\n",
606 __location__, smbcli_errstr(cli2->tree));
611 /* This should fail.. */
612 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
614 printf("(%s) open of %s succeeded should have been deleted on close !\n",
615 __location__, fname);
618 printf("eighth delete on close test succeeded.\n");
627 static BOOL deltest9(struct smbcli_state *cli1, struct smbcli_state *cli2)
631 del_clean_area(cli1, cli2);
633 /* This should fail - we need to set DELETE_ACCESS. */
634 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
635 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
636 FILE_ATTRIBUTE_NORMAL,
637 NTCREATEX_SHARE_ACCESS_NONE,
638 NTCREATEX_DISP_OVERWRITE_IF,
639 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
642 printf("(%s) open of %s succeeded should have failed!\n",
643 __location__, fname);
647 printf("ninth delete on close test succeeded.\n");
652 static BOOL deltest10(struct smbcli_state *cli1, struct smbcli_state *cli2)
657 del_clean_area(cli1, cli2);
659 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
663 FILE_ATTRIBUTE_NORMAL,
664 NTCREATEX_SHARE_ACCESS_NONE,
665 NTCREATEX_DISP_OVERWRITE_IF,
666 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
668 printf("(%s) open of %s failed (%s)\n",
669 __location__, fname, smbcli_errstr(cli1->tree));
674 /* This should delete the file. */
675 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
676 printf("(%s) close failed (%s)\n",
677 __location__, smbcli_errstr(cli1->tree));
682 /* This should fail.. */
683 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
685 printf("(%s) open of %s succeeded should have been deleted on close !\n",
686 __location__, fname);
690 printf("tenth delete on close test succeeded.\n");
699 static BOOL deltest11(struct smbcli_state *cli1, struct smbcli_state *cli2)
704 del_clean_area(cli1, cli2);
706 /* test 11 - does having read only attribute still allow delete on close. */
708 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
710 FILE_ATTRIBUTE_READONLY,
711 NTCREATEX_SHARE_ACCESS_NONE,
712 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
715 printf("(%s) open of %s failed (%s)\n",
716 __location__, fname, smbcli_errstr(cli1->tree));
720 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, True);
722 if (!NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
723 printf("(%s) setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n",
724 __location__, smbcli_errstr(cli1->tree));
728 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
729 printf("(%s) close failed (%s)\n",
730 __location__, smbcli_errstr(cli1->tree));
734 printf("eleventh delete on close test succeeded.\n");
739 static BOOL deltest12(struct smbcli_state *cli1, struct smbcli_state *cli2)
744 del_clean_area(cli1, cli2);
746 /* test 12 - does having read only attribute still allow delete on
747 * close at time of open. */
749 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
751 FILE_ATTRIBUTE_READONLY,
752 NTCREATEX_SHARE_ACCESS_DELETE,
753 NTCREATEX_DISP_OVERWRITE_IF,
754 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
757 printf("(%s) open of %s succeeded. Should fail with "
758 "NT_STATUS_CANNOT_DELETE.\n", __location__, fname);
759 smbcli_close(cli1->tree, fnum1);
762 status = smbcli_nt_error(cli1->tree);
763 if (!NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
764 printf("(%s) setting delete_on_close on open should "
765 "fail with NT_STATUS_CANNOT_DELETE. Got %s "
767 __location__, smbcli_errstr(cli1->tree));
772 printf("twelvth delete on close test succeeded.\n");
777 static BOOL deltest13(struct smbcli_state *cli1, struct smbcli_state *cli2)
783 del_clean_area(cli1, cli2);
785 /* Test 13: Does resetting the delete on close flag affect a second
788 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
792 FILE_ATTRIBUTE_NORMAL,
793 NTCREATEX_SHARE_ACCESS_READ|
794 NTCREATEX_SHARE_ACCESS_WRITE|
795 NTCREATEX_SHARE_ACCESS_DELETE,
796 NTCREATEX_DISP_OVERWRITE_IF,
800 printf("(%s) open of %s failed (%s)\n",
801 __location__, fname, smbcli_errstr(cli1->tree));
806 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
810 FILE_ATTRIBUTE_NORMAL,
811 NTCREATEX_SHARE_ACCESS_READ|
812 NTCREATEX_SHARE_ACCESS_WRITE|
813 NTCREATEX_SHARE_ACCESS_DELETE,
814 NTCREATEX_DISP_OPEN, 0, 0);
817 printf("(%s) open of %s failed (%s)\n",
818 __location__, fname, smbcli_errstr(cli2->tree));
823 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1,
825 printf("(%s) setting delete_on_close on file failed !\n",
831 correct &= check_delete_on_close(cli1, fnum1, fname, True);
832 correct &= check_delete_on_close(cli2, fnum2, fname, True);
834 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli2->tree, fnum2,
836 printf("(%s) setting delete_on_close on file failed !\n",
842 correct &= check_delete_on_close(cli1, fnum1, fname, False);
843 correct &= check_delete_on_close(cli2, fnum2, fname, False);
845 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
846 printf("(%s) close - 1 failed (%s)\n",
847 __location__, smbcli_errstr(cli1->tree));
852 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
853 printf("(%s) close - 2 failed (%s)\n",
854 __location__, smbcli_errstr(cli2->tree));
859 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
862 printf("(%s) open of %s failed!\n",
863 __location__, fname);
868 printf("thirteenth delete on close test succeeded.\n");
876 static BOOL deltest14(struct smbcli_state *cli1, struct smbcli_state *cli2)
881 del_clean_area(cli1, cli2);
883 /* Test 14 -- directory */
885 dnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
889 FILE_ATTRIBUTE_DIRECTORY,
890 NTCREATEX_SHARE_ACCESS_READ|
891 NTCREATEX_SHARE_ACCESS_WRITE|
892 NTCREATEX_SHARE_ACCESS_DELETE,
893 NTCREATEX_DISP_CREATE, 0, 0);
895 printf("(%s) open of %s failed: %s!\n",
896 __location__, dirname, smbcli_errstr(cli1->tree));
901 check_delete_on_close(cli1, dnum1, dirname, False);
902 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, dnum1, True))) {
903 printf("(%s) setting delete_on_close on file failed !\n",
908 check_delete_on_close(cli1, dnum1, dirname, True);
909 smbcli_close(cli1->tree, dnum1);
911 /* Now it should be gone... */
913 dnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
917 FILE_ATTRIBUTE_DIRECTORY,
918 NTCREATEX_SHARE_ACCESS_READ|
919 NTCREATEX_SHARE_ACCESS_WRITE|
920 NTCREATEX_SHARE_ACCESS_DELETE,
921 NTCREATEX_DISP_OPEN, 0, 0);
923 printf("(%s) setting delete_on_close on file succeeded !\n",
929 printf("fourteenth delete on close test succeeded.\n");
937 static BOOL deltest15(struct smbcli_state *cli1, struct smbcli_state *cli2)
944 del_clean_area(cli1, cli2);
946 /* Test 15: delete on close under rename */
948 smbcli_setatr(cli1->tree, fname, 0, 0);
949 smbcli_unlink(cli1->tree, fname);
950 smbcli_unlink(cli1->tree, fname_new);
952 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
954 FILE_ATTRIBUTE_NORMAL,
955 NTCREATEX_SHARE_ACCESS_READ|
956 NTCREATEX_SHARE_ACCESS_WRITE|
957 NTCREATEX_SHARE_ACCESS_DELETE,
958 NTCREATEX_DISP_OVERWRITE_IF,
962 printf("(%s) open - 1 of %s failed (%s)\n",
963 __location__, fname, smbcli_errstr(cli1->tree));
968 status = smbcli_rename(cli2->tree, fname, fname_new);
970 if (!NT_STATUS_IS_OK(status)) {
971 printf("(%s) renaming failed: %s !\n",
972 __location__, nt_errstr(status));
977 fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
979 FILE_ATTRIBUTE_NORMAL,
980 NTCREATEX_SHARE_ACCESS_READ|
981 NTCREATEX_SHARE_ACCESS_WRITE|
982 NTCREATEX_SHARE_ACCESS_DELETE,
983 NTCREATEX_DISP_OVERWRITE_IF,
987 printf("(%s) open - 1 of %s failed (%s)\n",
988 __location__, fname_new, smbcli_errstr(cli1->tree));
993 status = smbcli_nt_delete_on_close(cli2->tree, fnum2, True);
995 if (!NT_STATUS_IS_OK(status)) {
996 printf("(%s) setting delete_on_close on file failed !\n",
1002 smbcli_close(cli2->tree, fnum2);
1004 /* The file should be around under the new name, there's a second
1007 if (!check_delete_on_close(cli1, fnum1, fname_new, True)) {
1008 printf("(%s) checking delete on close on file %s failed!\n",
1009 __location__, fname_new);
1014 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1016 FILE_ATTRIBUTE_NORMAL,
1017 NTCREATEX_SHARE_ACCESS_READ|
1018 NTCREATEX_SHARE_ACCESS_WRITE|
1019 NTCREATEX_SHARE_ACCESS_DELETE,
1020 NTCREATEX_DISP_OVERWRITE_IF,
1024 printf("(%s) open - 1 of %s failed (%s)\n",
1025 __location__, fname, smbcli_errstr(cli1->tree));
1030 smbcli_close(cli2->tree, fnum2);
1031 smbcli_close(cli1->tree, fnum1);
1033 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1035 FILE_ATTRIBUTE_NORMAL,
1036 NTCREATEX_SHARE_ACCESS_READ|
1037 NTCREATEX_SHARE_ACCESS_WRITE|
1038 NTCREATEX_SHARE_ACCESS_DELETE,
1039 NTCREATEX_DISP_OPEN,
1043 printf("(%s) open - 1 of %s failed (%s)\n",
1044 __location__, fname, smbcli_errstr(cli1->tree));
1049 smbcli_close(cli1->tree, fnum1);
1051 fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
1053 FILE_ATTRIBUTE_NORMAL,
1054 NTCREATEX_SHARE_ACCESS_READ|
1055 NTCREATEX_SHARE_ACCESS_WRITE|
1056 NTCREATEX_SHARE_ACCESS_DELETE,
1057 NTCREATEX_DISP_OPEN,
1061 printf("(%s) smbcli_open succeeded, should have "
1062 "failed\n", __location__);
1063 smbcli_close(cli1->tree, fnum1);
1068 printf("fifteenth delete on close test succeeded.\n");
1076 static BOOL deltest16(struct smbcli_state *cli1, struct smbcli_state *cli2)
1080 BOOL correct = True;
1082 del_clean_area(cli1, cli2);
1086 /* Ensure the file doesn't already exist. */
1087 smbcli_close(cli1->tree, fnum1);
1088 smbcli_close(cli1->tree, fnum2);
1089 smbcli_setatr(cli1->tree, fname, 0, 0);
1090 smbcli_unlink(cli1->tree, fname);
1092 /* Firstly create with all access, but delete on close. */
1093 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1094 SEC_RIGHTS_FILE_ALL,
1095 FILE_ATTRIBUTE_NORMAL,
1096 NTCREATEX_SHARE_ACCESS_READ|
1097 NTCREATEX_SHARE_ACCESS_WRITE|
1098 NTCREATEX_SHARE_ACCESS_DELETE,
1099 NTCREATEX_DISP_CREATE,
1100 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1103 printf("(%s) open - 1 of %s failed (%s)\n",
1104 __location__, fname, smbcli_errstr(cli1->tree));
1109 /* The delete on close bit is *not* reported as being set. */
1110 check_delete_on_close(cli1, fnum1, fname, False);
1112 /* Now try opening again for read-only. */
1113 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1114 SEC_RIGHTS_FILE_READ,
1115 FILE_ATTRIBUTE_NORMAL,
1116 NTCREATEX_SHARE_ACCESS_READ|
1117 NTCREATEX_SHARE_ACCESS_WRITE|
1118 NTCREATEX_SHARE_ACCESS_DELETE,
1119 NTCREATEX_DISP_OPEN,
1125 printf("(%s) open - 1 of %s failed (%s)\n",
1126 __location__, fname, smbcli_errstr(cli1->tree));
1131 /* Now close both.... */
1132 smbcli_close(cli1->tree, fnum1);
1133 smbcli_close(cli1->tree, fnum2);
1135 /* And the file should be deleted ! */
1136 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1138 printf("(%s) open of %s succeeded (should fail)\n",
1139 __location__, fname);
1144 printf("sixteenth delete on close test succeeded.\n");
1152 static BOOL deltest17(struct smbcli_state *cli1, struct smbcli_state *cli2)
1156 BOOL correct = True;
1158 del_clean_area(cli1, cli2);
1162 /* Ensure the file doesn't already exist. */
1163 smbcli_close(cli1->tree, fnum1);
1164 smbcli_close(cli1->tree, fnum2);
1165 smbcli_setatr(cli1->tree, fname, 0, 0);
1166 smbcli_unlink(cli1->tree, fname);
1168 /* Firstly open and create with all access */
1169 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1170 SEC_RIGHTS_FILE_ALL,
1171 FILE_ATTRIBUTE_NORMAL,
1172 NTCREATEX_SHARE_ACCESS_READ|
1173 NTCREATEX_SHARE_ACCESS_WRITE|
1174 NTCREATEX_SHARE_ACCESS_DELETE,
1175 NTCREATEX_DISP_CREATE,
1178 printf("(%s) open - 1 of %s failed (%s)\n",
1179 __location__, fname, smbcli_errstr(cli1->tree));
1184 /* And close - just to create the file. */
1185 smbcli_close(cli1->tree, fnum1);
1187 /* Next open with all access, but add delete on close. */
1188 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1189 SEC_RIGHTS_FILE_ALL,
1190 FILE_ATTRIBUTE_NORMAL,
1191 NTCREATEX_SHARE_ACCESS_READ|
1192 NTCREATEX_SHARE_ACCESS_WRITE|
1193 NTCREATEX_SHARE_ACCESS_DELETE,
1194 NTCREATEX_DISP_OPEN,
1195 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1198 printf("(%s) open - 1 of %s failed (%s)\n",
1199 __location__, fname, smbcli_errstr(cli1->tree));
1204 /* The delete on close bit is *not* reported as being set. */
1205 check_delete_on_close(cli1, fnum1, fname, False);
1207 /* Now try opening again for read-only. */
1208 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1209 SEC_RIGHTS_FILE_READ,
1210 FILE_ATTRIBUTE_NORMAL,
1211 NTCREATEX_SHARE_ACCESS_READ|
1212 NTCREATEX_SHARE_ACCESS_WRITE|
1213 NTCREATEX_SHARE_ACCESS_DELETE,
1214 NTCREATEX_DISP_OPEN,
1219 printf("(%s) open - 1 of %s failed (%s)\n",
1220 __location__, fname, smbcli_errstr(cli1->tree));
1225 /* Now close both.... */
1226 smbcli_close(cli1->tree, fnum1);
1227 smbcli_close(cli1->tree, fnum2);
1229 /* See if the file is deleted - shouldn't be.... */
1230 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1232 printf("(%s) open of %s failed (should succeed) - %s\n",
1233 __location__, fname, smbcli_errstr(cli1->tree));
1238 printf("seventeenth delete on close test succeeded.\n");
1246 static BOOL deltest18(struct smbcli_state *cli1, struct smbcli_state *cli2)
1250 BOOL correct = True;
1252 del_clean_area(cli1, cli2);
1254 /* Test 18. With directories. */
1256 /* Ensure the file doesn't already exist. */
1257 smbcli_close(cli1->tree, fnum1);
1258 smbcli_close(cli1->tree, fnum2);
1260 smbcli_deltree(cli1->tree, dirname);
1262 /* Firstly create with all access, but delete on close. */
1263 fnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1265 SEC_FILE_WRITE_DATA|
1267 FILE_ATTRIBUTE_DIRECTORY,
1268 NTCREATEX_SHARE_ACCESS_READ|
1269 NTCREATEX_SHARE_ACCESS_WRITE|
1270 NTCREATEX_SHARE_ACCESS_DELETE,
1271 NTCREATEX_DISP_CREATE,
1272 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1275 printf("(%s) open - 1 of %s failed (%s)\n",
1276 __location__, dirname, smbcli_errstr(cli1->tree));
1281 /* The delete on close bit is *not* reported as being set. */
1282 check_delete_on_close(cli1, fnum1, dirname, False);
1284 /* Now try opening again for read-only. */
1285 fnum2 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1286 SEC_RIGHTS_FILE_READ,
1287 FILE_ATTRIBUTE_DIRECTORY,
1288 NTCREATEX_SHARE_ACCESS_READ|
1289 NTCREATEX_SHARE_ACCESS_WRITE|
1290 NTCREATEX_SHARE_ACCESS_DELETE,
1291 NTCREATEX_DISP_OPEN,
1292 NTCREATEX_OPTIONS_DIRECTORY, 0);
1297 printf("(%s) open - 1 of %s failed (%s)\n",
1298 __location__, dirname, smbcli_errstr(cli1->tree));
1303 /* Now close both.... */
1304 smbcli_close(cli1->tree, fnum1);
1305 smbcli_close(cli1->tree, fnum2);
1307 /* And the directory should be deleted ! */
1308 fnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1309 SEC_RIGHTS_FILE_READ,
1310 FILE_ATTRIBUTE_DIRECTORY,
1311 NTCREATEX_SHARE_ACCESS_READ|
1312 NTCREATEX_SHARE_ACCESS_WRITE|
1313 NTCREATEX_SHARE_ACCESS_DELETE,
1314 NTCREATEX_DISP_OPEN,
1315 NTCREATEX_OPTIONS_DIRECTORY, 0);
1317 printf("(%s) open of %s succeeded (should fail)\n",
1318 __location__, dirname);
1323 printf("eighteenth delete on close test succeeded.\n");
1331 static BOOL deltest19(struct smbcli_state *cli1, struct smbcli_state *cli2)
1335 BOOL correct = True;
1337 del_clean_area(cli1, cli2);
1341 smbcli_deltree(cli1->tree, dirname);
1343 /* Firstly open and create with all access */
1344 fnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1346 SEC_FILE_WRITE_DATA|
1348 FILE_ATTRIBUTE_DIRECTORY,
1349 NTCREATEX_SHARE_ACCESS_READ|
1350 NTCREATEX_SHARE_ACCESS_WRITE|
1351 NTCREATEX_SHARE_ACCESS_DELETE,
1352 NTCREATEX_DISP_CREATE,
1353 NTCREATEX_OPTIONS_DIRECTORY, 0);
1356 printf("(%s) open - 1 of %s failed (%s)\n",
1357 __location__, dirname, smbcli_errstr(cli1->tree));
1362 /* And close - just to create the directory. */
1363 smbcli_close(cli1->tree, fnum1);
1365 /* Next open with all access, but add delete on close. */
1366 fnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1368 SEC_FILE_WRITE_DATA|
1370 FILE_ATTRIBUTE_DIRECTORY,
1371 NTCREATEX_SHARE_ACCESS_READ|
1372 NTCREATEX_SHARE_ACCESS_WRITE|
1373 NTCREATEX_SHARE_ACCESS_DELETE,
1374 NTCREATEX_DISP_OPEN,
1375 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1378 printf("(%s) open - 1 of %s failed (%s)\n",
1379 __location__, fname, smbcli_errstr(cli1->tree));
1384 /* The delete on close bit is *not* reported as being set. */
1385 check_delete_on_close(cli1, fnum1, dirname, False);
1387 /* Now try opening again for read-only. */
1388 fnum2 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1389 SEC_RIGHTS_FILE_READ,
1390 FILE_ATTRIBUTE_DIRECTORY,
1391 NTCREATEX_SHARE_ACCESS_READ|
1392 NTCREATEX_SHARE_ACCESS_WRITE|
1393 NTCREATEX_SHARE_ACCESS_DELETE,
1394 NTCREATEX_DISP_OPEN,
1395 NTCREATEX_OPTIONS_DIRECTORY, 0);
1399 printf("(%s) open - 1 of %s failed (%s)\n",
1400 __location__, dirname, smbcli_errstr(cli1->tree));
1405 /* Now close both.... */
1406 smbcli_close(cli1->tree, fnum1);
1407 smbcli_close(cli1->tree, fnum2);
1409 /* See if the file is deleted - for a directory this seems to be true ! */
1410 fnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1411 SEC_RIGHTS_FILE_READ,
1412 FILE_ATTRIBUTE_DIRECTORY,
1413 NTCREATEX_SHARE_ACCESS_READ|
1414 NTCREATEX_SHARE_ACCESS_WRITE|
1415 NTCREATEX_SHARE_ACCESS_DELETE,
1416 NTCREATEX_DISP_OPEN,
1417 NTCREATEX_OPTIONS_DIRECTORY, 0);
1419 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1422 printf("(%s) open of %s succeeded (should fail)\n",
1423 __location__, dirname);
1428 printf("nineteenth delete on close test succeeded.\n");
1436 static BOOL deltest20(struct smbcli_state *cli1, struct smbcli_state *cli2)
1440 BOOL correct = True;
1443 del_clean_area(cli1, cli2);
1445 /* Test 20 -- non-empty directory hardest to get right... */
1447 smbcli_deltree(cli1->tree, dirname);
1449 dnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1451 SEC_FILE_WRITE_DATA|
1453 FILE_ATTRIBUTE_DIRECTORY,
1454 NTCREATEX_SHARE_ACCESS_READ|
1455 NTCREATEX_SHARE_ACCESS_WRITE|
1456 NTCREATEX_SHARE_ACCESS_DELETE,
1457 NTCREATEX_DISP_CREATE,
1458 NTCREATEX_OPTIONS_DIRECTORY, 0);
1460 printf("(%s) open of %s failed: %s!\n",
1461 __location__, dirname, smbcli_errstr(cli1->tree));
1466 check_delete_on_close(cli1, dnum1, dirname, False);
1467 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
1471 asprintf(&fullname, "\\%s%s", dirname, fname);
1472 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1475 printf("(%s) smbcli_open succeeded, should have "
1477 __location__, smbcli_errstr(cli1->tree));
1482 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree),
1483 NT_STATUS_DELETE_PENDING)) {
1484 printf("(%s) smbcli_open returned %s, expected "
1485 "NT_STATUS_DELETE_PENDING\n",
1486 __location__, smbcli_errstr(cli1->tree));
1492 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, False);
1493 if (!NT_STATUS_IS_OK(status)) {
1494 printf("(%s) setting delete_on_close on file failed !\n",
1502 asprintf(&fullname, "\\%s%s", dirname, fname);
1503 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1506 printf("(%s) smbcli_open failed: %s\n",
1507 __location__, smbcli_errstr(cli1->tree));
1511 smbcli_close(cli1->tree, fnum1);
1514 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
1516 if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
1517 printf("(%s) setting delete_on_close returned %s, expected "
1518 "NT_STATUS_DIRECTORY_NOT_EMPTY\n", __location__,
1519 smbcli_errstr(cli1->tree));
1524 smbcli_close(cli1->tree, dnum1);
1526 printf("twentieth delete on close test succeeded.\n");
1534 Test delete on close semantics.
1536 BOOL torture_test_delete(void)
1538 struct smbcli_state *cli1 = NULL;
1539 struct smbcli_state *cli2 = NULL;
1540 BOOL correct = True;
1542 printf("starting delete test\n");
1544 if (!torture_open_connection(&cli1)) {
1548 if (!torture_open_connection(&cli2)) {
1549 printf("(%s) failed to open second connection.\n",
1555 if (!deltest1(cli1, cli2)) {
1559 if (!deltest2(cli1, cli2)) {
1563 if (!deltest3(cli1, cli2)) {
1567 if (!deltest4(cli1, cli2)) {
1571 if (!deltest5(cli1, cli2)) {
1575 if (!deltest6(cli1, cli2)) {
1579 if (!deltest7(cli1, cli2)) {
1583 if (!deltest8(cli1, cli2)) {
1587 if (!deltest9(cli1, cli2)) {
1591 if (!deltest10(cli1, cli2)) {
1595 if (!deltest11(cli1, cli2)) {
1599 if (!deltest12(cli1, cli2)) {
1603 if (!deltest13(cli1, cli2)) {
1607 if (!deltest14(cli1, cli2)) {
1611 if (!deltest15(cli1, cli2)) {
1615 if (!deltest16(cli1, cli2)) {
1619 if (!deltest17(cli1, cli2)) {
1623 if (!deltest18(cli1, cli2)) {
1627 if (!deltest19(cli1, cli2)) {
1631 if (!deltest20(cli1, cli2)) {
1635 printf("finished delete test\n");
1638 del_clean_area(cli1, cli2);
1640 if (!torture_close_connection(cli1)) {
1643 if (!torture_close_connection(cli2)) {