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 "system/filesys.h"
25 #include "librpc/gen_ndr/ndr_security.h"
29 Test delete on close semantics.
31 BOOL torture_test_delete(void)
33 struct smbcli_state *cli1;
34 struct smbcli_state *cli2 = NULL;
35 const char *fname = "\\delete.file";
41 printf("starting delete test\n");
43 if (!torture_open_connection(&cli1)) {
47 /* Test 1 - this should delete the file on close. */
49 smbcli_setatr(cli1->tree, fname, 0, 0);
50 smbcli_unlink(cli1->tree, fname);
52 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
54 FILE_ATTRIBUTE_NORMAL,
55 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
56 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
59 printf("(%s) open of %s failed (%s)\n",
60 __location__, fname, smbcli_errstr(cli1->tree));
65 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
66 printf("(%s) close failed (%s)\n",
67 __location__, smbcli_errstr(cli1->tree));
72 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
74 printf("(%s) open of %s succeeded (should fail)\n",
80 printf("first delete on close test succeeded.\n");
82 /* Test 2 - this should delete the file on close. */
84 smbcli_setatr(cli1->tree, fname, 0, 0);
85 smbcli_unlink(cli1->tree, fname);
87 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
89 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
90 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
93 printf("(%s) open of %s failed (%s)\n",
94 __location__, fname, smbcli_errstr(cli1->tree));
99 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
100 printf("(%s) setting delete_on_close failed (%s)\n",
101 __location__, smbcli_errstr(cli1->tree));
106 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
107 printf("(%s) close failed (%s)\n",
108 __location__, smbcli_errstr(cli1->tree));
113 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
115 printf("(%s) open of %s succeeded should have been deleted on close !\n",
116 __location__, fname);
117 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
118 printf("(%s) close failed (%s)\n",
119 __location__, smbcli_errstr(cli1->tree));
123 smbcli_unlink(cli1->tree, fname);
125 printf("second delete on close test succeeded.\n");
128 smbcli_setatr(cli1->tree, fname, 0, 0);
129 smbcli_unlink(cli1->tree, fname);
131 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
133 FILE_ATTRIBUTE_NORMAL,
134 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
135 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
138 printf("(%s) open - 1 of %s failed (%s)\n",
139 __location__, fname, smbcli_errstr(cli1->tree));
144 /* This should fail with a sharing violation - open for delete is only compatible
145 with SHARE_DELETE. */
147 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
148 SEC_RIGHTS_FILE_READ,
149 FILE_ATTRIBUTE_NORMAL,
150 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
151 NTCREATEX_DISP_OPEN, 0, 0);
154 printf("(%s) open - 2 of %s succeeded - should have failed.\n",
155 __location__, fname);
160 /* This should succeed. */
162 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
163 SEC_RIGHTS_FILE_READ,
164 FILE_ATTRIBUTE_NORMAL,
165 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
166 NTCREATEX_DISP_OPEN, 0, 0);
169 printf("(%s) open - 2 of %s failed (%s)\n",
170 __location__, fname, smbcli_errstr(cli1->tree));
175 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
176 printf("(%s) setting delete_on_close failed (%s)\n",
177 __location__, smbcli_errstr(cli1->tree));
182 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
183 printf("(%s) close 1 failed (%s)\n",
184 __location__, smbcli_errstr(cli1->tree));
189 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
190 printf("(%s) close 2 failed (%s)\n",
191 __location__, smbcli_errstr(cli1->tree));
196 /* This should fail - file should no longer be there. */
198 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
200 printf("(%s) open of %s succeeded should have been deleted on close !\n",
201 __location__, fname);
202 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
203 printf("(%s) close failed (%s)\n",
204 __location__, smbcli_errstr(cli1->tree));
206 smbcli_unlink(cli1->tree, fname);
210 printf("third delete on close test succeeded.\n");
213 smbcli_setatr(cli1->tree, fname, 0, 0);
214 status = smbcli_unlink(cli1->tree, fname);
215 if (NT_STATUS_IS_OK(status)) {
216 printf("(%s) succeeded unlink of %s\n", __location__, fname);
221 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
223 SEC_FILE_WRITE_DATA |
225 FILE_ATTRIBUTE_NORMAL,
226 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
227 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
230 printf("(%s) open of %s failed (%s)\n",
231 __location__, fname, smbcli_errstr(cli1->tree));
236 /* This should succeed. */
237 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
238 SEC_RIGHTS_FILE_READ,
239 FILE_ATTRIBUTE_NORMAL,
240 NTCREATEX_SHARE_ACCESS_READ |
241 NTCREATEX_SHARE_ACCESS_WRITE |
242 NTCREATEX_SHARE_ACCESS_DELETE,
243 NTCREATEX_DISP_OPEN, 0, 0);
245 printf("(%s) open - 2 of %s failed (%s)\n",
246 __location__, fname, smbcli_errstr(cli1->tree));
251 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
252 printf("(%s) close - 1 failed (%s)\n",
253 __location__, smbcli_errstr(cli1->tree));
258 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
259 printf("(%s) setting delete_on_close failed (%s)\n",
260 __location__, smbcli_errstr(cli1->tree));
265 /* This should fail - no more opens once delete on close set. */
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|NTCREATEX_SHARE_ACCESS_DELETE,
270 NTCREATEX_DISP_OPEN, 0, 0);
272 printf("(%s) open - 3 of %s succeeded ! Should have failed.\n",
273 __location__, fname );
277 printf("fourth delete on close test succeeded.\n");
279 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
280 printf("(%s) close - 2 failed (%s)\n",
281 __location__, smbcli_errstr(cli1->tree));
287 smbcli_setatr(cli1->tree, fname, 0, 0);
288 smbcli_unlink(cli1->tree, fname);
290 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
292 printf("(%s) open of %s failed (%s)\n",
293 __location__, fname, smbcli_errstr(cli1->tree));
298 /* This should fail - only allowed on NT opens with DELETE access. */
300 if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
301 printf("(%s) setting delete_on_close on OpenX file succeeded - should fail !\n",
307 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
308 printf("(%s) close - 2 failed (%s)\n",
309 __location__, smbcli_errstr(cli1->tree));
314 printf("fifth delete on close test succeeded.\n");
317 smbcli_setatr(cli1->tree, fname, 0, 0);
318 smbcli_unlink(cli1->tree, fname);
320 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
321 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
322 FILE_ATTRIBUTE_NORMAL,
323 NTCREATEX_SHARE_ACCESS_READ |
324 NTCREATEX_SHARE_ACCESS_WRITE |
325 NTCREATEX_SHARE_ACCESS_DELETE,
326 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
329 printf("(%s) open of %s failed (%s)\n",
330 __location__, fname, smbcli_errstr(cli1->tree));
335 /* This should fail - only allowed on NT opens with DELETE access. */
337 if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
338 printf("(%s) setting delete_on_close on file with no delete access succeeded - should fail !\n",
344 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
345 printf("(%s) close - 2 failed (%s)\n",
346 __location__, smbcli_errstr(cli1->tree));
351 printf("sixth delete on close test succeeded.\n");
354 smbcli_setatr(cli1->tree, fname, 0, 0);
355 smbcli_unlink(cli1->tree, fname);
357 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
359 SEC_FILE_WRITE_DATA |
361 FILE_ATTRIBUTE_NORMAL, 0,
362 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
365 printf("(%s) open of %s failed (%s)\n",
366 __location__, fname, 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 on file failed !\n",
378 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, False))) {
379 printf("(%s) unsetting delete_on_close on file failed !\n",
385 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
386 printf("(%s) close - 2 failed (%s)\n",
387 __location__, smbcli_errstr(cli1->tree));
392 /* This next open should succeed - we reset the flag. */
394 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
396 printf("(%s) open of %s failed (%s)\n",
397 __location__, fname, smbcli_errstr(cli1->tree));
402 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
403 printf("(%s) close - 2 failed (%s)\n",
404 __location__, smbcli_errstr(cli1->tree));
409 printf("seventh delete on close test succeeded.\n");
412 smbcli_setatr(cli1->tree, fname, 0, 0);
413 smbcli_unlink(cli1->tree, fname);
415 if (!torture_open_connection(&cli2)) {
416 printf("(%s) failed to open second connection.\n",
422 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
426 FILE_ATTRIBUTE_NORMAL,
427 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
428 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
431 printf("(%s) open of %s failed (%s)\n",
432 __location__, fname, smbcli_errstr(cli1->tree));
437 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
441 FILE_ATTRIBUTE_NORMAL,
442 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
443 NTCREATEX_DISP_OPEN, 0, 0);
446 printf("(%s) open of %s failed (%s)\n",
447 __location__, fname, smbcli_errstr(cli1->tree));
452 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
453 printf("(%s) setting delete_on_close on file failed !\n",
459 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
460 printf("(%s) close - 1 failed (%s)\n",
461 __location__, smbcli_errstr(cli1->tree));
466 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
467 printf("(%s) close - 2 failed (%s)\n",
468 __location__, smbcli_errstr(cli2->tree));
473 /* This should fail.. */
474 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
476 printf("(%s) open of %s succeeded should have been deleted on close !\n",
477 __location__, fname);
481 printf("eighth delete on close test succeeded.\n");
483 /* This should fail - we need to set DELETE_ACCESS. */
484 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
485 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
486 FILE_ATTRIBUTE_NORMAL,
487 NTCREATEX_SHARE_ACCESS_NONE,
488 NTCREATEX_DISP_OVERWRITE_IF,
489 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
492 printf("(%s) open of %s succeeded should have failed!\n",
493 __location__, fname);
498 printf("ninth delete on close test succeeded.\n");
500 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
504 FILE_ATTRIBUTE_NORMAL,
505 NTCREATEX_SHARE_ACCESS_NONE,
506 NTCREATEX_DISP_OVERWRITE_IF,
507 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
509 printf("(%s) open of %s failed (%s)\n",
510 __location__, fname, smbcli_errstr(cli1->tree));
515 /* This should delete the file. */
516 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
517 printf("(%s) close failed (%s)\n",
518 __location__, smbcli_errstr(cli1->tree));
523 /* This should fail.. */
524 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
526 printf("(%s) open of %s succeeded should have been deleted on close !\n",
527 __location__, fname);
531 printf("tenth delete on close test succeeded.\n");
533 /* test 11 - does having read only attribute still allow delete on close. */
535 smbcli_setatr(cli1->tree, fname, 0, 0);
536 smbcli_unlink(cli1->tree, fname);
538 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
540 FILE_ATTRIBUTE_READONLY,
541 NTCREATEX_SHARE_ACCESS_NONE,
542 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
545 printf("(%s) open of %s failed (%s)\n",
546 __location__, fname, smbcli_errstr(cli1->tree));
551 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, True);
553 if (!NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
554 printf("(%s) setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n",
555 __location__, smbcli_errstr(cli1->tree));
560 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
561 printf("(%s) close failed (%s)\n",
562 __location__, smbcli_errstr(cli1->tree));
567 smbcli_setatr(cli1->tree, fname, 0, 0);
568 smbcli_unlink(cli1->tree, fname);
570 printf("eleventh delete on close test succeeded.\n");
572 /* test 12 - does having read only attribute still allow delete on close at time of open. */
574 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
576 FILE_ATTRIBUTE_READONLY,
577 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
578 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
581 printf("(%s) open of %s succeeded. Should fail with NT_STATUS_CANNOT_DELETE.\n",
582 __location__, fname);
583 smbcli_close(cli1->tree, fnum1);
587 status = smbcli_nt_error(cli1->tree);
588 if (!NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
589 printf("(%s) setting delete_on_close on open should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n",
590 __location__, smbcli_errstr(cli1->tree));
596 printf("twelvth delete on close test succeeded.\n");
598 printf("finished delete test\n");
601 /* FIXME: This will crash if we aborted before cli2 got
602 * intialized, because these functions don't handle
603 * uninitialized connections. */
605 smbcli_close(cli1->tree, fnum1);
606 smbcli_close(cli1->tree, fnum2);
607 smbcli_setatr(cli1->tree, fname, 0, 0);
608 smbcli_unlink(cli1->tree, fname);
610 if (!torture_close_connection(cli1)) {
613 if (!torture_close_connection(cli2)) {