r13297: It's a good thing the shipment of function headers tridge
[Samba.git] / source4 / torture / basic / delete.c
blobac168b3ed47a7a224b1d4f7bab86ce6c3b1ee669
1 /*
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.
23 #include "includes.h"
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;
34 NTSTATUS status;
36 time_t c_time, a_time, m_time;
37 size_t size;
38 uint16_t mode;
40 BOOL res = True;
42 status = torture_single_search(cli, mem_ctx,
43 fname, RAW_SEARCH_FULL_DIRECTORY_INFO,
44 FILE_ATTRIBUTE_DIRECTORY,
45 &data);
46 if (!NT_STATUS_IS_OK(status)) {
47 printf("(%s) single_search failed (%s)\n",
48 __location__, nt_errstr(status));
49 res = False;
50 goto done;
53 if (fnum != -1) {
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__,
63 nt_errstr(status));
64 res = False;
65 goto done;
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);
71 res = False;
72 goto done;
75 if (nlink != io.all_info.out.nlink) {
76 printf("Expected nlink %d, qfileinfo gave %d\n",
77 nlink, io.all_info.out.nlink);
78 res = False;
79 goto done;
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__,
88 nt_errstr(status));
89 res = False;
90 goto done;
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);
96 res = False;
97 goto done;
100 if (nlink != io.standard_info.out.nlink) {
101 printf("Expected nlink %d, qfileinfo gave %d\n",
102 nlink, io.all_info.out.nlink);
103 res = False;
104 goto done;
109 status = smbcli_qpathinfo(cli->tree, fname,
110 &c_time, &a_time, &m_time,
111 &size, &mode);
113 if (expect_it) {
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__,
118 nt_errstr(status));
119 res = False;
120 goto done;
122 } else {
123 if (!NT_STATUS_IS_OK(status)) {
124 printf("(%s) qpathinfo failed (%s)\n", __location__,
125 nt_errstr(status));
126 res = False;
127 goto done;
131 done:
132 talloc_free(mem_ctx);
133 return res;
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)); \
140 correct = False; \
141 goto fail; \
142 }} while (0)
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)
164 int fnum1 = -1;
166 del_clean_area(cli1, cli2);
168 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
169 SEC_RIGHTS_FILE_ALL,
170 FILE_ATTRIBUTE_NORMAL,
171 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
172 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
174 if (fnum1 == -1) {
175 printf("(%s) open of %s failed (%s)\n",
176 __location__, fname, smbcli_errstr(cli1->tree));
177 return False;
180 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
181 printf("(%s) close failed (%s)\n",
182 __location__, smbcli_errstr(cli1->tree));
183 return False;
186 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
187 if (fnum1 != -1) {
188 printf("(%s) open of %s succeeded (should fail)\n",
189 __location__, fname);
190 return False;
193 printf("first delete on close test succeeded.\n");
194 return True;
197 /* Test 2 - this should delete the file on close. */
198 static BOOL deltest2(struct smbcli_state *cli1, struct smbcli_state *cli2)
200 int fnum1 = -1;
202 del_clean_area(cli1, cli2);
204 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
205 SEC_RIGHTS_FILE_ALL,
206 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
207 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
209 if (fnum1 == -1) {
210 printf("(%s) open of %s failed (%s)\n",
211 __location__, fname, smbcli_errstr(cli1->tree));
212 return False;
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));
218 return False;
221 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
222 printf("(%s) close failed (%s)\n",
223 __location__, smbcli_errstr(cli1->tree));
224 return False;
227 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
228 if (fnum1 != -1) {
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));
234 return False;
236 smbcli_unlink(cli1->tree, fname);
237 } else {
238 printf("second delete on close test succeeded.\n");
240 return True;
243 /* Test 3 - ... */
244 static BOOL deltest3(struct smbcli_state *cli1, struct smbcli_state *cli2)
246 int fnum1 = -1;
247 int fnum2 = -1;
249 del_clean_area(cli1, cli2);
251 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
252 SEC_RIGHTS_FILE_ALL,
253 FILE_ATTRIBUTE_NORMAL,
254 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
255 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
257 if (fnum1 == -1) {
258 printf("(%s) open - 1 of %s failed (%s)\n",
259 __location__, fname, smbcli_errstr(cli1->tree));
260 return False;
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);
272 if (fnum2 != -1) {
273 printf("(%s) open - 2 of %s succeeded - should have failed.\n",
274 __location__, fname);
275 return False;
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);
286 if (fnum2 == -1) {
287 printf("(%s) open - 2 of %s failed (%s)\n",
288 __location__, fname, smbcli_errstr(cli1->tree));
289 return False;
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));
295 return False;
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));
301 return False;
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));
307 return False;
310 /* This should fail - file should no longer be there. */
312 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
313 if (fnum1 != -1) {
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);
321 return False;
322 } else {
323 printf("third delete on close test succeeded.\n");
325 return True;
328 /* Test 4 ... */
329 static BOOL deltest4(struct smbcli_state *cli1, struct smbcli_state *cli2)
331 int fnum1 = -1;
332 int fnum2 = -1;
333 BOOL correct = True;
335 del_clean_area(cli1, cli2);
337 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
338 SEC_FILE_READ_DATA |
339 SEC_FILE_WRITE_DATA |
340 SEC_STD_DELETE,
341 FILE_ATTRIBUTE_NORMAL,
342 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
343 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
345 if (fnum1 == -1) {
346 printf("(%s) open of %s failed (%s)\n",
347 __location__, fname, smbcli_errstr(cli1->tree));
348 return False;
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);
359 if (fnum2 == -1) {
360 printf("(%s) open - 2 of %s failed (%s)\n",
361 __location__, fname, smbcli_errstr(cli1->tree));
362 return False;
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));
368 return False;
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));
374 return False;
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);
383 if (fnum2 != -1) {
384 printf("(%s) open - 3 of %s succeeded ! Should have failed.\n",
385 __location__, fname );
386 return False;
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));
393 return False;
396 printf("fourth delete on close test succeeded.\n");
398 fail:
400 return correct;
403 /* Test 5 ... */
404 static BOOL deltest5(struct smbcli_state *cli1, struct smbcli_state *cli2)
406 int fnum1 = -1;
408 del_clean_area(cli1, cli2);
410 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
411 if (fnum1 == -1) {
412 printf("(%s) open of %s failed (%s)\n",
413 __location__, fname, smbcli_errstr(cli1->tree));
414 return False;
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",
421 __location__);
422 return False;
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));
428 return False;
431 printf("fifth delete on close test succeeded.\n");
432 return True;
435 /* Test 6 ... */
436 static BOOL deltest6(struct smbcli_state *cli1, struct smbcli_state *cli2)
438 int fnum1 = -1;
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);
450 if (fnum1 == -1) {
451 printf("(%s) open of %s failed (%s)\n",
452 __location__, fname, smbcli_errstr(cli1->tree));
453 return False;
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",
460 __location__);
461 return False;
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));
467 return False;
470 printf("sixth delete on close test succeeded.\n");
471 return True;
474 /* Test 7 ... */
475 static BOOL deltest7(struct smbcli_state *cli1, struct smbcli_state *cli2)
477 int fnum1 = -1;
478 BOOL correct = True;
480 del_clean_area(cli1, cli2);
482 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
483 SEC_FILE_READ_DATA |
484 SEC_FILE_WRITE_DATA |
485 SEC_STD_DELETE,
486 FILE_ATTRIBUTE_NORMAL, 0,
487 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
489 if (fnum1 == -1) {
490 printf("(%s) open of %s failed (%s)\n",
491 __location__, fname, smbcli_errstr(cli1->tree));
492 correct = False;
493 goto fail;
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",
498 __location__);
499 correct = False;
500 goto fail;
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",
507 __location__);
508 correct = False;
509 goto fail;
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));
517 correct = False;
518 goto fail;
521 /* This next open should succeed - we reset the flag. */
523 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
524 if (fnum1 == -1) {
525 printf("(%s) open of %s failed (%s)\n",
526 __location__, fname, smbcli_errstr(cli1->tree));
527 correct = False;
528 goto fail;
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));
534 correct = False;
535 goto fail;
538 printf("seventh delete on close test succeeded.\n");
540 fail:
542 return correct;
545 /* Test 8 ... */
546 static BOOL deltest8(struct smbcli_state *cli1, struct smbcli_state *cli2)
548 int fnum1 = -1;
549 int fnum2 = -1;
550 BOOL correct = True;
552 del_clean_area(cli1, cli2);
554 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
555 SEC_FILE_READ_DATA|
556 SEC_FILE_WRITE_DATA|
557 SEC_STD_DELETE,
558 FILE_ATTRIBUTE_NORMAL,
559 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
560 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
562 if (fnum1 == -1) {
563 printf("(%s) open of %s failed (%s)\n",
564 __location__, fname, smbcli_errstr(cli1->tree));
565 correct = False;
566 goto fail;
569 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
570 SEC_FILE_READ_DATA|
571 SEC_FILE_WRITE_DATA|
572 SEC_STD_DELETE,
573 FILE_ATTRIBUTE_NORMAL,
574 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
575 NTCREATEX_DISP_OPEN, 0, 0);
577 if (fnum2 == -1) {
578 printf("(%s) open of %s failed (%s)\n",
579 __location__, fname, smbcli_errstr(cli1->tree));
580 correct = False;
581 goto fail;
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",
586 __location__);
587 correct = False;
588 goto fail;
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));
597 correct = False;
598 goto fail;
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));
607 correct = False;
608 goto fail;
611 /* This should fail.. */
612 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
613 if (fnum1 != -1) {
614 printf("(%s) open of %s succeeded should have been deleted on close !\n",
615 __location__, fname);
616 correct = False;
617 } else {
618 printf("eighth delete on close test succeeded.\n");
621 fail:
623 return correct;
626 /* Test 9 ... */
627 static BOOL deltest9(struct smbcli_state *cli1, struct smbcli_state *cli2)
629 int fnum1 = -1;
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);
641 if (fnum1 != -1) {
642 printf("(%s) open of %s succeeded should have failed!\n",
643 __location__, fname);
644 return False;
647 printf("ninth delete on close test succeeded.\n");
648 return True;
651 /* Test 10 ... */
652 static BOOL deltest10(struct smbcli_state *cli1, struct smbcli_state *cli2)
654 int fnum1 = -1;
655 BOOL correct = True;
657 del_clean_area(cli1, cli2);
659 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
660 SEC_FILE_READ_DATA|
661 SEC_FILE_WRITE_DATA|
662 SEC_STD_DELETE,
663 FILE_ATTRIBUTE_NORMAL,
664 NTCREATEX_SHARE_ACCESS_NONE,
665 NTCREATEX_DISP_OVERWRITE_IF,
666 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
667 if (fnum1 == -1) {
668 printf("(%s) open of %s failed (%s)\n",
669 __location__, fname, smbcli_errstr(cli1->tree));
670 correct = False;
671 goto fail;
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));
678 correct = False;
679 goto fail;
682 /* This should fail.. */
683 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
684 if (fnum1 != -1) {
685 printf("(%s) open of %s succeeded should have been deleted on close !\n",
686 __location__, fname);
687 correct = False;
688 goto fail;
689 } else {
690 printf("tenth delete on close test succeeded.\n");
693 fail:
695 return correct;
698 /* Test 11 ... */
699 static BOOL deltest11(struct smbcli_state *cli1, struct smbcli_state *cli2)
701 int fnum1 = -1;
702 NTSTATUS status;
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,
709 SEC_RIGHTS_FILE_ALL,
710 FILE_ATTRIBUTE_READONLY,
711 NTCREATEX_SHARE_ACCESS_NONE,
712 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
714 if (fnum1 == -1) {
715 printf("(%s) open of %s failed (%s)\n",
716 __location__, fname, smbcli_errstr(cli1->tree));
717 return False;
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));
725 return False;
728 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
729 printf("(%s) close failed (%s)\n",
730 __location__, smbcli_errstr(cli1->tree));
731 return False;
734 printf("eleventh delete on close test succeeded.\n");
735 return True;
738 /* Test 12 ... */
739 static BOOL deltest12(struct smbcli_state *cli1, struct smbcli_state *cli2)
741 int fnum1 = -1;
742 NTSTATUS status;
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,
750 SEC_RIGHTS_FILE_ALL,
751 FILE_ATTRIBUTE_READONLY,
752 NTCREATEX_SHARE_ACCESS_DELETE,
753 NTCREATEX_DISP_OVERWRITE_IF,
754 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
756 if (fnum1 != -1) {
757 printf("(%s) open of %s succeeded. Should fail with "
758 "NT_STATUS_CANNOT_DELETE.\n", __location__, fname);
759 smbcli_close(cli1->tree, fnum1);
760 return False;
761 } else {
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 "
766 "instead)\n",
767 __location__, smbcli_errstr(cli1->tree));
768 return False;
772 printf("twelvth delete on close test succeeded.\n");
773 return True;
776 /* Test 13 ... */
777 static BOOL deltest13(struct smbcli_state *cli1, struct smbcli_state *cli2)
779 int fnum1 = -1;
780 int fnum2 = -1;
781 BOOL correct = True;
783 del_clean_area(cli1, cli2);
785 /* Test 13: Does resetting the delete on close flag affect a second
786 * fd? */
788 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
789 SEC_FILE_READ_DATA|
790 SEC_FILE_WRITE_DATA|
791 SEC_STD_DELETE,
792 FILE_ATTRIBUTE_NORMAL,
793 NTCREATEX_SHARE_ACCESS_READ|
794 NTCREATEX_SHARE_ACCESS_WRITE|
795 NTCREATEX_SHARE_ACCESS_DELETE,
796 NTCREATEX_DISP_OVERWRITE_IF,
797 0, 0);
799 if (fnum1 == -1) {
800 printf("(%s) open of %s failed (%s)\n",
801 __location__, fname, smbcli_errstr(cli1->tree));
802 correct = False;
803 goto fail;
806 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
807 SEC_FILE_READ_DATA|
808 SEC_FILE_WRITE_DATA|
809 SEC_STD_DELETE,
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);
816 if (fnum2 == -1) {
817 printf("(%s) open of %s failed (%s)\n",
818 __location__, fname, smbcli_errstr(cli2->tree));
819 correct = False;
820 goto fail;
823 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1,
824 True))) {
825 printf("(%s) setting delete_on_close on file failed !\n",
826 __location__);
827 correct = False;
828 goto fail;
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,
835 False))) {
836 printf("(%s) setting delete_on_close on file failed !\n",
837 __location__);
838 correct = False;
839 goto fail;
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));
848 correct = False;
849 goto fail;
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));
855 correct = False;
856 goto fail;
859 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
861 if (fnum1 == -1) {
862 printf("(%s) open of %s failed!\n",
863 __location__, fname);
864 correct = False;
865 goto fail;
868 printf("thirteenth delete on close test succeeded.\n");
870 fail:
872 return correct;
875 /* Test 14 ... */
876 static BOOL deltest14(struct smbcli_state *cli1, struct smbcli_state *cli2)
878 int dnum1 = -1;
879 BOOL correct = True;
881 del_clean_area(cli1, cli2);
883 /* Test 14 -- directory */
885 dnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
886 SEC_FILE_READ_DATA|
887 SEC_FILE_WRITE_DATA|
888 SEC_STD_DELETE,
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);
894 if (dnum1 == -1) {
895 printf("(%s) open of %s failed: %s!\n",
896 __location__, dirname, smbcli_errstr(cli1->tree));
897 correct = False;
898 goto fail;
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",
904 __location__);
905 correct = False;
906 goto fail;
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,
914 SEC_FILE_READ_DATA|
915 SEC_FILE_WRITE_DATA|
916 SEC_STD_DELETE,
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);
922 if (dnum1 != -1) {
923 printf("(%s) setting delete_on_close on file succeeded !\n",
924 __location__);
925 correct = False;
926 goto fail;
929 printf("fourteenth delete on close test succeeded.\n");
931 fail:
933 return correct;
936 /* Test 15 ... */
937 static BOOL deltest15(struct smbcli_state *cli1, struct smbcli_state *cli2)
939 int fnum1 = -1;
940 int fnum2 = -1;
941 BOOL correct = True;
942 NTSTATUS status;
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,
953 SEC_FILE_READ_DATA,
954 FILE_ATTRIBUTE_NORMAL,
955 NTCREATEX_SHARE_ACCESS_READ|
956 NTCREATEX_SHARE_ACCESS_WRITE|
957 NTCREATEX_SHARE_ACCESS_DELETE,
958 NTCREATEX_DISP_OVERWRITE_IF,
959 0, 0);
961 if (fnum1 == -1) {
962 printf("(%s) open - 1 of %s failed (%s)\n",
963 __location__, fname, smbcli_errstr(cli1->tree));
964 correct = False;
965 goto fail;
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));
973 correct = False;
974 goto fail;
977 fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
978 SEC_GENERIC_ALL,
979 FILE_ATTRIBUTE_NORMAL,
980 NTCREATEX_SHARE_ACCESS_READ|
981 NTCREATEX_SHARE_ACCESS_WRITE|
982 NTCREATEX_SHARE_ACCESS_DELETE,
983 NTCREATEX_DISP_OVERWRITE_IF,
984 0, 0);
986 if (fnum2 == -1) {
987 printf("(%s) open - 1 of %s failed (%s)\n",
988 __location__, fname_new, smbcli_errstr(cli1->tree));
989 correct = False;
990 goto fail;
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",
997 __location__);
998 correct = False;
999 goto fail;
1002 smbcli_close(cli2->tree, fnum2);
1004 /* The file should be around under the new name, there's a second
1005 * handle open */
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);
1010 correct = False;
1011 goto fail;
1014 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1015 SEC_GENERIC_ALL,
1016 FILE_ATTRIBUTE_NORMAL,
1017 NTCREATEX_SHARE_ACCESS_READ|
1018 NTCREATEX_SHARE_ACCESS_WRITE|
1019 NTCREATEX_SHARE_ACCESS_DELETE,
1020 NTCREATEX_DISP_OVERWRITE_IF,
1021 0, 0);
1023 if (fnum2 == -1) {
1024 printf("(%s) open - 1 of %s failed (%s)\n",
1025 __location__, fname, smbcli_errstr(cli1->tree));
1026 correct = False;
1027 goto fail;
1030 smbcli_close(cli2->tree, fnum2);
1031 smbcli_close(cli1->tree, fnum1);
1033 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1034 SEC_FILE_READ_EA,
1035 FILE_ATTRIBUTE_NORMAL,
1036 NTCREATEX_SHARE_ACCESS_READ|
1037 NTCREATEX_SHARE_ACCESS_WRITE|
1038 NTCREATEX_SHARE_ACCESS_DELETE,
1039 NTCREATEX_DISP_OPEN,
1040 0, 0);
1042 if (fnum1 == -1) {
1043 printf("(%s) open - 1 of %s failed (%s)\n",
1044 __location__, fname, smbcli_errstr(cli1->tree));
1045 correct = False;
1046 goto fail;
1049 smbcli_close(cli1->tree, fnum1);
1051 fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
1052 SEC_FILE_READ_EA,
1053 FILE_ATTRIBUTE_NORMAL,
1054 NTCREATEX_SHARE_ACCESS_READ|
1055 NTCREATEX_SHARE_ACCESS_WRITE|
1056 NTCREATEX_SHARE_ACCESS_DELETE,
1057 NTCREATEX_DISP_OPEN,
1058 0, 0);
1060 if (fnum1 != -1) {
1061 printf("(%s) smbcli_open succeeded, should have "
1062 "failed\n", __location__);
1063 smbcli_close(cli1->tree, fnum1);
1064 correct = False;
1065 goto fail;
1068 printf("fifteenth delete on close test succeeded.\n");
1070 fail:
1072 return correct;
1075 /* Test 16 ... */
1076 static BOOL deltest16(struct smbcli_state *cli1, struct smbcli_state *cli2)
1078 int fnum1 = -1;
1079 int fnum2 = -1;
1080 BOOL correct = True;
1082 del_clean_area(cli1, cli2);
1084 /* Test 16. */
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);
1102 if (fnum1 == -1) {
1103 printf("(%s) open - 1 of %s failed (%s)\n",
1104 __location__, fname, smbcli_errstr(cli1->tree));
1105 correct = False;
1106 goto fail;
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,
1120 0, 0);
1123 /* Should work. */
1124 if (fnum2 == -1) {
1125 printf("(%s) open - 1 of %s failed (%s)\n",
1126 __location__, fname, smbcli_errstr(cli1->tree));
1127 correct = False;
1128 goto fail;
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);
1137 if (fnum1 != -1) {
1138 printf("(%s) open of %s succeeded (should fail)\n",
1139 __location__, fname);
1140 correct = False;
1141 goto fail;
1144 printf("sixteenth delete on close test succeeded.\n");
1146 fail:
1148 return correct;
1151 /* Test 17 ... */
1152 static BOOL deltest17(struct smbcli_state *cli1, struct smbcli_state *cli2)
1154 int fnum1 = -1;
1155 int fnum2 = -1;
1156 BOOL correct = True;
1158 del_clean_area(cli1, cli2);
1160 /* Test 17. */
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,
1176 0, 0);
1177 if (fnum1 == -1) {
1178 printf("(%s) open - 1 of %s failed (%s)\n",
1179 __location__, fname, smbcli_errstr(cli1->tree));
1180 correct = False;
1181 goto fail;
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);
1197 if (fnum1 == -1) {
1198 printf("(%s) open - 1 of %s failed (%s)\n",
1199 __location__, fname, smbcli_errstr(cli1->tree));
1200 correct = False;
1201 goto fail;
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,
1215 0, 0);
1217 /* Should work. */
1218 if (fnum2 == -1) {
1219 printf("(%s) open - 1 of %s failed (%s)\n",
1220 __location__, fname, smbcli_errstr(cli1->tree));
1221 correct = False;
1222 goto fail;
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);
1231 if (fnum1 == -1) {
1232 printf("(%s) open of %s failed (should succeed) - %s\n",
1233 __location__, fname, smbcli_errstr(cli1->tree));
1234 correct = False;
1235 goto fail;
1238 printf("seventeenth delete on close test succeeded.\n");
1240 fail:
1242 return correct;
1245 /* Test 18 ... */
1246 static BOOL deltest18(struct smbcli_state *cli1, struct smbcli_state *cli2)
1248 int fnum1 = -1;
1249 int fnum2 = -1;
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,
1264 SEC_FILE_READ_DATA|
1265 SEC_FILE_WRITE_DATA|
1266 SEC_STD_DELETE,
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);
1274 if (fnum1 == -1) {
1275 printf("(%s) open - 1 of %s failed (%s)\n",
1276 __location__, dirname, smbcli_errstr(cli1->tree));
1277 correct = False;
1278 goto fail;
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);
1295 /* Should work. */
1296 if (fnum2 == -1) {
1297 printf("(%s) open - 1 of %s failed (%s)\n",
1298 __location__, dirname, smbcli_errstr(cli1->tree));
1299 correct = False;
1300 goto fail;
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);
1316 if (fnum1 != -1) {
1317 printf("(%s) open of %s succeeded (should fail)\n",
1318 __location__, dirname);
1319 correct = False;
1320 goto fail;
1323 printf("eighteenth delete on close test succeeded.\n");
1325 fail:
1327 return correct;
1330 /* Test 19 ... */
1331 static BOOL deltest19(struct smbcli_state *cli1, struct smbcli_state *cli2)
1333 int fnum1 = -1;
1334 int fnum2 = -1;
1335 BOOL correct = True;
1337 del_clean_area(cli1, cli2);
1339 /* Test 19. */
1341 smbcli_deltree(cli1->tree, dirname);
1343 /* Firstly open and create with all access */
1344 fnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
1345 SEC_FILE_READ_DATA|
1346 SEC_FILE_WRITE_DATA|
1347 SEC_STD_DELETE,
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);
1355 if (fnum1 == -1) {
1356 printf("(%s) open - 1 of %s failed (%s)\n",
1357 __location__, dirname, smbcli_errstr(cli1->tree));
1358 correct = False;
1359 goto fail;
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,
1367 SEC_FILE_READ_DATA|
1368 SEC_FILE_WRITE_DATA|
1369 SEC_STD_DELETE,
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);
1377 if (fnum1 == -1) {
1378 printf("(%s) open - 1 of %s failed (%s)\n",
1379 __location__, fname, smbcli_errstr(cli1->tree));
1380 correct = False;
1381 goto fail;
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);
1397 /* Should work. */
1398 if (fnum2 == -1) {
1399 printf("(%s) open - 1 of %s failed (%s)\n",
1400 __location__, dirname, smbcli_errstr(cli1->tree));
1401 correct = False;
1402 goto fail;
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);
1421 if (fnum1 != -1) {
1422 printf("(%s) open of %s succeeded (should fail)\n",
1423 __location__, dirname);
1424 correct = False;
1425 goto fail;
1428 printf("nineteenth delete on close test succeeded.\n");
1430 fail:
1432 return correct;
1435 /* Test 20 ... */
1436 static BOOL deltest20(struct smbcli_state *cli1, struct smbcli_state *cli2)
1438 int fnum1 = -1;
1439 int dnum1 = -1;
1440 BOOL correct = True;
1441 NTSTATUS status;
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,
1450 SEC_FILE_READ_DATA|
1451 SEC_FILE_WRITE_DATA|
1452 SEC_STD_DELETE,
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);
1459 if (dnum1 == -1) {
1460 printf("(%s) open of %s failed: %s!\n",
1461 __location__, dirname, smbcli_errstr(cli1->tree));
1462 correct = False;
1463 goto fail;
1466 check_delete_on_close(cli1, dnum1, dirname, False);
1467 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
1470 char *fullname;
1471 asprintf(&fullname, "\\%s%s", dirname, fname);
1472 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1473 DENY_NONE);
1474 if (fnum1 != -1) {
1475 printf("(%s) smbcli_open succeeded, should have "
1476 "failed: %s\n",
1477 __location__, smbcli_errstr(cli1->tree));
1478 correct = False;
1479 goto fail;
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));
1487 correct = False;
1488 goto fail;
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",
1495 __location__);
1496 correct = False;
1497 goto fail;
1501 char *fullname;
1502 asprintf(&fullname, "\\%s%s", dirname, fname);
1503 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1504 DENY_NONE);
1505 if (fnum1 == -1) {
1506 printf("(%s) smbcli_open failed: %s\n",
1507 __location__, smbcli_errstr(cli1->tree));
1508 correct = False;
1509 goto fail;
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));
1520 correct = False;
1521 goto fail;
1524 smbcli_close(cli1->tree, dnum1);
1526 printf("twentieth delete on close test succeeded.\n");
1528 fail:
1530 return correct;
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)) {
1545 return False;
1548 if (!torture_open_connection(&cli2)) {
1549 printf("(%s) failed to open second connection.\n",
1550 __location__);
1551 correct = False;
1552 goto fail;
1555 if (!deltest1(cli1, cli2)) {
1556 correct = False;
1557 goto fail;
1559 if (!deltest2(cli1, cli2)) {
1560 correct = False;
1561 goto fail;
1563 if (!deltest3(cli1, cli2)) {
1564 correct = False;
1565 goto fail;
1567 if (!deltest4(cli1, cli2)) {
1568 correct = False;
1569 goto fail;
1571 if (!deltest5(cli1, cli2)) {
1572 correct = False;
1573 goto fail;
1575 if (!deltest6(cli1, cli2)) {
1576 correct = False;
1577 goto fail;
1579 if (!deltest7(cli1, cli2)) {
1580 correct = False;
1581 goto fail;
1583 if (!deltest8(cli1, cli2)) {
1584 correct = False;
1585 goto fail;
1587 if (!deltest9(cli1, cli2)) {
1588 correct = False;
1589 goto fail;
1591 if (!deltest10(cli1, cli2)) {
1592 correct = False;
1593 goto fail;
1595 if (!deltest11(cli1, cli2)) {
1596 correct = False;
1597 goto fail;
1599 if (!deltest12(cli1, cli2)) {
1600 correct = False;
1601 goto fail;
1603 if (!deltest13(cli1, cli2)) {
1604 correct = False;
1605 goto fail;
1607 if (!deltest14(cli1, cli2)) {
1608 correct = False;
1609 goto fail;
1611 if (!deltest15(cli1, cli2)) {
1612 correct = False;
1613 goto fail;
1615 if (!deltest16(cli1, cli2)) {
1616 correct = False;
1617 goto fail;
1619 if (!deltest17(cli1, cli2)) {
1620 correct = False;
1621 goto fail;
1623 if (!deltest18(cli1, cli2)) {
1624 correct = False;
1625 goto fail;
1627 if (!deltest19(cli1, cli2)) {
1628 correct = False;
1629 goto fail;
1631 if (!deltest20(cli1, cli2)) {
1632 correct = False;
1633 goto fail;
1635 printf("finished delete test\n");
1637 fail:
1638 del_clean_area(cli1, cli2);
1640 if (!torture_close_connection(cli1)) {
1641 correct = False;
1643 if (!torture_close_connection(cli2)) {
1644 correct = False;
1646 return correct;