s3:smbd: s/event_add_fd/tevent_add_fd and s/EVENT_FD_/TEVENT_FD_
[Samba/gebeck_regimport.git] / source4 / torture / basic / delete.c
blobe3d830da627b7a96b8a23c9dc12a16d9dea2bad8
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 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/>.
22 #include "includes.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "system/filesys.h"
26 #include "libcli/raw/raw_proto.h"
28 #include "torture/raw/proto.h"
29 #include "torture/basic/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,
34 const char *where)
36 union smb_search_data data;
37 NTSTATUS status;
39 time_t c_time, a_time, m_time;
40 size_t size;
41 uint16_t mode;
43 status = torture_single_search(cli, tctx,
44 fname,
45 RAW_SEARCH_TRANS2,
46 RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
47 FILE_ATTRIBUTE_DIRECTORY,
48 &data);
49 torture_assert_ntstatus_ok(tctx, status,
50 talloc_asprintf(tctx, "single_search failed (%s)", where));
52 if (fnum != -1) {
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,
64 talloc_asprintf(tctx,
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,
69 talloc_asprintf(tctx,
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,
90 &size, &mode);
92 if (expect_it) {
93 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
94 "qpathinfo did not give correct error code");
95 } else {
96 torture_assert_ntstatus_ok(tctx, status,
97 talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
100 return true;
103 #define CHECK_STATUS(_cli, _expected) \
104 torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
105 "Incorrect status")
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)
127 int fnum1 = -1;
129 del_clean_area(cli1, cli2);
131 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
132 SEC_RIGHTS_FILE_ALL,
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)",
145 fname));
147 return true;
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)
153 int fnum1 = -1;
155 del_clean_area(cli1, cli2);
157 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
158 SEC_RIGHTS_FILE_ALL,
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);
175 if (fnum1 != -1) {
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));
181 return false;
183 smbcli_unlink(cli1->tree, fname);
185 return true;
188 /* Test 3 - ... */
189 static bool deltest3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
191 int fnum1 = -1;
192 int fnum2 = -1;
194 del_clean_area(cli1, cli2);
196 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
197 SEC_RIGHTS_FILE_ALL,
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.",
216 fname));
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);
245 if (fnum1 != -1) {
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);
253 return false;
255 return true;
258 /* Test 4 ... */
259 static bool deltest4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
261 int fnum1 = -1;
262 int fnum2 = -1;
263 bool correct = true;
265 del_clean_area(cli1, cli2);
267 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
268 SEC_FILE_READ_DATA |
269 SEC_FILE_WRITE_DATA |
270 SEC_STD_DELETE,
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.",
307 fname ));
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)));
315 return correct;
318 /* Test 5 ... */
319 static bool deltest5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
321 int fnum1 = -1;
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)));
337 return true;
340 /* Test 6 ... */
341 static bool deltest6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
343 int fnum1 = -1;
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. */
360 torture_assert(tctx,
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,
367 "close - 2 failed (%s)",
368 smbcli_errstr(cli1->tree)));
370 return true;
373 /* Test 7 ... */
374 static bool deltest7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
376 int fnum1 = -1;
377 bool correct = true;
379 del_clean_area(cli1, cli2);
381 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
382 SEC_FILE_READ_DATA |
383 SEC_FILE_WRITE_DATA |
384 SEC_STD_DELETE,
385 FILE_ATTRIBUTE_NORMAL, 0,
386 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
388 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
389 fname, smbcli_errstr(cli1->tree)));
391 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
392 "setting delete_on_close on file failed !");
394 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
396 torture_assert_ntstatus_ok(tctx,
397 smbcli_nt_delete_on_close(cli1->tree, fnum1, false),
398 "unsetting delete_on_close on file failed !");
400 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
402 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
403 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
405 /* This next open should succeed - we reset the flag. */
407 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
408 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
409 fname, smbcli_errstr(cli1->tree)));
411 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
412 talloc_asprintf(tctx, "close - 2 failed (%s)",
413 smbcli_errstr(cli1->tree)));
415 return correct;
418 /* Test 8 ... */
419 static bool deltest8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
421 int fnum1 = -1;
422 int fnum2 = -1;
423 bool correct = true;
425 del_clean_area(cli1, cli2);
427 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
428 SEC_FILE_READ_DATA|
429 SEC_FILE_WRITE_DATA|
430 SEC_STD_DELETE,
431 FILE_ATTRIBUTE_NORMAL,
432 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
433 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
435 torture_assert(tctx, fnum1 != -1,
436 talloc_asprintf(tctx, "open of %s failed (%s)",
437 fname, smbcli_errstr(cli1->tree)));
439 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
440 SEC_FILE_READ_DATA|
441 SEC_FILE_WRITE_DATA|
442 SEC_STD_DELETE,
443 FILE_ATTRIBUTE_NORMAL,
444 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
445 NTCREATEX_DISP_OPEN, 0, 0);
447 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
448 fname, smbcli_errstr(cli1->tree)));
450 torture_assert_ntstatus_ok(tctx,
451 smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
452 "setting delete_on_close on file failed !");
454 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
455 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
457 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
458 talloc_asprintf(tctx, "close - 1 failed (%s)",
459 smbcli_errstr(cli1->tree)));
461 correct &= check_delete_on_close(tctx, cli1, -1, fname, true, __location__);
462 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
464 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
465 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli2->tree)));
467 /* This should fail.. */
468 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
469 torture_assert(tctx, fnum1 == -1,
470 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !\n", fname));
472 return correct;
475 /* Test 9 ... */
476 static bool deltest9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
478 int fnum1 = -1;
480 del_clean_area(cli1, cli2);
482 /* This should fail - we need to set DELETE_ACCESS. */
483 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
484 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
485 FILE_ATTRIBUTE_NORMAL,
486 NTCREATEX_SHARE_ACCESS_NONE,
487 NTCREATEX_DISP_OVERWRITE_IF,
488 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
490 torture_assert(tctx, fnum1 == -1,
491 talloc_asprintf(tctx, "open of %s succeeded should have failed!",
492 fname));
494 return true;
497 /* Test 10 ... */
498 static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
500 int fnum1 = -1;
502 del_clean_area(cli1, cli2);
504 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
505 SEC_FILE_READ_DATA|
506 SEC_FILE_WRITE_DATA|
507 SEC_STD_DELETE,
508 FILE_ATTRIBUTE_NORMAL,
509 NTCREATEX_SHARE_ACCESS_NONE,
510 NTCREATEX_DISP_OVERWRITE_IF,
511 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
512 torture_assert(tctx, fnum1 != -1,
513 talloc_asprintf(tctx, "open of %s failed (%s)",
514 fname, smbcli_errstr(cli1->tree)));
516 /* This should delete the file. */
517 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
518 talloc_asprintf(tctx, "close failed (%s)",
519 smbcli_errstr(cli1->tree)));
521 /* This should fail.. */
522 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
523 torture_assert(tctx, fnum1 == -1,
524 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
525 fname));
526 return true;
529 /* Test 11 ... */
530 static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
532 int fnum1 = -1;
533 NTSTATUS status;
535 del_clean_area(cli1, cli2);
537 /* test 11 - does having read only attribute still allow delete on close. */
539 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
540 SEC_RIGHTS_FILE_ALL,
541 FILE_ATTRIBUTE_READONLY,
542 NTCREATEX_SHARE_ACCESS_NONE,
543 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
545 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
546 fname, smbcli_errstr(cli1->tree)));
548 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, true);
550 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
551 talloc_asprintf(tctx, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1->tree)));
553 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
554 talloc_asprintf(tctx, "close failed (%s)",
555 smbcli_errstr(cli1->tree)));
557 return true;
560 /* Test 12 ... */
561 static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
563 int fnum1 = -1;
564 NTSTATUS status;
566 del_clean_area(cli1, cli2);
568 /* test 12 - does having read only attribute still allow delete on
569 * close at time of open. */
571 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
572 SEC_RIGHTS_FILE_ALL,
573 FILE_ATTRIBUTE_READONLY,
574 NTCREATEX_SHARE_ACCESS_DELETE,
575 NTCREATEX_DISP_OVERWRITE_IF,
576 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
578 torture_assert(tctx, fnum1 == -1,
579 talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
580 "NT_STATUS_CANNOT_DELETE.\n", fname));
582 status = smbcli_nt_error(cli1->tree);
583 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
584 talloc_asprintf(tctx, "setting delete_on_close on open should "
585 "fail with NT_STATUS_CANNOT_DELETE. Got %s "
586 "instead)",
587 smbcli_errstr(cli1->tree)));
589 return true;
592 /* Test 13 ... */
593 static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
595 int fnum1 = -1;
596 int fnum2 = -1;
597 bool correct = true;
599 del_clean_area(cli1, cli2);
601 /* Test 13: Does resetting the delete on close flag affect a second
602 * fd? */
604 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
605 SEC_FILE_READ_DATA|
606 SEC_FILE_WRITE_DATA|
607 SEC_STD_DELETE,
608 FILE_ATTRIBUTE_NORMAL,
609 NTCREATEX_SHARE_ACCESS_READ|
610 NTCREATEX_SHARE_ACCESS_WRITE|
611 NTCREATEX_SHARE_ACCESS_DELETE,
612 NTCREATEX_DISP_OVERWRITE_IF,
613 0, 0);
615 torture_assert(tctx, fnum1 != -1,
616 talloc_asprintf(tctx, "open of %s failed (%s)",
617 fname, smbcli_errstr(cli1->tree)));
619 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
620 SEC_FILE_READ_DATA|
621 SEC_FILE_WRITE_DATA|
622 SEC_STD_DELETE,
623 FILE_ATTRIBUTE_NORMAL,
624 NTCREATEX_SHARE_ACCESS_READ|
625 NTCREATEX_SHARE_ACCESS_WRITE|
626 NTCREATEX_SHARE_ACCESS_DELETE,
627 NTCREATEX_DISP_OPEN, 0, 0);
629 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
630 "open of %s failed (%s)",
631 fname, smbcli_errstr(cli2->tree)));
633 torture_assert_ntstatus_ok(tctx,
634 smbcli_nt_delete_on_close(cli1->tree, fnum1,
635 true),
636 "setting delete_on_close on file failed !");
638 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
639 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
641 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
642 false),
643 "setting delete_on_close on file failed !");
645 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
646 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
648 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
649 talloc_asprintf(tctx, "close - 1 failed (%s)",
650 smbcli_errstr(cli1->tree)));
652 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
653 talloc_asprintf(tctx, "close - 2 failed (%s)",
654 smbcli_errstr(cli2->tree)));
656 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
658 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!",
659 fname));
661 smbcli_close(cli1->tree, fnum1);
663 return correct;
666 /* Test 14 ... */
667 static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
669 int dnum1 = -1;
670 bool correct = true;
672 del_clean_area(cli1, cli2);
674 /* Test 14 -- directory */
676 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
677 SEC_FILE_READ_DATA|
678 SEC_FILE_WRITE_DATA|
679 SEC_STD_DELETE,
680 FILE_ATTRIBUTE_DIRECTORY,
681 NTCREATEX_SHARE_ACCESS_READ|
682 NTCREATEX_SHARE_ACCESS_WRITE|
683 NTCREATEX_SHARE_ACCESS_DELETE,
684 NTCREATEX_DISP_CREATE, 0, 0);
685 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
686 dname, smbcli_errstr(cli1->tree)));
688 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
689 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
690 "setting delete_on_close on file failed !");
691 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, true, __location__);
692 smbcli_close(cli1->tree, dnum1);
694 /* Now it should be gone... */
696 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
697 SEC_FILE_READ_DATA|
698 SEC_FILE_WRITE_DATA|
699 SEC_STD_DELETE,
700 FILE_ATTRIBUTE_DIRECTORY,
701 NTCREATEX_SHARE_ACCESS_READ|
702 NTCREATEX_SHARE_ACCESS_WRITE|
703 NTCREATEX_SHARE_ACCESS_DELETE,
704 NTCREATEX_DISP_OPEN, 0, 0);
705 torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
707 return correct;
710 /* Test 15 ... */
711 static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
713 int fnum1 = -1;
714 bool correct = true;
715 int fnum2 = -1;
716 NTSTATUS status;
718 del_clean_area(cli1, cli2);
720 /* Test 15: delete on close under rename */
722 smbcli_setatr(cli1->tree, fname, 0, 0);
723 smbcli_unlink(cli1->tree, fname);
724 smbcli_unlink(cli1->tree, fname_new);
726 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
727 SEC_FILE_READ_DATA,
728 FILE_ATTRIBUTE_NORMAL,
729 NTCREATEX_SHARE_ACCESS_READ|
730 NTCREATEX_SHARE_ACCESS_WRITE|
731 NTCREATEX_SHARE_ACCESS_DELETE,
732 NTCREATEX_DISP_OVERWRITE_IF,
733 0, 0);
735 torture_assert(tctx, fnum1 != -1,
736 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
738 status = smbcli_rename(cli2->tree, fname, fname_new);
740 torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
742 fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
743 SEC_GENERIC_ALL,
744 FILE_ATTRIBUTE_NORMAL,
745 NTCREATEX_SHARE_ACCESS_READ|
746 NTCREATEX_SHARE_ACCESS_WRITE|
747 NTCREATEX_SHARE_ACCESS_DELETE,
748 NTCREATEX_DISP_OVERWRITE_IF,
749 0, 0);
751 torture_assert(tctx, fnum2 != -1,
752 talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
753 fname_new, smbcli_errstr(cli1->tree)));
755 status = smbcli_nt_delete_on_close(cli2->tree, fnum2, true);
757 torture_assert_ntstatus_ok(tctx, status,
758 "setting delete_on_close on file failed !");
760 smbcli_close(cli2->tree, fnum2);
762 /* The file should be around under the new name, there's a second
763 * handle open */
765 correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, true, __location__);
767 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
768 SEC_GENERIC_ALL,
769 FILE_ATTRIBUTE_NORMAL,
770 NTCREATEX_SHARE_ACCESS_READ|
771 NTCREATEX_SHARE_ACCESS_WRITE|
772 NTCREATEX_SHARE_ACCESS_DELETE,
773 NTCREATEX_DISP_OVERWRITE_IF,
774 0, 0);
776 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
777 fname, smbcli_errstr(cli1->tree)));
779 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
781 smbcli_close(cli2->tree, fnum2);
782 smbcli_close(cli1->tree, fnum1);
784 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
785 SEC_FILE_READ_EA,
786 FILE_ATTRIBUTE_NORMAL,
787 NTCREATEX_SHARE_ACCESS_READ|
788 NTCREATEX_SHARE_ACCESS_WRITE|
789 NTCREATEX_SHARE_ACCESS_DELETE,
790 NTCREATEX_DISP_OPEN,
791 0, 0);
793 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
794 fname, smbcli_errstr(cli1->tree)));
796 smbcli_close(cli1->tree, fnum1);
798 fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
799 SEC_FILE_READ_EA,
800 FILE_ATTRIBUTE_NORMAL,
801 NTCREATEX_SHARE_ACCESS_READ|
802 NTCREATEX_SHARE_ACCESS_WRITE|
803 NTCREATEX_SHARE_ACCESS_DELETE,
804 NTCREATEX_DISP_OPEN,
805 0, 0);
807 torture_assert(tctx, fnum1 == -1,
808 "smbcli_open succeeded, should have "
809 "failed");
811 return correct;
814 /* Test 16 ... */
815 static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
817 int fnum1 = -1;
818 int fnum2 = -1;
819 bool correct = true;
821 del_clean_area(cli1, cli2);
823 /* Test 16. */
825 /* Ensure the file doesn't already exist. */
826 smbcli_close(cli1->tree, fnum1);
827 smbcli_close(cli1->tree, fnum2);
828 smbcli_setatr(cli1->tree, fname, 0, 0);
829 smbcli_unlink(cli1->tree, fname);
831 /* Firstly create with all access, but delete on close. */
832 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
833 SEC_RIGHTS_FILE_ALL,
834 FILE_ATTRIBUTE_NORMAL,
835 NTCREATEX_SHARE_ACCESS_READ|
836 NTCREATEX_SHARE_ACCESS_WRITE|
837 NTCREATEX_SHARE_ACCESS_DELETE,
838 NTCREATEX_DISP_CREATE,
839 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
841 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
843 /* The delete on close bit is *not* reported as being set. */
844 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
846 /* The delete on close bit is *not* reported as being set. */
847 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
848 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
850 /* Now try opening again for read-only. */
851 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
852 SEC_RIGHTS_FILE_READ,
853 FILE_ATTRIBUTE_NORMAL,
854 NTCREATEX_SHARE_ACCESS_READ|
855 NTCREATEX_SHARE_ACCESS_WRITE|
856 NTCREATEX_SHARE_ACCESS_DELETE,
857 NTCREATEX_DISP_OPEN,
858 0, 0);
860 /* Should work. */
861 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
862 fname, smbcli_errstr(cli1->tree)));
864 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
865 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
866 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
867 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
869 smbcli_close(cli1->tree, fnum1);
871 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
872 correct &= check_delete_on_close(tctx, cli2, -1, fname, true, __location__);
874 smbcli_close(cli2->tree, fnum2);
876 /* And the file should be deleted ! */
877 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
878 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
879 fname));
881 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
883 return correct;
886 /* Test 16 ... */
887 static bool deltest16a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
889 int fnum1 = -1;
890 int fnum2 = -1;
891 bool correct = true;
893 del_clean_area(cli1, cli2);
895 /* Test 16. */
897 /* Ensure the file doesn't already exist. */
898 smbcli_close(cli1->tree, fnum1);
899 smbcli_close(cli1->tree, fnum2);
900 smbcli_setatr(cli1->tree, fname, 0, 0);
901 smbcli_unlink(cli1->tree, fname);
903 /* Firstly open and create with all access */
904 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
905 SEC_RIGHTS_FILE_ALL,
906 FILE_ATTRIBUTE_NORMAL,
907 NTCREATEX_SHARE_ACCESS_READ|
908 NTCREATEX_SHARE_ACCESS_WRITE|
909 NTCREATEX_SHARE_ACCESS_DELETE,
910 NTCREATEX_DISP_CREATE,
911 0, 0);
912 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
913 fname, smbcli_errstr(cli1->tree)));
915 /* And close - just to create the file. */
916 smbcli_close(cli1->tree, fnum1);
918 /* Firstly create with all access, but delete on close. */
919 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
920 SEC_RIGHTS_FILE_ALL,
921 FILE_ATTRIBUTE_NORMAL,
922 NTCREATEX_SHARE_ACCESS_READ|
923 NTCREATEX_SHARE_ACCESS_WRITE|
924 NTCREATEX_SHARE_ACCESS_DELETE,
925 NTCREATEX_DISP_OPEN,
926 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
928 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
930 /* The delete on close bit is *not* reported as being set. */
931 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
933 /* The delete on close bit is *not* reported as being set. */
934 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
935 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
937 /* Now try opening again for read-only. */
938 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
939 SEC_RIGHTS_FILE_READ,
940 FILE_ATTRIBUTE_NORMAL,
941 NTCREATEX_SHARE_ACCESS_READ|
942 NTCREATEX_SHARE_ACCESS_WRITE|
943 NTCREATEX_SHARE_ACCESS_DELETE,
944 NTCREATEX_DISP_OPEN,
945 0, 0);
947 /* Should work. */
948 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
949 fname, smbcli_errstr(cli1->tree)));
951 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
952 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
953 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
954 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
956 smbcli_close(cli1->tree, fnum1);
958 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
959 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
961 smbcli_close(cli2->tree, fnum2);
963 /* And the file should be deleted ! */
964 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
965 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
966 fname, smbcli_errstr(cli1->tree)));
968 smbcli_close(cli1->tree, fnum1);
969 smbcli_setatr(cli1->tree, fname, 0, 0);
970 smbcli_unlink(cli1->tree, fname);
972 return correct;
975 /* Test 17 ... */
976 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
978 int fnum1 = -1;
979 int fnum2 = -1;
980 bool correct = true;
982 del_clean_area(cli1, cli2);
984 /* Test 17. */
986 /* Ensure the file doesn't already exist. */
987 smbcli_close(cli1->tree, fnum1);
988 smbcli_close(cli1->tree, fnum2);
989 smbcli_setatr(cli1->tree, fname, 0, 0);
990 smbcli_unlink(cli1->tree, fname);
992 /* Firstly open and create with all access */
993 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
994 SEC_RIGHTS_FILE_ALL,
995 FILE_ATTRIBUTE_NORMAL,
996 NTCREATEX_SHARE_ACCESS_READ|
997 NTCREATEX_SHARE_ACCESS_WRITE|
998 NTCREATEX_SHARE_ACCESS_DELETE,
999 NTCREATEX_DISP_CREATE,
1000 0, 0);
1001 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1002 fname, smbcli_errstr(cli1->tree)));
1004 /* And close - just to create the file. */
1005 smbcli_close(cli1->tree, fnum1);
1007 /* Next open with all access, but add delete on close. */
1008 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1009 SEC_RIGHTS_FILE_ALL,
1010 FILE_ATTRIBUTE_NORMAL,
1011 NTCREATEX_SHARE_ACCESS_READ|
1012 NTCREATEX_SHARE_ACCESS_WRITE|
1013 NTCREATEX_SHARE_ACCESS_DELETE,
1014 NTCREATEX_DISP_OPEN,
1015 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1017 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1018 fname, smbcli_errstr(cli1->tree)));
1020 /* The delete on close bit is *not* reported as being set. */
1021 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1023 /* Now try opening again for read-only. */
1024 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1025 SEC_RIGHTS_FILE_READ|
1026 SEC_STD_DELETE,
1027 FILE_ATTRIBUTE_NORMAL,
1028 NTCREATEX_SHARE_ACCESS_READ|
1029 NTCREATEX_SHARE_ACCESS_WRITE|
1030 NTCREATEX_SHARE_ACCESS_DELETE,
1031 NTCREATEX_DISP_OPEN,
1032 0, 0);
1034 /* Should work. */
1035 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1036 fname, smbcli_errstr(cli1->tree)));
1038 /* still not reported as being set on either */
1039 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1040 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1042 smbcli_close(cli1->tree, fnum1);
1044 /* After the first close, the files has the delete on close bit set. */
1045 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1047 smbcli_close(cli1->tree, fnum2);
1049 /* Make sure the file has been deleted */
1050 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1051 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
1052 fname, smbcli_errstr(cli1->tree)));
1054 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1056 return correct;
1059 /* Test 17a - like 17, but the delete on close handle is closed last */
1060 static bool deltest17a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1062 int fnum1 = -1;
1063 int fnum2 = -1;
1064 bool correct = true;
1066 del_clean_area(cli1, cli2);
1068 /* Ensure the file doesn't already exist. */
1069 smbcli_close(cli1->tree, fnum1);
1070 smbcli_close(cli1->tree, fnum2);
1071 smbcli_setatr(cli1->tree, fname, 0, 0);
1072 smbcli_unlink(cli1->tree, fname);
1074 /* Firstly open and create with all access */
1075 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1076 SEC_RIGHTS_FILE_ALL,
1077 FILE_ATTRIBUTE_NORMAL,
1078 NTCREATEX_SHARE_ACCESS_READ|
1079 NTCREATEX_SHARE_ACCESS_WRITE|
1080 NTCREATEX_SHARE_ACCESS_DELETE,
1081 NTCREATEX_DISP_CREATE,
1082 0, 0);
1083 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1084 fname, smbcli_errstr(cli1->tree)));
1086 /* And close - just to create the file. */
1087 smbcli_close(cli1->tree, fnum1);
1089 /* Next open with all access, but add delete on close. */
1090 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1091 SEC_RIGHTS_FILE_ALL,
1092 FILE_ATTRIBUTE_NORMAL,
1093 NTCREATEX_SHARE_ACCESS_READ|
1094 NTCREATEX_SHARE_ACCESS_WRITE|
1095 NTCREATEX_SHARE_ACCESS_DELETE,
1096 NTCREATEX_DISP_OPEN,
1097 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1099 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1100 fname, smbcli_errstr(cli1->tree)));
1102 /* The delete on close bit is *not* reported as being set. */
1103 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1105 /* Now try opening again for read-only. */
1106 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1107 SEC_RIGHTS_FILE_READ|
1108 SEC_STD_DELETE,
1109 FILE_ATTRIBUTE_NORMAL,
1110 NTCREATEX_SHARE_ACCESS_READ|
1111 NTCREATEX_SHARE_ACCESS_WRITE|
1112 NTCREATEX_SHARE_ACCESS_DELETE,
1113 NTCREATEX_DISP_OPEN,
1114 0, 0);
1116 /* Should work. */
1117 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1118 fname, smbcli_errstr(cli1->tree)));
1120 /* still not reported as being set on either */
1121 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1122 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1124 smbcli_close(cli1->tree, fnum2);
1126 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1128 smbcli_close(cli1->tree, fnum1);
1131 * The file is still there:
1132 * The second open seems to have removed the initial
1133 * delete on close flag from the first handle
1135 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1136 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1137 fname, smbcli_errstr(cli1->tree)));
1139 smbcli_close(cli1->tree, fnum1);
1140 smbcli_setatr(cli1->tree, fname, 0, 0);
1141 smbcli_unlink(cli1->tree, fname);
1143 return correct;
1146 /* Test 17b - like 17a, but the initial delete on close is set on the second handle */
1147 static bool deltest17b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1149 int fnum1 = -1;
1150 int fnum2 = -1;
1151 bool correct = true;
1153 del_clean_area(cli1, cli2);
1155 /* Ensure the file doesn't already exist. */
1156 smbcli_close(cli1->tree, fnum1);
1157 smbcli_close(cli1->tree, fnum2);
1158 smbcli_setatr(cli1->tree, fname, 0, 0);
1159 smbcli_unlink(cli1->tree, fname);
1161 /* Firstly open and create with all access */
1162 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1163 SEC_RIGHTS_FILE_ALL,
1164 FILE_ATTRIBUTE_NORMAL,
1165 NTCREATEX_SHARE_ACCESS_READ|
1166 NTCREATEX_SHARE_ACCESS_WRITE|
1167 NTCREATEX_SHARE_ACCESS_DELETE,
1168 NTCREATEX_DISP_CREATE,
1169 0, 0);
1170 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1171 fname, smbcli_errstr(cli1->tree)));
1173 /* And close - just to create the file. */
1174 smbcli_close(cli1->tree, fnum1);
1176 /* Next open with all access, but add delete on close. */
1177 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1178 SEC_RIGHTS_FILE_ALL,
1179 FILE_ATTRIBUTE_NORMAL,
1180 NTCREATEX_SHARE_ACCESS_READ|
1181 NTCREATEX_SHARE_ACCESS_WRITE|
1182 NTCREATEX_SHARE_ACCESS_DELETE,
1183 NTCREATEX_DISP_OPEN,
1184 0, 0);
1186 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1187 fname, smbcli_errstr(cli1->tree)));
1189 /* The delete on close bit is *not* reported as being set. */
1190 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1192 /* Now try opening again for read-only. */
1193 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1194 SEC_RIGHTS_FILE_READ|
1195 SEC_STD_DELETE,
1196 FILE_ATTRIBUTE_NORMAL,
1197 NTCREATEX_SHARE_ACCESS_READ|
1198 NTCREATEX_SHARE_ACCESS_WRITE|
1199 NTCREATEX_SHARE_ACCESS_DELETE,
1200 NTCREATEX_DISP_OPEN,
1201 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1203 /* Should work. */
1204 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1205 fname, smbcli_errstr(cli1->tree)));
1207 /* still not reported as being set on either */
1208 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1209 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1211 smbcli_close(cli1->tree, fnum1);
1213 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1215 smbcli_close(cli1->tree, fnum2);
1217 /* Make sure the file has been deleted */
1218 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1219 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1220 fname));
1222 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1224 return correct;
1227 /* Test 17c - like 17, but the initial delete on close is set on the second handle */
1228 static bool deltest17c(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1230 int fnum1 = -1;
1231 int fnum2 = -1;
1232 bool correct = true;
1234 del_clean_area(cli1, cli2);
1236 /* Ensure the file doesn't already exist. */
1237 smbcli_close(cli1->tree, fnum1);
1238 smbcli_close(cli1->tree, fnum2);
1239 smbcli_setatr(cli1->tree, fname, 0, 0);
1240 smbcli_unlink(cli1->tree, fname);
1242 /* Firstly open and create with all access */
1243 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1244 SEC_RIGHTS_FILE_ALL,
1245 FILE_ATTRIBUTE_NORMAL,
1246 NTCREATEX_SHARE_ACCESS_READ|
1247 NTCREATEX_SHARE_ACCESS_WRITE|
1248 NTCREATEX_SHARE_ACCESS_DELETE,
1249 NTCREATEX_DISP_CREATE,
1250 0, 0);
1251 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1252 fname, smbcli_errstr(cli1->tree)));
1254 /* And close - just to create the file. */
1255 smbcli_close(cli1->tree, fnum1);
1257 /* Next open with all access, but add delete on close. */
1258 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1259 SEC_RIGHTS_FILE_ALL,
1260 FILE_ATTRIBUTE_NORMAL,
1261 NTCREATEX_SHARE_ACCESS_READ|
1262 NTCREATEX_SHARE_ACCESS_WRITE|
1263 NTCREATEX_SHARE_ACCESS_DELETE,
1264 NTCREATEX_DISP_OPEN,
1265 0, 0);
1267 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1268 fname, smbcli_errstr(cli1->tree)));
1270 /* The delete on close bit is *not* reported as being set. */
1271 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1273 /* Now try opening again for read-only. */
1274 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1275 SEC_RIGHTS_FILE_READ|
1276 SEC_STD_DELETE,
1277 FILE_ATTRIBUTE_NORMAL,
1278 NTCREATEX_SHARE_ACCESS_READ|
1279 NTCREATEX_SHARE_ACCESS_WRITE|
1280 NTCREATEX_SHARE_ACCESS_DELETE,
1281 NTCREATEX_DISP_OPEN,
1282 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1284 /* Should work. */
1285 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1286 fname, smbcli_errstr(cli1->tree)));
1288 /* still not reported as being set on either */
1289 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1290 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1292 smbcli_close(cli1->tree, fnum2);
1294 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
1296 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1297 torture_assert(tctx, fnum2 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1298 fname));
1300 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1302 smbcli_close(cli1->tree, fnum1);
1304 /* Make sure the file has been deleted */
1305 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1306 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1307 fname));
1309 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1311 return correct;
1314 /* Test 17d - like 17a, but the first delete-on-close opener creates the file */
1315 static bool deltest17d(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1317 int fnum1 = -1;
1318 int fnum2 = -1;
1319 bool correct = true;
1321 del_clean_area(cli1, cli2);
1323 /* Ensure the file doesn't already exist. */
1324 smbcli_close(cli1->tree, fnum1);
1325 smbcli_close(cli1->tree, fnum2);
1326 smbcli_setatr(cli1->tree, fname, 0, 0);
1327 smbcli_unlink(cli1->tree, fname);
1330 /* Create the file with delete on close. */
1331 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1332 SEC_RIGHTS_FILE_ALL,
1333 FILE_ATTRIBUTE_NORMAL,
1334 NTCREATEX_SHARE_ACCESS_READ|
1335 NTCREATEX_SHARE_ACCESS_WRITE|
1336 NTCREATEX_SHARE_ACCESS_DELETE,
1337 NTCREATEX_DISP_CREATE,
1338 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1340 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1341 fname, smbcli_errstr(cli1->tree)));
1343 /* The delete on close bit is *not* reported as being set. */
1344 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1346 /* Now try opening again for read-only. */
1347 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1348 SEC_RIGHTS_FILE_READ|
1349 SEC_STD_DELETE,
1350 FILE_ATTRIBUTE_NORMAL,
1351 NTCREATEX_SHARE_ACCESS_READ|
1352 NTCREATEX_SHARE_ACCESS_WRITE|
1353 NTCREATEX_SHARE_ACCESS_DELETE,
1354 NTCREATEX_DISP_OPEN,
1355 0, 0);
1357 /* Should work. */
1358 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1359 fname, smbcli_errstr(cli1->tree)));
1361 /* still not reported as being set on either */
1362 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1363 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1365 smbcli_close(cli1->tree, fnum2);
1367 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1369 smbcli_close(cli1->tree, fnum1);
1372 * The file is still there:
1373 * The second open seems to have removed the initial
1374 * delete on close flag from the first handle
1376 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1377 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeed (should fail)",
1378 fname));
1380 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1382 return correct;
1385 static bool deltest17e(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1387 int fnum1 = -1;
1388 int fnum2 = -1;
1389 int fnum3 = -1;
1390 bool correct = true;
1392 del_clean_area(cli1, cli2);
1394 /* Ensure the file doesn't already exist. */
1395 smbcli_close(cli1->tree, fnum1);
1396 smbcli_close(cli1->tree, fnum2);
1397 smbcli_setatr(cli1->tree, fname, 0, 0);
1398 smbcli_unlink(cli1->tree, fname);
1400 /* Firstly open and create with all access */
1401 fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1402 SEC_RIGHTS_FILE_ALL,
1403 FILE_ATTRIBUTE_NORMAL,
1404 NTCREATEX_SHARE_ACCESS_READ|
1405 NTCREATEX_SHARE_ACCESS_WRITE|
1406 NTCREATEX_SHARE_ACCESS_DELETE,
1407 NTCREATEX_DISP_CREATE,
1408 0, 0);
1409 torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1410 fname, smbcli_errstr(cli1->tree)));
1412 /* Next open with all access, but add delete on close. */
1413 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1414 SEC_RIGHTS_FILE_ALL,
1415 FILE_ATTRIBUTE_NORMAL,
1416 NTCREATEX_SHARE_ACCESS_READ|
1417 NTCREATEX_SHARE_ACCESS_WRITE|
1418 NTCREATEX_SHARE_ACCESS_DELETE,
1419 NTCREATEX_DISP_OPEN,
1420 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1422 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1423 fname, smbcli_errstr(cli1->tree)));
1425 /* The delete on close bit is *not* reported as being set. */
1426 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1427 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1429 /* Now try opening again for read-only. */
1430 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1431 SEC_RIGHTS_FILE_READ|
1432 SEC_STD_DELETE,
1433 FILE_ATTRIBUTE_NORMAL,
1434 NTCREATEX_SHARE_ACCESS_READ|
1435 NTCREATEX_SHARE_ACCESS_WRITE|
1436 NTCREATEX_SHARE_ACCESS_DELETE,
1437 NTCREATEX_DISP_OPEN,
1438 0, 0);
1440 /* Should work. */
1441 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1442 fname, smbcli_errstr(cli1->tree)));
1444 /* still not reported as being set on either */
1445 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1446 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1447 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1449 smbcli_close(cli1->tree, fnum1);
1452 * closing the handle that has delete_on_close set
1453 * inherits the flag to the global context
1455 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1456 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1458 smbcli_close(cli1->tree, fnum2);
1460 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1462 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1463 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1464 fname));
1466 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1468 smbcli_close(cli1->tree, fnum3);
1470 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1471 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1472 fname));
1474 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1476 return correct;
1479 static bool deltest17f(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1481 int fnum1 = -1;
1482 int fnum2 = -1;
1483 int fnum3 = -1;
1484 bool correct = true;
1485 NTSTATUS status;
1487 del_clean_area(cli1, cli2);
1489 /* Ensure the file doesn't already exist. */
1490 smbcli_close(cli1->tree, fnum1);
1491 smbcli_close(cli1->tree, fnum2);
1492 smbcli_setatr(cli1->tree, fname, 0, 0);
1493 smbcli_unlink(cli1->tree, fname);
1495 /* Firstly open and create with all access */
1496 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1497 SEC_RIGHTS_FILE_ALL,
1498 FILE_ATTRIBUTE_NORMAL,
1499 NTCREATEX_SHARE_ACCESS_READ|
1500 NTCREATEX_SHARE_ACCESS_WRITE|
1501 NTCREATEX_SHARE_ACCESS_DELETE,
1502 NTCREATEX_DISP_CREATE,
1503 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1504 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1505 fname, smbcli_errstr(cli1->tree)));
1507 /* The delete on close bit is *not* reported as being set. */
1508 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1510 /* Next open with all access, but add delete on close. */
1511 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1512 SEC_RIGHTS_FILE_ALL,
1513 FILE_ATTRIBUTE_NORMAL,
1514 NTCREATEX_SHARE_ACCESS_READ|
1515 NTCREATEX_SHARE_ACCESS_WRITE|
1516 NTCREATEX_SHARE_ACCESS_DELETE,
1517 NTCREATEX_DISP_OPEN,
1518 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1520 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1521 fname, smbcli_errstr(cli1->tree)));
1523 /* still not reported as being set on either */
1524 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1525 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1527 /* Now try opening again for read-only. */
1528 fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1529 SEC_RIGHTS_FILE_READ|
1530 SEC_STD_DELETE,
1531 FILE_ATTRIBUTE_NORMAL,
1532 NTCREATEX_SHARE_ACCESS_READ|
1533 NTCREATEX_SHARE_ACCESS_WRITE|
1534 NTCREATEX_SHARE_ACCESS_DELETE,
1535 NTCREATEX_DISP_OPEN,
1536 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1538 /* Should work. */
1539 torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1540 fname, smbcli_errstr(cli1->tree)));
1542 /* still not reported as being set on either */
1543 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1544 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1545 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1547 smbcli_close(cli1->tree, fnum1);
1550 * closing the handle that has delete_on_close set
1551 * inherits the flag to the global context
1553 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1554 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1557 status = smbcli_nt_delete_on_close(cli1->tree, fnum2, false);
1558 torture_assert_ntstatus_ok(tctx, status,
1559 "clearing delete_on_close on file failed !");
1561 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1562 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1564 smbcli_close(cli1->tree, fnum2);
1566 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1568 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1569 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1570 fname));
1572 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1574 smbcli_close(cli1->tree, fnum3);
1576 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1577 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1578 fname));
1580 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1582 return correct;
1585 /* Test 18 ... */
1586 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1588 int fnum1 = -1;
1589 int fnum2 = -1;
1590 bool correct = true;
1592 del_clean_area(cli1, cli2);
1594 /* Test 18. With directories. */
1596 /* Ensure the file doesn't already exist. */
1597 smbcli_close(cli1->tree, fnum1);
1598 smbcli_close(cli1->tree, fnum2);
1600 smbcli_deltree(cli1->tree, dname);
1602 /* Firstly create with all access, but delete on close. */
1603 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1604 SEC_FILE_READ_DATA|
1605 SEC_FILE_WRITE_DATA|
1606 SEC_STD_DELETE,
1607 FILE_ATTRIBUTE_DIRECTORY,
1608 NTCREATEX_SHARE_ACCESS_READ|
1609 NTCREATEX_SHARE_ACCESS_WRITE|
1610 NTCREATEX_SHARE_ACCESS_DELETE,
1611 NTCREATEX_DISP_CREATE,
1612 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1614 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1615 dname, smbcli_errstr(cli1->tree)));
1618 * The delete on close bit is *not* reported as being set.
1619 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1620 * close as being set. This causes the subsequent create to fail with
1621 * NT_STATUS_DELETE_PENDING.
1623 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1625 /* Now try opening again for read-only. */
1626 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1627 SEC_RIGHTS_FILE_READ,
1628 FILE_ATTRIBUTE_DIRECTORY,
1629 NTCREATEX_SHARE_ACCESS_READ|
1630 NTCREATEX_SHARE_ACCESS_WRITE|
1631 NTCREATEX_SHARE_ACCESS_DELETE,
1632 NTCREATEX_DISP_OPEN,
1633 NTCREATEX_OPTIONS_DIRECTORY, 0);
1636 /* Should work. */
1637 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1638 dname, smbcli_errstr(cli1->tree)));
1640 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1641 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, false, __location__);
1643 smbcli_close(cli1->tree, fnum1);
1645 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1647 smbcli_close(cli1->tree, fnum2);
1649 /* And the directory should be deleted ! */
1650 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1651 SEC_RIGHTS_FILE_READ,
1652 FILE_ATTRIBUTE_DIRECTORY,
1653 NTCREATEX_SHARE_ACCESS_READ|
1654 NTCREATEX_SHARE_ACCESS_WRITE|
1655 NTCREATEX_SHARE_ACCESS_DELETE,
1656 NTCREATEX_DISP_OPEN,
1657 NTCREATEX_OPTIONS_DIRECTORY, 0);
1658 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
1659 dname));
1661 return correct;
1664 /* Test 19 ... */
1665 static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1667 int fnum1 = -1;
1668 int fnum2 = -1;
1669 bool correct = true;
1671 del_clean_area(cli1, cli2);
1673 /* Test 19. */
1675 smbcli_deltree(cli1->tree, dname);
1677 /* Firstly open and create with all access */
1678 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1679 SEC_FILE_READ_DATA|
1680 SEC_FILE_WRITE_DATA|
1681 SEC_STD_DELETE,
1682 FILE_ATTRIBUTE_DIRECTORY,
1683 NTCREATEX_SHARE_ACCESS_READ|
1684 NTCREATEX_SHARE_ACCESS_WRITE|
1685 NTCREATEX_SHARE_ACCESS_DELETE,
1686 NTCREATEX_DISP_CREATE,
1687 NTCREATEX_OPTIONS_DIRECTORY, 0);
1689 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1690 dname, smbcli_errstr(cli1->tree)));
1692 /* And close - just to create the directory. */
1693 smbcli_close(cli1->tree, fnum1);
1695 /* Next open with all access, but add delete on close. */
1696 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1697 SEC_FILE_READ_DATA|
1698 SEC_FILE_WRITE_DATA|
1699 SEC_STD_DELETE,
1700 FILE_ATTRIBUTE_DIRECTORY,
1701 NTCREATEX_SHARE_ACCESS_READ|
1702 NTCREATEX_SHARE_ACCESS_WRITE|
1703 NTCREATEX_SHARE_ACCESS_DELETE,
1704 NTCREATEX_DISP_OPEN,
1705 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1707 torture_assert(tctx, fnum1 != -1,
1708 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1711 * The delete on close bit is *not* reported as being set.
1712 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1713 * close as being set. This causes the subsequent create to fail with
1714 * NT_STATUS_DELETE_PENDING.
1716 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1718 /* Now try opening again for read-only. */
1719 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1720 SEC_RIGHTS_FILE_READ,
1721 FILE_ATTRIBUTE_DIRECTORY,
1722 NTCREATEX_SHARE_ACCESS_READ|
1723 NTCREATEX_SHARE_ACCESS_WRITE|
1724 NTCREATEX_SHARE_ACCESS_DELETE,
1725 NTCREATEX_DISP_OPEN,
1726 NTCREATEX_OPTIONS_DIRECTORY, 0);
1728 /* Should work. */
1729 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1730 dname, smbcli_errstr(cli1->tree)));
1732 smbcli_close(cli1->tree, fnum1);
1734 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1736 smbcli_close(cli1->tree, fnum2);
1738 /* See if the file is deleted - for a directory this seems to be true ! */
1739 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1740 SEC_RIGHTS_FILE_READ,
1741 FILE_ATTRIBUTE_DIRECTORY,
1742 NTCREATEX_SHARE_ACCESS_READ|
1743 NTCREATEX_SHARE_ACCESS_WRITE|
1744 NTCREATEX_SHARE_ACCESS_DELETE,
1745 NTCREATEX_DISP_OPEN,
1746 NTCREATEX_OPTIONS_DIRECTORY, 0);
1748 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1750 torture_assert(tctx, fnum1 == -1,
1751 talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1753 return correct;
1756 /* Test 20 ... */
1757 static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1759 int fnum1 = -1;
1760 int dnum1 = -1;
1761 bool correct = true;
1762 NTSTATUS status;
1764 del_clean_area(cli1, cli2);
1766 /* Test 20 -- non-empty directory hardest to get right... */
1768 if (torture_setting_bool(tctx, "samba3", false)) {
1769 return true;
1772 smbcli_deltree(cli1->tree, dname);
1774 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1775 SEC_FILE_READ_DATA|
1776 SEC_FILE_WRITE_DATA|
1777 SEC_STD_DELETE,
1778 FILE_ATTRIBUTE_DIRECTORY,
1779 NTCREATEX_SHARE_ACCESS_READ|
1780 NTCREATEX_SHARE_ACCESS_WRITE|
1781 NTCREATEX_SHARE_ACCESS_DELETE,
1782 NTCREATEX_DISP_CREATE,
1783 NTCREATEX_OPTIONS_DIRECTORY, 0);
1784 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
1785 dname, smbcli_errstr(cli1->tree)));
1787 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
1788 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1791 char *fullname;
1792 asprintf(&fullname, "\\%s%s", dname, fname);
1793 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1794 DENY_NONE);
1795 torture_assert(tctx, fnum1 == -1,
1796 "smbcli_open succeeded, should have "
1797 "failed with NT_STATUS_DELETE_PENDING"
1800 torture_assert_ntstatus_equal(tctx,
1801 smbcli_nt_error(cli1->tree),
1802 NT_STATUS_DELETE_PENDING,
1803 "smbcli_open failed");
1806 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, false);
1807 torture_assert_ntstatus_ok(tctx, status,
1808 "setting delete_on_close on file failed !");
1811 char *fullname;
1812 asprintf(&fullname, "\\%s%s", dname, fname);
1813 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1814 DENY_NONE);
1815 torture_assert(tctx, fnum1 != -1,
1816 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1817 smbcli_errstr(cli1->tree)));
1818 smbcli_close(cli1->tree, fnum1);
1821 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1823 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1824 "setting delete_on_close failed");
1825 smbcli_close(cli1->tree, dnum1);
1827 return correct;
1830 /* Test 20a ... */
1831 static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1833 int fnum1 = -1;
1834 int fnum2 = -1;
1835 bool correct = true;
1837 del_clean_area(cli1, cli2);
1839 /* Test 20a. */
1841 /* Ensure the file doesn't already exist. */
1842 smbcli_close(cli1->tree, fnum1);
1843 smbcli_close(cli1->tree, fnum2);
1844 smbcli_setatr(cli1->tree, fname, 0, 0);
1845 smbcli_unlink(cli1->tree, fname);
1847 /* Firstly open and create with all access */
1848 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1849 SEC_RIGHTS_FILE_ALL,
1850 FILE_ATTRIBUTE_NORMAL,
1851 NTCREATEX_SHARE_ACCESS_READ|
1852 NTCREATEX_SHARE_ACCESS_WRITE|
1853 NTCREATEX_SHARE_ACCESS_DELETE,
1854 NTCREATEX_DISP_CREATE,
1855 0, 0);
1856 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1857 fname, smbcli_errstr(cli1->tree)));
1859 /* Next open with all access, but add delete on close. */
1860 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1861 SEC_RIGHTS_FILE_ALL,
1862 FILE_ATTRIBUTE_NORMAL,
1863 NTCREATEX_SHARE_ACCESS_READ|
1864 NTCREATEX_SHARE_ACCESS_WRITE|
1865 NTCREATEX_SHARE_ACCESS_DELETE,
1866 NTCREATEX_DISP_OPEN,
1867 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1869 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1870 fname, smbcli_errstr(cli2->tree)));
1872 /* The delete on close bit is *not* reported as being set. */
1873 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1874 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1876 smbcli_close(cli1->tree, fnum1);
1878 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1880 smbcli_close(cli2->tree, fnum2);
1882 /* See if the file is deleted - should be.... */
1883 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1884 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1885 fname, smbcli_errstr(cli1->tree)));
1887 return correct;
1890 /* Test 20b ... */
1891 /* This is the delete semantics that the cifsfs client depends on when
1892 * trying to delete an open file on a Windows server. It
1893 * opens a file with initial delete on close set, renames it then closes
1894 * all open handles. The file goes away on Windows.
1897 static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1899 int fnum1 = -1;
1900 int fnum2 = -1;
1901 bool correct = true;
1903 del_clean_area(cli1, cli2);
1905 /* Test 20b. */
1907 /* Ensure the file doesn't already exist. */
1908 smbcli_close(cli1->tree, fnum1);
1909 smbcli_close(cli1->tree, fnum2);
1910 smbcli_setatr(cli1->tree, fname, 0, 0);
1911 smbcli_unlink(cli1->tree, fname);
1912 smbcli_setatr(cli1->tree, fname_new, 0, 0);
1913 smbcli_unlink(cli1->tree, fname_new);
1915 /* Firstly open and create with all access */
1916 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1917 SEC_RIGHTS_FILE_ALL,
1918 FILE_ATTRIBUTE_NORMAL,
1919 NTCREATEX_SHARE_ACCESS_READ|
1920 NTCREATEX_SHARE_ACCESS_WRITE|
1921 NTCREATEX_SHARE_ACCESS_DELETE,
1922 NTCREATEX_DISP_CREATE,
1923 0, 0);
1924 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1925 fname, smbcli_errstr(cli1->tree)));
1927 /* And close - just to create the file. */
1928 smbcli_close(cli1->tree, fnum1);
1930 /* Firstly open and create with all access */
1931 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1932 SEC_RIGHTS_FILE_ALL,
1933 FILE_ATTRIBUTE_NORMAL,
1934 NTCREATEX_SHARE_ACCESS_READ|
1935 NTCREATEX_SHARE_ACCESS_WRITE|
1936 NTCREATEX_SHARE_ACCESS_DELETE,
1937 NTCREATEX_DISP_OPEN,
1938 0, 0);
1939 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1940 fname, smbcli_errstr(cli1->tree)));
1942 /* Next open with all access, but add delete on close. */
1943 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1944 SEC_RIGHTS_FILE_ALL,
1945 FILE_ATTRIBUTE_NORMAL,
1946 NTCREATEX_SHARE_ACCESS_READ|
1947 NTCREATEX_SHARE_ACCESS_WRITE|
1948 NTCREATEX_SHARE_ACCESS_DELETE,
1949 NTCREATEX_DISP_OPEN,
1950 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1952 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1953 fname, smbcli_errstr(cli2->tree)));
1955 /* The delete on close bit is *not* reported as being set. */
1956 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1957 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1959 smbcli_close(cli1->tree, fnum1);
1961 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1963 /* Rename the file by handle. */
1966 union smb_setfileinfo sfinfo;
1967 NTSTATUS status;
1969 memset(&sfinfo, '\0', sizeof(sfinfo));
1970 sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
1971 sfinfo.generic.in.file.fnum = fnum2;
1972 sfinfo.rename_information.in.root_fid = 0;
1973 /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
1974 sfinfo.rename_information.in.new_name = fname_new + 1;
1975 sfinfo.rename_information.in.overwrite = 1;
1977 status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
1979 torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
1980 fname, fname_new, smbcli_errstr(cli2->tree)));
1983 correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, false, __location__);
1985 smbcli_close(cli2->tree, fnum2);
1987 /* See if the file is deleted - should be.... */
1988 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1989 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1990 fname, smbcli_errstr(cli1->tree)));
1991 fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
1992 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1993 fname_new, smbcli_errstr(cli1->tree)));
1995 return correct;
1999 /* Test 21 ... */
2000 static bool deltest21(struct torture_context *tctx)
2002 int fnum1 = -1;
2003 struct smbcli_state *cli1;
2004 struct smbcli_state *cli2;
2005 bool correct = true;
2007 if (!torture_open_connection(&cli1, tctx, 0))
2008 return false;
2010 if (!torture_open_connection(&cli2, tctx, 1))
2011 return false;
2013 del_clean_area(cli1, cli2);
2015 /* Test 21 -- Test removal of file after socket close. */
2017 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2018 SEC_RIGHTS_FILE_ALL,
2019 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
2020 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2022 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
2023 fname, smbcli_errstr(cli1->tree)));
2025 torture_assert_ntstatus_ok(tctx,
2026 smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
2027 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2028 smbcli_errstr(cli1->tree)));
2030 /* Ensure delete on close is set. */
2031 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
2033 /* Now yank the rug from under cli1. */
2034 smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
2036 fnum1 = -1;
2038 if (!torture_open_connection(&cli1, tctx, 0)) {
2039 return false;
2042 /* On slow build farm machines it might happen that they are not fast
2043 * enogh to delete the file for this test */
2044 smb_msleep(200);
2046 /* File should not be there. */
2047 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2048 SEC_RIGHTS_FILE_READ,
2049 FILE_ATTRIBUTE_NORMAL,
2050 NTCREATEX_SHARE_ACCESS_READ|
2051 NTCREATEX_SHARE_ACCESS_WRITE|
2052 NTCREATEX_SHARE_ACCESS_DELETE,
2053 NTCREATEX_DISP_OPEN,
2054 0, 0);
2056 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2058 return correct;
2061 /* Test 22 ... */
2064 * Test whether a second *directory* handle inhibits delete if the first has
2065 * del-on-close set and is closed
2067 static bool deltest22(struct torture_context *tctx)
2069 int dnum1 = -1;
2070 int dnum2 = -1;
2071 struct smbcli_state *cli1;
2072 bool correct = true;
2074 if (!torture_open_connection(&cli1, tctx, 0))
2075 return false;
2077 smbcli_deltree(cli1->tree, dname);
2079 torture_assert_ntstatus_ok(
2080 tctx, smbcli_mkdir(cli1->tree, dname),
2081 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
2082 smbcli_errstr(cli1->tree)));
2084 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2085 SEC_FILE_READ_DATA|
2086 SEC_FILE_WRITE_DATA|
2087 SEC_STD_DELETE,
2088 FILE_ATTRIBUTE_DIRECTORY,
2089 NTCREATEX_SHARE_ACCESS_READ|
2090 NTCREATEX_SHARE_ACCESS_WRITE|
2091 NTCREATEX_SHARE_ACCESS_DELETE,
2092 NTCREATEX_DISP_OPEN,
2093 NTCREATEX_OPTIONS_DIRECTORY, 0);
2095 torture_assert(tctx, dnum1 != -1,
2096 talloc_asprintf(tctx, "open of %s failed: %s!",
2097 dname, smbcli_errstr(cli1->tree)));
2099 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2100 SEC_FILE_READ_DATA|
2101 SEC_FILE_WRITE_DATA,
2102 FILE_ATTRIBUTE_DIRECTORY,
2103 NTCREATEX_SHARE_ACCESS_READ|
2104 NTCREATEX_SHARE_ACCESS_WRITE|
2105 NTCREATEX_SHARE_ACCESS_DELETE,
2106 NTCREATEX_DISP_OPEN,
2107 NTCREATEX_OPTIONS_DIRECTORY, 0);
2109 torture_assert(tctx, dnum2 != -1,
2110 talloc_asprintf(tctx, "open of %s failed: %s!",
2111 dname, smbcli_errstr(cli1->tree)));
2113 torture_assert_ntstatus_ok(
2114 tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
2115 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2116 smbcli_errstr(cli1->tree)));
2118 smbcli_close(cli1->tree, dnum1);
2120 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2121 SEC_FILE_READ_DATA|
2122 SEC_FILE_WRITE_DATA|
2123 SEC_STD_DELETE,
2124 FILE_ATTRIBUTE_DIRECTORY,
2125 NTCREATEX_SHARE_ACCESS_READ|
2126 NTCREATEX_SHARE_ACCESS_WRITE|
2127 NTCREATEX_SHARE_ACCESS_DELETE,
2128 NTCREATEX_DISP_OPEN,
2129 NTCREATEX_OPTIONS_DIRECTORY, 0);
2131 torture_assert(tctx, dnum1 == -1,
2132 talloc_asprintf(tctx, "open of %s succeeded!\n",
2133 dname));
2135 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
2137 smbcli_close(cli1->tree, dnum2);
2138 CHECK_STATUS(cli1, NT_STATUS_OK);
2140 return correct;
2143 /* Test 23 - Second directory open fails when delete is pending. */
2144 static bool deltest23(struct torture_context *tctx,
2145 struct smbcli_state *cli1,
2146 struct smbcli_state *cli2)
2148 int dnum1 = -1;
2149 int dnum2 = -1;
2150 bool correct = true;
2152 del_clean_area(cli1, cli2);
2154 /* Test 23 -- Basic delete on close for directories. */
2156 /* Open a directory */
2157 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2158 SEC_FILE_READ_DATA|
2159 SEC_FILE_WRITE_DATA|
2160 SEC_STD_DELETE,
2161 FILE_ATTRIBUTE_DIRECTORY,
2162 NTCREATEX_SHARE_ACCESS_READ|
2163 NTCREATEX_SHARE_ACCESS_WRITE|
2164 NTCREATEX_SHARE_ACCESS_DELETE,
2165 NTCREATEX_DISP_CREATE,
2166 NTCREATEX_OPTIONS_DIRECTORY, 0);
2168 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx,
2169 "open of %s failed: %s!",
2170 dname, smbcli_errstr(cli1->tree)));
2172 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false,
2173 __location__);
2175 /* Set delete on close */
2176 (void)smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
2178 /* Attempt opening the directory again. It should fail. */
2179 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2180 SEC_FILE_READ_DATA|
2181 SEC_FILE_WRITE_DATA|
2182 SEC_STD_DELETE,
2183 FILE_ATTRIBUTE_DIRECTORY,
2184 NTCREATEX_SHARE_ACCESS_READ|
2185 NTCREATEX_SHARE_ACCESS_WRITE|
2186 NTCREATEX_SHARE_ACCESS_DELETE,
2187 NTCREATEX_DISP_OPEN,
2188 NTCREATEX_OPTIONS_DIRECTORY, 0);
2190 torture_assert(tctx, dnum2 == -1, talloc_asprintf(tctx,
2191 "open of %s succeeded: %s. It should have failed "
2192 "with NT_STATUS_DELETE_PENDING",
2193 dname, smbcli_errstr(cli1->tree)));
2195 torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree),
2196 NT_STATUS_DELETE_PENDING, "smbcli_open failed");
2198 return true;
2202 Test delete on close semantics.
2204 struct torture_suite *torture_test_delete(void)
2206 struct torture_suite *suite = torture_suite_create(
2207 talloc_autofree_context(), "delete");
2209 torture_suite_add_2smb_test(suite, "deltest1", deltest1);
2210 torture_suite_add_2smb_test(suite, "deltest2", deltest2);
2211 torture_suite_add_2smb_test(suite, "deltest3", deltest3);
2212 torture_suite_add_2smb_test(suite, "deltest4", deltest4);
2213 torture_suite_add_2smb_test(suite, "deltest5", deltest5);
2214 torture_suite_add_2smb_test(suite, "deltest6", deltest6);
2215 torture_suite_add_2smb_test(suite, "deltest7", deltest7);
2216 torture_suite_add_2smb_test(suite, "deltest8", deltest8);
2217 torture_suite_add_2smb_test(suite, "deltest9", deltest9);
2218 torture_suite_add_2smb_test(suite, "deltest10", deltest10);
2219 torture_suite_add_2smb_test(suite, "deltest11", deltest11);
2220 torture_suite_add_2smb_test(suite, "deltest12", deltest12);
2221 torture_suite_add_2smb_test(suite, "deltest13", deltest13);
2222 torture_suite_add_2smb_test(suite, "deltest14", deltest14);
2223 torture_suite_add_2smb_test(suite, "deltest15", deltest15);
2224 torture_suite_add_2smb_test(suite, "deltest16", deltest16);
2225 torture_suite_add_2smb_test(suite, "deltest16a", deltest16a);
2226 torture_suite_add_2smb_test(suite, "deltest17", deltest17);
2227 torture_suite_add_2smb_test(suite, "deltest17a", deltest17a);
2228 torture_suite_add_2smb_test(suite, "deltest17b", deltest17b);
2229 torture_suite_add_2smb_test(suite, "deltest17c", deltest17c);
2230 torture_suite_add_2smb_test(suite, "deltest17d", deltest17d);
2231 torture_suite_add_2smb_test(suite, "deltest17e", deltest17e);
2232 torture_suite_add_2smb_test(suite, "deltest17f", deltest17f);
2233 torture_suite_add_2smb_test(suite, "deltest18", deltest18);
2234 torture_suite_add_2smb_test(suite, "deltest19", deltest19);
2235 torture_suite_add_2smb_test(suite, "deltest20", deltest20);
2236 torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
2237 torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
2238 torture_suite_add_simple_test(suite, "deltest21", deltest21);
2239 torture_suite_add_simple_test(suite, "deltest22", deltest22);
2240 torture_suite_add_2smb_test(suite, "deltest23", deltest23);
2242 return suite;