2 Unix SMB/CIFS implementation.
4 delete on close testing
6 Copyright (C) Andrew Tridgell 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/libcli.h"
24 #include "torture/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
,
36 union smb_search_data data
;
39 time_t c_time
, a_time
, m_time
;
43 status
= torture_single_search(cli
, tctx
,
46 RAW_SEARCH_DATA_FULL_DIRECTORY_INFO
,
47 FILE_ATTRIBUTE_DIRECTORY
,
49 torture_assert_ntstatus_ok(tctx
, status
,
50 talloc_asprintf(tctx
, "single_search failed (%s)", where
));
53 union smb_fileinfo io
;
54 int nlink
= expect_it
? 0 : 1;
56 io
.all_info
.level
= RAW_FILEINFO_ALL_INFO
;
57 io
.all_info
.in
.file
.fnum
= fnum
;
59 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &io
);
60 torture_assert_ntstatus_ok(tctx
, status
, talloc_asprintf(tctx
,
61 "qfileinfo failed (%s)", where
));
63 torture_assert(tctx
, expect_it
== io
.all_info
.out
.delete_pending
,
65 "%s - Expected del_on_close flag %d, qfileinfo/all_info gave %d",
66 where
, expect_it
, io
.all_info
.out
.delete_pending
));
68 torture_assert(tctx
, nlink
== io
.all_info
.out
.nlink
,
70 "%s - Expected nlink %d, qfileinfo/all_info gave %d",
71 where
, nlink
, io
.all_info
.out
.nlink
));
73 io
.standard_info
.level
= RAW_FILEINFO_STANDARD_INFO
;
74 io
.standard_info
.in
.file
.fnum
= fnum
;
76 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &io
);
77 torture_assert_ntstatus_ok(tctx
, status
, talloc_asprintf(tctx
, "qpathinfo failed (%s)", where
));
79 torture_assert(tctx
, expect_it
== io
.standard_info
.out
.delete_pending
,
80 talloc_asprintf(tctx
, "%s - Expected del_on_close flag %d, qfileinfo/standard_info gave %d\n",
81 where
, expect_it
, io
.standard_info
.out
.delete_pending
));
83 torture_assert(tctx
, nlink
== io
.standard_info
.out
.nlink
,
84 talloc_asprintf(tctx
, "%s - Expected nlink %d, qfileinfo/standard_info gave %d",
85 where
, nlink
, io
.all_info
.out
.nlink
));
88 status
= smbcli_qpathinfo(cli
->tree
, fname
,
89 &c_time
, &a_time
, &m_time
,
93 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_DELETE_PENDING
,
94 "qpathinfo did not give correct error code");
96 torture_assert_ntstatus_ok(tctx
, status
,
97 talloc_asprintf(tctx
, "qpathinfo failed (%s)", where
));
103 #define CHECK_STATUS(_cli, _expected) \
104 torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
107 static const char *fname
= "\\delete.file";
108 static const char *fname_new
= "\\delete.new";
109 static const char *dname
= "\\delete.dir";
111 static void del_clean_area(struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
113 smb_raw_exit(cli1
->session
);
114 smb_raw_exit(cli2
->session
);
116 smbcli_deltree(cli1
->tree
, dname
);
117 smbcli_setatr(cli1
->tree
, fname
, 0, 0);
118 smbcli_unlink(cli1
->tree
, fname
);
119 smbcli_setatr(cli1
->tree
, fname_new
, 0, 0);
120 smbcli_unlink(cli1
->tree
, fname_new
);
123 /* Test 1 - this should delete the file on close. */
125 static bool deltest1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
129 del_clean_area(cli1
, cli2
);
131 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
133 FILE_ATTRIBUTE_NORMAL
,
134 NTCREATEX_SHARE_ACCESS_DELETE
, NTCREATEX_DISP_OVERWRITE_IF
,
135 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
137 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
138 fname
, smbcli_errstr(cli1
->tree
)));
140 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
141 talloc_asprintf(tctx
, "close failed (%s)", smbcli_errstr(cli1
->tree
)));
143 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
, DENY_NONE
);
144 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s succeeded (should fail)",
150 /* Test 2 - this should delete the file on close. */
151 static bool deltest2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
155 del_clean_area(cli1
, cli2
);
157 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
159 FILE_ATTRIBUTE_NORMAL
, NTCREATEX_SHARE_ACCESS_NONE
,
160 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
162 torture_assert(tctx
, fnum1
!= -1,
163 talloc_asprintf(tctx
, "open of %s failed (%s)",
164 fname
, smbcli_errstr(cli1
->tree
)));
166 torture_assert_ntstatus_ok(tctx
, smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
167 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
168 smbcli_errstr(cli1
->tree
)));
170 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
171 talloc_asprintf(tctx
, "close failed (%s)",
172 smbcli_errstr(cli1
->tree
)));
174 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
176 printf("(%s) open of %s succeeded should have been deleted on close !\n",
177 __location__
, fname
);
178 if (NT_STATUS_IS_ERR(smbcli_close(cli1
->tree
, fnum1
))) {
179 printf("(%s) close failed (%s)\n",
180 __location__
, smbcli_errstr(cli1
->tree
));
183 smbcli_unlink(cli1
->tree
, fname
);
189 static bool deltest3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
194 del_clean_area(cli1
, cli2
);
196 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
198 FILE_ATTRIBUTE_NORMAL
,
199 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
,
200 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
202 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
203 fname
, smbcli_errstr(cli1
->tree
)));
205 /* This should fail with a sharing violation - open for delete is only compatible
206 with SHARE_DELETE. */
208 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
209 SEC_RIGHTS_FILE_READ
,
210 FILE_ATTRIBUTE_NORMAL
,
211 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
,
212 NTCREATEX_DISP_OPEN
, 0, 0);
214 torture_assert(tctx
, fnum2
== -1,
215 talloc_asprintf(tctx
, "open - 2 of %s succeeded - should have failed.",
218 /* This should succeed. */
220 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
221 SEC_RIGHTS_FILE_READ
,
222 FILE_ATTRIBUTE_NORMAL
,
223 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
224 NTCREATEX_DISP_OPEN
, 0, 0);
226 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 2 of %s failed (%s)",
227 fname
, smbcli_errstr(cli1
->tree
)));
229 torture_assert_ntstatus_ok(tctx
,
230 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
231 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
232 smbcli_errstr(cli1
->tree
)));
234 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
235 talloc_asprintf(tctx
, "close 1 failed (%s)",
236 smbcli_errstr(cli1
->tree
)));
238 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum2
),
239 talloc_asprintf(tctx
, "close 2 failed (%s)",
240 smbcli_errstr(cli1
->tree
)));
242 /* This should fail - file should no longer be there. */
244 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
246 printf("(%s) open of %s succeeded should have been deleted on close !\n",
247 __location__
, fname
);
248 if (NT_STATUS_IS_ERR(smbcli_close(cli1
->tree
, fnum1
))) {
249 printf("(%s) close failed (%s)\n",
250 __location__
, smbcli_errstr(cli1
->tree
));
252 smbcli_unlink(cli1
->tree
, fname
);
259 static bool deltest4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
265 del_clean_area(cli1
, cli2
);
267 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
269 SEC_FILE_WRITE_DATA
|
271 FILE_ATTRIBUTE_NORMAL
,
272 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
,
273 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
275 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
276 fname
, smbcli_errstr(cli1
->tree
)));
278 /* This should succeed. */
279 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
280 SEC_RIGHTS_FILE_READ
,
281 FILE_ATTRIBUTE_NORMAL
,
282 NTCREATEX_SHARE_ACCESS_READ
|
283 NTCREATEX_SHARE_ACCESS_WRITE
|
284 NTCREATEX_SHARE_ACCESS_DELETE
,
285 NTCREATEX_DISP_OPEN
, 0, 0);
286 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 2 of %s failed (%s)",
287 fname
, smbcli_errstr(cli1
->tree
)));
289 torture_assert_ntstatus_ok(tctx
,
290 smbcli_close(cli1
->tree
, fnum2
),
291 talloc_asprintf(tctx
, "close - 1 failed (%s)",
292 smbcli_errstr(cli1
->tree
)));
294 torture_assert_ntstatus_ok(tctx
,
295 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
296 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
297 smbcli_errstr(cli1
->tree
)));
299 /* This should fail - no more opens once delete on close set. */
300 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
301 SEC_RIGHTS_FILE_READ
,
302 FILE_ATTRIBUTE_NORMAL
,
303 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
304 NTCREATEX_DISP_OPEN
, 0, 0);
305 torture_assert(tctx
, fnum2
== -1,
306 talloc_asprintf(tctx
, "open - 3 of %s succeeded ! Should have failed.",
309 CHECK_STATUS(cli1
, NT_STATUS_DELETE_PENDING
);
311 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
312 talloc_asprintf(tctx
, "close - 2 failed (%s)",
313 smbcli_errstr(cli1
->tree
)));
319 static bool deltest5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
323 del_clean_area(cli1
, cli2
);
325 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
326 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
327 fname
, smbcli_errstr(cli1
->tree
)));
329 /* This should fail - only allowed on NT opens with DELETE access. */
331 torture_assert(tctx
, !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true)),
332 "setting delete_on_close on OpenX file succeeded - should fail !");
334 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
335 talloc_asprintf(tctx
, "close - 2 failed (%s)", smbcli_errstr(cli1
->tree
)));
341 static bool deltest6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
345 del_clean_area(cli1
, cli2
);
347 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
348 SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
,
349 FILE_ATTRIBUTE_NORMAL
,
350 NTCREATEX_SHARE_ACCESS_READ
|
351 NTCREATEX_SHARE_ACCESS_WRITE
|
352 NTCREATEX_SHARE_ACCESS_DELETE
,
353 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
355 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
356 fname
, smbcli_errstr(cli1
->tree
)));
358 /* This should fail - only allowed on NT opens with DELETE access. */
361 !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true)),
362 "setting delete_on_close on file with no delete access succeeded - should fail !");
364 torture_assert_ntstatus_ok(tctx
,
365 smbcli_close(cli1
->tree
, fnum1
),
366 talloc_asprintf(tctx
,
367 "close - 2 failed (%s)",
368 smbcli_errstr(cli1
->tree
)));
374 static bool deltest7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
379 del_clean_area(cli1
, cli2
);
381 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
383 SEC_FILE_WRITE_DATA
|
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
)));
419 static bool deltest8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
425 del_clean_area(cli1
, cli2
);
427 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
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,
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
));
476 static bool deltest9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
480 uint32_t disps
[4] = {
481 NTCREATEX_DISP_SUPERSEDE
,
482 NTCREATEX_DISP_OVERWRITE_IF
,
483 NTCREATEX_DISP_CREATE
,
484 NTCREATEX_DISP_OPEN_IF
};
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
,
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!",
510 /* Must fail with NT_STATUS_INVALID_PARAMETER. */
511 status
= smbcli_nt_error(cli1
->tree
);
512 torture_assert_ntstatus_equal(tctx
,
514 NT_STATUS_INVALID_PARAMETER
,
515 talloc_asprintf(tctx
, "create of %s should return "
516 "NT_STATUS_INVALID_PARAMETER, got %s",
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
,
524 NT_STATUS_OBJECT_NAME_NOT_FOUND
,
525 talloc_asprintf(tctx
, "getattr of %s succeeded should "
526 "not have been created !",
534 static bool deltest9a(struct torture_context
*tctx
,
535 struct smbcli_state
*cli1
,
536 struct smbcli_state
*cli2
)
540 uint32_t disps
[4] = {
541 NTCREATEX_DISP_OVERWRITE_IF
,
543 NTCREATEX_DISP_OVERWRITE
,
544 NTCREATEX_DISP_OPEN_IF
};
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
);
554 talloc_asprintf(tctx
, "open of %s failed (%s)",
556 smbcli_errstr(cli1
->tree
)));
557 status
= smbcli_close(cli1
->tree
, fnum1
);
558 torture_assert_ntstatus_ok(tctx
,
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
,
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!",
575 /* Must fail with NT_STATUS_INVALID_PARAMETER. */
576 status
= smbcli_nt_error(cli1
->tree
);
577 torture_assert_ntstatus_equal(tctx
,
579 NT_STATUS_INVALID_PARAMETER
,
580 talloc_asprintf(tctx
, "create of %s should return "
581 "NT_STATUS_INVALID_PARAMETER, got %s",
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
,
591 talloc_asprintf(tctx
, "getattr of %s failed %s",
593 smbcli_errstr(cli1
->tree
)));
596 del_clean_area(cli1
, cli2
);
601 static bool deltest10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
605 del_clean_area(cli1
, cli2
);
607 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
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 !",
633 static bool deltest11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
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,
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
)));
664 static bool deltest12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
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,
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 "
690 smbcli_errstr(cli1
->tree
)));
696 static bool deltest13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
702 del_clean_area(cli1
, cli2
);
704 /* Test 13: Does resetting the delete on close flag affect a second
707 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
711 FILE_ATTRIBUTE_NORMAL
,
712 NTCREATEX_SHARE_ACCESS_READ
|
713 NTCREATEX_SHARE_ACCESS_WRITE
|
714 NTCREATEX_SHARE_ACCESS_DELETE
,
715 NTCREATEX_DISP_OVERWRITE_IF
,
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,
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
,
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
,
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!",
764 smbcli_close(cli1
->tree
, fnum1
);
770 static bool deltest14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
775 del_clean_area(cli1
, cli2
);
777 /* Test 14 -- directory */
779 dnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
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,
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 !");
814 static bool deltest15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
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,
831 FILE_ATTRIBUTE_NORMAL
,
832 NTCREATEX_SHARE_ACCESS_READ
|
833 NTCREATEX_SHARE_ACCESS_WRITE
|
834 NTCREATEX_SHARE_ACCESS_DELETE
,
835 NTCREATEX_DISP_OVERWRITE_IF
,
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,
847 FILE_ATTRIBUTE_NORMAL
,
848 NTCREATEX_SHARE_ACCESS_READ
|
849 NTCREATEX_SHARE_ACCESS_WRITE
|
850 NTCREATEX_SHARE_ACCESS_DELETE
,
851 NTCREATEX_DISP_OVERWRITE_IF
,
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
868 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname_new
, true, __location__
);
870 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname
, 0,
872 FILE_ATTRIBUTE_NORMAL
,
873 NTCREATEX_SHARE_ACCESS_READ
|
874 NTCREATEX_SHARE_ACCESS_WRITE
|
875 NTCREATEX_SHARE_ACCESS_DELETE
,
876 NTCREATEX_DISP_OVERWRITE_IF
,
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,
889 FILE_ATTRIBUTE_NORMAL
,
890 NTCREATEX_SHARE_ACCESS_READ
|
891 NTCREATEX_SHARE_ACCESS_WRITE
|
892 NTCREATEX_SHARE_ACCESS_DELETE
,
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,
903 FILE_ATTRIBUTE_NORMAL
,
904 NTCREATEX_SHARE_ACCESS_READ
|
905 NTCREATEX_SHARE_ACCESS_WRITE
|
906 NTCREATEX_SHARE_ACCESS_DELETE
,
910 torture_assert(tctx
, fnum1
== -1,
911 "smbcli_open succeeded, should have "
918 static bool deltest16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
924 del_clean_area(cli1
, cli2
);
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,
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
,
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)",
984 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
990 static bool deltest16a(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
996 del_clean_area(cli1
, cli2
);
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
,
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
,
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
);
1079 static bool deltest17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1083 bool correct
= true;
1085 del_clean_area(cli1
, cli2
);
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
,
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
|
1130 FILE_ATTRIBUTE_NORMAL
,
1131 NTCREATEX_SHARE_ACCESS_READ
|
1132 NTCREATEX_SHARE_ACCESS_WRITE
|
1133 NTCREATEX_SHARE_ACCESS_DELETE
,
1134 NTCREATEX_DISP_OPEN
,
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
);
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
)
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
,
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
|
1212 FILE_ATTRIBUTE_NORMAL
,
1213 NTCREATEX_SHARE_ACCESS_READ
|
1214 NTCREATEX_SHARE_ACCESS_WRITE
|
1215 NTCREATEX_SHARE_ACCESS_DELETE
,
1216 NTCREATEX_DISP_OPEN
,
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
);
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
)
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
,
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
,
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
|
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);
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)",
1325 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
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
)
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
,
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
,
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
|
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);
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)",
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)",
1412 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
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
)
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
|
1453 FILE_ATTRIBUTE_NORMAL
,
1454 NTCREATEX_SHARE_ACCESS_READ
|
1455 NTCREATEX_SHARE_ACCESS_WRITE
|
1456 NTCREATEX_SHARE_ACCESS_DELETE
,
1457 NTCREATEX_DISP_OPEN
,
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)",
1483 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1488 static bool deltest17e(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
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
,
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
|
1536 FILE_ATTRIBUTE_NORMAL
,
1537 NTCREATEX_SHARE_ACCESS_READ
|
1538 NTCREATEX_SHARE_ACCESS_WRITE
|
1539 NTCREATEX_SHARE_ACCESS_DELETE
,
1540 NTCREATEX_DISP_OPEN
,
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)",
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)",
1577 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1582 static bool deltest17f(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1587 bool correct
= true;
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
|
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);
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)",
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)",
1683 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1689 static bool deltest18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
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,
1708 SEC_FILE_WRITE_DATA
|
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);
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)",
1768 static bool deltest19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1772 bool correct
= true;
1774 del_clean_area(cli1
, cli2
);
1778 smbcli_deltree(cli1
->tree
, dname
);
1780 /* Firstly open and create with all access */
1781 fnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1783 SEC_FILE_WRITE_DATA
|
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,
1801 SEC_FILE_WRITE_DATA
|
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);
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
));
1860 static bool deltest20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1864 bool correct
= true;
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,
1876 SEC_FILE_WRITE_DATA
|
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);
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
,
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 !");
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
,
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
);
1933 static bool deltest20a(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1937 bool correct
= true;
1939 del_clean_area(cli1
, cli2
);
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
,
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
)));
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
)
2003 bool correct
= true;
2005 del_clean_area(cli1
, cli2
);
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
,
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
,
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
;
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
)));
2102 static bool deltest21(struct torture_context
*tctx
)
2105 struct smbcli_state
*cli1
;
2106 struct smbcli_state
*cli2
;
2107 bool correct
= true;
2109 if (!torture_open_connection(&cli1
, tctx
, 0))
2112 if (!torture_open_connection(&cli2
, tctx
, 1))
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
);
2140 if (!torture_open_connection(&cli1
, tctx
, 0)) {
2144 /* On slow build farm machines it might happen that they are not fast
2145 * enogh to delete the file for this test */
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
,
2158 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
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
)
2173 struct smbcli_state
*cli1
;
2174 bool correct
= true;
2176 if (!torture_open_connection(&cli1
, tctx
, 0))
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,
2188 SEC_FILE_WRITE_DATA
|
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,
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,
2224 SEC_FILE_WRITE_DATA
|
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",
2237 CHECK_STATUS(cli1
, NT_STATUS_DELETE_PENDING
);
2239 smbcli_close(cli1
->tree
, dnum2
);
2240 CHECK_STATUS(cli1
, NT_STATUS_OK
);
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
)
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,
2261 SEC_FILE_WRITE_DATA
|
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,
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,
2283 SEC_FILE_WRITE_DATA
|
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");
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
)
2312 struct smbcli_state
*cli1
;
2313 bool correct
= true;
2315 if (!torture_open_connection(&cli1
, tctx
, 0))
2318 smbcli_deltree(cli1
->tree
, fname
);
2320 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
2322 SEC_FILE_WRITE_DATA
|
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
,
2353 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2359 static bool deltest25(struct torture_context
*tctx
,
2360 struct smbcli_state
*cli1
,
2361 struct smbcli_state
*cli2
)
2365 uint32_t disps
[4] = {
2366 NTCREATEX_DISP_SUPERSEDE
,
2367 NTCREATEX_DISP_OVERWRITE_IF
,
2368 NTCREATEX_DISP_CREATE
,
2369 NTCREATEX_DISP_OPEN_IF
};
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,
2385 FILE_ATTRIBUTE_DIRECTORY
,
2386 NTCREATEX_SHARE_ACCESS_NONE
,
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!",
2396 /* Must fail with NT_STATUS_INVALID_PARAMETER. */
2397 status
= smbcli_nt_error(cli1
->tree
);
2398 torture_assert_ntstatus_equal(tctx
,
2400 NT_STATUS_INVALID_PARAMETER
,
2401 talloc_asprintf(tctx
, "create of %s should return "
2402 "NT_STATUS_INVALID_PARAMETER, got %s",
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
,
2413 NT_STATUS_OBJECT_NAME_NOT_FOUND
,
2414 talloc_asprintf(tctx
, "getattr of %s succeeded should "
2415 "not have been created !",
2423 Test delete on close semantics.
2425 struct torture_suite
*torture_test_delete(TALLOC_CTX
*ctx
)
2427 struct torture_suite
*suite
= torture_suite_create(
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
);