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.
27 Test delete on close semantics.
29 BOOL torture_test_delete(int dummy)
31 struct smbcli_state *cli1;
32 struct smbcli_state *cli2 = NULL;
33 const char *fname = "\\delete.file";
39 printf("starting delete test\n");
41 if (!torture_open_connection(&cli1)) {
45 /* Test 1 - this should delete the file on close. */
47 smbcli_setatr(cli1->tree, fname, 0, 0);
48 smbcli_unlink(cli1->tree, fname);
50 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
51 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
52 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
55 printf("(%s) open of %s failed (%s)\n",
56 __location__, fname, smbcli_errstr(cli1->tree));
61 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
62 printf("(%s) close failed (%s)\n",
63 __location__, smbcli_errstr(cli1->tree));
68 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
70 printf("(%s) open of %s succeeded (should fail)\n",
76 printf("first delete on close test succeeded.\n");
78 /* Test 2 - this should delete the file on close. */
80 smbcli_setatr(cli1->tree, fname, 0, 0);
81 smbcli_unlink(cli1->tree, fname);
83 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
84 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
85 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
88 printf("(%s) open of %s failed (%s)\n",
89 __location__, fname, smbcli_errstr(cli1->tree));
94 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
95 printf("(%s) setting delete_on_close failed (%s)\n",
96 __location__, smbcli_errstr(cli1->tree));
101 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
102 printf("(%s) close failed (%s)\n",
103 __location__, smbcli_errstr(cli1->tree));
108 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
110 printf("(%s) open of %s succeeded should have been deleted on close !\n",
111 __location__, fname);
112 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
113 printf("(%s) close failed (%s)\n",
114 __location__, smbcli_errstr(cli1->tree));
118 smbcli_unlink(cli1->tree, fname);
120 printf("second delete on close test succeeded.\n");
123 smbcli_setatr(cli1->tree, fname, 0, 0);
124 smbcli_unlink(cli1->tree, fname);
126 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
127 GENERIC_RIGHTS_FILE_ALL_ACCESS,
128 FILE_ATTRIBUTE_NORMAL,
129 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
130 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
133 printf("(%s) open - 1 of %s failed (%s)\n",
134 __location__, fname, smbcli_errstr(cli1->tree));
139 /* This should fail with a sharing violation - open for delete is only compatible
140 with SHARE_DELETE. */
142 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
143 GENERIC_RIGHTS_FILE_READ,
144 FILE_ATTRIBUTE_NORMAL,
145 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
146 NTCREATEX_DISP_OPEN, 0, 0);
149 printf("(%s) open - 2 of %s succeeded - should have failed.\n",
150 __location__, fname);
155 /* This should succeed. */
157 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ, FILE_ATTRIBUTE_NORMAL,
158 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0);
161 printf("(%s) open - 2 of %s failed (%s)\n",
162 __location__, fname, smbcli_errstr(cli1->tree));
167 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
168 printf("(%s) setting delete_on_close failed (%s)\n",
169 __location__, smbcli_errstr(cli1->tree));
174 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
175 printf("(%s) close 1 failed (%s)\n",
176 __location__, smbcli_errstr(cli1->tree));
181 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
182 printf("(%s) close 2 failed (%s)\n",
183 __location__, smbcli_errstr(cli1->tree));
188 /* This should fail - file should no longer be there. */
190 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
192 printf("(%s) open of %s succeeded should have been deleted on close !\n",
193 __location__, fname);
194 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
195 printf("(%s) close failed (%s)\n",
196 __location__, smbcli_errstr(cli1->tree));
198 smbcli_unlink(cli1->tree, fname);
202 printf("third delete on close test succeeded.\n");
205 smbcli_setatr(cli1->tree, fname, 0, 0);
206 status = smbcli_unlink(cli1->tree, fname);
207 if (NT_STATUS_IS_OK(status)) {
208 printf("(%s) succeeded unlink of %s\n", __location__, fname);
213 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
214 SA_RIGHT_FILE_READ_DATA |
215 SA_RIGHT_FILE_WRITE_DATA |
216 STD_RIGHT_DELETE_ACCESS,
217 FILE_ATTRIBUTE_NORMAL,
218 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
219 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
222 printf("(%s) open of %s failed (%s)\n",
223 __location__, fname, smbcli_errstr(cli1->tree));
228 /* This should succeed. */
229 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_READ,
230 FILE_ATTRIBUTE_NORMAL,
231 NTCREATEX_SHARE_ACCESS_READ |
232 NTCREATEX_SHARE_ACCESS_WRITE |
233 NTCREATEX_SHARE_ACCESS_DELETE,
234 NTCREATEX_DISP_OPEN, 0, 0);
236 printf("(%s) open - 2 of %s failed (%s)\n",
237 __location__, fname, smbcli_errstr(cli1->tree));
242 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
243 printf("(%s) close - 1 failed (%s)\n",
244 __location__, smbcli_errstr(cli1->tree));
249 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
250 printf("(%s) setting delete_on_close failed (%s)\n",
251 __location__, smbcli_errstr(cli1->tree));
256 /* This should fail - no more opens once delete on close set. */
257 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
258 GENERIC_RIGHTS_FILE_READ,
259 FILE_ATTRIBUTE_NORMAL,
260 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
261 NTCREATEX_DISP_OPEN, 0, 0);
263 printf("(%s) open - 3 of %s succeeded ! Should have failed.\n",
264 __location__, fname );
268 printf("fourth delete on close test succeeded.\n");
270 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
271 printf("(%s) close - 2 failed (%s)\n",
272 __location__, smbcli_errstr(cli1->tree));
278 smbcli_setatr(cli1->tree, fname, 0, 0);
279 smbcli_unlink(cli1->tree, fname);
281 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
283 printf("(%s) open of %s failed (%s)\n",
284 __location__, fname, smbcli_errstr(cli1->tree));
289 /* This should fail - only allowed on NT opens with DELETE access. */
291 if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
292 printf("(%s) setting delete_on_close on OpenX file succeeded - should fail !\n",
298 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
299 printf("(%s) close - 2 failed (%s)\n",
300 __location__, smbcli_errstr(cli1->tree));
305 printf("fifth delete on close test succeeded.\n");
308 smbcli_setatr(cli1->tree, fname, 0, 0);
309 smbcli_unlink(cli1->tree, fname);
311 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
312 SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA,
313 FILE_ATTRIBUTE_NORMAL,
314 NTCREATEX_SHARE_ACCESS_READ |
315 NTCREATEX_SHARE_ACCESS_WRITE |
316 NTCREATEX_SHARE_ACCESS_DELETE,
317 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
320 printf("(%s) open of %s failed (%s)\n",
321 __location__, fname, smbcli_errstr(cli1->tree));
326 /* This should fail - only allowed on NT opens with DELETE access. */
328 if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
329 printf("(%s) setting delete_on_close on file with no delete access succeeded - should fail !\n",
335 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
336 printf("(%s) close - 2 failed (%s)\n",
337 __location__, smbcli_errstr(cli1->tree));
342 printf("sixth delete on close test succeeded.\n");
345 smbcli_setatr(cli1->tree, fname, 0, 0);
346 smbcli_unlink(cli1->tree, fname);
348 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
349 SA_RIGHT_FILE_READ_DATA |
350 SA_RIGHT_FILE_WRITE_DATA |
351 STD_RIGHT_DELETE_ACCESS,
352 FILE_ATTRIBUTE_NORMAL, 0, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
355 printf("(%s) open of %s failed (%s)\n",
356 __location__, fname, smbcli_errstr(cli1->tree));
361 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
362 printf("(%s) setting delete_on_close on file failed !\n",
368 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, False))) {
369 printf("(%s) unsetting delete_on_close on file failed !\n",
375 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
376 printf("(%s) close - 2 failed (%s)\n",
377 __location__, smbcli_errstr(cli1->tree));
382 /* This next open should succeed - we reset the flag. */
384 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
386 printf("(%s) open of %s failed (%s)\n",
387 __location__, fname, smbcli_errstr(cli1->tree));
392 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
393 printf("(%s) close - 2 failed (%s)\n",
394 __location__, smbcli_errstr(cli1->tree));
399 printf("seventh delete on close test succeeded.\n");
402 smbcli_setatr(cli1->tree, fname, 0, 0);
403 smbcli_unlink(cli1->tree, fname);
405 if (!torture_open_connection(&cli2)) {
406 printf("(%s) failed to open second connection.\n",
412 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
413 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
414 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
417 printf("(%s) open of %s failed (%s)\n",
418 __location__, fname, smbcli_errstr(cli1->tree));
423 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
424 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
425 NTCREATEX_DISP_OPEN, 0, 0);
428 printf("(%s) open of %s failed (%s)\n",
429 __location__, fname, smbcli_errstr(cli1->tree));
434 if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
435 printf("(%s) setting delete_on_close on file failed !\n",
441 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
442 printf("(%s) close - 1 failed (%s)\n",
443 __location__, smbcli_errstr(cli1->tree));
448 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
449 printf("(%s) close - 2 failed (%s)\n",
450 __location__, smbcli_errstr(cli2->tree));
455 /* This should fail.. */
456 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
458 printf("(%s) open of %s succeeded should have been deleted on close !\n",
459 __location__, fname);
463 printf("eighth delete on close test succeeded.\n");
465 /* This should fail - we need to set DELETE_ACCESS. */
466 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
467 SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA,
468 FILE_ATTRIBUTE_NORMAL,
469 NTCREATEX_SHARE_ACCESS_NONE,
470 NTCREATEX_DISP_OVERWRITE_IF,
471 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
474 printf("(%s) open of %s succeeded should have failed!\n",
475 __location__, fname);
480 printf("ninth delete on close test succeeded.\n");
482 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
483 SA_RIGHT_FILE_READ_DATA|SA_RIGHT_FILE_WRITE_DATA|STD_RIGHT_DELETE_ACCESS,
484 FILE_ATTRIBUTE_NORMAL,
485 NTCREATEX_SHARE_ACCESS_NONE,
486 NTCREATEX_DISP_OVERWRITE_IF,
487 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
489 printf("(%s) open of %s failed (%s)\n",
490 __location__, fname, smbcli_errstr(cli1->tree));
495 /* This should delete the file. */
496 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
497 printf("(%s) close failed (%s)\n",
498 __location__, smbcli_errstr(cli1->tree));
503 /* This should fail.. */
504 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
506 printf("(%s) open of %s succeeded should have been deleted on close !\n",
507 __location__, fname);
511 printf("tenth delete on close test succeeded.\n");
513 /* test 11 - does having read only attribute still allow delete on close. */
515 smbcli_setatr(cli1->tree, fname, 0, 0);
516 smbcli_unlink(cli1->tree, fname);
518 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
519 GENERIC_RIGHTS_FILE_ALL_ACCESS,
520 FILE_ATTRIBUTE_READONLY,
521 NTCREATEX_SHARE_ACCESS_NONE,
522 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
525 printf("(%s) open of %s failed (%s)\n",
526 __location__, fname, smbcli_errstr(cli1->tree));
531 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, True);
533 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_CANNOT_DELETE)) {
534 printf("(%s) setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n",
535 __location__, smbcli_errstr(cli1->tree));
540 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
541 printf("(%s) close failed (%s)\n",
542 __location__, smbcli_errstr(cli1->tree));
547 smbcli_setatr(cli1->tree, fname, 0, 0);
548 smbcli_unlink(cli1->tree, fname);
550 printf("eleventh delete on close test succeeded.\n");
552 /* test 12 - does having read only attribute still allow delete on close at time of open. */
554 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS, FILE_ATTRIBUTE_READONLY,
555 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
556 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
559 printf("(%s) open of %s succeeded. Should fail with NT_STATUS_CANNOT_DELETE.\n",
560 __location__, fname);
561 smbcli_close(cli1->tree, fnum1);
565 status = smbcli_nt_error(cli1->tree);
566 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_CANNOT_DELETE)) {
567 printf("(%s) setting delete_on_close on open should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n",
568 __location__, smbcli_errstr(cli1->tree));
574 printf("twelvth delete on close test succeeded.\n");
576 printf("finished delete test\n");
579 /* FIXME: This will crash if we aborted before cli2 got
580 * intialized, because these functions don't handle
581 * uninitialized connections. */
583 smbcli_close(cli1->tree, fnum1);
584 smbcli_close(cli1->tree, fnum2);
585 smbcli_setatr(cli1->tree, fname, 0, 0);
586 smbcli_unlink(cli1->tree, fname);
588 if (!torture_close_connection(cli1)) {
591 if (!torture_close_connection(cli2)) {