s4: torture: Test all combinations of directory create to ensure behavior is the...
[Samba.git] / source4 / torture / basic / delete.c
blob744ac6802d5fc1c36208ecf4caae564d3252eb1a
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;
480 uint32_t disps[4] = {
481 NTCREATEX_DISP_SUPERSEDE,
482 NTCREATEX_DISP_OVERWRITE_IF,
483 NTCREATEX_DISP_CREATE,
484 NTCREATEX_DISP_OPEN_IF};
485 unsigned int i;
487 del_clean_area(cli1, cli2);
489 for (i = 0; i < sizeof(disps)/sizeof(disps[0]); i++) {
490 /* This should fail - we need to set DELETE_ACCESS. */
493 * A file or directory create with DELETE_ON_CLOSE but
494 * without DELETE_ACCESS should fail with
495 * NT_STATUS_INVALID_PARAMETER.
498 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
499 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
500 FILE_ATTRIBUTE_NORMAL,
501 NTCREATEX_SHARE_ACCESS_NONE,
502 disps[i],
503 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
505 torture_assert(tctx, fnum1 == -1,
506 talloc_asprintf(tctx, "open of %s succeeded "
507 "should have failed!",
508 fname));
510 /* Must fail with NT_STATUS_INVALID_PARAMETER. */
511 status = smbcli_nt_error(cli1->tree);
512 torture_assert_ntstatus_equal(tctx,
513 status,
514 NT_STATUS_INVALID_PARAMETER,
515 talloc_asprintf(tctx, "create of %s should return "
516 "NT_STATUS_INVALID_PARAMETER, got %s",
517 fname,
518 smbcli_errstr(cli1->tree)));
520 /* This should fail - the file should not have been created. */
521 status = smbcli_getatr(cli1->tree, fname, NULL, NULL, NULL);
522 torture_assert_ntstatus_equal(tctx,
523 status,
524 NT_STATUS_OBJECT_NAME_NOT_FOUND,
525 talloc_asprintf(tctx, "getattr of %s succeeded should "
526 "not have been created !",
527 fname));
530 return true;
533 /* Test 9a ... */
534 static bool deltest9a(struct torture_context *tctx,
535 struct smbcli_state *cli1,
536 struct smbcli_state *cli2)
538 int fnum1 = -1;
539 NTSTATUS status;
540 uint32_t disps[4] = {
541 NTCREATEX_DISP_OVERWRITE_IF,
542 NTCREATEX_DISP_OPEN,
543 NTCREATEX_DISP_OVERWRITE,
544 NTCREATEX_DISP_OPEN_IF};
546 unsigned int i;
548 del_clean_area(cli1, cli2);
550 /* Create the file, and try with open calls. */
551 fnum1 = smbcli_open(cli1->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
552 torture_assert(tctx,
553 fnum1 != -1,
554 talloc_asprintf(tctx, "open of %s failed (%s)",
555 fname,
556 smbcli_errstr(cli1->tree)));
557 status = smbcli_close(cli1->tree, fnum1);
558 torture_assert_ntstatus_ok(tctx,
559 status,
560 talloc_asprintf(tctx, "close failed"));
562 for (i = 0; i < sizeof(disps)/sizeof(disps[0]); i++) {
563 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
564 SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
565 FILE_ATTRIBUTE_NORMAL,
566 NTCREATEX_SHARE_ACCESS_NONE,
567 disps[i],
568 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
570 torture_assert(tctx, fnum1 == -1,
571 talloc_asprintf(tctx, "open of %s succeeded "
572 "should have failed!",
573 fname));
575 /* Must fail with NT_STATUS_INVALID_PARAMETER. */
576 status = smbcli_nt_error(cli1->tree);
577 torture_assert_ntstatus_equal(tctx,
578 status,
579 NT_STATUS_INVALID_PARAMETER,
580 talloc_asprintf(tctx, "create of %s should return "
581 "NT_STATUS_INVALID_PARAMETER, got %s",
582 fname,
583 smbcli_errstr(cli1->tree)));
586 * This should succeed - the file should not have been deleted.
588 status = smbcli_getatr(cli1->tree, fname, NULL, NULL, NULL);
589 torture_assert_ntstatus_ok(tctx,
590 status,
591 talloc_asprintf(tctx, "getattr of %s failed %s",
592 fname,
593 smbcli_errstr(cli1->tree)));
596 del_clean_area(cli1, cli2);
597 return true;
600 /* Test 10 ... */
601 static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
603 int fnum1 = -1;
605 del_clean_area(cli1, cli2);
607 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
608 SEC_FILE_READ_DATA|
609 SEC_FILE_WRITE_DATA|
610 SEC_STD_DELETE,
611 FILE_ATTRIBUTE_NORMAL,
612 NTCREATEX_SHARE_ACCESS_NONE,
613 NTCREATEX_DISP_OVERWRITE_IF,
614 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
615 torture_assert(tctx, fnum1 != -1,
616 talloc_asprintf(tctx, "open of %s failed (%s)",
617 fname, smbcli_errstr(cli1->tree)));
619 /* This should delete the file. */
620 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
621 talloc_asprintf(tctx, "close failed (%s)",
622 smbcli_errstr(cli1->tree)));
624 /* This should fail.. */
625 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
626 torture_assert(tctx, fnum1 == -1,
627 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
628 fname));
629 return true;
632 /* Test 11 ... */
633 static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
635 int fnum1 = -1;
636 NTSTATUS status;
638 del_clean_area(cli1, cli2);
640 /* test 11 - does having read only attribute still allow delete on close. */
642 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
643 SEC_RIGHTS_FILE_ALL,
644 FILE_ATTRIBUTE_READONLY,
645 NTCREATEX_SHARE_ACCESS_NONE,
646 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
648 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
649 fname, smbcli_errstr(cli1->tree)));
651 status = smbcli_nt_delete_on_close(cli1->tree, fnum1, true);
653 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
654 talloc_asprintf(tctx, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1->tree)));
656 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
657 talloc_asprintf(tctx, "close failed (%s)",
658 smbcli_errstr(cli1->tree)));
660 return true;
663 /* Test 12 ... */
664 static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
666 int fnum1 = -1;
667 NTSTATUS status;
669 del_clean_area(cli1, cli2);
671 /* test 12 - does having read only attribute still allow delete on
672 * close at time of open. */
674 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
675 SEC_RIGHTS_FILE_ALL,
676 FILE_ATTRIBUTE_READONLY,
677 NTCREATEX_SHARE_ACCESS_DELETE,
678 NTCREATEX_DISP_OVERWRITE_IF,
679 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
681 torture_assert(tctx, fnum1 == -1,
682 talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
683 "NT_STATUS_CANNOT_DELETE.\n", fname));
685 status = smbcli_nt_error(cli1->tree);
686 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
687 talloc_asprintf(tctx, "setting delete_on_close on open should "
688 "fail with NT_STATUS_CANNOT_DELETE. Got %s "
689 "instead)",
690 smbcli_errstr(cli1->tree)));
692 return true;
695 /* Test 13 ... */
696 static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
698 int fnum1 = -1;
699 int fnum2 = -1;
700 bool correct = true;
702 del_clean_area(cli1, cli2);
704 /* Test 13: Does resetting the delete on close flag affect a second
705 * fd? */
707 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
708 SEC_FILE_READ_DATA|
709 SEC_FILE_WRITE_DATA|
710 SEC_STD_DELETE,
711 FILE_ATTRIBUTE_NORMAL,
712 NTCREATEX_SHARE_ACCESS_READ|
713 NTCREATEX_SHARE_ACCESS_WRITE|
714 NTCREATEX_SHARE_ACCESS_DELETE,
715 NTCREATEX_DISP_OVERWRITE_IF,
716 0, 0);
718 torture_assert(tctx, fnum1 != -1,
719 talloc_asprintf(tctx, "open of %s failed (%s)",
720 fname, smbcli_errstr(cli1->tree)));
722 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
723 SEC_FILE_READ_DATA|
724 SEC_FILE_WRITE_DATA|
725 SEC_STD_DELETE,
726 FILE_ATTRIBUTE_NORMAL,
727 NTCREATEX_SHARE_ACCESS_READ|
728 NTCREATEX_SHARE_ACCESS_WRITE|
729 NTCREATEX_SHARE_ACCESS_DELETE,
730 NTCREATEX_DISP_OPEN, 0, 0);
732 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
733 "open of %s failed (%s)",
734 fname, smbcli_errstr(cli2->tree)));
736 torture_assert_ntstatus_ok(tctx,
737 smbcli_nt_delete_on_close(cli1->tree, fnum1,
738 true),
739 "setting delete_on_close on file failed !");
741 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
742 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
744 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
745 false),
746 "unsetting delete_on_close on file failed !");
748 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
749 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
751 torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
752 talloc_asprintf(tctx, "close - 1 failed (%s)",
753 smbcli_errstr(cli1->tree)));
755 torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
756 talloc_asprintf(tctx, "close - 2 failed (%s)",
757 smbcli_errstr(cli2->tree)));
759 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
761 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!",
762 fname));
764 smbcli_close(cli1->tree, fnum1);
766 return correct;
769 /* Test 14 ... */
770 static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
772 int dnum1 = -1;
773 bool correct = true;
775 del_clean_area(cli1, cli2);
777 /* Test 14 -- directory */
779 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
780 SEC_FILE_READ_DATA|
781 SEC_FILE_WRITE_DATA|
782 SEC_STD_DELETE,
783 FILE_ATTRIBUTE_DIRECTORY,
784 NTCREATEX_SHARE_ACCESS_READ|
785 NTCREATEX_SHARE_ACCESS_WRITE|
786 NTCREATEX_SHARE_ACCESS_DELETE,
787 NTCREATEX_DISP_CREATE, 0, 0);
788 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
789 dname, smbcli_errstr(cli1->tree)));
791 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
792 torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
793 "setting delete_on_close on file failed !");
794 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, true, __location__);
795 smbcli_close(cli1->tree, dnum1);
797 /* Now it should be gone... */
799 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
800 SEC_FILE_READ_DATA|
801 SEC_FILE_WRITE_DATA|
802 SEC_STD_DELETE,
803 FILE_ATTRIBUTE_DIRECTORY,
804 NTCREATEX_SHARE_ACCESS_READ|
805 NTCREATEX_SHARE_ACCESS_WRITE|
806 NTCREATEX_SHARE_ACCESS_DELETE,
807 NTCREATEX_DISP_OPEN, 0, 0);
808 torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
810 return correct;
813 /* Test 15 ... */
814 static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
816 int fnum1 = -1;
817 bool correct = true;
818 int fnum2 = -1;
819 NTSTATUS status;
821 del_clean_area(cli1, cli2);
823 /* Test 15: delete on close under rename */
825 smbcli_setatr(cli1->tree, fname, 0, 0);
826 smbcli_unlink(cli1->tree, fname);
827 smbcli_unlink(cli1->tree, fname_new);
829 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
830 SEC_FILE_READ_DATA,
831 FILE_ATTRIBUTE_NORMAL,
832 NTCREATEX_SHARE_ACCESS_READ|
833 NTCREATEX_SHARE_ACCESS_WRITE|
834 NTCREATEX_SHARE_ACCESS_DELETE,
835 NTCREATEX_DISP_OVERWRITE_IF,
836 0, 0);
838 torture_assert(tctx, fnum1 != -1,
839 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
841 status = smbcli_rename(cli2->tree, fname, fname_new);
843 torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
845 fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
846 SEC_GENERIC_ALL,
847 FILE_ATTRIBUTE_NORMAL,
848 NTCREATEX_SHARE_ACCESS_READ|
849 NTCREATEX_SHARE_ACCESS_WRITE|
850 NTCREATEX_SHARE_ACCESS_DELETE,
851 NTCREATEX_DISP_OVERWRITE_IF,
852 0, 0);
854 torture_assert(tctx, fnum2 != -1,
855 talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
856 fname_new, smbcli_errstr(cli1->tree)));
858 status = smbcli_nt_delete_on_close(cli2->tree, fnum2, true);
860 torture_assert_ntstatus_ok(tctx, status,
861 "setting delete_on_close on file failed !");
863 smbcli_close(cli2->tree, fnum2);
865 /* The file should be around under the new name, there's a second
866 * handle open */
868 correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, true, __location__);
870 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
871 SEC_GENERIC_ALL,
872 FILE_ATTRIBUTE_NORMAL,
873 NTCREATEX_SHARE_ACCESS_READ|
874 NTCREATEX_SHARE_ACCESS_WRITE|
875 NTCREATEX_SHARE_ACCESS_DELETE,
876 NTCREATEX_DISP_OVERWRITE_IF,
877 0, 0);
879 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
880 fname, smbcli_errstr(cli1->tree)));
882 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
884 smbcli_close(cli2->tree, fnum2);
885 smbcli_close(cli1->tree, fnum1);
887 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
888 SEC_FILE_READ_EA,
889 FILE_ATTRIBUTE_NORMAL,
890 NTCREATEX_SHARE_ACCESS_READ|
891 NTCREATEX_SHARE_ACCESS_WRITE|
892 NTCREATEX_SHARE_ACCESS_DELETE,
893 NTCREATEX_DISP_OPEN,
894 0, 0);
896 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
897 fname, smbcli_errstr(cli1->tree)));
899 smbcli_close(cli1->tree, fnum1);
901 fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
902 SEC_FILE_READ_EA,
903 FILE_ATTRIBUTE_NORMAL,
904 NTCREATEX_SHARE_ACCESS_READ|
905 NTCREATEX_SHARE_ACCESS_WRITE|
906 NTCREATEX_SHARE_ACCESS_DELETE,
907 NTCREATEX_DISP_OPEN,
908 0, 0);
910 torture_assert(tctx, fnum1 == -1,
911 "smbcli_open succeeded, should have "
912 "failed");
914 return correct;
917 /* Test 16 ... */
918 static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
920 int fnum1 = -1;
921 int fnum2 = -1;
922 bool correct = true;
924 del_clean_area(cli1, cli2);
926 /* Test 16. */
928 /* Ensure the file doesn't already exist. */
929 smbcli_close(cli1->tree, fnum1);
930 smbcli_close(cli1->tree, fnum2);
931 smbcli_setatr(cli1->tree, fname, 0, 0);
932 smbcli_unlink(cli1->tree, fname);
934 /* Firstly create with all access, but delete on close. */
935 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
936 SEC_RIGHTS_FILE_ALL,
937 FILE_ATTRIBUTE_NORMAL,
938 NTCREATEX_SHARE_ACCESS_READ|
939 NTCREATEX_SHARE_ACCESS_WRITE|
940 NTCREATEX_SHARE_ACCESS_DELETE,
941 NTCREATEX_DISP_CREATE,
942 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
944 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
946 /* The delete on close bit is *not* reported as being set. */
947 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
949 /* The delete on close bit is *not* reported as being set. */
950 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
951 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
953 /* Now try opening again for read-only. */
954 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
955 SEC_RIGHTS_FILE_READ,
956 FILE_ATTRIBUTE_NORMAL,
957 NTCREATEX_SHARE_ACCESS_READ|
958 NTCREATEX_SHARE_ACCESS_WRITE|
959 NTCREATEX_SHARE_ACCESS_DELETE,
960 NTCREATEX_DISP_OPEN,
961 0, 0);
963 /* Should work. */
964 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
965 fname, smbcli_errstr(cli1->tree)));
967 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
968 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
969 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
970 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
972 smbcli_close(cli1->tree, fnum1);
974 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
975 correct &= check_delete_on_close(tctx, cli2, -1, fname, true, __location__);
977 smbcli_close(cli2->tree, fnum2);
979 /* And the file should be deleted ! */
980 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
981 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
982 fname));
984 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
986 return correct;
989 /* Test 16 ... */
990 static bool deltest16a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
992 int fnum1 = -1;
993 int fnum2 = -1;
994 bool correct = true;
996 del_clean_area(cli1, cli2);
998 /* Test 16. */
1000 /* Ensure the file doesn't already exist. */
1001 smbcli_close(cli1->tree, fnum1);
1002 smbcli_close(cli1->tree, fnum2);
1003 smbcli_setatr(cli1->tree, fname, 0, 0);
1004 smbcli_unlink(cli1->tree, fname);
1006 /* Firstly open and create with all access */
1007 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1008 SEC_RIGHTS_FILE_ALL,
1009 FILE_ATTRIBUTE_NORMAL,
1010 NTCREATEX_SHARE_ACCESS_READ|
1011 NTCREATEX_SHARE_ACCESS_WRITE|
1012 NTCREATEX_SHARE_ACCESS_DELETE,
1013 NTCREATEX_DISP_CREATE,
1014 0, 0);
1015 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1016 fname, smbcli_errstr(cli1->tree)));
1018 /* And close - just to create the file. */
1019 smbcli_close(cli1->tree, fnum1);
1021 /* Firstly create with all access, but delete on close. */
1022 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1023 SEC_RIGHTS_FILE_ALL,
1024 FILE_ATTRIBUTE_NORMAL,
1025 NTCREATEX_SHARE_ACCESS_READ|
1026 NTCREATEX_SHARE_ACCESS_WRITE|
1027 NTCREATEX_SHARE_ACCESS_DELETE,
1028 NTCREATEX_DISP_OPEN,
1029 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1031 torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1033 /* The delete on close bit is *not* reported as being set. */
1034 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1036 /* The delete on close bit is *not* reported as being set. */
1037 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
1038 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
1040 /* Now try opening again for read-only. */
1041 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1042 SEC_RIGHTS_FILE_READ,
1043 FILE_ATTRIBUTE_NORMAL,
1044 NTCREATEX_SHARE_ACCESS_READ|
1045 NTCREATEX_SHARE_ACCESS_WRITE|
1046 NTCREATEX_SHARE_ACCESS_DELETE,
1047 NTCREATEX_DISP_OPEN,
1048 0, 0);
1050 /* Should work. */
1051 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1052 fname, smbcli_errstr(cli1->tree)));
1054 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1055 correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
1056 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1057 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
1059 smbcli_close(cli1->tree, fnum1);
1061 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1062 correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
1064 smbcli_close(cli2->tree, fnum2);
1066 /* And the file should be deleted ! */
1067 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1068 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
1069 fname, smbcli_errstr(cli1->tree)));
1071 smbcli_close(cli1->tree, fnum1);
1072 smbcli_setatr(cli1->tree, fname, 0, 0);
1073 smbcli_unlink(cli1->tree, fname);
1075 return correct;
1078 /* Test 17 ... */
1079 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1081 int fnum1 = -1;
1082 int fnum2 = -1;
1083 bool correct = true;
1085 del_clean_area(cli1, cli2);
1087 /* Test 17. */
1089 /* Ensure the file doesn't already exist. */
1090 smbcli_close(cli1->tree, fnum1);
1091 smbcli_close(cli1->tree, fnum2);
1092 smbcli_setatr(cli1->tree, fname, 0, 0);
1093 smbcli_unlink(cli1->tree, fname);
1095 /* Firstly open and create with all access */
1096 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1097 SEC_RIGHTS_FILE_ALL,
1098 FILE_ATTRIBUTE_NORMAL,
1099 NTCREATEX_SHARE_ACCESS_READ|
1100 NTCREATEX_SHARE_ACCESS_WRITE|
1101 NTCREATEX_SHARE_ACCESS_DELETE,
1102 NTCREATEX_DISP_CREATE,
1103 0, 0);
1104 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1105 fname, smbcli_errstr(cli1->tree)));
1107 /* And close - just to create the file. */
1108 smbcli_close(cli1->tree, fnum1);
1110 /* Next open with all access, but add delete on close. */
1111 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1112 SEC_RIGHTS_FILE_ALL,
1113 FILE_ATTRIBUTE_NORMAL,
1114 NTCREATEX_SHARE_ACCESS_READ|
1115 NTCREATEX_SHARE_ACCESS_WRITE|
1116 NTCREATEX_SHARE_ACCESS_DELETE,
1117 NTCREATEX_DISP_OPEN,
1118 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1120 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1121 fname, smbcli_errstr(cli1->tree)));
1123 /* The delete on close bit is *not* reported as being set. */
1124 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1126 /* Now try opening again for read-only. */
1127 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1128 SEC_RIGHTS_FILE_READ|
1129 SEC_STD_DELETE,
1130 FILE_ATTRIBUTE_NORMAL,
1131 NTCREATEX_SHARE_ACCESS_READ|
1132 NTCREATEX_SHARE_ACCESS_WRITE|
1133 NTCREATEX_SHARE_ACCESS_DELETE,
1134 NTCREATEX_DISP_OPEN,
1135 0, 0);
1137 /* Should work. */
1138 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1139 fname, smbcli_errstr(cli1->tree)));
1141 /* still not reported as being set on either */
1142 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1143 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1145 smbcli_close(cli1->tree, fnum1);
1147 /* After the first close, the files has the delete on close bit set. */
1148 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1150 smbcli_close(cli1->tree, fnum2);
1152 /* Make sure the file has been deleted */
1153 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1154 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
1155 fname, smbcli_errstr(cli1->tree)));
1157 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1159 return correct;
1162 /* Test 17a - like 17, but the delete on close handle is closed last */
1163 static bool deltest17a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1165 int fnum1 = -1;
1166 int fnum2 = -1;
1167 bool correct = true;
1169 del_clean_area(cli1, cli2);
1171 /* Ensure the file doesn't already exist. */
1172 smbcli_close(cli1->tree, fnum1);
1173 smbcli_close(cli1->tree, fnum2);
1174 smbcli_setatr(cli1->tree, fname, 0, 0);
1175 smbcli_unlink(cli1->tree, fname);
1177 /* Firstly open and create with all access */
1178 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1179 SEC_RIGHTS_FILE_ALL,
1180 FILE_ATTRIBUTE_NORMAL,
1181 NTCREATEX_SHARE_ACCESS_READ|
1182 NTCREATEX_SHARE_ACCESS_WRITE|
1183 NTCREATEX_SHARE_ACCESS_DELETE,
1184 NTCREATEX_DISP_CREATE,
1185 0, 0);
1186 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1187 fname, smbcli_errstr(cli1->tree)));
1189 /* And close - just to create the file. */
1190 smbcli_close(cli1->tree, fnum1);
1192 /* Next open with all access, but add delete on close. */
1193 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1194 SEC_RIGHTS_FILE_ALL,
1195 FILE_ATTRIBUTE_NORMAL,
1196 NTCREATEX_SHARE_ACCESS_READ|
1197 NTCREATEX_SHARE_ACCESS_WRITE|
1198 NTCREATEX_SHARE_ACCESS_DELETE,
1199 NTCREATEX_DISP_OPEN,
1200 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1202 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1203 fname, smbcli_errstr(cli1->tree)));
1205 /* The delete on close bit is *not* reported as being set. */
1206 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1208 /* Now try opening again for read-only. */
1209 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1210 SEC_RIGHTS_FILE_READ|
1211 SEC_STD_DELETE,
1212 FILE_ATTRIBUTE_NORMAL,
1213 NTCREATEX_SHARE_ACCESS_READ|
1214 NTCREATEX_SHARE_ACCESS_WRITE|
1215 NTCREATEX_SHARE_ACCESS_DELETE,
1216 NTCREATEX_DISP_OPEN,
1217 0, 0);
1219 /* Should work. */
1220 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1221 fname, smbcli_errstr(cli1->tree)));
1223 /* still not reported as being set on either */
1224 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1225 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1227 smbcli_close(cli1->tree, fnum2);
1229 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1231 smbcli_close(cli1->tree, fnum1);
1234 * The file is still there:
1235 * The second open seems to have removed the initial
1236 * delete on close flag from the first handle
1238 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1239 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1240 fname, smbcli_errstr(cli1->tree)));
1242 smbcli_close(cli1->tree, fnum1);
1243 smbcli_setatr(cli1->tree, fname, 0, 0);
1244 smbcli_unlink(cli1->tree, fname);
1246 return correct;
1249 /* Test 17b - like 17a, but the initial delete on close is set on the second handle */
1250 static bool deltest17b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1252 int fnum1 = -1;
1253 int fnum2 = -1;
1254 bool correct = true;
1256 del_clean_area(cli1, cli2);
1258 /* Ensure the file doesn't already exist. */
1259 smbcli_close(cli1->tree, fnum1);
1260 smbcli_close(cli1->tree, fnum2);
1261 smbcli_setatr(cli1->tree, fname, 0, 0);
1262 smbcli_unlink(cli1->tree, fname);
1264 /* Firstly open and create with all access */
1265 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1266 SEC_RIGHTS_FILE_ALL,
1267 FILE_ATTRIBUTE_NORMAL,
1268 NTCREATEX_SHARE_ACCESS_READ|
1269 NTCREATEX_SHARE_ACCESS_WRITE|
1270 NTCREATEX_SHARE_ACCESS_DELETE,
1271 NTCREATEX_DISP_CREATE,
1272 0, 0);
1273 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1274 fname, smbcli_errstr(cli1->tree)));
1276 /* And close - just to create the file. */
1277 smbcli_close(cli1->tree, fnum1);
1279 /* Next open with all access, but add delete on close. */
1280 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1281 SEC_RIGHTS_FILE_ALL,
1282 FILE_ATTRIBUTE_NORMAL,
1283 NTCREATEX_SHARE_ACCESS_READ|
1284 NTCREATEX_SHARE_ACCESS_WRITE|
1285 NTCREATEX_SHARE_ACCESS_DELETE,
1286 NTCREATEX_DISP_OPEN,
1287 0, 0);
1289 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1290 fname, smbcli_errstr(cli1->tree)));
1292 /* The delete on close bit is *not* reported as being set. */
1293 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1295 /* Now try opening again for read-only. */
1296 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1297 SEC_RIGHTS_FILE_READ|
1298 SEC_STD_DELETE,
1299 FILE_ATTRIBUTE_NORMAL,
1300 NTCREATEX_SHARE_ACCESS_READ|
1301 NTCREATEX_SHARE_ACCESS_WRITE|
1302 NTCREATEX_SHARE_ACCESS_DELETE,
1303 NTCREATEX_DISP_OPEN,
1304 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1306 /* Should work. */
1307 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1308 fname, smbcli_errstr(cli1->tree)));
1310 /* still not reported as being set on either */
1311 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1312 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1314 smbcli_close(cli1->tree, fnum1);
1316 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1318 smbcli_close(cli1->tree, fnum2);
1320 /* Make sure the file has been deleted */
1321 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1322 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1323 fname));
1325 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1327 return correct;
1330 /* Test 17c - like 17, but the initial delete on close is set on the second handle */
1331 static bool deltest17c(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1333 int fnum1 = -1;
1334 int fnum2 = -1;
1335 bool correct = true;
1337 del_clean_area(cli1, cli2);
1339 /* Ensure the file doesn't already exist. */
1340 smbcli_close(cli1->tree, fnum1);
1341 smbcli_close(cli1->tree, fnum2);
1342 smbcli_setatr(cli1->tree, fname, 0, 0);
1343 smbcli_unlink(cli1->tree, fname);
1345 /* Firstly open and create with all access */
1346 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1347 SEC_RIGHTS_FILE_ALL,
1348 FILE_ATTRIBUTE_NORMAL,
1349 NTCREATEX_SHARE_ACCESS_READ|
1350 NTCREATEX_SHARE_ACCESS_WRITE|
1351 NTCREATEX_SHARE_ACCESS_DELETE,
1352 NTCREATEX_DISP_CREATE,
1353 0, 0);
1354 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1355 fname, smbcli_errstr(cli1->tree)));
1357 /* And close - just to create the file. */
1358 smbcli_close(cli1->tree, fnum1);
1360 /* Next open with all access, but add delete on close. */
1361 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1362 SEC_RIGHTS_FILE_ALL,
1363 FILE_ATTRIBUTE_NORMAL,
1364 NTCREATEX_SHARE_ACCESS_READ|
1365 NTCREATEX_SHARE_ACCESS_WRITE|
1366 NTCREATEX_SHARE_ACCESS_DELETE,
1367 NTCREATEX_DISP_OPEN,
1368 0, 0);
1370 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1371 fname, smbcli_errstr(cli1->tree)));
1373 /* The delete on close bit is *not* reported as being set. */
1374 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1376 /* Now try opening again for read-only. */
1377 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1378 SEC_RIGHTS_FILE_READ|
1379 SEC_STD_DELETE,
1380 FILE_ATTRIBUTE_NORMAL,
1381 NTCREATEX_SHARE_ACCESS_READ|
1382 NTCREATEX_SHARE_ACCESS_WRITE|
1383 NTCREATEX_SHARE_ACCESS_DELETE,
1384 NTCREATEX_DISP_OPEN,
1385 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1387 /* Should work. */
1388 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1389 fname, smbcli_errstr(cli1->tree)));
1391 /* still not reported as being set on either */
1392 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1393 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1395 smbcli_close(cli1->tree, fnum2);
1397 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
1399 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1400 torture_assert(tctx, fnum2 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1401 fname));
1403 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1405 smbcli_close(cli1->tree, fnum1);
1407 /* Make sure the file has been deleted */
1408 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1409 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1410 fname));
1412 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1414 return correct;
1417 /* Test 17d - like 17a, but the first delete-on-close opener creates the file */
1418 static bool deltest17d(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1420 int fnum1 = -1;
1421 int fnum2 = -1;
1422 bool correct = true;
1424 del_clean_area(cli1, cli2);
1426 /* Ensure the file doesn't already exist. */
1427 smbcli_close(cli1->tree, fnum1);
1428 smbcli_close(cli1->tree, fnum2);
1429 smbcli_setatr(cli1->tree, fname, 0, 0);
1430 smbcli_unlink(cli1->tree, fname);
1433 /* Create the file with delete on close. */
1434 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1435 SEC_RIGHTS_FILE_ALL,
1436 FILE_ATTRIBUTE_NORMAL,
1437 NTCREATEX_SHARE_ACCESS_READ|
1438 NTCREATEX_SHARE_ACCESS_WRITE|
1439 NTCREATEX_SHARE_ACCESS_DELETE,
1440 NTCREATEX_DISP_CREATE,
1441 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1443 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1444 fname, smbcli_errstr(cli1->tree)));
1446 /* The delete on close bit is *not* reported as being set. */
1447 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1449 /* Now try opening again for read-only. */
1450 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1451 SEC_RIGHTS_FILE_READ|
1452 SEC_STD_DELETE,
1453 FILE_ATTRIBUTE_NORMAL,
1454 NTCREATEX_SHARE_ACCESS_READ|
1455 NTCREATEX_SHARE_ACCESS_WRITE|
1456 NTCREATEX_SHARE_ACCESS_DELETE,
1457 NTCREATEX_DISP_OPEN,
1458 0, 0);
1460 /* Should work. */
1461 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1462 fname, smbcli_errstr(cli1->tree)));
1464 /* still not reported as being set on either */
1465 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1466 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1468 smbcli_close(cli1->tree, fnum2);
1470 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1472 smbcli_close(cli1->tree, fnum1);
1475 * The file is still there:
1476 * The second open seems to have removed the initial
1477 * delete on close flag from the first handle
1479 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1480 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeed (should fail)",
1481 fname));
1483 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1485 return correct;
1488 static bool deltest17e(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1490 int fnum1 = -1;
1491 int fnum2 = -1;
1492 int fnum3 = -1;
1493 bool correct = true;
1495 del_clean_area(cli1, cli2);
1497 /* Ensure the file doesn't already exist. */
1498 smbcli_close(cli1->tree, fnum1);
1499 smbcli_close(cli1->tree, fnum2);
1500 smbcli_setatr(cli1->tree, fname, 0, 0);
1501 smbcli_unlink(cli1->tree, fname);
1503 /* Firstly open and create with all access */
1504 fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1505 SEC_RIGHTS_FILE_ALL,
1506 FILE_ATTRIBUTE_NORMAL,
1507 NTCREATEX_SHARE_ACCESS_READ|
1508 NTCREATEX_SHARE_ACCESS_WRITE|
1509 NTCREATEX_SHARE_ACCESS_DELETE,
1510 NTCREATEX_DISP_CREATE,
1511 0, 0);
1512 torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1513 fname, smbcli_errstr(cli1->tree)));
1515 /* Next open with all access, but add delete on close. */
1516 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1517 SEC_RIGHTS_FILE_ALL,
1518 FILE_ATTRIBUTE_NORMAL,
1519 NTCREATEX_SHARE_ACCESS_READ|
1520 NTCREATEX_SHARE_ACCESS_WRITE|
1521 NTCREATEX_SHARE_ACCESS_DELETE,
1522 NTCREATEX_DISP_OPEN,
1523 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1525 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1526 fname, smbcli_errstr(cli1->tree)));
1528 /* The delete on close bit is *not* reported as being set. */
1529 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1530 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1532 /* Now try opening again for read-only. */
1533 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1534 SEC_RIGHTS_FILE_READ|
1535 SEC_STD_DELETE,
1536 FILE_ATTRIBUTE_NORMAL,
1537 NTCREATEX_SHARE_ACCESS_READ|
1538 NTCREATEX_SHARE_ACCESS_WRITE|
1539 NTCREATEX_SHARE_ACCESS_DELETE,
1540 NTCREATEX_DISP_OPEN,
1541 0, 0);
1543 /* Should work. */
1544 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1545 fname, smbcli_errstr(cli1->tree)));
1547 /* still not reported as being set on either */
1548 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1549 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1550 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1552 smbcli_close(cli1->tree, fnum1);
1555 * closing the handle that has delete_on_close set
1556 * inherits the flag to the global context
1558 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1559 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1561 smbcli_close(cli1->tree, fnum2);
1563 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1565 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1566 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1567 fname));
1569 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1571 smbcli_close(cli1->tree, fnum3);
1573 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1574 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1575 fname));
1577 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1579 return correct;
1582 static bool deltest17f(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1584 int fnum1 = -1;
1585 int fnum2 = -1;
1586 int fnum3 = -1;
1587 bool correct = true;
1588 NTSTATUS status;
1590 del_clean_area(cli1, cli2);
1592 /* Ensure the file doesn't already exist. */
1593 smbcli_close(cli1->tree, fnum1);
1594 smbcli_close(cli1->tree, fnum2);
1595 smbcli_setatr(cli1->tree, fname, 0, 0);
1596 smbcli_unlink(cli1->tree, fname);
1598 /* Firstly open and create with all access */
1599 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1600 SEC_RIGHTS_FILE_ALL,
1601 FILE_ATTRIBUTE_NORMAL,
1602 NTCREATEX_SHARE_ACCESS_READ|
1603 NTCREATEX_SHARE_ACCESS_WRITE|
1604 NTCREATEX_SHARE_ACCESS_DELETE,
1605 NTCREATEX_DISP_CREATE,
1606 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1607 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1608 fname, smbcli_errstr(cli1->tree)));
1610 /* The delete on close bit is *not* reported as being set. */
1611 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1613 /* Next open with all access, but add delete on close. */
1614 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1615 SEC_RIGHTS_FILE_ALL,
1616 FILE_ATTRIBUTE_NORMAL,
1617 NTCREATEX_SHARE_ACCESS_READ|
1618 NTCREATEX_SHARE_ACCESS_WRITE|
1619 NTCREATEX_SHARE_ACCESS_DELETE,
1620 NTCREATEX_DISP_OPEN,
1621 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1623 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1624 fname, smbcli_errstr(cli1->tree)));
1626 /* still not reported as being set on either */
1627 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1628 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1630 /* Now try opening again for read-only. */
1631 fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1632 SEC_RIGHTS_FILE_READ|
1633 SEC_STD_DELETE,
1634 FILE_ATTRIBUTE_NORMAL,
1635 NTCREATEX_SHARE_ACCESS_READ|
1636 NTCREATEX_SHARE_ACCESS_WRITE|
1637 NTCREATEX_SHARE_ACCESS_DELETE,
1638 NTCREATEX_DISP_OPEN,
1639 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1641 /* Should work. */
1642 torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1643 fname, smbcli_errstr(cli1->tree)));
1645 /* still not reported as being set on either */
1646 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1647 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1648 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1650 smbcli_close(cli1->tree, fnum1);
1653 * closing the handle that has delete_on_close set
1654 * inherits the flag to the global context
1656 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1657 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1660 status = smbcli_nt_delete_on_close(cli1->tree, fnum2, false);
1661 torture_assert_ntstatus_ok(tctx, status,
1662 "clearing delete_on_close on file failed !");
1664 correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1665 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1667 smbcli_close(cli1->tree, fnum2);
1669 correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1671 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1672 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1673 fname));
1675 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1677 smbcli_close(cli1->tree, fnum3);
1679 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1680 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1681 fname));
1683 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1685 return correct;
1688 /* Test 18 ... */
1689 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1691 int fnum1 = -1;
1692 int fnum2 = -1;
1693 bool correct = true;
1695 del_clean_area(cli1, cli2);
1697 /* Test 18. With directories. */
1699 /* Ensure the file doesn't already exist. */
1700 smbcli_close(cli1->tree, fnum1);
1701 smbcli_close(cli1->tree, fnum2);
1703 smbcli_deltree(cli1->tree, dname);
1705 /* Firstly create with all access, but delete on close. */
1706 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1707 SEC_FILE_READ_DATA|
1708 SEC_FILE_WRITE_DATA|
1709 SEC_STD_DELETE,
1710 FILE_ATTRIBUTE_DIRECTORY,
1711 NTCREATEX_SHARE_ACCESS_READ|
1712 NTCREATEX_SHARE_ACCESS_WRITE|
1713 NTCREATEX_SHARE_ACCESS_DELETE,
1714 NTCREATEX_DISP_CREATE,
1715 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1717 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1718 dname, smbcli_errstr(cli1->tree)));
1721 * The delete on close bit is *not* reported as being set.
1722 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1723 * close as being set. This causes the subsequent create to fail with
1724 * NT_STATUS_DELETE_PENDING.
1726 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1728 /* Now try opening again for read-only. */
1729 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1730 SEC_RIGHTS_FILE_READ,
1731 FILE_ATTRIBUTE_DIRECTORY,
1732 NTCREATEX_SHARE_ACCESS_READ|
1733 NTCREATEX_SHARE_ACCESS_WRITE|
1734 NTCREATEX_SHARE_ACCESS_DELETE,
1735 NTCREATEX_DISP_OPEN,
1736 NTCREATEX_OPTIONS_DIRECTORY, 0);
1739 /* Should work. */
1740 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1741 dname, smbcli_errstr(cli1->tree)));
1743 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1744 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, false, __location__);
1746 smbcli_close(cli1->tree, fnum1);
1748 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1750 smbcli_close(cli1->tree, fnum2);
1752 /* And the directory should be deleted ! */
1753 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1754 SEC_RIGHTS_FILE_READ,
1755 FILE_ATTRIBUTE_DIRECTORY,
1756 NTCREATEX_SHARE_ACCESS_READ|
1757 NTCREATEX_SHARE_ACCESS_WRITE|
1758 NTCREATEX_SHARE_ACCESS_DELETE,
1759 NTCREATEX_DISP_OPEN,
1760 NTCREATEX_OPTIONS_DIRECTORY, 0);
1761 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
1762 dname));
1764 return correct;
1767 /* Test 19 ... */
1768 static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1770 int fnum1 = -1;
1771 int fnum2 = -1;
1772 bool correct = true;
1774 del_clean_area(cli1, cli2);
1776 /* Test 19. */
1778 smbcli_deltree(cli1->tree, dname);
1780 /* Firstly open and create with all access */
1781 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1782 SEC_FILE_READ_DATA|
1783 SEC_FILE_WRITE_DATA|
1784 SEC_STD_DELETE,
1785 FILE_ATTRIBUTE_DIRECTORY,
1786 NTCREATEX_SHARE_ACCESS_READ|
1787 NTCREATEX_SHARE_ACCESS_WRITE|
1788 NTCREATEX_SHARE_ACCESS_DELETE,
1789 NTCREATEX_DISP_CREATE,
1790 NTCREATEX_OPTIONS_DIRECTORY, 0);
1792 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1793 dname, smbcli_errstr(cli1->tree)));
1795 /* And close - just to create the directory. */
1796 smbcli_close(cli1->tree, fnum1);
1798 /* Next open with all access, but add delete on close. */
1799 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1800 SEC_FILE_READ_DATA|
1801 SEC_FILE_WRITE_DATA|
1802 SEC_STD_DELETE,
1803 FILE_ATTRIBUTE_DIRECTORY,
1804 NTCREATEX_SHARE_ACCESS_READ|
1805 NTCREATEX_SHARE_ACCESS_WRITE|
1806 NTCREATEX_SHARE_ACCESS_DELETE,
1807 NTCREATEX_DISP_OPEN,
1808 NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1810 torture_assert(tctx, fnum1 != -1,
1811 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1814 * The delete on close bit is *not* reported as being set.
1815 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1816 * close as being set. This causes the subsequent create to fail with
1817 * NT_STATUS_DELETE_PENDING.
1819 correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1821 /* Now try opening again for read-only. */
1822 fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1823 SEC_RIGHTS_FILE_READ,
1824 FILE_ATTRIBUTE_DIRECTORY,
1825 NTCREATEX_SHARE_ACCESS_READ|
1826 NTCREATEX_SHARE_ACCESS_WRITE|
1827 NTCREATEX_SHARE_ACCESS_DELETE,
1828 NTCREATEX_DISP_OPEN,
1829 NTCREATEX_OPTIONS_DIRECTORY, 0);
1831 /* Should work. */
1832 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1833 dname, smbcli_errstr(cli1->tree)));
1835 smbcli_close(cli1->tree, fnum1);
1837 correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1839 smbcli_close(cli1->tree, fnum2);
1841 /* See if the file is deleted - for a directory this seems to be true ! */
1842 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1843 SEC_RIGHTS_FILE_READ,
1844 FILE_ATTRIBUTE_DIRECTORY,
1845 NTCREATEX_SHARE_ACCESS_READ|
1846 NTCREATEX_SHARE_ACCESS_WRITE|
1847 NTCREATEX_SHARE_ACCESS_DELETE,
1848 NTCREATEX_DISP_OPEN,
1849 NTCREATEX_OPTIONS_DIRECTORY, 0);
1851 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1853 torture_assert(tctx, fnum1 == -1,
1854 talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1856 return correct;
1859 /* Test 20 ... */
1860 static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1862 int fnum1 = -1;
1863 int dnum1 = -1;
1864 bool correct = true;
1865 NTSTATUS status;
1866 int ret;
1868 del_clean_area(cli1, cli2);
1870 /* Test 20 -- non-empty directory hardest to get right... */
1872 smbcli_deltree(cli1->tree, dname);
1874 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1875 SEC_FILE_READ_DATA|
1876 SEC_FILE_WRITE_DATA|
1877 SEC_STD_DELETE,
1878 FILE_ATTRIBUTE_DIRECTORY,
1879 NTCREATEX_SHARE_ACCESS_READ|
1880 NTCREATEX_SHARE_ACCESS_WRITE|
1881 NTCREATEX_SHARE_ACCESS_DELETE,
1882 NTCREATEX_DISP_CREATE,
1883 NTCREATEX_OPTIONS_DIRECTORY, 0);
1884 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
1885 dname, smbcli_errstr(cli1->tree)));
1887 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
1888 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1891 char *fullname;
1892 ret = asprintf(&fullname, "\\%s%s", dname, fname);
1893 torture_assert(tctx, ret != -1, "asprintf failed");
1894 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1895 DENY_NONE);
1896 torture_assert(tctx, fnum1 == -1,
1897 "smbcli_open succeeded, should have "
1898 "failed with NT_STATUS_DELETE_PENDING"
1901 torture_assert_ntstatus_equal(tctx,
1902 smbcli_nt_error(cli1->tree),
1903 NT_STATUS_DELETE_PENDING,
1904 "smbcli_open failed");
1907 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, false);
1908 torture_assert_ntstatus_ok(tctx, status,
1909 "unsetting delete_on_close on file failed !");
1912 char *fullname;
1913 ret = asprintf(&fullname, "\\%s%s", dname, fname);
1914 torture_assert(tctx, ret != -1, "asprintf failed");
1915 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1916 DENY_NONE);
1917 torture_assert(tctx, fnum1 != -1,
1918 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1919 smbcli_errstr(cli1->tree)));
1920 smbcli_close(cli1->tree, fnum1);
1923 status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1925 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1926 "setting delete_on_close failed");
1927 smbcli_close(cli1->tree, dnum1);
1929 return correct;
1932 /* Test 20a ... */
1933 static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1935 int fnum1 = -1;
1936 int fnum2 = -1;
1937 bool correct = true;
1939 del_clean_area(cli1, cli2);
1941 /* Test 20a. */
1943 /* Ensure the file doesn't already exist. */
1944 smbcli_close(cli1->tree, fnum1);
1945 smbcli_close(cli1->tree, fnum2);
1946 smbcli_setatr(cli1->tree, fname, 0, 0);
1947 smbcli_unlink(cli1->tree, fname);
1949 /* Firstly open and create with all access */
1950 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1951 SEC_RIGHTS_FILE_ALL,
1952 FILE_ATTRIBUTE_NORMAL,
1953 NTCREATEX_SHARE_ACCESS_READ|
1954 NTCREATEX_SHARE_ACCESS_WRITE|
1955 NTCREATEX_SHARE_ACCESS_DELETE,
1956 NTCREATEX_DISP_CREATE,
1957 0, 0);
1958 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1959 fname, smbcli_errstr(cli1->tree)));
1961 /* Next open with all access, but add delete on close. */
1962 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1963 SEC_RIGHTS_FILE_ALL,
1964 FILE_ATTRIBUTE_NORMAL,
1965 NTCREATEX_SHARE_ACCESS_READ|
1966 NTCREATEX_SHARE_ACCESS_WRITE|
1967 NTCREATEX_SHARE_ACCESS_DELETE,
1968 NTCREATEX_DISP_OPEN,
1969 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1971 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1972 fname, smbcli_errstr(cli2->tree)));
1974 /* The delete on close bit is *not* reported as being set. */
1975 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1976 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1978 smbcli_close(cli1->tree, fnum1);
1980 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1982 smbcli_close(cli2->tree, fnum2);
1984 /* See if the file is deleted - should be.... */
1985 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1986 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1987 fname, smbcli_errstr(cli1->tree)));
1989 return correct;
1992 /* Test 20b ... */
1993 /* This is the delete semantics that the cifsfs client depends on when
1994 * trying to delete an open file on a Windows server. It
1995 * opens a file with initial delete on close set, renames it then closes
1996 * all open handles. The file goes away on Windows.
1999 static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2001 int fnum1 = -1;
2002 int fnum2 = -1;
2003 bool correct = true;
2005 del_clean_area(cli1, cli2);
2007 /* Test 20b. */
2009 /* Ensure the file doesn't already exist. */
2010 smbcli_close(cli1->tree, fnum1);
2011 smbcli_close(cli1->tree, fnum2);
2012 smbcli_setatr(cli1->tree, fname, 0, 0);
2013 smbcli_unlink(cli1->tree, fname);
2014 smbcli_setatr(cli1->tree, fname_new, 0, 0);
2015 smbcli_unlink(cli1->tree, fname_new);
2017 /* Firstly open and create with all access */
2018 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2019 SEC_RIGHTS_FILE_ALL,
2020 FILE_ATTRIBUTE_NORMAL,
2021 NTCREATEX_SHARE_ACCESS_READ|
2022 NTCREATEX_SHARE_ACCESS_WRITE|
2023 NTCREATEX_SHARE_ACCESS_DELETE,
2024 NTCREATEX_DISP_CREATE,
2025 0, 0);
2026 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
2027 fname, smbcli_errstr(cli1->tree)));
2029 /* And close - just to create the file. */
2030 smbcli_close(cli1->tree, fnum1);
2032 /* Firstly open and create with all access */
2033 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2034 SEC_RIGHTS_FILE_ALL,
2035 FILE_ATTRIBUTE_NORMAL,
2036 NTCREATEX_SHARE_ACCESS_READ|
2037 NTCREATEX_SHARE_ACCESS_WRITE|
2038 NTCREATEX_SHARE_ACCESS_DELETE,
2039 NTCREATEX_DISP_OPEN,
2040 0, 0);
2041 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
2042 fname, smbcli_errstr(cli1->tree)));
2044 /* Next open with all access, but add delete on close. */
2045 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
2046 SEC_RIGHTS_FILE_ALL,
2047 FILE_ATTRIBUTE_NORMAL,
2048 NTCREATEX_SHARE_ACCESS_READ|
2049 NTCREATEX_SHARE_ACCESS_WRITE|
2050 NTCREATEX_SHARE_ACCESS_DELETE,
2051 NTCREATEX_DISP_OPEN,
2052 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2054 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
2055 fname, smbcli_errstr(cli2->tree)));
2057 /* The delete on close bit is *not* reported as being set. */
2058 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
2059 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
2061 smbcli_close(cli1->tree, fnum1);
2063 correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
2065 /* Rename the file by handle. */
2068 union smb_setfileinfo sfinfo;
2069 NTSTATUS status;
2071 memset(&sfinfo, '\0', sizeof(sfinfo));
2072 sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2073 sfinfo.generic.in.file.fnum = fnum2;
2074 sfinfo.rename_information.in.root_fid = 0;
2075 /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
2076 sfinfo.rename_information.in.new_name = fname_new + 1;
2077 sfinfo.rename_information.in.overwrite = 1;
2079 status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
2081 torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
2082 fname, fname_new, smbcli_errstr(cli2->tree)));
2085 correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, false, __location__);
2087 smbcli_close(cli2->tree, fnum2);
2089 /* See if the file is deleted - should be.... */
2090 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2091 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
2092 fname, smbcli_errstr(cli1->tree)));
2093 fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
2094 torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
2095 fname_new, smbcli_errstr(cli1->tree)));
2097 return correct;
2101 /* Test 21 ... */
2102 static bool deltest21(struct torture_context *tctx)
2104 int fnum1 = -1;
2105 struct smbcli_state *cli1;
2106 struct smbcli_state *cli2;
2107 bool correct = true;
2109 if (!torture_open_connection(&cli1, tctx, 0))
2110 return false;
2112 if (!torture_open_connection(&cli2, tctx, 1))
2113 return false;
2115 del_clean_area(cli1, cli2);
2117 /* Test 21 -- Test removal of file after socket close. */
2119 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2120 SEC_RIGHTS_FILE_ALL,
2121 FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
2122 NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2124 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
2125 fname, smbcli_errstr(cli1->tree)));
2127 torture_assert_ntstatus_ok(tctx,
2128 smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
2129 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2130 smbcli_errstr(cli1->tree)));
2132 /* Ensure delete on close is set. */
2133 correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
2135 /* Now yank the rug from under cli1. */
2136 smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
2138 fnum1 = -1;
2140 if (!torture_open_connection(&cli1, tctx, 0)) {
2141 return false;
2144 /* On slow build farm machines it might happen that they are not fast
2145 * enogh to delete the file for this test */
2146 smb_msleep(200);
2148 /* File should not be there. */
2149 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2150 SEC_RIGHTS_FILE_READ,
2151 FILE_ATTRIBUTE_NORMAL,
2152 NTCREATEX_SHARE_ACCESS_READ|
2153 NTCREATEX_SHARE_ACCESS_WRITE|
2154 NTCREATEX_SHARE_ACCESS_DELETE,
2155 NTCREATEX_DISP_OPEN,
2156 0, 0);
2158 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2160 return correct;
2163 /* Test 22 ... */
2166 * Test whether a second *directory* handle inhibits delete if the first has
2167 * del-on-close set and is closed
2169 static bool deltest22(struct torture_context *tctx)
2171 int dnum1 = -1;
2172 int dnum2 = -1;
2173 struct smbcli_state *cli1;
2174 bool correct = true;
2176 if (!torture_open_connection(&cli1, tctx, 0))
2177 return false;
2179 smbcli_deltree(cli1->tree, dname);
2181 torture_assert_ntstatus_ok(
2182 tctx, smbcli_mkdir(cli1->tree, dname),
2183 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
2184 smbcli_errstr(cli1->tree)));
2186 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2187 SEC_FILE_READ_DATA|
2188 SEC_FILE_WRITE_DATA|
2189 SEC_STD_DELETE,
2190 FILE_ATTRIBUTE_DIRECTORY,
2191 NTCREATEX_SHARE_ACCESS_READ|
2192 NTCREATEX_SHARE_ACCESS_WRITE|
2193 NTCREATEX_SHARE_ACCESS_DELETE,
2194 NTCREATEX_DISP_OPEN,
2195 NTCREATEX_OPTIONS_DIRECTORY, 0);
2197 torture_assert(tctx, dnum1 != -1,
2198 talloc_asprintf(tctx, "open of %s failed: %s!",
2199 dname, smbcli_errstr(cli1->tree)));
2201 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2202 SEC_FILE_READ_DATA|
2203 SEC_FILE_WRITE_DATA,
2204 FILE_ATTRIBUTE_DIRECTORY,
2205 NTCREATEX_SHARE_ACCESS_READ|
2206 NTCREATEX_SHARE_ACCESS_WRITE|
2207 NTCREATEX_SHARE_ACCESS_DELETE,
2208 NTCREATEX_DISP_OPEN,
2209 NTCREATEX_OPTIONS_DIRECTORY, 0);
2211 torture_assert(tctx, dnum2 != -1,
2212 talloc_asprintf(tctx, "open of %s failed: %s!",
2213 dname, smbcli_errstr(cli1->tree)));
2215 torture_assert_ntstatus_ok(
2216 tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
2217 talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2218 smbcli_errstr(cli1->tree)));
2220 smbcli_close(cli1->tree, dnum1);
2222 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2223 SEC_FILE_READ_DATA|
2224 SEC_FILE_WRITE_DATA|
2225 SEC_STD_DELETE,
2226 FILE_ATTRIBUTE_DIRECTORY,
2227 NTCREATEX_SHARE_ACCESS_READ|
2228 NTCREATEX_SHARE_ACCESS_WRITE|
2229 NTCREATEX_SHARE_ACCESS_DELETE,
2230 NTCREATEX_DISP_OPEN,
2231 NTCREATEX_OPTIONS_DIRECTORY, 0);
2233 torture_assert(tctx, dnum1 == -1,
2234 talloc_asprintf(tctx, "open of %s succeeded!\n",
2235 dname));
2237 CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
2239 smbcli_close(cli1->tree, dnum2);
2240 CHECK_STATUS(cli1, NT_STATUS_OK);
2242 return correct;
2245 /* Test 23 - Second directory open fails when delete is pending. */
2246 static bool deltest23(struct torture_context *tctx,
2247 struct smbcli_state *cli1,
2248 struct smbcli_state *cli2)
2250 int dnum1 = -1;
2251 int dnum2 = -1;
2252 bool correct = true;
2254 del_clean_area(cli1, cli2);
2256 /* Test 23 -- Basic delete on close for directories. */
2258 /* Open a directory */
2259 dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2260 SEC_FILE_READ_DATA|
2261 SEC_FILE_WRITE_DATA|
2262 SEC_STD_DELETE,
2263 FILE_ATTRIBUTE_DIRECTORY,
2264 NTCREATEX_SHARE_ACCESS_READ|
2265 NTCREATEX_SHARE_ACCESS_WRITE|
2266 NTCREATEX_SHARE_ACCESS_DELETE,
2267 NTCREATEX_DISP_CREATE,
2268 NTCREATEX_OPTIONS_DIRECTORY, 0);
2270 torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx,
2271 "open of %s failed: %s!",
2272 dname, smbcli_errstr(cli1->tree)));
2274 correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false,
2275 __location__);
2277 /* Set delete on close */
2278 (void)smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
2280 /* Attempt opening the directory again. It should fail. */
2281 dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2282 SEC_FILE_READ_DATA|
2283 SEC_FILE_WRITE_DATA|
2284 SEC_STD_DELETE,
2285 FILE_ATTRIBUTE_DIRECTORY,
2286 NTCREATEX_SHARE_ACCESS_READ|
2287 NTCREATEX_SHARE_ACCESS_WRITE|
2288 NTCREATEX_SHARE_ACCESS_DELETE,
2289 NTCREATEX_DISP_OPEN,
2290 NTCREATEX_OPTIONS_DIRECTORY, 0);
2292 torture_assert(tctx, dnum2 == -1, talloc_asprintf(tctx,
2293 "open of %s succeeded: %s. It should have failed "
2294 "with NT_STATUS_DELETE_PENDING",
2295 dname, smbcli_errstr(cli1->tree)));
2297 torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree),
2298 NT_STATUS_DELETE_PENDING, "smbcli_open failed");
2300 return true;
2303 /* Test 24 ... */
2306 * Test whether unsetting delete-on-close before the close has any effect.
2307 * It should be ignored.
2309 static bool deltest24(struct torture_context *tctx)
2311 int fnum1 = -1;
2312 struct smbcli_state *cli1;
2313 bool correct = true;
2315 if (!torture_open_connection(&cli1, tctx, 0))
2316 return false;
2318 smbcli_deltree(cli1->tree, fname);
2320 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2321 SEC_FILE_READ_DATA|
2322 SEC_FILE_WRITE_DATA|
2323 SEC_STD_DELETE,
2324 FILE_ATTRIBUTE_NORMAL,
2325 NTCREATEX_SHARE_ACCESS_READ|
2326 NTCREATEX_SHARE_ACCESS_WRITE|
2327 NTCREATEX_SHARE_ACCESS_DELETE,
2328 NTCREATEX_DISP_CREATE,
2329 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2331 torture_assert(tctx, fnum1 != -1,
2332 talloc_asprintf(tctx, "open of %s failed: %s!",
2333 fname, smbcli_errstr(cli1->tree)));
2335 /* Now, unset Delete-On-Close, but it should have no effect */
2336 torture_assert_ntstatus_ok(
2337 tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, false),
2338 talloc_asprintf(tctx, "unsetting delete_on_close failed (%s)",
2339 smbcli_errstr(cli1->tree)));
2341 smbcli_close(cli1->tree, fnum1);
2343 /* File should not be there. */
2344 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2345 SEC_RIGHTS_FILE_READ,
2346 FILE_ATTRIBUTE_NORMAL,
2347 NTCREATEX_SHARE_ACCESS_READ|
2348 NTCREATEX_SHARE_ACCESS_WRITE|
2349 NTCREATEX_SHARE_ACCESS_DELETE,
2350 NTCREATEX_DISP_OPEN,
2351 0, 0);
2353 CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2355 return correct;
2358 /* Test 25 ... */
2359 static bool deltest25(struct torture_context *tctx,
2360 struct smbcli_state *cli1,
2361 struct smbcli_state *cli2)
2363 int fnum1 = -1;
2364 NTSTATUS status;
2365 uint32_t disps[4] = {
2366 NTCREATEX_DISP_SUPERSEDE,
2367 NTCREATEX_DISP_OVERWRITE_IF,
2368 NTCREATEX_DISP_CREATE,
2369 NTCREATEX_DISP_OPEN_IF};
2370 unsigned int i;
2372 del_clean_area(cli1, cli2);
2374 for (i = 0; i < sizeof(disps)/sizeof(disps[0]); i++) {
2375 /* This should fail - we need to set DELETE_ACCESS. */
2378 * A file or directory create with DELETE_ON_CLOSE but
2379 * without DELETE_ACCESS should fail with
2380 * NT_STATUS_INVALID_PARAMETER.
2383 fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2384 SEC_FILE_READ_DATA,
2385 FILE_ATTRIBUTE_DIRECTORY,
2386 NTCREATEX_SHARE_ACCESS_NONE,
2387 disps[i],
2388 NTCREATEX_OPTIONS_DIRECTORY|
2389 NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2391 torture_assert(tctx, fnum1 == -1,
2392 talloc_asprintf(tctx, "open of %s succeeded "
2393 "should have failed!",
2394 dname));
2396 /* Must fail with NT_STATUS_INVALID_PARAMETER. */
2397 status = smbcli_nt_error(cli1->tree);
2398 torture_assert_ntstatus_equal(tctx,
2399 status,
2400 NT_STATUS_INVALID_PARAMETER,
2401 talloc_asprintf(tctx, "create of %s should return "
2402 "NT_STATUS_INVALID_PARAMETER, got %s",
2403 dname,
2404 smbcli_errstr(cli1->tree)));
2407 * This should fail - the directory
2408 * should not have been created.
2410 status = smbcli_getatr(cli1->tree, dname, NULL, NULL, NULL);
2411 torture_assert_ntstatus_equal(tctx,
2412 status,
2413 NT_STATUS_OBJECT_NAME_NOT_FOUND,
2414 talloc_asprintf(tctx, "getattr of %s succeeded should "
2415 "not have been created !",
2416 dname));
2419 return true;
2423 Test delete on close semantics.
2425 struct torture_suite *torture_test_delete(TALLOC_CTX *ctx)
2427 struct torture_suite *suite = torture_suite_create(
2428 ctx, "delete");
2430 torture_suite_add_2smb_test(suite, "deltest1", deltest1);
2431 torture_suite_add_2smb_test(suite, "deltest2", deltest2);
2432 torture_suite_add_2smb_test(suite, "deltest3", deltest3);
2433 torture_suite_add_2smb_test(suite, "deltest4", deltest4);
2434 torture_suite_add_2smb_test(suite, "deltest5", deltest5);
2435 torture_suite_add_2smb_test(suite, "deltest6", deltest6);
2436 torture_suite_add_2smb_test(suite, "deltest7", deltest7);
2437 torture_suite_add_2smb_test(suite, "deltest8", deltest8);
2438 torture_suite_add_2smb_test(suite, "deltest9", deltest9);
2439 torture_suite_add_2smb_test(suite, "deltest9a", deltest9a);
2440 torture_suite_add_2smb_test(suite, "deltest10", deltest10);
2441 torture_suite_add_2smb_test(suite, "deltest11", deltest11);
2442 torture_suite_add_2smb_test(suite, "deltest12", deltest12);
2443 torture_suite_add_2smb_test(suite, "deltest13", deltest13);
2444 torture_suite_add_2smb_test(suite, "deltest14", deltest14);
2445 torture_suite_add_2smb_test(suite, "deltest15", deltest15);
2446 torture_suite_add_2smb_test(suite, "deltest16", deltest16);
2447 torture_suite_add_2smb_test(suite, "deltest16a", deltest16a);
2448 torture_suite_add_2smb_test(suite, "deltest17", deltest17);
2449 torture_suite_add_2smb_test(suite, "deltest17a", deltest17a);
2450 torture_suite_add_2smb_test(suite, "deltest17b", deltest17b);
2451 torture_suite_add_2smb_test(suite, "deltest17c", deltest17c);
2452 torture_suite_add_2smb_test(suite, "deltest17d", deltest17d);
2453 torture_suite_add_2smb_test(suite, "deltest17e", deltest17e);
2454 torture_suite_add_2smb_test(suite, "deltest17f", deltest17f);
2455 torture_suite_add_2smb_test(suite, "deltest18", deltest18);
2456 torture_suite_add_2smb_test(suite, "deltest19", deltest19);
2457 torture_suite_add_2smb_test(suite, "deltest20", deltest20);
2458 torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
2459 torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
2460 torture_suite_add_simple_test(suite, "deltest21", deltest21);
2461 torture_suite_add_simple_test(suite, "deltest22", deltest22);
2462 torture_suite_add_2smb_test(suite, "deltest23", deltest23);
2463 torture_suite_add_simple_test(suite, "deltest24", deltest24);
2464 torture_suite_add_2smb_test(suite, "deltest25", deltest25);
2466 return suite;