s4: torture: Ensure a failed file create doesn't create the file.
[Samba.git] / source4 / torture / basic / delete.c
blobbc23b5fd1d0fc4622aaba50062eff90895d79afb
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;
479 NTSTATUS status;
481 del_clean_area(cli1, cli2);
483 /* This should fail - we need to set DELETE_ACCESS. */
486 * A file or directory create with DELETE_ON_CLOSE but
487 * without DELETE_ACCESS should fail with
488 * NT_STATUS_INVALID_PARAMETER.
491 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
492 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
493 FILE_ATTRIBUTE_NORMAL,
494 NTCREATEX_SHARE_ACCESS_NONE,
495 NTCREATEX_DISP_OVERWRITE_IF,
496 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
498 torture_assert(tctx, fnum1 == -1,
499 talloc_asprintf(tctx, "open of %s succeeded should have failed!",
500 fname));
502 /* Must fail with NT_STATUS_INVALID_PARAMETER. */
503 status = smbcli_nt_error(cli1->tree);
504 torture_assert_ntstatus_equal(tctx,
505 status,
506 NT_STATUS_INVALID_PARAMETER,
507 talloc_asprintf(tctx, "create of %s should return "
508 "NT_STATUS_INVALID_PARAMETER, got %s",
509 fname,
510 smbcli_errstr(cli1->tree)));
512 /* This should fail - the file should not have been created. */
513 status = smbcli_getatr(cli1->tree, fname, NULL, NULL, NULL);
514 torture_assert_ntstatus_equal(tctx,
515 status,
516 NT_STATUS_OBJECT_NAME_NOT_FOUND,
517 talloc_asprintf(tctx, "getattr of %s succeeded should "
518 "not have been created !",
519 fname));
521 return true;
524 /* Test 10 ... */
525 static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
527 int fnum1 = -1;
529 del_clean_area(cli1, cli2);
531 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
532 SEC_FILE_READ_DATA|
533 SEC_FILE_WRITE_DATA|
534 SEC_STD_DELETE,
535 FILE_ATTRIBUTE_NORMAL,
536 NTCREATEX_SHARE_ACCESS_NONE,
537 NTCREATEX_DISP_OVERWRITE_IF,
538 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
539 torture_assert(tctx, fnum1 != -1,
540 talloc_asprintf(tctx, "open of %s failed (%s)",
541 fname, smbcli_errstr(cli1->tree)));
543 /* This should delete the file. */
544 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
545 talloc_asprintf(tctx, "close failed (%s)",
546 smbcli_errstr(cli1->tree)));
548 /* This should fail.. */
549 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
550 torture_assert(tctx, fnum1 == -1,
551 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
552 fname));
553 return true;
556 /* Test 11 ... */
557 static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
559 int fnum1 = -1;
560 NTSTATUS status;
562 del_clean_area(cli1, cli2);
564 /* test 11 - does having read only attribute still allow delete on close. */
566 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
567 SEC_RIGHTS_FILE_ALL,
568 FILE_ATTRIBUTE_READONLY,
569 NTCREATEX_SHARE_ACCESS_NONE,
570 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
572 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
573 fname, smbcli_errstr(cli1->tree)));
575 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, true);
577 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
578 talloc_asprintf(tctx, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1->tree)));
580 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
581 talloc_asprintf(tctx, "close failed (%s)",
582 smbcli_errstr(cli1->tree)));
584 return true;
587 /* Test 12 ... */
588 static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
590 int fnum1 = -1;
591 NTSTATUS status;
593 del_clean_area(cli1, cli2);
595 /* test 12 - does having read only attribute still allow delete on
596 * close at time of open. */
598 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
599 SEC_RIGHTS_FILE_ALL,
600 FILE_ATTRIBUTE_READONLY,
601 NTCREATEX_SHARE_ACCESS_DELETE,
602 NTCREATEX_DISP_OVERWRITE_IF,
603 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
605 torture_assert(tctx, fnum1 == -1,
606 talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
607 "NT_STATUS_CANNOT_DELETE.\n", fname));
609 status = smbcli_nt_error(cli1->tree);
610 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
611 talloc_asprintf(tctx, "setting delete_on_close on open should "
612 "fail with NT_STATUS_CANNOT_DELETE. Got %s "
613 "instead)",
614 smbcli_errstr(cli1->tree)));
616 return true;
619 /* Test 13 ... */
620 static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
622 int fnum1 = -1;
623 int fnum2 = -1;
624 bool correct = true;
626 del_clean_area(cli1, cli2);
628 /* Test 13: Does resetting the delete on close flag affect a second
629 * fd? */
631 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
632 SEC_FILE_READ_DATA|
633 SEC_FILE_WRITE_DATA|
634 SEC_STD_DELETE,
635 FILE_ATTRIBUTE_NORMAL,
636 NTCREATEX_SHARE_ACCESS_READ|
637 NTCREATEX_SHARE_ACCESS_WRITE|
638 NTCREATEX_SHARE_ACCESS_DELETE,
639 NTCREATEX_DISP_OVERWRITE_IF,
640 0, 0);
642 torture_assert(tctx, fnum1 != -1,
643 talloc_asprintf(tctx, "open of %s failed (%s)",
644 fname, smbcli_errstr(cli1->tree)));
646 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
647 SEC_FILE_READ_DATA|
648 SEC_FILE_WRITE_DATA|
649 SEC_STD_DELETE,
650 FILE_ATTRIBUTE_NORMAL,
651 NTCREATEX_SHARE_ACCESS_READ|
652 NTCREATEX_SHARE_ACCESS_WRITE|
653 NTCREATEX_SHARE_ACCESS_DELETE,
654 NTCREATEX_DISP_OPEN, 0, 0);
656 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
657 "open of %s failed (%s)",
658 fname, smbcli_errstr(cli2->tree)));
660 torture_assert_ntstatus_ok(tctx,
661 smbcli_nt_delete_on_close(cli1->tree, fnum1,
662 true),
663 "setting delete_on_close on file failed !");
665 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
666 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
668 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
669 false),
670 "unsetting delete_on_close on file failed !");
672 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
673 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
675 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
676 talloc_asprintf(tctx, "close - 1 failed (%s)",
677 smbcli_errstr(cli1->tree)));
679 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
680 talloc_asprintf(tctx, "close - 2 failed (%s)",
681 smbcli_errstr(cli2->tree)));
683 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
685 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!",
686 fname));
688 smbcli_close(cli1->tree, fnum1);
690 return correct;
693 /* Test 14 ... */
694 static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
696 int dnum1 = -1;
697 bool correct = true;
699 del_clean_area(cli1, cli2);
701 /* Test 14 -- directory */
703 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
704 SEC_FILE_READ_DATA|
705 SEC_FILE_WRITE_DATA|
706 SEC_STD_DELETE,
707 FILE_ATTRIBUTE_DIRECTORY,
708 NTCREATEX_SHARE_ACCESS_READ|
709 NTCREATEX_SHARE_ACCESS_WRITE|
710 NTCREATEX_SHARE_ACCESS_DELETE,
711 NTCREATEX_DISP_CREATE, 0, 0);
712 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
713 dname, smbcli_errstr(cli1->tree)));
715 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
716 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
717 "setting delete_on_close on file failed !");
718 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, true, __location__);
719 smbcli_close(cli1->tree, dnum1);
721 /* Now it should be gone... */
723 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
724 SEC_FILE_READ_DATA|
725 SEC_FILE_WRITE_DATA|
726 SEC_STD_DELETE,
727 FILE_ATTRIBUTE_DIRECTORY,
728 NTCREATEX_SHARE_ACCESS_READ|
729 NTCREATEX_SHARE_ACCESS_WRITE|
730 NTCREATEX_SHARE_ACCESS_DELETE,
731 NTCREATEX_DISP_OPEN, 0, 0);
732 torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
734 return correct;
737 /* Test 15 ... */
738 static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
740 int fnum1 = -1;
741 bool correct = true;
742 int fnum2 = -1;
743 NTSTATUS status;
745 del_clean_area(cli1, cli2);
747 /* Test 15: delete on close under rename */
749 smbcli_setatr(cli1->tree, fname, 0, 0);
750 smbcli_unlink(cli1->tree, fname);
751 smbcli_unlink(cli1->tree, fname_new);
753 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
754 SEC_FILE_READ_DATA,
755 FILE_ATTRIBUTE_NORMAL,
756 NTCREATEX_SHARE_ACCESS_READ|
757 NTCREATEX_SHARE_ACCESS_WRITE|
758 NTCREATEX_SHARE_ACCESS_DELETE,
759 NTCREATEX_DISP_OVERWRITE_IF,
760 0, 0);
762 torture_assert(tctx, fnum1 != -1,
763 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
765 status = smbcli_rename(cli2->tree, fname, fname_new);
767 torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
769 fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
770 SEC_GENERIC_ALL,
771 FILE_ATTRIBUTE_NORMAL,
772 NTCREATEX_SHARE_ACCESS_READ|
773 NTCREATEX_SHARE_ACCESS_WRITE|
774 NTCREATEX_SHARE_ACCESS_DELETE,
775 NTCREATEX_DISP_OVERWRITE_IF,
776 0, 0);
778 torture_assert(tctx, fnum2 != -1,
779 talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
780 fname_new, smbcli_errstr(cli1->tree)));
782 status = smbcli_nt_delete_on_close(cli2->tree, fnum2, true);
784 torture_assert_ntstatus_ok(tctx, status,
785 "setting delete_on_close on file failed !");
787 smbcli_close(cli2->tree, fnum2);
789 /* The file should be around under the new name, there's a second
790 * handle open */
792 correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, true, __location__);
794 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
795 SEC_GENERIC_ALL,
796 FILE_ATTRIBUTE_NORMAL,
797 NTCREATEX_SHARE_ACCESS_READ|
798 NTCREATEX_SHARE_ACCESS_WRITE|
799 NTCREATEX_SHARE_ACCESS_DELETE,
800 NTCREATEX_DISP_OVERWRITE_IF,
801 0, 0);
803 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
804 fname, smbcli_errstr(cli1->tree)));
806 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
808 smbcli_close(cli2->tree, fnum2);
809 smbcli_close(cli1->tree, fnum1);
811 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
812 SEC_FILE_READ_EA,
813 FILE_ATTRIBUTE_NORMAL,
814 NTCREATEX_SHARE_ACCESS_READ|
815 NTCREATEX_SHARE_ACCESS_WRITE|
816 NTCREATEX_SHARE_ACCESS_DELETE,
817 NTCREATEX_DISP_OPEN,
818 0, 0);
820 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
821 fname, smbcli_errstr(cli1->tree)));
823 smbcli_close(cli1->tree, fnum1);
825 fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
826 SEC_FILE_READ_EA,
827 FILE_ATTRIBUTE_NORMAL,
828 NTCREATEX_SHARE_ACCESS_READ|
829 NTCREATEX_SHARE_ACCESS_WRITE|
830 NTCREATEX_SHARE_ACCESS_DELETE,
831 NTCREATEX_DISP_OPEN,
832 0, 0);
834 torture_assert(tctx, fnum1 == -1,
835 "smbcli_open succeeded, should have "
836 "failed");
838 return correct;
841 /* Test 16 ... */
842 static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
844 int fnum1 = -1;
845 int fnum2 = -1;
846 bool correct = true;
848 del_clean_area(cli1, cli2);
850 /* Test 16. */
852 /* Ensure the file doesn't already exist. */
853 smbcli_close(cli1->tree, fnum1);
854 smbcli_close(cli1->tree, fnum2);
855 smbcli_setatr(cli1->tree, fname, 0, 0);
856 smbcli_unlink(cli1->tree, fname);
858 /* Firstly create with all access, but delete on close. */
859 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
860 SEC_RIGHTS_FILE_ALL,
861 FILE_ATTRIBUTE_NORMAL,
862 NTCREATEX_SHARE_ACCESS_READ|
863 NTCREATEX_SHARE_ACCESS_WRITE|
864 NTCREATEX_SHARE_ACCESS_DELETE,
865 NTCREATEX_DISP_CREATE,
866 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
868 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
870 /* The delete on close bit is *not* reported as being set. */
871 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
873 /* The delete on close bit is *not* reported as being set. */
874 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
875 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
877 /* Now try opening again for read-only. */
878 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
879 SEC_RIGHTS_FILE_READ,
880 FILE_ATTRIBUTE_NORMAL,
881 NTCREATEX_SHARE_ACCESS_READ|
882 NTCREATEX_SHARE_ACCESS_WRITE|
883 NTCREATEX_SHARE_ACCESS_DELETE,
884 NTCREATEX_DISP_OPEN,
885 0, 0);
887 /* Should work. */
888 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
889 fname, smbcli_errstr(cli1->tree)));
891 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
892 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
893 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
894 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
896 smbcli_close(cli1->tree, fnum1);
898 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
899 correct &= check_delete_on_close(tctx, cli2, -1, fname, true, __location__);
901 smbcli_close(cli2->tree, fnum2);
903 /* And the file should be deleted ! */
904 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
905 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
906 fname));
908 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
910 return correct;
913 /* Test 16 ... */
914 static bool deltest16a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
916 int fnum1 = -1;
917 int fnum2 = -1;
918 bool correct = true;
920 del_clean_area(cli1, cli2);
922 /* Test 16. */
924 /* Ensure the file doesn't already exist. */
925 smbcli_close(cli1->tree, fnum1);
926 smbcli_close(cli1->tree, fnum2);
927 smbcli_setatr(cli1->tree, fname, 0, 0);
928 smbcli_unlink(cli1->tree, fname);
930 /* Firstly open and create with all access */
931 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
932 SEC_RIGHTS_FILE_ALL,
933 FILE_ATTRIBUTE_NORMAL,
934 NTCREATEX_SHARE_ACCESS_READ|
935 NTCREATEX_SHARE_ACCESS_WRITE|
936 NTCREATEX_SHARE_ACCESS_DELETE,
937 NTCREATEX_DISP_CREATE,
938 0, 0);
939 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
940 fname, smbcli_errstr(cli1->tree)));
942 /* And close - just to create the file. */
943 smbcli_close(cli1->tree, fnum1);
945 /* Firstly create with all access, but delete on close. */
946 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
947 SEC_RIGHTS_FILE_ALL,
948 FILE_ATTRIBUTE_NORMAL,
949 NTCREATEX_SHARE_ACCESS_READ|
950 NTCREATEX_SHARE_ACCESS_WRITE|
951 NTCREATEX_SHARE_ACCESS_DELETE,
952 NTCREATEX_DISP_OPEN,
953 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
955 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
957 /* The delete on close bit is *not* reported as being set. */
958 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
960 /* The delete on close bit is *not* reported as being set. */
961 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
962 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
964 /* Now try opening again for read-only. */
965 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
966 SEC_RIGHTS_FILE_READ,
967 FILE_ATTRIBUTE_NORMAL,
968 NTCREATEX_SHARE_ACCESS_READ|
969 NTCREATEX_SHARE_ACCESS_WRITE|
970 NTCREATEX_SHARE_ACCESS_DELETE,
971 NTCREATEX_DISP_OPEN,
972 0, 0);
974 /* Should work. */
975 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
976 fname, smbcli_errstr(cli1->tree)));
978 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
979 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
980 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
981 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
983 smbcli_close(cli1->tree, fnum1);
985 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
986 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
988 smbcli_close(cli2->tree, fnum2);
990 /* And the file should be deleted ! */
991 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
992 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
993 fname, smbcli_errstr(cli1->tree)));
995 smbcli_close(cli1->tree, fnum1);
996 smbcli_setatr(cli1->tree, fname, 0, 0);
997 smbcli_unlink(cli1->tree, fname);
999 return correct;
1002 /* Test 17 ... */
1003 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1005 int fnum1 = -1;
1006 int fnum2 = -1;
1007 bool correct = true;
1009 del_clean_area(cli1, cli2);
1011 /* Test 17. */
1013 /* Ensure the file doesn't already exist. */
1014 smbcli_close(cli1->tree, fnum1);
1015 smbcli_close(cli1->tree, fnum2);
1016 smbcli_setatr(cli1->tree, fname, 0, 0);
1017 smbcli_unlink(cli1->tree, fname);
1019 /* Firstly open and create with all access */
1020 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1021 SEC_RIGHTS_FILE_ALL,
1022 FILE_ATTRIBUTE_NORMAL,
1023 NTCREATEX_SHARE_ACCESS_READ|
1024 NTCREATEX_SHARE_ACCESS_WRITE|
1025 NTCREATEX_SHARE_ACCESS_DELETE,
1026 NTCREATEX_DISP_CREATE,
1027 0, 0);
1028 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1029 fname, smbcli_errstr(cli1->tree)));
1031 /* And close - just to create the file. */
1032 smbcli_close(cli1->tree, fnum1);
1034 /* Next open with all access, but add delete on close. */
1035 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1036 SEC_RIGHTS_FILE_ALL,
1037 FILE_ATTRIBUTE_NORMAL,
1038 NTCREATEX_SHARE_ACCESS_READ|
1039 NTCREATEX_SHARE_ACCESS_WRITE|
1040 NTCREATEX_SHARE_ACCESS_DELETE,
1041 NTCREATEX_DISP_OPEN,
1042 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1044 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1045 fname, smbcli_errstr(cli1->tree)));
1047 /* The delete on close bit is *not* reported as being set. */
1048 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1050 /* Now try opening again for read-only. */
1051 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1052 SEC_RIGHTS_FILE_READ|
1053 SEC_STD_DELETE,
1054 FILE_ATTRIBUTE_NORMAL,
1055 NTCREATEX_SHARE_ACCESS_READ|
1056 NTCREATEX_SHARE_ACCESS_WRITE|
1057 NTCREATEX_SHARE_ACCESS_DELETE,
1058 NTCREATEX_DISP_OPEN,
1059 0, 0);
1061 /* Should work. */
1062 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1063 fname, smbcli_errstr(cli1->tree)));
1065 /* still not reported as being set on either */
1066 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1067 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1069 smbcli_close(cli1->tree, fnum1);
1071 /* After the first close, the files has the delete on close bit set. */
1072 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1074 smbcli_close(cli1->tree, fnum2);
1076 /* Make sure the file has been deleted */
1077 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1078 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
1079 fname, smbcli_errstr(cli1->tree)));
1081 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1083 return correct;
1086 /* Test 17a - like 17, but the delete on close handle is closed last */
1087 static bool deltest17a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1089 int fnum1 = -1;
1090 int fnum2 = -1;
1091 bool correct = true;
1093 del_clean_area(cli1, cli2);
1095 /* Ensure the file doesn't already exist. */
1096 smbcli_close(cli1->tree, fnum1);
1097 smbcli_close(cli1->tree, fnum2);
1098 smbcli_setatr(cli1->tree, fname, 0, 0);
1099 smbcli_unlink(cli1->tree, fname);
1101 /* Firstly open and create with all access */
1102 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1103 SEC_RIGHTS_FILE_ALL,
1104 FILE_ATTRIBUTE_NORMAL,
1105 NTCREATEX_SHARE_ACCESS_READ|
1106 NTCREATEX_SHARE_ACCESS_WRITE|
1107 NTCREATEX_SHARE_ACCESS_DELETE,
1108 NTCREATEX_DISP_CREATE,
1109 0, 0);
1110 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1111 fname, smbcli_errstr(cli1->tree)));
1113 /* And close - just to create the file. */
1114 smbcli_close(cli1->tree, fnum1);
1116 /* Next open with all access, but add delete on close. */
1117 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1118 SEC_RIGHTS_FILE_ALL,
1119 FILE_ATTRIBUTE_NORMAL,
1120 NTCREATEX_SHARE_ACCESS_READ|
1121 NTCREATEX_SHARE_ACCESS_WRITE|
1122 NTCREATEX_SHARE_ACCESS_DELETE,
1123 NTCREATEX_DISP_OPEN,
1124 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1126 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1127 fname, smbcli_errstr(cli1->tree)));
1129 /* The delete on close bit is *not* reported as being set. */
1130 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1132 /* Now try opening again for read-only. */
1133 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1134 SEC_RIGHTS_FILE_READ|
1135 SEC_STD_DELETE,
1136 FILE_ATTRIBUTE_NORMAL,
1137 NTCREATEX_SHARE_ACCESS_READ|
1138 NTCREATEX_SHARE_ACCESS_WRITE|
1139 NTCREATEX_SHARE_ACCESS_DELETE,
1140 NTCREATEX_DISP_OPEN,
1141 0, 0);
1143 /* Should work. */
1144 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1145 fname, smbcli_errstr(cli1->tree)));
1147 /* still not reported as being set on either */
1148 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1149 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1151 smbcli_close(cli1->tree, fnum2);
1153 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1155 smbcli_close(cli1->tree, fnum1);
1158 * The file is still there:
1159 * The second open seems to have removed the initial
1160 * delete on close flag from the first handle
1162 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1163 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1164 fname, smbcli_errstr(cli1->tree)));
1166 smbcli_close(cli1->tree, fnum1);
1167 smbcli_setatr(cli1->tree, fname, 0, 0);
1168 smbcli_unlink(cli1->tree, fname);
1170 return correct;
1173 /* Test 17b - like 17a, but the initial delete on close is set on the second handle */
1174 static bool deltest17b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1176 int fnum1 = -1;
1177 int fnum2 = -1;
1178 bool correct = true;
1180 del_clean_area(cli1, cli2);
1182 /* Ensure the file doesn't already exist. */
1183 smbcli_close(cli1->tree, fnum1);
1184 smbcli_close(cli1->tree, fnum2);
1185 smbcli_setatr(cli1->tree, fname, 0, 0);
1186 smbcli_unlink(cli1->tree, fname);
1188 /* Firstly open and create with all access */
1189 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1190 SEC_RIGHTS_FILE_ALL,
1191 FILE_ATTRIBUTE_NORMAL,
1192 NTCREATEX_SHARE_ACCESS_READ|
1193 NTCREATEX_SHARE_ACCESS_WRITE|
1194 NTCREATEX_SHARE_ACCESS_DELETE,
1195 NTCREATEX_DISP_CREATE,
1196 0, 0);
1197 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1198 fname, smbcli_errstr(cli1->tree)));
1200 /* And close - just to create the file. */
1201 smbcli_close(cli1->tree, fnum1);
1203 /* Next open with all access, but add delete on close. */
1204 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1205 SEC_RIGHTS_FILE_ALL,
1206 FILE_ATTRIBUTE_NORMAL,
1207 NTCREATEX_SHARE_ACCESS_READ|
1208 NTCREATEX_SHARE_ACCESS_WRITE|
1209 NTCREATEX_SHARE_ACCESS_DELETE,
1210 NTCREATEX_DISP_OPEN,
1211 0, 0);
1213 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1214 fname, smbcli_errstr(cli1->tree)));
1216 /* The delete on close bit is *not* reported as being set. */
1217 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1219 /* Now try opening again for read-only. */
1220 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1221 SEC_RIGHTS_FILE_READ|
1222 SEC_STD_DELETE,
1223 FILE_ATTRIBUTE_NORMAL,
1224 NTCREATEX_SHARE_ACCESS_READ|
1225 NTCREATEX_SHARE_ACCESS_WRITE|
1226 NTCREATEX_SHARE_ACCESS_DELETE,
1227 NTCREATEX_DISP_OPEN,
1228 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1230 /* Should work. */
1231 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1232 fname, smbcli_errstr(cli1->tree)));
1234 /* still not reported as being set on either */
1235 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1236 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1238 smbcli_close(cli1->tree, fnum1);
1240 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1242 smbcli_close(cli1->tree, fnum2);
1244 /* Make sure the file has been deleted */
1245 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1246 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1247 fname));
1249 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1251 return correct;
1254 /* Test 17c - like 17, but the initial delete on close is set on the second handle */
1255 static bool deltest17c(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1257 int fnum1 = -1;
1258 int fnum2 = -1;
1259 bool correct = true;
1261 del_clean_area(cli1, cli2);
1263 /* Ensure the file doesn't already exist. */
1264 smbcli_close(cli1->tree, fnum1);
1265 smbcli_close(cli1->tree, fnum2);
1266 smbcli_setatr(cli1->tree, fname, 0, 0);
1267 smbcli_unlink(cli1->tree, fname);
1269 /* Firstly open and create with all access */
1270 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1271 SEC_RIGHTS_FILE_ALL,
1272 FILE_ATTRIBUTE_NORMAL,
1273 NTCREATEX_SHARE_ACCESS_READ|
1274 NTCREATEX_SHARE_ACCESS_WRITE|
1275 NTCREATEX_SHARE_ACCESS_DELETE,
1276 NTCREATEX_DISP_CREATE,
1277 0, 0);
1278 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1279 fname, smbcli_errstr(cli1->tree)));
1281 /* And close - just to create the file. */
1282 smbcli_close(cli1->tree, fnum1);
1284 /* Next open with all access, but add delete on close. */
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_OPEN,
1292 0, 0);
1294 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1295 fname, smbcli_errstr(cli1->tree)));
1297 /* The delete on close bit is *not* reported as being set. */
1298 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1300 /* Now try opening again for read-only. */
1301 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1302 SEC_RIGHTS_FILE_READ|
1303 SEC_STD_DELETE,
1304 FILE_ATTRIBUTE_NORMAL,
1305 NTCREATEX_SHARE_ACCESS_READ|
1306 NTCREATEX_SHARE_ACCESS_WRITE|
1307 NTCREATEX_SHARE_ACCESS_DELETE,
1308 NTCREATEX_DISP_OPEN,
1309 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1311 /* Should work. */
1312 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1313 fname, smbcli_errstr(cli1->tree)));
1315 /* still not reported as being set on either */
1316 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1317 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1319 smbcli_close(cli1->tree, fnum2);
1321 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
1323 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1324 torture_assert(tctx, fnum2 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1325 fname));
1327 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1329 smbcli_close(cli1->tree, fnum1);
1331 /* Make sure the file has been deleted */
1332 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1333 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1334 fname));
1336 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1338 return correct;
1341 /* Test 17d - like 17a, but the first delete-on-close opener creates the file */
1342 static bool deltest17d(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1344 int fnum1 = -1;
1345 int fnum2 = -1;
1346 bool correct = true;
1348 del_clean_area(cli1, cli2);
1350 /* Ensure the file doesn't already exist. */
1351 smbcli_close(cli1->tree, fnum1);
1352 smbcli_close(cli1->tree, fnum2);
1353 smbcli_setatr(cli1->tree, fname, 0, 0);
1354 smbcli_unlink(cli1->tree, fname);
1357 /* Create the file with delete on close. */
1358 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1359 SEC_RIGHTS_FILE_ALL,
1360 FILE_ATTRIBUTE_NORMAL,
1361 NTCREATEX_SHARE_ACCESS_READ|
1362 NTCREATEX_SHARE_ACCESS_WRITE|
1363 NTCREATEX_SHARE_ACCESS_DELETE,
1364 NTCREATEX_DISP_CREATE,
1365 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1367 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1368 fname, smbcli_errstr(cli1->tree)));
1370 /* The delete on close bit is *not* reported as being set. */
1371 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1373 /* Now try opening again for read-only. */
1374 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1375 SEC_RIGHTS_FILE_READ|
1376 SEC_STD_DELETE,
1377 FILE_ATTRIBUTE_NORMAL,
1378 NTCREATEX_SHARE_ACCESS_READ|
1379 NTCREATEX_SHARE_ACCESS_WRITE|
1380 NTCREATEX_SHARE_ACCESS_DELETE,
1381 NTCREATEX_DISP_OPEN,
1382 0, 0);
1384 /* Should work. */
1385 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1386 fname, smbcli_errstr(cli1->tree)));
1388 /* still not reported as being set on either */
1389 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1390 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1392 smbcli_close(cli1->tree, fnum2);
1394 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1396 smbcli_close(cli1->tree, fnum1);
1399 * The file is still there:
1400 * The second open seems to have removed the initial
1401 * delete on close flag from the first handle
1403 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1404 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeed (should fail)",
1405 fname));
1407 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1409 return correct;
1412 static bool deltest17e(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1414 int fnum1 = -1;
1415 int fnum2 = -1;
1416 int fnum3 = -1;
1417 bool correct = true;
1419 del_clean_area(cli1, cli2);
1421 /* Ensure the file doesn't already exist. */
1422 smbcli_close(cli1->tree, fnum1);
1423 smbcli_close(cli1->tree, fnum2);
1424 smbcli_setatr(cli1->tree, fname, 0, 0);
1425 smbcli_unlink(cli1->tree, fname);
1427 /* Firstly open and create with all access */
1428 fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1429 SEC_RIGHTS_FILE_ALL,
1430 FILE_ATTRIBUTE_NORMAL,
1431 NTCREATEX_SHARE_ACCESS_READ|
1432 NTCREATEX_SHARE_ACCESS_WRITE|
1433 NTCREATEX_SHARE_ACCESS_DELETE,
1434 NTCREATEX_DISP_CREATE,
1435 0, 0);
1436 torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1437 fname, smbcli_errstr(cli1->tree)));
1439 /* Next open with all access, but add delete on close. */
1440 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1441 SEC_RIGHTS_FILE_ALL,
1442 FILE_ATTRIBUTE_NORMAL,
1443 NTCREATEX_SHARE_ACCESS_READ|
1444 NTCREATEX_SHARE_ACCESS_WRITE|
1445 NTCREATEX_SHARE_ACCESS_DELETE,
1446 NTCREATEX_DISP_OPEN,
1447 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1449 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1450 fname, smbcli_errstr(cli1->tree)));
1452 /* The delete on close bit is *not* reported as being set. */
1453 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1454 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1456 /* Now try opening again for read-only. */
1457 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1458 SEC_RIGHTS_FILE_READ|
1459 SEC_STD_DELETE,
1460 FILE_ATTRIBUTE_NORMAL,
1461 NTCREATEX_SHARE_ACCESS_READ|
1462 NTCREATEX_SHARE_ACCESS_WRITE|
1463 NTCREATEX_SHARE_ACCESS_DELETE,
1464 NTCREATEX_DISP_OPEN,
1465 0, 0);
1467 /* Should work. */
1468 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1469 fname, smbcli_errstr(cli1->tree)));
1471 /* still not reported as being set on either */
1472 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1473 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1474 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1476 smbcli_close(cli1->tree, fnum1);
1479 * closing the handle that has delete_on_close set
1480 * inherits the flag to the global context
1482 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1483 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1485 smbcli_close(cli1->tree, fnum2);
1487 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1489 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1490 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1491 fname));
1493 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1495 smbcli_close(cli1->tree, fnum3);
1497 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1498 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1499 fname));
1501 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1503 return correct;
1506 static bool deltest17f(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1508 int fnum1 = -1;
1509 int fnum2 = -1;
1510 int fnum3 = -1;
1511 bool correct = true;
1512 NTSTATUS status;
1514 del_clean_area(cli1, cli2);
1516 /* Ensure the file doesn't already exist. */
1517 smbcli_close(cli1->tree, fnum1);
1518 smbcli_close(cli1->tree, fnum2);
1519 smbcli_setatr(cli1->tree, fname, 0, 0);
1520 smbcli_unlink(cli1->tree, fname);
1522 /* Firstly open and create with all access */
1523 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1524 SEC_RIGHTS_FILE_ALL,
1525 FILE_ATTRIBUTE_NORMAL,
1526 NTCREATEX_SHARE_ACCESS_READ|
1527 NTCREATEX_SHARE_ACCESS_WRITE|
1528 NTCREATEX_SHARE_ACCESS_DELETE,
1529 NTCREATEX_DISP_CREATE,
1530 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1531 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1532 fname, smbcli_errstr(cli1->tree)));
1534 /* The delete on close bit is *not* reported as being set. */
1535 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1537 /* Next open with all access, but add delete on close. */
1538 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1539 SEC_RIGHTS_FILE_ALL,
1540 FILE_ATTRIBUTE_NORMAL,
1541 NTCREATEX_SHARE_ACCESS_READ|
1542 NTCREATEX_SHARE_ACCESS_WRITE|
1543 NTCREATEX_SHARE_ACCESS_DELETE,
1544 NTCREATEX_DISP_OPEN,
1545 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1547 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1548 fname, smbcli_errstr(cli1->tree)));
1550 /* still not reported as being set on either */
1551 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1552 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1554 /* Now try opening again for read-only. */
1555 fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1556 SEC_RIGHTS_FILE_READ|
1557 SEC_STD_DELETE,
1558 FILE_ATTRIBUTE_NORMAL,
1559 NTCREATEX_SHARE_ACCESS_READ|
1560 NTCREATEX_SHARE_ACCESS_WRITE|
1561 NTCREATEX_SHARE_ACCESS_DELETE,
1562 NTCREATEX_DISP_OPEN,
1563 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1565 /* Should work. */
1566 torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1567 fname, smbcli_errstr(cli1->tree)));
1569 /* still not reported as being set on either */
1570 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1571 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1572 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1574 smbcli_close(cli1->tree, fnum1);
1577 * closing the handle that has delete_on_close set
1578 * inherits the flag to the global context
1580 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1581 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1584 status = smbcli_nt_delete_on_close(cli1->tree, fnum2, false);
1585 torture_assert_ntstatus_ok(tctx, status,
1586 "clearing delete_on_close on file failed !");
1588 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1589 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1591 smbcli_close(cli1->tree, fnum2);
1593 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1595 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1596 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1597 fname));
1599 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1601 smbcli_close(cli1->tree, fnum3);
1603 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1604 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1605 fname));
1607 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1609 return correct;
1612 /* Test 18 ... */
1613 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1615 int fnum1 = -1;
1616 int fnum2 = -1;
1617 bool correct = true;
1619 del_clean_area(cli1, cli2);
1621 /* Test 18. With directories. */
1623 /* Ensure the file doesn't already exist. */
1624 smbcli_close(cli1->tree, fnum1);
1625 smbcli_close(cli1->tree, fnum2);
1627 smbcli_deltree(cli1->tree, dname);
1629 /* Firstly create with all access, but delete on close. */
1630 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1631 SEC_FILE_READ_DATA|
1632 SEC_FILE_WRITE_DATA|
1633 SEC_STD_DELETE,
1634 FILE_ATTRIBUTE_DIRECTORY,
1635 NTCREATEX_SHARE_ACCESS_READ|
1636 NTCREATEX_SHARE_ACCESS_WRITE|
1637 NTCREATEX_SHARE_ACCESS_DELETE,
1638 NTCREATEX_DISP_CREATE,
1639 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1641 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1642 dname, smbcli_errstr(cli1->tree)));
1645 * The delete on close bit is *not* reported as being set.
1646 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1647 * close as being set. This causes the subsequent create to fail with
1648 * NT_STATUS_DELETE_PENDING.
1650 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1652 /* Now try opening again for read-only. */
1653 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1654 SEC_RIGHTS_FILE_READ,
1655 FILE_ATTRIBUTE_DIRECTORY,
1656 NTCREATEX_SHARE_ACCESS_READ|
1657 NTCREATEX_SHARE_ACCESS_WRITE|
1658 NTCREATEX_SHARE_ACCESS_DELETE,
1659 NTCREATEX_DISP_OPEN,
1660 NTCREATEX_OPTIONS_DIRECTORY, 0);
1663 /* Should work. */
1664 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1665 dname, smbcli_errstr(cli1->tree)));
1667 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1668 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, false, __location__);
1670 smbcli_close(cli1->tree, fnum1);
1672 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1674 smbcli_close(cli1->tree, fnum2);
1676 /* And the directory should be deleted ! */
1677 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1678 SEC_RIGHTS_FILE_READ,
1679 FILE_ATTRIBUTE_DIRECTORY,
1680 NTCREATEX_SHARE_ACCESS_READ|
1681 NTCREATEX_SHARE_ACCESS_WRITE|
1682 NTCREATEX_SHARE_ACCESS_DELETE,
1683 NTCREATEX_DISP_OPEN,
1684 NTCREATEX_OPTIONS_DIRECTORY, 0);
1685 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
1686 dname));
1688 return correct;
1691 /* Test 19 ... */
1692 static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1694 int fnum1 = -1;
1695 int fnum2 = -1;
1696 bool correct = true;
1698 del_clean_area(cli1, cli2);
1700 /* Test 19. */
1702 smbcli_deltree(cli1->tree, dname);
1704 /* Firstly open and create with all access */
1705 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1706 SEC_FILE_READ_DATA|
1707 SEC_FILE_WRITE_DATA|
1708 SEC_STD_DELETE,
1709 FILE_ATTRIBUTE_DIRECTORY,
1710 NTCREATEX_SHARE_ACCESS_READ|
1711 NTCREATEX_SHARE_ACCESS_WRITE|
1712 NTCREATEX_SHARE_ACCESS_DELETE,
1713 NTCREATEX_DISP_CREATE,
1714 NTCREATEX_OPTIONS_DIRECTORY, 0);
1716 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1717 dname, smbcli_errstr(cli1->tree)));
1719 /* And close - just to create the directory. */
1720 smbcli_close(cli1->tree, fnum1);
1722 /* Next open with all access, but add delete on close. */
1723 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1724 SEC_FILE_READ_DATA|
1725 SEC_FILE_WRITE_DATA|
1726 SEC_STD_DELETE,
1727 FILE_ATTRIBUTE_DIRECTORY,
1728 NTCREATEX_SHARE_ACCESS_READ|
1729 NTCREATEX_SHARE_ACCESS_WRITE|
1730 NTCREATEX_SHARE_ACCESS_DELETE,
1731 NTCREATEX_DISP_OPEN,
1732 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1734 torture_assert(tctx, fnum1 != -1,
1735 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1738 * The delete on close bit is *not* reported as being set.
1739 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1740 * close as being set. This causes the subsequent create to fail with
1741 * NT_STATUS_DELETE_PENDING.
1743 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1745 /* Now try opening again for read-only. */
1746 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1747 SEC_RIGHTS_FILE_READ,
1748 FILE_ATTRIBUTE_DIRECTORY,
1749 NTCREATEX_SHARE_ACCESS_READ|
1750 NTCREATEX_SHARE_ACCESS_WRITE|
1751 NTCREATEX_SHARE_ACCESS_DELETE,
1752 NTCREATEX_DISP_OPEN,
1753 NTCREATEX_OPTIONS_DIRECTORY, 0);
1755 /* Should work. */
1756 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1757 dname, smbcli_errstr(cli1->tree)));
1759 smbcli_close(cli1->tree, fnum1);
1761 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1763 smbcli_close(cli1->tree, fnum2);
1765 /* See if the file is deleted - for a directory this seems to be true ! */
1766 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1767 SEC_RIGHTS_FILE_READ,
1768 FILE_ATTRIBUTE_DIRECTORY,
1769 NTCREATEX_SHARE_ACCESS_READ|
1770 NTCREATEX_SHARE_ACCESS_WRITE|
1771 NTCREATEX_SHARE_ACCESS_DELETE,
1772 NTCREATEX_DISP_OPEN,
1773 NTCREATEX_OPTIONS_DIRECTORY, 0);
1775 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1777 torture_assert(tctx, fnum1 == -1,
1778 talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1780 return correct;
1783 /* Test 20 ... */
1784 static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1786 int fnum1 = -1;
1787 int dnum1 = -1;
1788 bool correct = true;
1789 NTSTATUS status;
1790 int ret;
1792 del_clean_area(cli1, cli2);
1794 /* Test 20 -- non-empty directory hardest to get right... */
1796 smbcli_deltree(cli1->tree, dname);
1798 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1799 SEC_FILE_READ_DATA|
1800 SEC_FILE_WRITE_DATA|
1801 SEC_STD_DELETE,
1802 FILE_ATTRIBUTE_DIRECTORY,
1803 NTCREATEX_SHARE_ACCESS_READ|
1804 NTCREATEX_SHARE_ACCESS_WRITE|
1805 NTCREATEX_SHARE_ACCESS_DELETE,
1806 NTCREATEX_DISP_CREATE,
1807 NTCREATEX_OPTIONS_DIRECTORY, 0);
1808 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
1809 dname, smbcli_errstr(cli1->tree)));
1811 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
1812 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1815 char *fullname;
1816 ret = asprintf(&fullname, "\\%s%s", dname, fname);
1817 torture_assert(tctx, ret != -1, "asprintf failed");
1818 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1819 DENY_NONE);
1820 torture_assert(tctx, fnum1 == -1,
1821 "smbcli_open succeeded, should have "
1822 "failed with NT_STATUS_DELETE_PENDING"
1825 torture_assert_ntstatus_equal(tctx,
1826 smbcli_nt_error(cli1->tree),
1827 NT_STATUS_DELETE_PENDING,
1828 "smbcli_open failed");
1831 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, false);
1832 torture_assert_ntstatus_ok(tctx, status,
1833 "unsetting delete_on_close on file failed !");
1836 char *fullname;
1837 ret = asprintf(&fullname, "\\%s%s", dname, fname);
1838 torture_assert(tctx, ret != -1, "asprintf failed");
1839 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1840 DENY_NONE);
1841 torture_assert(tctx, fnum1 != -1,
1842 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1843 smbcli_errstr(cli1->tree)));
1844 smbcli_close(cli1->tree, fnum1);
1847 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1849 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1850 "setting delete_on_close failed");
1851 smbcli_close(cli1->tree, dnum1);
1853 return correct;
1856 /* Test 20a ... */
1857 static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1859 int fnum1 = -1;
1860 int fnum2 = -1;
1861 bool correct = true;
1863 del_clean_area(cli1, cli2);
1865 /* Test 20a. */
1867 /* Ensure the file doesn't already exist. */
1868 smbcli_close(cli1->tree, fnum1);
1869 smbcli_close(cli1->tree, fnum2);
1870 smbcli_setatr(cli1->tree, fname, 0, 0);
1871 smbcli_unlink(cli1->tree, fname);
1873 /* Firstly open and create with all access */
1874 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1875 SEC_RIGHTS_FILE_ALL,
1876 FILE_ATTRIBUTE_NORMAL,
1877 NTCREATEX_SHARE_ACCESS_READ|
1878 NTCREATEX_SHARE_ACCESS_WRITE|
1879 NTCREATEX_SHARE_ACCESS_DELETE,
1880 NTCREATEX_DISP_CREATE,
1881 0, 0);
1882 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1883 fname, smbcli_errstr(cli1->tree)));
1885 /* Next open with all access, but add delete on close. */
1886 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1887 SEC_RIGHTS_FILE_ALL,
1888 FILE_ATTRIBUTE_NORMAL,
1889 NTCREATEX_SHARE_ACCESS_READ|
1890 NTCREATEX_SHARE_ACCESS_WRITE|
1891 NTCREATEX_SHARE_ACCESS_DELETE,
1892 NTCREATEX_DISP_OPEN,
1893 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1895 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1896 fname, smbcli_errstr(cli2->tree)));
1898 /* The delete on close bit is *not* reported as being set. */
1899 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1900 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1902 smbcli_close(cli1->tree, fnum1);
1904 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1906 smbcli_close(cli2->tree, fnum2);
1908 /* See if the file is deleted - should be.... */
1909 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1910 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1911 fname, smbcli_errstr(cli1->tree)));
1913 return correct;
1916 /* Test 20b ... */
1917 /* This is the delete semantics that the cifsfs client depends on when
1918 * trying to delete an open file on a Windows server. It
1919 * opens a file with initial delete on close set, renames it then closes
1920 * all open handles. The file goes away on Windows.
1923 static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1925 int fnum1 = -1;
1926 int fnum2 = -1;
1927 bool correct = true;
1929 del_clean_area(cli1, cli2);
1931 /* Test 20b. */
1933 /* Ensure the file doesn't already exist. */
1934 smbcli_close(cli1->tree, fnum1);
1935 smbcli_close(cli1->tree, fnum2);
1936 smbcli_setatr(cli1->tree, fname, 0, 0);
1937 smbcli_unlink(cli1->tree, fname);
1938 smbcli_setatr(cli1->tree, fname_new, 0, 0);
1939 smbcli_unlink(cli1->tree, fname_new);
1941 /* Firstly open and create with all access */
1942 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1943 SEC_RIGHTS_FILE_ALL,
1944 FILE_ATTRIBUTE_NORMAL,
1945 NTCREATEX_SHARE_ACCESS_READ|
1946 NTCREATEX_SHARE_ACCESS_WRITE|
1947 NTCREATEX_SHARE_ACCESS_DELETE,
1948 NTCREATEX_DISP_CREATE,
1949 0, 0);
1950 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1951 fname, smbcli_errstr(cli1->tree)));
1953 /* And close - just to create the file. */
1954 smbcli_close(cli1->tree, fnum1);
1956 /* Firstly open and create with all access */
1957 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1958 SEC_RIGHTS_FILE_ALL,
1959 FILE_ATTRIBUTE_NORMAL,
1960 NTCREATEX_SHARE_ACCESS_READ|
1961 NTCREATEX_SHARE_ACCESS_WRITE|
1962 NTCREATEX_SHARE_ACCESS_DELETE,
1963 NTCREATEX_DISP_OPEN,
1964 0, 0);
1965 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1966 fname, smbcli_errstr(cli1->tree)));
1968 /* Next open with all access, but add delete on close. */
1969 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1970 SEC_RIGHTS_FILE_ALL,
1971 FILE_ATTRIBUTE_NORMAL,
1972 NTCREATEX_SHARE_ACCESS_READ|
1973 NTCREATEX_SHARE_ACCESS_WRITE|
1974 NTCREATEX_SHARE_ACCESS_DELETE,
1975 NTCREATEX_DISP_OPEN,
1976 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1978 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1979 fname, smbcli_errstr(cli2->tree)));
1981 /* The delete on close bit is *not* reported as being set. */
1982 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1983 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1985 smbcli_close(cli1->tree, fnum1);
1987 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1989 /* Rename the file by handle. */
1992 union smb_setfileinfo sfinfo;
1993 NTSTATUS status;
1995 memset(&sfinfo, '\0', sizeof(sfinfo));
1996 sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
1997 sfinfo.generic.in.file.fnum = fnum2;
1998 sfinfo.rename_information.in.root_fid = 0;
1999 /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
2000 sfinfo.rename_information.in.new_name = fname_new + 1;
2001 sfinfo.rename_information.in.overwrite = 1;
2003 status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
2005 torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
2006 fname, fname_new, smbcli_errstr(cli2->tree)));
2009 correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, false, __location__);
2011 smbcli_close(cli2->tree, fnum2);
2013 /* See if the file is deleted - should be.... */
2014 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2015 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
2016 fname, smbcli_errstr(cli1->tree)));
2017 fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
2018 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
2019 fname_new, smbcli_errstr(cli1->tree)));
2021 return correct;
2025 /* Test 21 ... */
2026 static bool deltest21(struct torture_context *tctx)
2028 int fnum1 = -1;
2029 struct smbcli_state *cli1;
2030 struct smbcli_state *cli2;
2031 bool correct = true;
2033 if (!torture_open_connection(&cli1, tctx, 0))
2034 return false;
2036 if (!torture_open_connection(&cli2, tctx, 1))
2037 return false;
2039 del_clean_area(cli1, cli2);
2041 /* Test 21 -- Test removal of file after socket close. */
2043 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2044 SEC_RIGHTS_FILE_ALL,
2045 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
2046 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2048 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
2049 fname, smbcli_errstr(cli1->tree)));
2051 torture_assert_ntstatus_ok(tctx,
2052 smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
2053 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2054 smbcli_errstr(cli1->tree)));
2056 /* Ensure delete on close is set. */
2057 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
2059 /* Now yank the rug from under cli1. */
2060 smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
2062 fnum1 = -1;
2064 if (!torture_open_connection(&cli1, tctx, 0)) {
2065 return false;
2068 /* On slow build farm machines it might happen that they are not fast
2069 * enogh to delete the file for this test */
2070 smb_msleep(200);
2072 /* File should not be there. */
2073 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2074 SEC_RIGHTS_FILE_READ,
2075 FILE_ATTRIBUTE_NORMAL,
2076 NTCREATEX_SHARE_ACCESS_READ|
2077 NTCREATEX_SHARE_ACCESS_WRITE|
2078 NTCREATEX_SHARE_ACCESS_DELETE,
2079 NTCREATEX_DISP_OPEN,
2080 0, 0);
2082 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2084 return correct;
2087 /* Test 22 ... */
2090 * Test whether a second *directory* handle inhibits delete if the first has
2091 * del-on-close set and is closed
2093 static bool deltest22(struct torture_context *tctx)
2095 int dnum1 = -1;
2096 int dnum2 = -1;
2097 struct smbcli_state *cli1;
2098 bool correct = true;
2100 if (!torture_open_connection(&cli1, tctx, 0))
2101 return false;
2103 smbcli_deltree(cli1->tree, dname);
2105 torture_assert_ntstatus_ok(
2106 tctx, smbcli_mkdir(cli1->tree, dname),
2107 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
2108 smbcli_errstr(cli1->tree)));
2110 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2111 SEC_FILE_READ_DATA|
2112 SEC_FILE_WRITE_DATA|
2113 SEC_STD_DELETE,
2114 FILE_ATTRIBUTE_DIRECTORY,
2115 NTCREATEX_SHARE_ACCESS_READ|
2116 NTCREATEX_SHARE_ACCESS_WRITE|
2117 NTCREATEX_SHARE_ACCESS_DELETE,
2118 NTCREATEX_DISP_OPEN,
2119 NTCREATEX_OPTIONS_DIRECTORY, 0);
2121 torture_assert(tctx, dnum1 != -1,
2122 talloc_asprintf(tctx, "open of %s failed: %s!",
2123 dname, smbcli_errstr(cli1->tree)));
2125 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2126 SEC_FILE_READ_DATA|
2127 SEC_FILE_WRITE_DATA,
2128 FILE_ATTRIBUTE_DIRECTORY,
2129 NTCREATEX_SHARE_ACCESS_READ|
2130 NTCREATEX_SHARE_ACCESS_WRITE|
2131 NTCREATEX_SHARE_ACCESS_DELETE,
2132 NTCREATEX_DISP_OPEN,
2133 NTCREATEX_OPTIONS_DIRECTORY, 0);
2135 torture_assert(tctx, dnum2 != -1,
2136 talloc_asprintf(tctx, "open of %s failed: %s!",
2137 dname, smbcli_errstr(cli1->tree)));
2139 torture_assert_ntstatus_ok(
2140 tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
2141 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2142 smbcli_errstr(cli1->tree)));
2144 smbcli_close(cli1->tree, dnum1);
2146 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2147 SEC_FILE_READ_DATA|
2148 SEC_FILE_WRITE_DATA|
2149 SEC_STD_DELETE,
2150 FILE_ATTRIBUTE_DIRECTORY,
2151 NTCREATEX_SHARE_ACCESS_READ|
2152 NTCREATEX_SHARE_ACCESS_WRITE|
2153 NTCREATEX_SHARE_ACCESS_DELETE,
2154 NTCREATEX_DISP_OPEN,
2155 NTCREATEX_OPTIONS_DIRECTORY, 0);
2157 torture_assert(tctx, dnum1 == -1,
2158 talloc_asprintf(tctx, "open of %s succeeded!\n",
2159 dname));
2161 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
2163 smbcli_close(cli1->tree, dnum2);
2164 CHECK_STATUS(cli1, NT_STATUS_OK);
2166 return correct;
2169 /* Test 23 - Second directory open fails when delete is pending. */
2170 static bool deltest23(struct torture_context *tctx,
2171 struct smbcli_state *cli1,
2172 struct smbcli_state *cli2)
2174 int dnum1 = -1;
2175 int dnum2 = -1;
2176 bool correct = true;
2178 del_clean_area(cli1, cli2);
2180 /* Test 23 -- Basic delete on close for directories. */
2182 /* Open a directory */
2183 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2184 SEC_FILE_READ_DATA|
2185 SEC_FILE_WRITE_DATA|
2186 SEC_STD_DELETE,
2187 FILE_ATTRIBUTE_DIRECTORY,
2188 NTCREATEX_SHARE_ACCESS_READ|
2189 NTCREATEX_SHARE_ACCESS_WRITE|
2190 NTCREATEX_SHARE_ACCESS_DELETE,
2191 NTCREATEX_DISP_CREATE,
2192 NTCREATEX_OPTIONS_DIRECTORY, 0);
2194 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx,
2195 "open of %s failed: %s!",
2196 dname, smbcli_errstr(cli1->tree)));
2198 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false,
2199 __location__);
2201 /* Set delete on close */
2202 (void)smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
2204 /* Attempt opening the directory again. It should fail. */
2205 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2206 SEC_FILE_READ_DATA|
2207 SEC_FILE_WRITE_DATA|
2208 SEC_STD_DELETE,
2209 FILE_ATTRIBUTE_DIRECTORY,
2210 NTCREATEX_SHARE_ACCESS_READ|
2211 NTCREATEX_SHARE_ACCESS_WRITE|
2212 NTCREATEX_SHARE_ACCESS_DELETE,
2213 NTCREATEX_DISP_OPEN,
2214 NTCREATEX_OPTIONS_DIRECTORY, 0);
2216 torture_assert(tctx, dnum2 == -1, talloc_asprintf(tctx,
2217 "open of %s succeeded: %s. It should have failed "
2218 "with NT_STATUS_DELETE_PENDING",
2219 dname, smbcli_errstr(cli1->tree)));
2221 torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree),
2222 NT_STATUS_DELETE_PENDING, "smbcli_open failed");
2224 return true;
2227 /* Test 24 ... */
2230 * Test whether unsetting delete-on-close before the close has any effect.
2231 * It should be ignored.
2233 static bool deltest24(struct torture_context *tctx)
2235 int fnum1 = -1;
2236 struct smbcli_state *cli1;
2237 bool correct = true;
2239 if (!torture_open_connection(&cli1, tctx, 0))
2240 return false;
2242 smbcli_deltree(cli1->tree, fname);
2244 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2245 SEC_FILE_READ_DATA|
2246 SEC_FILE_WRITE_DATA|
2247 SEC_STD_DELETE,
2248 FILE_ATTRIBUTE_NORMAL,
2249 NTCREATEX_SHARE_ACCESS_READ|
2250 NTCREATEX_SHARE_ACCESS_WRITE|
2251 NTCREATEX_SHARE_ACCESS_DELETE,
2252 NTCREATEX_DISP_CREATE,
2253 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2255 torture_assert(tctx, fnum1 != -1,
2256 talloc_asprintf(tctx, "open of %s failed: %s!",
2257 fname, smbcli_errstr(cli1->tree)));
2259 /* Now, unset Delete-On-Close, but it should have no effect */
2260 torture_assert_ntstatus_ok(
2261 tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, false),
2262 talloc_asprintf(tctx, "unsetting delete_on_close failed (%s)",
2263 smbcli_errstr(cli1->tree)));
2265 smbcli_close(cli1->tree, fnum1);
2267 /* File should not be there. */
2268 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2269 SEC_RIGHTS_FILE_READ,
2270 FILE_ATTRIBUTE_NORMAL,
2271 NTCREATEX_SHARE_ACCESS_READ|
2272 NTCREATEX_SHARE_ACCESS_WRITE|
2273 NTCREATEX_SHARE_ACCESS_DELETE,
2274 NTCREATEX_DISP_OPEN,
2275 0, 0);
2277 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2279 return correct;
2283 Test delete on close semantics.
2285 struct torture_suite *torture_test_delete(TALLOC_CTX *ctx)
2287 struct torture_suite *suite = torture_suite_create(
2288 ctx, "delete");
2290 torture_suite_add_2smb_test(suite, "deltest1", deltest1);
2291 torture_suite_add_2smb_test(suite, "deltest2", deltest2);
2292 torture_suite_add_2smb_test(suite, "deltest3", deltest3);
2293 torture_suite_add_2smb_test(suite, "deltest4", deltest4);
2294 torture_suite_add_2smb_test(suite, "deltest5", deltest5);
2295 torture_suite_add_2smb_test(suite, "deltest6", deltest6);
2296 torture_suite_add_2smb_test(suite, "deltest7", deltest7);
2297 torture_suite_add_2smb_test(suite, "deltest8", deltest8);
2298 torture_suite_add_2smb_test(suite, "deltest9", deltest9);
2299 torture_suite_add_2smb_test(suite, "deltest10", deltest10);
2300 torture_suite_add_2smb_test(suite, "deltest11", deltest11);
2301 torture_suite_add_2smb_test(suite, "deltest12", deltest12);
2302 torture_suite_add_2smb_test(suite, "deltest13", deltest13);
2303 torture_suite_add_2smb_test(suite, "deltest14", deltest14);
2304 torture_suite_add_2smb_test(suite, "deltest15", deltest15);
2305 torture_suite_add_2smb_test(suite, "deltest16", deltest16);
2306 torture_suite_add_2smb_test(suite, "deltest16a", deltest16a);
2307 torture_suite_add_2smb_test(suite, "deltest17", deltest17);
2308 torture_suite_add_2smb_test(suite, "deltest17a", deltest17a);
2309 torture_suite_add_2smb_test(suite, "deltest17b", deltest17b);
2310 torture_suite_add_2smb_test(suite, "deltest17c", deltest17c);
2311 torture_suite_add_2smb_test(suite, "deltest17d", deltest17d);
2312 torture_suite_add_2smb_test(suite, "deltest17e", deltest17e);
2313 torture_suite_add_2smb_test(suite, "deltest17f", deltest17f);
2314 torture_suite_add_2smb_test(suite, "deltest18", deltest18);
2315 torture_suite_add_2smb_test(suite, "deltest19", deltest19);
2316 torture_suite_add_2smb_test(suite, "deltest20", deltest20);
2317 torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
2318 torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
2319 torture_suite_add_simple_test(suite, "deltest21", deltest21);
2320 torture_suite_add_simple_test(suite, "deltest22", deltest22);
2321 torture_suite_add_2smb_test(suite, "deltest23", deltest23);
2322 torture_suite_add_simple_test(suite, "deltest24", deltest24);
2324 return suite;