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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "libcli/libcli.h"
24 #include "torture/torture.h"
25 #include "torture/util.h"
26 #include "system/filesys.h"
27 #include "libcli/raw/libcliraw.h"
29 #include "torture/raw/proto.h"
31 static bool check_delete_on_close(struct torture_context *tctx,
32 struct smbcli_state *cli, int fnum,
33 const char *fname, bool expect_it,
36 union smb_search_data data;
39 time_t c_time, a_time, m_time;
43 status = torture_single_search(cli, tctx,
46 RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
47 FILE_ATTRIBUTE_DIRECTORY,
49 torture_assert_ntstatus_ok(tctx, status,
50 talloc_asprintf(tctx, "single_search failed (%s)", where));
53 union smb_fileinfo io;
54 int nlink = expect_it ? 0 : 1;
56 io.all_info.level = RAW_FILEINFO_ALL_INFO;
57 io.all_info.in.file.fnum = fnum;
59 status = smb_raw_fileinfo(cli->tree, tctx, &io);
60 torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx,
61 "qfileinfo failed (%s)", where));
63 torture_assert(tctx, expect_it == io.all_info.out.delete_pending,
65 "%s - Expected del_on_close flag %d, qfileinfo/all_info gave %d",
66 where, expect_it, io.all_info.out.delete_pending));
68 torture_assert(tctx, nlink == io.all_info.out.nlink,
70 "%s - Expected nlink %d, qfileinfo/all_info gave %d",
71 where, nlink, io.all_info.out.nlink));
73 io.standard_info.level = RAW_FILEINFO_STANDARD_INFO;
74 io.standard_info.in.file.fnum = fnum;
76 status = smb_raw_fileinfo(cli->tree, tctx, &io);
77 torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
79 torture_assert(tctx, expect_it == io.standard_info.out.delete_pending,
80 talloc_asprintf(tctx, "%s - Expected del_on_close flag %d, qfileinfo/standard_info gave %d\n",
81 where, expect_it, io.standard_info.out.delete_pending));
83 torture_assert(tctx, nlink == io.standard_info.out.nlink,
84 talloc_asprintf(tctx, "%s - Expected nlink %d, qfileinfo/standard_info gave %d",
85 where, nlink, io.all_info.out.nlink));
88 status = smbcli_qpathinfo(cli->tree, fname,
89 &c_time, &a_time, &m_time,
93 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
94 "qpathinfo did not give correct error code");
96 torture_assert_ntstatus_ok(tctx, status,
97 talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
103 #define CHECK_STATUS(_cli, _expected) \
104 torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
107 static const char *fname = "\\delete.file";
108 static const char *fname_new = "\\delete.new";
109 static const char *dname = "\\delete.dir";
111 static void del_clean_area(struct smbcli_state *cli1, struct smbcli_state *cli2)
113 smb_raw_exit(cli1->session);
114 smb_raw_exit(cli2->session);
116 smbcli_deltree(cli1->tree, dname);
117 smbcli_setatr(cli1->tree, fname, 0, 0);
118 smbcli_unlink(cli1->tree, fname);
119 smbcli_setatr(cli1->tree, fname_new, 0, 0);
120 smbcli_unlink(cli1->tree, fname_new);
123 /* Test 1 - this should delete the file on close. */
125 static bool deltest1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
129 del_clean_area(cli1, cli2);
131 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
133 FILE_ATTRIBUTE_NORMAL,
134 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
135 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
137 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
138 fname, smbcli_errstr(cli1->tree)));
140 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
141 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli1->tree)));
143 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
144 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
150 /* Test 2 - this should delete the file on close. */
151 static bool deltest2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
155 del_clean_area(cli1, cli2);
157 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
159 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
160 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
162 torture_assert(tctx, fnum1 != -1,
163 talloc_asprintf(tctx, "open of %s failed (%s)",
164 fname, smbcli_errstr(cli1->tree)));
166 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
167 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
168 smbcli_errstr(cli1->tree)));
170 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
171 talloc_asprintf(tctx, "close failed (%s)",
172 smbcli_errstr(cli1->tree)));
174 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
176 printf("(%s) open of %s succeeded should have been deleted on close !\n",
177 __location__, fname);
178 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
179 printf("(%s) close failed (%s)\n",
180 __location__, smbcli_errstr(cli1->tree));
183 smbcli_unlink(cli1->tree, fname);
189 static bool deltest3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
194 del_clean_area(cli1, cli2);
196 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
198 FILE_ATTRIBUTE_NORMAL,
199 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
200 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
202 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
203 fname, smbcli_errstr(cli1->tree)));
205 /* This should fail with a sharing violation - open for delete is only compatible
206 with SHARE_DELETE. */
208 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
209 SEC_RIGHTS_FILE_READ,
210 FILE_ATTRIBUTE_NORMAL,
211 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
212 NTCREATEX_DISP_OPEN, 0, 0);
214 torture_assert(tctx, fnum2 == -1,
215 talloc_asprintf(tctx, "open - 2 of %s succeeded - should have failed.",
218 /* This should succeed. */
220 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
221 SEC_RIGHTS_FILE_READ,
222 FILE_ATTRIBUTE_NORMAL,
223 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
224 NTCREATEX_DISP_OPEN, 0, 0);
226 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
227 fname, smbcli_errstr(cli1->tree)));
229 torture_assert_ntstatus_ok(tctx,
230 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
231 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
232 smbcli_errstr(cli1->tree)));
234 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
235 talloc_asprintf(tctx, "close 1 failed (%s)",
236 smbcli_errstr(cli1->tree)));
238 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum2),
239 talloc_asprintf(tctx, "close 2 failed (%s)",
240 smbcli_errstr(cli1->tree)));
242 /* This should fail - file should no longer be there. */
244 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
246 printf("(%s) open of %s succeeded should have been deleted on close !\n",
247 __location__, fname);
248 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
249 printf("(%s) close failed (%s)\n",
250 __location__, smbcli_errstr(cli1->tree));
252 smbcli_unlink(cli1->tree, fname);
259 static bool deltest4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
265 del_clean_area(cli1, cli2);
267 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
269 SEC_FILE_WRITE_DATA |
271 FILE_ATTRIBUTE_NORMAL,
272 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
273 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
275 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
276 fname, smbcli_errstr(cli1->tree)));
278 /* This should succeed. */
279 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
280 SEC_RIGHTS_FILE_READ,
281 FILE_ATTRIBUTE_NORMAL,
282 NTCREATEX_SHARE_ACCESS_READ |
283 NTCREATEX_SHARE_ACCESS_WRITE |
284 NTCREATEX_SHARE_ACCESS_DELETE,
285 NTCREATEX_DISP_OPEN, 0, 0);
286 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
287 fname, smbcli_errstr(cli1->tree)));
289 torture_assert_ntstatus_ok(tctx,
290 smbcli_close(cli1->tree, fnum2),
291 talloc_asprintf(tctx, "close - 1 failed (%s)",
292 smbcli_errstr(cli1->tree)));
294 torture_assert_ntstatus_ok(tctx,
295 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
296 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
297 smbcli_errstr(cli1->tree)));
299 /* This should fail - no more opens once delete on close set. */
300 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
301 SEC_RIGHTS_FILE_READ,
302 FILE_ATTRIBUTE_NORMAL,
303 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
304 NTCREATEX_DISP_OPEN, 0, 0);
305 torture_assert(tctx, fnum2 == -1,
306 talloc_asprintf(tctx, "open - 3 of %s succeeded ! Should have failed.",
309 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
311 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
312 talloc_asprintf(tctx, "close - 2 failed (%s)",
313 smbcli_errstr(cli1->tree)));
319 static bool deltest5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
323 del_clean_area(cli1, cli2);
325 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
326 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
327 fname, smbcli_errstr(cli1->tree)));
329 /* This should fail - only allowed on NT opens with DELETE access. */
331 torture_assert(tctx, !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True)),
332 "setting delete_on_close on OpenX file succeeded - should fail !");
334 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
335 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
341 static bool deltest6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
345 del_clean_area(cli1, cli2);
347 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
348 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
349 FILE_ATTRIBUTE_NORMAL,
350 NTCREATEX_SHARE_ACCESS_READ |
351 NTCREATEX_SHARE_ACCESS_WRITE |
352 NTCREATEX_SHARE_ACCESS_DELETE,
353 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
355 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
356 fname, smbcli_errstr(cli1->tree)));
358 /* This should fail - only allowed on NT opens with DELETE access. */
361 !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True)),
362 "setting delete_on_close on file with no delete access succeeded - should fail !");
364 torture_assert_ntstatus_ok(tctx,
365 smbcli_close(cli1->tree, fnum1),
366 talloc_asprintf(tctx, "close - 2 failed (%s)",
367 smbcli_errstr(cli1->tree)));
373 static bool deltest7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
378 del_clean_area(cli1, cli2);
380 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
382 SEC_FILE_WRITE_DATA |
384 FILE_ATTRIBUTE_NORMAL, 0,
385 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
387 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
388 fname, smbcli_errstr(cli1->tree)));
390 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
391 "setting delete_on_close on file failed !");
393 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
395 torture_assert_ntstatus_ok(tctx,
396 smbcli_nt_delete_on_close(cli1->tree, fnum1, False),
397 "unsetting delete_on_close on file failed !");
399 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
401 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
402 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
404 /* This next open should succeed - we reset the flag. */
406 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
407 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
408 fname, smbcli_errstr(cli1->tree)));
410 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
411 talloc_asprintf(tctx, "close - 2 failed (%s)",
412 smbcli_errstr(cli1->tree)));
418 static bool deltest8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
424 del_clean_area(cli1, cli2);
426 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
430 FILE_ATTRIBUTE_NORMAL,
431 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
432 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
434 torture_assert(tctx, fnum1 != -1,
435 talloc_asprintf(tctx, "open of %s failed (%s)",
436 fname, smbcli_errstr(cli1->tree)));
438 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
442 FILE_ATTRIBUTE_NORMAL,
443 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
444 NTCREATEX_DISP_OPEN, 0, 0);
446 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
447 fname, smbcli_errstr(cli1->tree)));
449 torture_assert_ntstatus_ok(tctx,
450 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
451 "setting delete_on_close on file failed !");
453 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
454 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
456 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
457 talloc_asprintf(tctx, "close - 1 failed (%s)",
458 smbcli_errstr(cli1->tree)));
460 correct &= check_delete_on_close(tctx, cli1, -1, fname, True, __location__);
461 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
463 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
464 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli2->tree)));
466 /* This should fail.. */
467 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
468 torture_assert(tctx, fnum1 == -1,
469 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !\n", fname));
475 static bool deltest9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
479 del_clean_area(cli1, cli2);
481 /* This should fail - we need to set DELETE_ACCESS. */
482 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
483 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
484 FILE_ATTRIBUTE_NORMAL,
485 NTCREATEX_SHARE_ACCESS_NONE,
486 NTCREATEX_DISP_OVERWRITE_IF,
487 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
489 torture_assert(tctx, fnum1 == -1,
490 talloc_asprintf(tctx, "open of %s succeeded should have failed!",
497 static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
501 del_clean_area(cli1, cli2);
503 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
507 FILE_ATTRIBUTE_NORMAL,
508 NTCREATEX_SHARE_ACCESS_NONE,
509 NTCREATEX_DISP_OVERWRITE_IF,
510 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
511 torture_assert(tctx, fnum1 != -1,
512 talloc_asprintf(tctx, "open of %s failed (%s)",
513 fname, smbcli_errstr(cli1->tree)));
515 /* This should delete the file. */
516 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
517 talloc_asprintf(tctx, "close failed (%s)",
518 smbcli_errstr(cli1->tree)));
520 /* This should fail.. */
521 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
522 torture_assert(tctx, fnum1 == -1,
523 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
529 static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
534 del_clean_area(cli1, cli2);
536 /* test 11 - does having read only attribute still allow delete on close. */
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);
544 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
545 fname, smbcli_errstr(cli1->tree)));
547 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, True);
549 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
550 talloc_asprintf(tctx, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1->tree)));
552 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
553 talloc_asprintf(tctx, "close failed (%s)",
554 smbcli_errstr(cli1->tree)));
560 static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
565 del_clean_area(cli1, cli2);
567 /* test 12 - does having read only attribute still allow delete on
568 * close at time of open. */
570 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
572 FILE_ATTRIBUTE_READONLY,
573 NTCREATEX_SHARE_ACCESS_DELETE,
574 NTCREATEX_DISP_OVERWRITE_IF,
575 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
577 torture_assert(tctx, fnum1 == -1,
578 talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
579 "NT_STATUS_CANNOT_DELETE.\n", fname));
581 status = smbcli_nt_error(cli1->tree);
582 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
583 talloc_asprintf(tctx, "setting delete_on_close on open should "
584 "fail with NT_STATUS_CANNOT_DELETE. Got %s "
586 smbcli_errstr(cli1->tree)));
592 static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
598 del_clean_area(cli1, cli2);
600 /* Test 13: Does resetting the delete on close flag affect a second
603 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
607 FILE_ATTRIBUTE_NORMAL,
608 NTCREATEX_SHARE_ACCESS_READ|
609 NTCREATEX_SHARE_ACCESS_WRITE|
610 NTCREATEX_SHARE_ACCESS_DELETE,
611 NTCREATEX_DISP_OVERWRITE_IF,
614 torture_assert(tctx, fnum1 != -1,
615 talloc_asprintf(tctx, "open of %s failed (%s)",
616 fname, smbcli_errstr(cli1->tree)));
618 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
622 FILE_ATTRIBUTE_NORMAL,
623 NTCREATEX_SHARE_ACCESS_READ|
624 NTCREATEX_SHARE_ACCESS_WRITE|
625 NTCREATEX_SHARE_ACCESS_DELETE,
626 NTCREATEX_DISP_OPEN, 0, 0);
628 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
629 "open of %s failed (%s)",
630 fname, smbcli_errstr(cli2->tree)));
632 torture_assert_ntstatus_ok(tctx,
633 smbcli_nt_delete_on_close(cli1->tree, fnum1,
635 "setting delete_on_close on file failed !");
637 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
638 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
640 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
642 "setting delete_on_close on file failed !");
644 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
645 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
647 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
648 talloc_asprintf(tctx, "close - 1 failed (%s)",
649 smbcli_errstr(cli1->tree)));
651 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
652 talloc_asprintf(tctx, "close - 2 failed (%s)",
653 smbcli_errstr(cli2->tree)));
655 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
657 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!",
660 smbcli_close(cli1->tree, fnum1);
666 static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
671 del_clean_area(cli1, cli2);
673 /* Test 14 -- directory */
675 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
679 FILE_ATTRIBUTE_DIRECTORY,
680 NTCREATEX_SHARE_ACCESS_READ|
681 NTCREATEX_SHARE_ACCESS_WRITE|
682 NTCREATEX_SHARE_ACCESS_DELETE,
683 NTCREATEX_DISP_CREATE, 0, 0);
684 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
685 dname, smbcli_errstr(cli1->tree)));
687 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, False, __location__);
688 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, True),
689 "setting delete_on_close on file failed !");
690 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, True, __location__);
691 smbcli_close(cli1->tree, dnum1);
693 /* Now it should be gone... */
695 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
699 FILE_ATTRIBUTE_DIRECTORY,
700 NTCREATEX_SHARE_ACCESS_READ|
701 NTCREATEX_SHARE_ACCESS_WRITE|
702 NTCREATEX_SHARE_ACCESS_DELETE,
703 NTCREATEX_DISP_OPEN, 0, 0);
704 torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
710 static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
717 del_clean_area(cli1, cli2);
719 /* Test 15: delete on close under rename */
721 smbcli_setatr(cli1->tree, fname, 0, 0);
722 smbcli_unlink(cli1->tree, fname);
723 smbcli_unlink(cli1->tree, fname_new);
725 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
727 FILE_ATTRIBUTE_NORMAL,
728 NTCREATEX_SHARE_ACCESS_READ|
729 NTCREATEX_SHARE_ACCESS_WRITE|
730 NTCREATEX_SHARE_ACCESS_DELETE,
731 NTCREATEX_DISP_OVERWRITE_IF,
734 torture_assert(tctx, fnum1 != -1,
735 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
737 status = smbcli_rename(cli2->tree, fname, fname_new);
739 torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
741 fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
743 FILE_ATTRIBUTE_NORMAL,
744 NTCREATEX_SHARE_ACCESS_READ|
745 NTCREATEX_SHARE_ACCESS_WRITE|
746 NTCREATEX_SHARE_ACCESS_DELETE,
747 NTCREATEX_DISP_OVERWRITE_IF,
750 torture_assert(tctx, fnum2 != -1,
751 talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
752 fname_new, smbcli_errstr(cli1->tree)));
754 status = smbcli_nt_delete_on_close(cli2->tree, fnum2, True);
756 torture_assert_ntstatus_ok(tctx, status,
757 "setting delete_on_close on file failed !");
759 smbcli_close(cli2->tree, fnum2);
761 /* The file should be around under the new name, there's a second
764 correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, True, __location__);
766 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
768 FILE_ATTRIBUTE_NORMAL,
769 NTCREATEX_SHARE_ACCESS_READ|
770 NTCREATEX_SHARE_ACCESS_WRITE|
771 NTCREATEX_SHARE_ACCESS_DELETE,
772 NTCREATEX_DISP_OVERWRITE_IF,
775 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
776 fname, smbcli_errstr(cli1->tree)));
778 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
780 smbcli_close(cli2->tree, fnum2);
781 smbcli_close(cli1->tree, fnum1);
783 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
785 FILE_ATTRIBUTE_NORMAL,
786 NTCREATEX_SHARE_ACCESS_READ|
787 NTCREATEX_SHARE_ACCESS_WRITE|
788 NTCREATEX_SHARE_ACCESS_DELETE,
792 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
793 fname, smbcli_errstr(cli1->tree)));
795 smbcli_close(cli1->tree, fnum1);
797 fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
799 FILE_ATTRIBUTE_NORMAL,
800 NTCREATEX_SHARE_ACCESS_READ|
801 NTCREATEX_SHARE_ACCESS_WRITE|
802 NTCREATEX_SHARE_ACCESS_DELETE,
806 torture_assert(tctx, fnum1 == -1,
807 "smbcli_open succeeded, should have "
814 static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
820 del_clean_area(cli1, cli2);
824 /* Ensure the file doesn't already exist. */
825 smbcli_close(cli1->tree, fnum1);
826 smbcli_close(cli1->tree, fnum2);
827 smbcli_setatr(cli1->tree, fname, 0, 0);
828 smbcli_unlink(cli1->tree, fname);
830 /* Firstly create with all access, but delete on close. */
831 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
833 FILE_ATTRIBUTE_NORMAL,
834 NTCREATEX_SHARE_ACCESS_READ|
835 NTCREATEX_SHARE_ACCESS_WRITE|
836 NTCREATEX_SHARE_ACCESS_DELETE,
837 NTCREATEX_DISP_CREATE,
838 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
840 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
842 /* The delete on close bit is *not* reported as being set. */
843 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
845 /* The delete on close bit is *not* reported as being set. */
846 correct &= check_delete_on_close(tctx, cli1, -1, fname, False, __location__);
847 correct &= check_delete_on_close(tctx, cli2, -1, fname, False, __location__);
849 /* Now try opening again for read-only. */
850 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
851 SEC_RIGHTS_FILE_READ,
852 FILE_ATTRIBUTE_NORMAL,
853 NTCREATEX_SHARE_ACCESS_READ|
854 NTCREATEX_SHARE_ACCESS_WRITE|
855 NTCREATEX_SHARE_ACCESS_DELETE,
860 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
861 fname, smbcli_errstr(cli1->tree)));
863 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
864 correct &= check_delete_on_close(tctx, cli1, -1, fname, False, __location__);
865 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
866 correct &= check_delete_on_close(tctx, cli2, -1, fname, False, __location__);
868 smbcli_close(cli1->tree, fnum1);
870 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, True, __location__);
871 correct &= check_delete_on_close(tctx, cli2, -1, fname, True, __location__);
873 smbcli_close(cli2->tree, fnum2);
875 /* And the file should be deleted ! */
876 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
877 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
884 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
890 del_clean_area(cli1, cli2);
894 /* Ensure the file doesn't already exist. */
895 smbcli_close(cli1->tree, fnum1);
896 smbcli_close(cli1->tree, fnum2);
897 smbcli_setatr(cli1->tree, fname, 0, 0);
898 smbcli_unlink(cli1->tree, fname);
900 /* Firstly open and create with all access */
901 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
903 FILE_ATTRIBUTE_NORMAL,
904 NTCREATEX_SHARE_ACCESS_READ|
905 NTCREATEX_SHARE_ACCESS_WRITE|
906 NTCREATEX_SHARE_ACCESS_DELETE,
907 NTCREATEX_DISP_CREATE,
909 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
910 fname, smbcli_errstr(cli1->tree)));
912 /* And close - just to create the file. */
913 smbcli_close(cli1->tree, fnum1);
915 /* Next open with all access, but add delete on close. */
916 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
918 FILE_ATTRIBUTE_NORMAL,
919 NTCREATEX_SHARE_ACCESS_READ|
920 NTCREATEX_SHARE_ACCESS_WRITE|
921 NTCREATEX_SHARE_ACCESS_DELETE,
923 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
925 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
926 fname, smbcli_errstr(cli1->tree)));
928 /* The delete on close bit is *not* reported as being set. */
929 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
931 /* Now try opening again for read-only. */
932 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
933 SEC_RIGHTS_FILE_READ|
935 FILE_ATTRIBUTE_NORMAL,
936 NTCREATEX_SHARE_ACCESS_READ|
937 NTCREATEX_SHARE_ACCESS_WRITE|
938 NTCREATEX_SHARE_ACCESS_DELETE,
943 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
944 fname, smbcli_errstr(cli1->tree)));
946 /* still not reported as being set on either */
947 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
948 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, False, __location__);
950 smbcli_close(cli1->tree, fnum1);
952 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, False, __location__);
954 smbcli_close(cli1->tree, fnum2);
956 /* See if the file is deleted - shouldn't be.... */
957 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
958 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
959 fname, smbcli_errstr(cli1->tree)));
965 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
971 del_clean_area(cli1, cli2);
973 /* Test 18. With directories. */
975 /* Ensure the file doesn't already exist. */
976 smbcli_close(cli1->tree, fnum1);
977 smbcli_close(cli1->tree, fnum2);
979 smbcli_deltree(cli1->tree, dname);
981 /* Firstly create with all access, but delete on close. */
982 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
986 FILE_ATTRIBUTE_DIRECTORY,
987 NTCREATEX_SHARE_ACCESS_READ|
988 NTCREATEX_SHARE_ACCESS_WRITE|
989 NTCREATEX_SHARE_ACCESS_DELETE,
990 NTCREATEX_DISP_CREATE,
991 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
993 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
994 dname, smbcli_errstr(cli1->tree)));
996 /* The delete on close bit is *not* reported as being set. */
997 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, False, __location__);
999 /* Now try opening again for read-only. */
1000 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1001 SEC_RIGHTS_FILE_READ,
1002 FILE_ATTRIBUTE_DIRECTORY,
1003 NTCREATEX_SHARE_ACCESS_READ|
1004 NTCREATEX_SHARE_ACCESS_WRITE|
1005 NTCREATEX_SHARE_ACCESS_DELETE,
1006 NTCREATEX_DISP_OPEN,
1007 NTCREATEX_OPTIONS_DIRECTORY, 0);
1011 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1012 dname, smbcli_errstr(cli1->tree)));
1014 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, False, __location__);
1015 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, False, __location__);
1017 smbcli_close(cli1->tree, fnum1);
1019 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, True, __location__);
1021 smbcli_close(cli1->tree, fnum2);
1023 /* And the directory should be deleted ! */
1024 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1025 SEC_RIGHTS_FILE_READ,
1026 FILE_ATTRIBUTE_DIRECTORY,
1027 NTCREATEX_SHARE_ACCESS_READ|
1028 NTCREATEX_SHARE_ACCESS_WRITE|
1029 NTCREATEX_SHARE_ACCESS_DELETE,
1030 NTCREATEX_DISP_OPEN,
1031 NTCREATEX_OPTIONS_DIRECTORY, 0);
1032 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
1039 static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1043 bool correct = True;
1045 del_clean_area(cli1, cli2);
1049 smbcli_deltree(cli1->tree, dname);
1051 /* Firstly open and create with all access */
1052 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1054 SEC_FILE_WRITE_DATA|
1056 FILE_ATTRIBUTE_DIRECTORY,
1057 NTCREATEX_SHARE_ACCESS_READ|
1058 NTCREATEX_SHARE_ACCESS_WRITE|
1059 NTCREATEX_SHARE_ACCESS_DELETE,
1060 NTCREATEX_DISP_CREATE,
1061 NTCREATEX_OPTIONS_DIRECTORY, 0);
1063 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1064 dname, smbcli_errstr(cli1->tree)));
1066 /* And close - just to create the directory. */
1067 smbcli_close(cli1->tree, fnum1);
1069 /* Next open with all access, but add delete on close. */
1070 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1072 SEC_FILE_WRITE_DATA|
1074 FILE_ATTRIBUTE_DIRECTORY,
1075 NTCREATEX_SHARE_ACCESS_READ|
1076 NTCREATEX_SHARE_ACCESS_WRITE|
1077 NTCREATEX_SHARE_ACCESS_DELETE,
1078 NTCREATEX_DISP_OPEN,
1079 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1081 torture_assert(tctx, fnum1 != -1,
1082 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1084 /* The delete on close bit is *not* reported as being set. */
1085 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, False, __location__);
1087 /* Now try opening again for read-only. */
1088 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1089 SEC_RIGHTS_FILE_READ,
1090 FILE_ATTRIBUTE_DIRECTORY,
1091 NTCREATEX_SHARE_ACCESS_READ|
1092 NTCREATEX_SHARE_ACCESS_WRITE|
1093 NTCREATEX_SHARE_ACCESS_DELETE,
1094 NTCREATEX_DISP_OPEN,
1095 NTCREATEX_OPTIONS_DIRECTORY, 0);
1098 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1099 dname, smbcli_errstr(cli1->tree)));
1101 smbcli_close(cli1->tree, fnum1);
1103 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, True, __location__);
1105 smbcli_close(cli1->tree, fnum2);
1107 /* See if the file is deleted - for a directory this seems to be true ! */
1108 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1109 SEC_RIGHTS_FILE_READ,
1110 FILE_ATTRIBUTE_DIRECTORY,
1111 NTCREATEX_SHARE_ACCESS_READ|
1112 NTCREATEX_SHARE_ACCESS_WRITE|
1113 NTCREATEX_SHARE_ACCESS_DELETE,
1114 NTCREATEX_DISP_OPEN,
1115 NTCREATEX_OPTIONS_DIRECTORY, 0);
1117 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1119 torture_assert(tctx, fnum1 == -1,
1120 talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1126 static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1130 bool correct = True;
1133 del_clean_area(cli1, cli2);
1135 /* Test 20 -- non-empty directory hardest to get right... */
1137 if (torture_setting_bool(tctx, "samba3", False)) {
1141 smbcli_deltree(cli1->tree, dname);
1143 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1145 SEC_FILE_WRITE_DATA|
1147 FILE_ATTRIBUTE_DIRECTORY,
1148 NTCREATEX_SHARE_ACCESS_READ|
1149 NTCREATEX_SHARE_ACCESS_WRITE|
1150 NTCREATEX_SHARE_ACCESS_DELETE,
1151 NTCREATEX_DISP_CREATE,
1152 NTCREATEX_OPTIONS_DIRECTORY, 0);
1153 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
1154 dname, smbcli_errstr(cli1->tree)));
1156 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, False, __location__);
1157 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
1161 asprintf(&fullname, "\\%s%s", dname, fname);
1162 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1164 torture_assert(tctx, fnum1 == -1,
1165 "smbcli_open succeeded, should have "
1166 "failed with NT_STATUS_DELETE_PENDING"
1169 torture_assert_ntstatus_equal(tctx,
1170 smbcli_nt_error(cli1->tree),
1171 NT_STATUS_DELETE_PENDING,
1172 "smbcli_open failed");
1175 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, False);
1176 torture_assert_ntstatus_ok(tctx, status,
1177 "setting delete_on_close on file failed !");
1181 asprintf(&fullname, "\\%s%s", dname, fname);
1182 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1184 torture_assert(tctx, fnum1 != -1,
1185 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1186 smbcli_errstr(cli1->tree)));
1187 smbcli_close(cli1->tree, fnum1);
1190 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
1192 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1193 "setting delete_on_close failed");
1194 smbcli_close(cli1->tree, dnum1);
1200 static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1204 bool correct = True;
1206 del_clean_area(cli1, cli2);
1210 /* Ensure the file doesn't already exist. */
1211 smbcli_close(cli1->tree, fnum1);
1212 smbcli_close(cli1->tree, fnum2);
1213 smbcli_setatr(cli1->tree, fname, 0, 0);
1214 smbcli_unlink(cli1->tree, fname);
1216 /* Firstly open and create with all access */
1217 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1218 SEC_RIGHTS_FILE_ALL,
1219 FILE_ATTRIBUTE_NORMAL,
1220 NTCREATEX_SHARE_ACCESS_READ|
1221 NTCREATEX_SHARE_ACCESS_WRITE|
1222 NTCREATEX_SHARE_ACCESS_DELETE,
1223 NTCREATEX_DISP_CREATE,
1225 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1226 fname, smbcli_errstr(cli1->tree)));
1228 /* Next open with all access, but add delete on close. */
1229 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1230 SEC_RIGHTS_FILE_ALL,
1231 FILE_ATTRIBUTE_NORMAL,
1232 NTCREATEX_SHARE_ACCESS_READ|
1233 NTCREATEX_SHARE_ACCESS_WRITE|
1234 NTCREATEX_SHARE_ACCESS_DELETE,
1235 NTCREATEX_DISP_OPEN,
1236 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1238 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1239 fname, smbcli_errstr(cli2->tree)));
1241 /* The delete on close bit is *not* reported as being set. */
1242 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
1243 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
1245 smbcli_close(cli1->tree, fnum1);
1247 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
1249 smbcli_close(cli2->tree, fnum2);
1251 /* See if the file is deleted - should be.... */
1252 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1253 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1254 fname, smbcli_errstr(cli1->tree)));
1260 /* This is the delete semantics that the cifsfs client depends on when
1261 * trying to delete an open file on a Windows server. It
1262 * opens a file with initial delete on close set, renames it then closes
1263 * all open handles. The file goes away on Windows.
1266 static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1270 bool correct = True;
1272 del_clean_area(cli1, cli2);
1276 /* Ensure the file doesn't already exist. */
1277 smbcli_close(cli1->tree, fnum1);
1278 smbcli_close(cli1->tree, fnum2);
1279 smbcli_setatr(cli1->tree, fname, 0, 0);
1280 smbcli_unlink(cli1->tree, fname);
1281 smbcli_setatr(cli1->tree, fname_new, 0, 0);
1282 smbcli_unlink(cli1->tree, fname_new);
1284 /* Firstly open and create with all access */
1285 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1286 SEC_RIGHTS_FILE_ALL,
1287 FILE_ATTRIBUTE_NORMAL,
1288 NTCREATEX_SHARE_ACCESS_READ|
1289 NTCREATEX_SHARE_ACCESS_WRITE|
1290 NTCREATEX_SHARE_ACCESS_DELETE,
1291 NTCREATEX_DISP_CREATE,
1293 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1294 fname, smbcli_errstr(cli1->tree)));
1296 /* And close - just to create the file. */
1297 smbcli_close(cli1->tree, fnum1);
1299 /* Firstly open and create with all access */
1300 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1301 SEC_RIGHTS_FILE_ALL,
1302 FILE_ATTRIBUTE_NORMAL,
1303 NTCREATEX_SHARE_ACCESS_READ|
1304 NTCREATEX_SHARE_ACCESS_WRITE|
1305 NTCREATEX_SHARE_ACCESS_DELETE,
1306 NTCREATEX_DISP_OPEN,
1308 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1309 fname, smbcli_errstr(cli1->tree)));
1311 /* Next open with all access, but add delete on close. */
1312 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1313 SEC_RIGHTS_FILE_ALL,
1314 FILE_ATTRIBUTE_NORMAL,
1315 NTCREATEX_SHARE_ACCESS_READ|
1316 NTCREATEX_SHARE_ACCESS_WRITE|
1317 NTCREATEX_SHARE_ACCESS_DELETE,
1318 NTCREATEX_DISP_OPEN,
1319 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1321 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1322 fname, smbcli_errstr(cli2->tree)));
1324 /* The delete on close bit is *not* reported as being set. */
1325 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, False, __location__);
1326 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
1328 smbcli_close(cli1->tree, fnum1);
1330 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, False, __location__);
1332 /* Rename the file by handle. */
1335 union smb_setfileinfo sfinfo;
1338 memset(&sfinfo, '\0', sizeof(sfinfo));
1339 sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
1340 sfinfo.generic.in.file.fnum = fnum2;
1341 sfinfo.rename_information.in.root_fid = 0;
1342 /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
1343 sfinfo.rename_information.in.new_name = fname_new + 1;
1344 sfinfo.rename_information.in.overwrite = 1;
1346 status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
1348 torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
1349 fname, fname_new, smbcli_errstr(cli2->tree)));
1352 correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, False, __location__);
1354 smbcli_close(cli2->tree, fnum2);
1356 /* See if the file is deleted - should be.... */
1357 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1358 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1359 fname, smbcli_errstr(cli1->tree)));
1360 fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
1361 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1362 fname_new, smbcli_errstr(cli1->tree)));
1369 static bool deltest21(struct torture_context *tctx)
1372 struct smbcli_state *cli1;
1373 struct smbcli_state *cli2;
1374 bool correct = True;
1376 if (!torture_open_connection(&cli1, 0))
1379 if (!torture_open_connection(&cli2, 1))
1382 del_clean_area(cli1, cli2);
1384 /* Test 21 -- Test removal of file after socket close. */
1386 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1387 SEC_RIGHTS_FILE_ALL,
1388 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
1389 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1391 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
1392 fname, smbcli_errstr(cli1->tree)));
1394 torture_assert_ntstatus_ok(tctx,
1395 smbcli_nt_delete_on_close(cli1->tree, fnum1, True),
1396 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
1397 smbcli_errstr(cli1->tree)));
1399 /* Ensure delete on close is set. */
1400 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, True, __location__);
1402 /* Now yank the rug from under cli1. */
1403 smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
1407 if (!torture_open_connection(&cli1, 0)) {
1411 /* On slow build farm machines it might happen that they are not fast
1412 * enogh to delete the file for this test */
1415 /* File should not be there. */
1416 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1417 SEC_RIGHTS_FILE_READ,
1418 FILE_ATTRIBUTE_NORMAL,
1419 NTCREATEX_SHARE_ACCESS_READ|
1420 NTCREATEX_SHARE_ACCESS_WRITE|
1421 NTCREATEX_SHARE_ACCESS_DELETE,
1422 NTCREATEX_DISP_OPEN,
1425 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1433 * Test whether a second *directory* handle inhibits delete if the first has
1434 * del-on-close set and is closed
1436 static bool deltest22(struct torture_context *tctx)
1440 struct smbcli_state *cli1;
1441 bool correct = True;
1443 if (!torture_open_connection(&cli1, 0))
1446 smbcli_deltree(cli1->tree, dname);
1448 torture_assert_ntstatus_ok(
1449 tctx, smbcli_mkdir(cli1->tree, dname),
1450 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
1451 smbcli_errstr(cli1->tree)));
1453 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1455 SEC_FILE_WRITE_DATA|
1457 FILE_ATTRIBUTE_DIRECTORY,
1458 NTCREATEX_SHARE_ACCESS_READ|
1459 NTCREATEX_SHARE_ACCESS_WRITE|
1460 NTCREATEX_SHARE_ACCESS_DELETE,
1461 NTCREATEX_DISP_OPEN,
1462 NTCREATEX_OPTIONS_DIRECTORY, 0);
1464 torture_assert(tctx, dnum1 != -1,
1465 talloc_asprintf(tctx, "open of %s failed: %s!",
1466 dname, smbcli_errstr(cli1->tree)));
1468 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1470 SEC_FILE_WRITE_DATA,
1471 FILE_ATTRIBUTE_DIRECTORY,
1472 NTCREATEX_SHARE_ACCESS_READ|
1473 NTCREATEX_SHARE_ACCESS_WRITE|
1474 NTCREATEX_SHARE_ACCESS_DELETE,
1475 NTCREATEX_DISP_OPEN,
1476 NTCREATEX_OPTIONS_DIRECTORY, 0);
1478 torture_assert(tctx, dnum2 != -1,
1479 talloc_asprintf(tctx, "open of %s failed: %s!",
1480 dname, smbcli_errstr(cli1->tree)));
1482 torture_assert_ntstatus_ok(
1483 tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, True),
1484 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
1485 smbcli_errstr(cli1->tree)));
1487 smbcli_close(cli1->tree, dnum1);
1489 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1491 SEC_FILE_WRITE_DATA|
1493 FILE_ATTRIBUTE_DIRECTORY,
1494 NTCREATEX_SHARE_ACCESS_READ|
1495 NTCREATEX_SHARE_ACCESS_WRITE|
1496 NTCREATEX_SHARE_ACCESS_DELETE,
1497 NTCREATEX_DISP_OPEN,
1498 NTCREATEX_OPTIONS_DIRECTORY, 0);
1500 torture_assert(tctx, dnum1 == -1,
1501 talloc_asprintf(tctx, "open of %s succeeded!\n",
1504 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1510 Test delete on close semantics.
1512 struct torture_suite *torture_test_delete(void)
1514 struct torture_suite *suite = torture_suite_create(
1515 talloc_autofree_context(),
1518 torture_suite_add_2smb_test(suite, "deltest1", deltest1);
1519 torture_suite_add_2smb_test(suite, "deltest2", deltest2);
1520 torture_suite_add_2smb_test(suite, "deltest3", deltest3);
1521 torture_suite_add_2smb_test(suite, "deltest4", deltest4);
1522 torture_suite_add_2smb_test(suite, "deltest5", deltest5);
1523 torture_suite_add_2smb_test(suite, "deltest6", deltest6);
1524 torture_suite_add_2smb_test(suite, "deltest7", deltest7);
1525 torture_suite_add_2smb_test(suite, "deltest8", deltest8);
1526 torture_suite_add_2smb_test(suite, "deltest9", deltest9);
1527 torture_suite_add_2smb_test(suite, "deltest10", deltest10);
1528 torture_suite_add_2smb_test(suite, "deltest11", deltest11);
1529 torture_suite_add_2smb_test(suite, "deltest12", deltest12);
1530 torture_suite_add_2smb_test(suite, "deltest13", deltest13);
1531 torture_suite_add_2smb_test(suite, "deltest14", deltest14);
1532 torture_suite_add_2smb_test(suite, "deltest15", deltest15);
1533 torture_suite_add_2smb_test(suite, "deltest16", deltest16);
1534 torture_suite_add_2smb_test(suite, "deltest17", deltest17);
1535 torture_suite_add_2smb_test(suite, "deltest18", deltest18);
1536 torture_suite_add_2smb_test(suite, "deltest19", deltest19);
1537 torture_suite_add_2smb_test(suite, "deltest20", deltest20);
1538 torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
1539 torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
1540 torture_suite_add_simple_test(suite, "deltest21", deltest21);
1541 torture_suite_add_simple_test(suite, "deltest22", deltest22);