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"
30 static bool check_delete_on_close(struct torture_context
*tctx
,
31 struct smbcli_state
*cli
, int fnum
,
32 const char *fname
, bool expect_it
,
35 union smb_search_data data
;
38 time_t c_time
, a_time
, m_time
;
42 status
= torture_single_search(cli
, tctx
,
45 RAW_SEARCH_DATA_FULL_DIRECTORY_INFO
,
46 FILE_ATTRIBUTE_DIRECTORY
,
48 torture_assert_ntstatus_ok(tctx
, status
,
49 talloc_asprintf(tctx
, "single_search failed (%s)", where
));
52 union smb_fileinfo io
;
53 int nlink
= expect_it
? 0 : 1;
55 io
.all_info
.level
= RAW_FILEINFO_ALL_INFO
;
56 io
.all_info
.in
.file
.fnum
= fnum
;
58 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &io
);
59 torture_assert_ntstatus_ok(tctx
, status
, talloc_asprintf(tctx
,
60 "qfileinfo failed (%s)", where
));
62 torture_assert(tctx
, expect_it
== io
.all_info
.out
.delete_pending
,
64 "%s - Expected del_on_close flag %d, qfileinfo/all_info gave %d",
65 where
, expect_it
, io
.all_info
.out
.delete_pending
));
67 torture_assert(tctx
, nlink
== io
.all_info
.out
.nlink
,
69 "%s - Expected nlink %d, qfileinfo/all_info gave %d",
70 where
, nlink
, io
.all_info
.out
.nlink
));
72 io
.standard_info
.level
= RAW_FILEINFO_STANDARD_INFO
;
73 io
.standard_info
.in
.file
.fnum
= fnum
;
75 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &io
);
76 torture_assert_ntstatus_ok(tctx
, status
, talloc_asprintf(tctx
, "qpathinfo failed (%s)", where
));
78 torture_assert(tctx
, expect_it
== io
.standard_info
.out
.delete_pending
,
79 talloc_asprintf(tctx
, "%s - Expected del_on_close flag %d, qfileinfo/standard_info gave %d\n",
80 where
, expect_it
, io
.standard_info
.out
.delete_pending
));
82 torture_assert(tctx
, nlink
== io
.standard_info
.out
.nlink
,
83 talloc_asprintf(tctx
, "%s - Expected nlink %d, qfileinfo/standard_info gave %d",
84 where
, nlink
, io
.all_info
.out
.nlink
));
87 status
= smbcli_qpathinfo(cli
->tree
, fname
,
88 &c_time
, &a_time
, &m_time
,
92 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_DELETE_PENDING
,
93 "qpathinfo did not give correct error code");
95 torture_assert_ntstatus_ok(tctx
, status
,
96 talloc_asprintf(tctx
, "qpathinfo failed (%s)", where
));
102 #define CHECK_STATUS(_cli, _expected) \
103 torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
106 static const char *fname
= "\\delete.file";
107 static const char *fname_new
= "\\delete.new";
108 static const char *dname
= "\\delete.dir";
110 static void del_clean_area(struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
112 smb_raw_exit(cli1
->session
);
113 smb_raw_exit(cli2
->session
);
115 smbcli_deltree(cli1
->tree
, dname
);
116 smbcli_setatr(cli1
->tree
, fname
, 0, 0);
117 smbcli_unlink(cli1
->tree
, fname
);
118 smbcli_setatr(cli1
->tree
, fname_new
, 0, 0);
119 smbcli_unlink(cli1
->tree
, fname_new
);
122 /* Test 1 - this should delete the file on close. */
124 static bool deltest1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
128 del_clean_area(cli1
, cli2
);
130 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
132 FILE_ATTRIBUTE_NORMAL
,
133 NTCREATEX_SHARE_ACCESS_DELETE
, NTCREATEX_DISP_OVERWRITE_IF
,
134 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
136 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
137 fname
, smbcli_errstr(cli1
->tree
)));
139 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
140 talloc_asprintf(tctx
, "close failed (%s)", smbcli_errstr(cli1
->tree
)));
142 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
, DENY_NONE
);
143 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s succeeded (should fail)",
149 /* Test 2 - this should delete the file on close. */
150 static bool deltest2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
154 del_clean_area(cli1
, cli2
);
156 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
158 FILE_ATTRIBUTE_NORMAL
, NTCREATEX_SHARE_ACCESS_NONE
,
159 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
161 torture_assert(tctx
, fnum1
!= -1,
162 talloc_asprintf(tctx
, "open of %s failed (%s)",
163 fname
, smbcli_errstr(cli1
->tree
)));
165 torture_assert_ntstatus_ok(tctx
, smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
166 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
167 smbcli_errstr(cli1
->tree
)));
169 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
170 talloc_asprintf(tctx
, "close failed (%s)",
171 smbcli_errstr(cli1
->tree
)));
173 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
175 printf("(%s) open of %s succeeded should have been deleted on close !\n",
176 __location__
, fname
);
177 if (NT_STATUS_IS_ERR(smbcli_close(cli1
->tree
, fnum1
))) {
178 printf("(%s) close failed (%s)\n",
179 __location__
, smbcli_errstr(cli1
->tree
));
182 smbcli_unlink(cli1
->tree
, fname
);
188 static bool deltest3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
193 del_clean_area(cli1
, cli2
);
195 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
197 FILE_ATTRIBUTE_NORMAL
,
198 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
,
199 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
201 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
202 fname
, smbcli_errstr(cli1
->tree
)));
204 /* This should fail with a sharing violation - open for delete is only compatible
205 with SHARE_DELETE. */
207 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
208 SEC_RIGHTS_FILE_READ
,
209 FILE_ATTRIBUTE_NORMAL
,
210 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
,
211 NTCREATEX_DISP_OPEN
, 0, 0);
213 torture_assert(tctx
, fnum2
== -1,
214 talloc_asprintf(tctx
, "open - 2 of %s succeeded - should have failed.",
217 /* This should succeed. */
219 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
220 SEC_RIGHTS_FILE_READ
,
221 FILE_ATTRIBUTE_NORMAL
,
222 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
223 NTCREATEX_DISP_OPEN
, 0, 0);
225 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 2 of %s failed (%s)",
226 fname
, smbcli_errstr(cli1
->tree
)));
228 torture_assert_ntstatus_ok(tctx
,
229 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
230 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
231 smbcli_errstr(cli1
->tree
)));
233 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
234 talloc_asprintf(tctx
, "close 1 failed (%s)",
235 smbcli_errstr(cli1
->tree
)));
237 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum2
),
238 talloc_asprintf(tctx
, "close 2 failed (%s)",
239 smbcli_errstr(cli1
->tree
)));
241 /* This should fail - file should no longer be there. */
243 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
245 printf("(%s) open of %s succeeded should have been deleted on close !\n",
246 __location__
, fname
);
247 if (NT_STATUS_IS_ERR(smbcli_close(cli1
->tree
, fnum1
))) {
248 printf("(%s) close failed (%s)\n",
249 __location__
, smbcli_errstr(cli1
->tree
));
251 smbcli_unlink(cli1
->tree
, fname
);
258 static bool deltest4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
264 del_clean_area(cli1
, cli2
);
266 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
268 SEC_FILE_WRITE_DATA
|
270 FILE_ATTRIBUTE_NORMAL
,
271 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
,
272 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
274 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
275 fname
, smbcli_errstr(cli1
->tree
)));
277 /* This should succeed. */
278 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
279 SEC_RIGHTS_FILE_READ
,
280 FILE_ATTRIBUTE_NORMAL
,
281 NTCREATEX_SHARE_ACCESS_READ
|
282 NTCREATEX_SHARE_ACCESS_WRITE
|
283 NTCREATEX_SHARE_ACCESS_DELETE
,
284 NTCREATEX_DISP_OPEN
, 0, 0);
285 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 2 of %s failed (%s)",
286 fname
, smbcli_errstr(cli1
->tree
)));
288 torture_assert_ntstatus_ok(tctx
,
289 smbcli_close(cli1
->tree
, fnum2
),
290 talloc_asprintf(tctx
, "close - 1 failed (%s)",
291 smbcli_errstr(cli1
->tree
)));
293 torture_assert_ntstatus_ok(tctx
,
294 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
295 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
296 smbcli_errstr(cli1
->tree
)));
298 /* This should fail - no more opens once delete on close set. */
299 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
300 SEC_RIGHTS_FILE_READ
,
301 FILE_ATTRIBUTE_NORMAL
,
302 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
303 NTCREATEX_DISP_OPEN
, 0, 0);
304 torture_assert(tctx
, fnum2
== -1,
305 talloc_asprintf(tctx
, "open - 3 of %s succeeded ! Should have failed.",
308 CHECK_STATUS(cli1
, NT_STATUS_DELETE_PENDING
);
310 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
311 talloc_asprintf(tctx
, "close - 2 failed (%s)",
312 smbcli_errstr(cli1
->tree
)));
318 static bool deltest5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
322 del_clean_area(cli1
, cli2
);
324 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
325 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
326 fname
, smbcli_errstr(cli1
->tree
)));
328 /* This should fail - only allowed on NT opens with DELETE access. */
330 torture_assert(tctx
, !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true)),
331 "setting delete_on_close on OpenX file succeeded - should fail !");
333 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
334 talloc_asprintf(tctx
, "close - 2 failed (%s)", smbcli_errstr(cli1
->tree
)));
340 static bool deltest6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
344 del_clean_area(cli1
, cli2
);
346 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
347 SEC_FILE_READ_DATA
| SEC_FILE_WRITE_DATA
,
348 FILE_ATTRIBUTE_NORMAL
,
349 NTCREATEX_SHARE_ACCESS_READ
|
350 NTCREATEX_SHARE_ACCESS_WRITE
|
351 NTCREATEX_SHARE_ACCESS_DELETE
,
352 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
354 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
355 fname
, smbcli_errstr(cli1
->tree
)));
357 /* This should fail - only allowed on NT opens with DELETE access. */
360 !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true)),
361 "setting delete_on_close on file with no delete access succeeded - should fail !");
363 torture_assert_ntstatus_ok(tctx
,
364 smbcli_close(cli1
->tree
, fnum1
),
365 talloc_asprintf(tctx
, "close - 2 failed (%s)",
366 smbcli_errstr(cli1
->tree
)));
372 static bool deltest7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
377 del_clean_area(cli1
, cli2
);
379 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
381 SEC_FILE_WRITE_DATA
|
383 FILE_ATTRIBUTE_NORMAL
, 0,
384 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
386 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
387 fname
, smbcli_errstr(cli1
->tree
)));
389 torture_assert_ntstatus_ok(tctx
, smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
390 "setting delete_on_close on file failed !");
392 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, true, __location__
);
394 torture_assert_ntstatus_ok(tctx
,
395 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, false),
396 "unsetting delete_on_close on file failed !");
398 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
400 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
401 talloc_asprintf(tctx
, "close - 2 failed (%s)", smbcli_errstr(cli1
->tree
)));
403 /* This next open should succeed - we reset the flag. */
405 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
406 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
407 fname
, smbcli_errstr(cli1
->tree
)));
409 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
410 talloc_asprintf(tctx
, "close - 2 failed (%s)",
411 smbcli_errstr(cli1
->tree
)));
417 static bool deltest8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
423 del_clean_area(cli1
, cli2
);
425 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
429 FILE_ATTRIBUTE_NORMAL
,
430 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
431 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
433 torture_assert(tctx
, fnum1
!= -1,
434 talloc_asprintf(tctx
, "open of %s failed (%s)",
435 fname
, smbcli_errstr(cli1
->tree
)));
437 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname
, 0,
441 FILE_ATTRIBUTE_NORMAL
,
442 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
,
443 NTCREATEX_DISP_OPEN
, 0, 0);
445 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
446 fname
, smbcli_errstr(cli1
->tree
)));
448 torture_assert_ntstatus_ok(tctx
,
449 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
450 "setting delete_on_close on file failed !");
452 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, true, __location__
);
453 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, true, __location__
);
455 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
456 talloc_asprintf(tctx
, "close - 1 failed (%s)",
457 smbcli_errstr(cli1
->tree
)));
459 correct
&= check_delete_on_close(tctx
, cli1
, -1, fname
, true, __location__
);
460 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, true, __location__
);
462 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli2
->tree
, fnum2
),
463 talloc_asprintf(tctx
, "close - 2 failed (%s)", smbcli_errstr(cli2
->tree
)));
465 /* This should fail.. */
466 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
467 torture_assert(tctx
, fnum1
== -1,
468 talloc_asprintf(tctx
, "open of %s succeeded should have been deleted on close !\n", fname
));
474 static bool deltest9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
478 del_clean_area(cli1
, cli2
);
480 /* This should fail - we need to set DELETE_ACCESS. */
481 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
482 SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
,
483 FILE_ATTRIBUTE_NORMAL
,
484 NTCREATEX_SHARE_ACCESS_NONE
,
485 NTCREATEX_DISP_OVERWRITE_IF
,
486 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
488 torture_assert(tctx
, fnum1
== -1,
489 talloc_asprintf(tctx
, "open of %s succeeded should have failed!",
496 static bool deltest10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
500 del_clean_area(cli1
, cli2
);
502 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
506 FILE_ATTRIBUTE_NORMAL
,
507 NTCREATEX_SHARE_ACCESS_NONE
,
508 NTCREATEX_DISP_OVERWRITE_IF
,
509 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
510 torture_assert(tctx
, fnum1
!= -1,
511 talloc_asprintf(tctx
, "open of %s failed (%s)",
512 fname
, smbcli_errstr(cli1
->tree
)));
514 /* This should delete the file. */
515 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
516 talloc_asprintf(tctx
, "close failed (%s)",
517 smbcli_errstr(cli1
->tree
)));
519 /* This should fail.. */
520 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
521 torture_assert(tctx
, fnum1
== -1,
522 talloc_asprintf(tctx
, "open of %s succeeded should have been deleted on close !",
528 static bool deltest11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
533 del_clean_area(cli1
, cli2
);
535 /* test 11 - does having read only attribute still allow delete on close. */
537 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
539 FILE_ATTRIBUTE_READONLY
,
540 NTCREATEX_SHARE_ACCESS_NONE
,
541 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
543 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
544 fname
, smbcli_errstr(cli1
->tree
)));
546 status
= smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true);
548 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_CANNOT_DELETE
,
549 talloc_asprintf(tctx
, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1
->tree
)));
551 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
552 talloc_asprintf(tctx
, "close failed (%s)",
553 smbcli_errstr(cli1
->tree
)));
559 static bool deltest12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
564 del_clean_area(cli1
, cli2
);
566 /* test 12 - does having read only attribute still allow delete on
567 * close at time of open. */
569 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
571 FILE_ATTRIBUTE_READONLY
,
572 NTCREATEX_SHARE_ACCESS_DELETE
,
573 NTCREATEX_DISP_OVERWRITE_IF
,
574 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
576 torture_assert(tctx
, fnum1
== -1,
577 talloc_asprintf(tctx
, "open of %s succeeded. Should fail with "
578 "NT_STATUS_CANNOT_DELETE.\n", fname
));
580 status
= smbcli_nt_error(cli1
->tree
);
581 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_CANNOT_DELETE
,
582 talloc_asprintf(tctx
, "setting delete_on_close on open should "
583 "fail with NT_STATUS_CANNOT_DELETE. Got %s "
585 smbcli_errstr(cli1
->tree
)));
591 static bool deltest13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
597 del_clean_area(cli1
, cli2
);
599 /* Test 13: Does resetting the delete on close flag affect a second
602 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
606 FILE_ATTRIBUTE_NORMAL
,
607 NTCREATEX_SHARE_ACCESS_READ
|
608 NTCREATEX_SHARE_ACCESS_WRITE
|
609 NTCREATEX_SHARE_ACCESS_DELETE
,
610 NTCREATEX_DISP_OVERWRITE_IF
,
613 torture_assert(tctx
, fnum1
!= -1,
614 talloc_asprintf(tctx
, "open of %s failed (%s)",
615 fname
, smbcli_errstr(cli1
->tree
)));
617 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname
, 0,
621 FILE_ATTRIBUTE_NORMAL
,
622 NTCREATEX_SHARE_ACCESS_READ
|
623 NTCREATEX_SHARE_ACCESS_WRITE
|
624 NTCREATEX_SHARE_ACCESS_DELETE
,
625 NTCREATEX_DISP_OPEN
, 0, 0);
627 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
,
628 "open of %s failed (%s)",
629 fname
, smbcli_errstr(cli2
->tree
)));
631 torture_assert_ntstatus_ok(tctx
,
632 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
,
634 "setting delete_on_close on file failed !");
636 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, true, __location__
);
637 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, true, __location__
);
639 torture_assert_ntstatus_ok(tctx
, smbcli_nt_delete_on_close(cli2
->tree
, fnum2
,
641 "setting delete_on_close on file failed !");
643 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
644 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, false, __location__
);
646 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli1
->tree
, fnum1
),
647 talloc_asprintf(tctx
, "close - 1 failed (%s)",
648 smbcli_errstr(cli1
->tree
)));
650 torture_assert_ntstatus_ok(tctx
, smbcli_close(cli2
->tree
, fnum2
),
651 talloc_asprintf(tctx
, "close - 2 failed (%s)",
652 smbcli_errstr(cli2
->tree
)));
654 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDONLY
, DENY_NONE
);
656 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed!",
659 smbcli_close(cli1
->tree
, fnum1
);
665 static bool deltest14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
670 del_clean_area(cli1
, cli2
);
672 /* Test 14 -- directory */
674 dnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
678 FILE_ATTRIBUTE_DIRECTORY
,
679 NTCREATEX_SHARE_ACCESS_READ
|
680 NTCREATEX_SHARE_ACCESS_WRITE
|
681 NTCREATEX_SHARE_ACCESS_DELETE
,
682 NTCREATEX_DISP_CREATE
, 0, 0);
683 torture_assert(tctx
, dnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed: %s!",
684 dname
, smbcli_errstr(cli1
->tree
)));
686 correct
&= check_delete_on_close(tctx
, cli1
, dnum1
, dname
, false, __location__
);
687 torture_assert_ntstatus_ok(tctx
, smbcli_nt_delete_on_close(cli1
->tree
, dnum1
, true),
688 "setting delete_on_close on file failed !");
689 correct
&= check_delete_on_close(tctx
, cli1
, dnum1
, dname
, true, __location__
);
690 smbcli_close(cli1
->tree
, dnum1
);
692 /* Now it should be gone... */
694 dnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
698 FILE_ATTRIBUTE_DIRECTORY
,
699 NTCREATEX_SHARE_ACCESS_READ
|
700 NTCREATEX_SHARE_ACCESS_WRITE
|
701 NTCREATEX_SHARE_ACCESS_DELETE
,
702 NTCREATEX_DISP_OPEN
, 0, 0);
703 torture_assert(tctx
, dnum1
== -1, "setting delete_on_close on file succeeded !");
709 static bool deltest15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
716 del_clean_area(cli1
, cli2
);
718 /* Test 15: delete on close under rename */
720 smbcli_setatr(cli1
->tree
, fname
, 0, 0);
721 smbcli_unlink(cli1
->tree
, fname
);
722 smbcli_unlink(cli1
->tree
, fname_new
);
724 fnum1
= smbcli_nt_create_full(cli1
->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_OVERWRITE_IF
,
733 torture_assert(tctx
, fnum1
!= -1,
734 talloc_asprintf(tctx
, "open - 1 of %s failed (%s)", fname
, smbcli_errstr(cli1
->tree
)));
736 status
= smbcli_rename(cli2
->tree
, fname
, fname_new
);
738 torture_assert_ntstatus_ok(tctx
, status
, "renaming failed!");
740 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname_new
, 0,
742 FILE_ATTRIBUTE_NORMAL
,
743 NTCREATEX_SHARE_ACCESS_READ
|
744 NTCREATEX_SHARE_ACCESS_WRITE
|
745 NTCREATEX_SHARE_ACCESS_DELETE
,
746 NTCREATEX_DISP_OVERWRITE_IF
,
749 torture_assert(tctx
, fnum2
!= -1,
750 talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
751 fname_new
, smbcli_errstr(cli1
->tree
)));
753 status
= smbcli_nt_delete_on_close(cli2
->tree
, fnum2
, true);
755 torture_assert_ntstatus_ok(tctx
, status
,
756 "setting delete_on_close on file failed !");
758 smbcli_close(cli2
->tree
, fnum2
);
760 /* The file should be around under the new name, there's a second
763 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname_new
, true, __location__
);
765 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname
, 0,
767 FILE_ATTRIBUTE_NORMAL
,
768 NTCREATEX_SHARE_ACCESS_READ
|
769 NTCREATEX_SHARE_ACCESS_WRITE
|
770 NTCREATEX_SHARE_ACCESS_DELETE
,
771 NTCREATEX_DISP_OVERWRITE_IF
,
774 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
775 fname
, smbcli_errstr(cli1
->tree
)));
777 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, false, __location__
);
779 smbcli_close(cli2
->tree
, fnum2
);
780 smbcli_close(cli1
->tree
, fnum1
);
782 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
784 FILE_ATTRIBUTE_NORMAL
,
785 NTCREATEX_SHARE_ACCESS_READ
|
786 NTCREATEX_SHARE_ACCESS_WRITE
|
787 NTCREATEX_SHARE_ACCESS_DELETE
,
791 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
792 fname
, smbcli_errstr(cli1
->tree
)));
794 smbcli_close(cli1
->tree
, fnum1
);
796 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname_new
, 0,
798 FILE_ATTRIBUTE_NORMAL
,
799 NTCREATEX_SHARE_ACCESS_READ
|
800 NTCREATEX_SHARE_ACCESS_WRITE
|
801 NTCREATEX_SHARE_ACCESS_DELETE
,
805 torture_assert(tctx
, fnum1
== -1,
806 "smbcli_open succeeded, should have "
813 static bool deltest16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
819 del_clean_area(cli1
, cli2
);
823 /* Ensure the file doesn't already exist. */
824 smbcli_close(cli1
->tree
, fnum1
);
825 smbcli_close(cli1
->tree
, fnum2
);
826 smbcli_setatr(cli1
->tree
, fname
, 0, 0);
827 smbcli_unlink(cli1
->tree
, fname
);
829 /* Firstly create with all access, but delete on close. */
830 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
832 FILE_ATTRIBUTE_NORMAL
,
833 NTCREATEX_SHARE_ACCESS_READ
|
834 NTCREATEX_SHARE_ACCESS_WRITE
|
835 NTCREATEX_SHARE_ACCESS_DELETE
,
836 NTCREATEX_DISP_CREATE
,
837 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
839 torture_assert (tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)", fname
, smbcli_errstr(cli1
->tree
)));
841 /* The delete on close bit is *not* reported as being set. */
842 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
844 /* The delete on close bit is *not* reported as being set. */
845 correct
&= check_delete_on_close(tctx
, cli1
, -1, fname
, false, __location__
);
846 correct
&= check_delete_on_close(tctx
, cli2
, -1, fname
, false, __location__
);
848 /* Now try opening again for read-only. */
849 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname
, 0,
850 SEC_RIGHTS_FILE_READ
,
851 FILE_ATTRIBUTE_NORMAL
,
852 NTCREATEX_SHARE_ACCESS_READ
|
853 NTCREATEX_SHARE_ACCESS_WRITE
|
854 NTCREATEX_SHARE_ACCESS_DELETE
,
859 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
860 fname
, smbcli_errstr(cli1
->tree
)));
862 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
863 correct
&= check_delete_on_close(tctx
, cli1
, -1, fname
, false, __location__
);
864 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, false, __location__
);
865 correct
&= check_delete_on_close(tctx
, cli2
, -1, fname
, false, __location__
);
867 smbcli_close(cli1
->tree
, fnum1
);
869 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, true, __location__
);
870 correct
&= check_delete_on_close(tctx
, cli2
, -1, fname
, true, __location__
);
872 smbcli_close(cli2
->tree
, fnum2
);
874 /* And the file should be deleted ! */
875 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
, DENY_NONE
);
876 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s succeeded (should fail)",
883 static bool deltest17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
889 del_clean_area(cli1
, cli2
);
893 /* Ensure the file doesn't already exist. */
894 smbcli_close(cli1
->tree
, fnum1
);
895 smbcli_close(cli1
->tree
, fnum2
);
896 smbcli_setatr(cli1
->tree
, fname
, 0, 0);
897 smbcli_unlink(cli1
->tree
, fname
);
899 /* Firstly open and create with all access */
900 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
902 FILE_ATTRIBUTE_NORMAL
,
903 NTCREATEX_SHARE_ACCESS_READ
|
904 NTCREATEX_SHARE_ACCESS_WRITE
|
905 NTCREATEX_SHARE_ACCESS_DELETE
,
906 NTCREATEX_DISP_CREATE
,
908 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
909 fname
, smbcli_errstr(cli1
->tree
)));
911 /* And close - just to create the file. */
912 smbcli_close(cli1
->tree
, fnum1
);
914 /* Next open with all access, but add delete on close. */
915 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
917 FILE_ATTRIBUTE_NORMAL
,
918 NTCREATEX_SHARE_ACCESS_READ
|
919 NTCREATEX_SHARE_ACCESS_WRITE
|
920 NTCREATEX_SHARE_ACCESS_DELETE
,
922 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
924 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
925 fname
, smbcli_errstr(cli1
->tree
)));
927 /* The delete on close bit is *not* reported as being set. */
928 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
930 /* Now try opening again for read-only. */
931 fnum2
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
932 SEC_RIGHTS_FILE_READ
|
934 FILE_ATTRIBUTE_NORMAL
,
935 NTCREATEX_SHARE_ACCESS_READ
|
936 NTCREATEX_SHARE_ACCESS_WRITE
|
937 NTCREATEX_SHARE_ACCESS_DELETE
,
942 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
943 fname
, smbcli_errstr(cli1
->tree
)));
945 /* still not reported as being set on either */
946 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
947 correct
&= check_delete_on_close(tctx
, cli1
, fnum2
, fname
, false, __location__
);
949 smbcli_close(cli1
->tree
, fnum1
);
951 /* After the first close, the files has the delete on close bit set. */
952 correct
&= check_delete_on_close(tctx
, cli1
, fnum2
, fname
, true, __location__
);
954 smbcli_close(cli1
->tree
, fnum2
);
956 /* Make sure the file has been deleted */
957 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
, DENY_NONE
);
958 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s failed (should succeed) - %s",
959 fname
, smbcli_errstr(cli1
->tree
)));
961 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
967 static bool deltest18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
973 del_clean_area(cli1
, cli2
);
975 /* Test 18. With directories. */
977 /* Ensure the file doesn't already exist. */
978 smbcli_close(cli1
->tree
, fnum1
);
979 smbcli_close(cli1
->tree
, fnum2
);
981 smbcli_deltree(cli1
->tree
, dname
);
983 /* Firstly create with all access, but delete on close. */
984 fnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
988 FILE_ATTRIBUTE_DIRECTORY
,
989 NTCREATEX_SHARE_ACCESS_READ
|
990 NTCREATEX_SHARE_ACCESS_WRITE
|
991 NTCREATEX_SHARE_ACCESS_DELETE
,
992 NTCREATEX_DISP_CREATE
,
993 NTCREATEX_OPTIONS_DIRECTORY
|NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
995 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
996 dname
, smbcli_errstr(cli1
->tree
)));
999 * The delete on close bit is *not* reported as being set.
1000 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1001 * close as being set. This causes the subsequent create to fail with
1002 * NT_STATUS_DELETE_PENDING.
1004 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, dname
, false, __location__
);
1006 /* Now try opening again for read-only. */
1007 fnum2
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1008 SEC_RIGHTS_FILE_READ
,
1009 FILE_ATTRIBUTE_DIRECTORY
,
1010 NTCREATEX_SHARE_ACCESS_READ
|
1011 NTCREATEX_SHARE_ACCESS_WRITE
|
1012 NTCREATEX_SHARE_ACCESS_DELETE
,
1013 NTCREATEX_DISP_OPEN
,
1014 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1018 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
1019 dname
, smbcli_errstr(cli1
->tree
)));
1021 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, dname
, false, __location__
);
1022 correct
&= check_delete_on_close(tctx
, cli1
, fnum2
, dname
, false, __location__
);
1024 smbcli_close(cli1
->tree
, fnum1
);
1026 correct
&= check_delete_on_close(tctx
, cli1
, fnum2
, dname
, true, __location__
);
1028 smbcli_close(cli1
->tree
, fnum2
);
1030 /* And the directory should be deleted ! */
1031 fnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1032 SEC_RIGHTS_FILE_READ
,
1033 FILE_ATTRIBUTE_DIRECTORY
,
1034 NTCREATEX_SHARE_ACCESS_READ
|
1035 NTCREATEX_SHARE_ACCESS_WRITE
|
1036 NTCREATEX_SHARE_ACCESS_DELETE
,
1037 NTCREATEX_DISP_OPEN
,
1038 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1039 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s succeeded (should fail)",
1046 static bool deltest19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1050 bool correct
= true;
1052 del_clean_area(cli1
, cli2
);
1056 smbcli_deltree(cli1
->tree
, dname
);
1058 /* Firstly open and create with all access */
1059 fnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1061 SEC_FILE_WRITE_DATA
|
1063 FILE_ATTRIBUTE_DIRECTORY
,
1064 NTCREATEX_SHARE_ACCESS_READ
|
1065 NTCREATEX_SHARE_ACCESS_WRITE
|
1066 NTCREATEX_SHARE_ACCESS_DELETE
,
1067 NTCREATEX_DISP_CREATE
,
1068 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1070 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
1071 dname
, smbcli_errstr(cli1
->tree
)));
1073 /* And close - just to create the directory. */
1074 smbcli_close(cli1
->tree
, fnum1
);
1076 /* Next open with all access, but add delete on close. */
1077 fnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1079 SEC_FILE_WRITE_DATA
|
1081 FILE_ATTRIBUTE_DIRECTORY
,
1082 NTCREATEX_SHARE_ACCESS_READ
|
1083 NTCREATEX_SHARE_ACCESS_WRITE
|
1084 NTCREATEX_SHARE_ACCESS_DELETE
,
1085 NTCREATEX_DISP_OPEN
,
1086 NTCREATEX_OPTIONS_DIRECTORY
|NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
1088 torture_assert(tctx
, fnum1
!= -1,
1089 talloc_asprintf(tctx
, "open - 1 of %s failed (%s)", fname
, smbcli_errstr(cli1
->tree
)));
1092 * The delete on close bit is *not* reported as being set.
1093 * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1094 * close as being set. This causes the subsequent create to fail with
1095 * NT_STATUS_DELETE_PENDING.
1097 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, dname
, false, __location__
);
1099 /* Now try opening again for read-only. */
1100 fnum2
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1101 SEC_RIGHTS_FILE_READ
,
1102 FILE_ATTRIBUTE_DIRECTORY
,
1103 NTCREATEX_SHARE_ACCESS_READ
|
1104 NTCREATEX_SHARE_ACCESS_WRITE
|
1105 NTCREATEX_SHARE_ACCESS_DELETE
,
1106 NTCREATEX_DISP_OPEN
,
1107 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1110 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
1111 dname
, smbcli_errstr(cli1
->tree
)));
1113 smbcli_close(cli1
->tree
, fnum1
);
1115 correct
&= check_delete_on_close(tctx
, cli1
, fnum2
, dname
, true, __location__
);
1117 smbcli_close(cli1
->tree
, fnum2
);
1119 /* See if the file is deleted - for a directory this seems to be true ! */
1120 fnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1121 SEC_RIGHTS_FILE_READ
,
1122 FILE_ATTRIBUTE_DIRECTORY
,
1123 NTCREATEX_SHARE_ACCESS_READ
|
1124 NTCREATEX_SHARE_ACCESS_WRITE
|
1125 NTCREATEX_SHARE_ACCESS_DELETE
,
1126 NTCREATEX_DISP_OPEN
,
1127 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1129 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1131 torture_assert(tctx
, fnum1
== -1,
1132 talloc_asprintf(tctx
, "open of %s succeeded (should fail)", dname
));
1138 static bool deltest20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1142 bool correct
= true;
1145 del_clean_area(cli1
, cli2
);
1147 /* Test 20 -- non-empty directory hardest to get right... */
1149 if (torture_setting_bool(tctx
, "samba3", false)) {
1153 smbcli_deltree(cli1
->tree
, dname
);
1155 dnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1157 SEC_FILE_WRITE_DATA
|
1159 FILE_ATTRIBUTE_DIRECTORY
,
1160 NTCREATEX_SHARE_ACCESS_READ
|
1161 NTCREATEX_SHARE_ACCESS_WRITE
|
1162 NTCREATEX_SHARE_ACCESS_DELETE
,
1163 NTCREATEX_DISP_CREATE
,
1164 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1165 torture_assert(tctx
, dnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed: %s!",
1166 dname
, smbcli_errstr(cli1
->tree
)));
1168 correct
&= check_delete_on_close(tctx
, cli1
, dnum1
, dname
, false, __location__
);
1169 status
= smbcli_nt_delete_on_close(cli1
->tree
, dnum1
, true);
1173 asprintf(&fullname
, "\\%s%s", dname
, fname
);
1174 fnum1
= smbcli_open(cli1
->tree
, fullname
, O_CREAT
|O_RDWR
,
1176 torture_assert(tctx
, fnum1
== -1,
1177 "smbcli_open succeeded, should have "
1178 "failed with NT_STATUS_DELETE_PENDING"
1181 torture_assert_ntstatus_equal(tctx
,
1182 smbcli_nt_error(cli1
->tree
),
1183 NT_STATUS_DELETE_PENDING
,
1184 "smbcli_open failed");
1187 status
= smbcli_nt_delete_on_close(cli1
->tree
, dnum1
, false);
1188 torture_assert_ntstatus_ok(tctx
, status
,
1189 "setting delete_on_close on file failed !");
1193 asprintf(&fullname
, "\\%s%s", dname
, fname
);
1194 fnum1
= smbcli_open(cli1
->tree
, fullname
, O_CREAT
|O_RDWR
,
1196 torture_assert(tctx
, fnum1
!= -1,
1197 talloc_asprintf(tctx
, "smbcli_open failed: %s\n",
1198 smbcli_errstr(cli1
->tree
)));
1199 smbcli_close(cli1
->tree
, fnum1
);
1202 status
= smbcli_nt_delete_on_close(cli1
->tree
, dnum1
, true);
1204 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_DIRECTORY_NOT_EMPTY
,
1205 "setting delete_on_close failed");
1206 smbcli_close(cli1
->tree
, dnum1
);
1212 static bool deltest20a(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1216 bool correct
= true;
1218 del_clean_area(cli1
, cli2
);
1222 /* Ensure the file doesn't already exist. */
1223 smbcli_close(cli1
->tree
, fnum1
);
1224 smbcli_close(cli1
->tree
, fnum2
);
1225 smbcli_setatr(cli1
->tree
, fname
, 0, 0);
1226 smbcli_unlink(cli1
->tree
, fname
);
1228 /* Firstly open and create with all access */
1229 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
1230 SEC_RIGHTS_FILE_ALL
,
1231 FILE_ATTRIBUTE_NORMAL
,
1232 NTCREATEX_SHARE_ACCESS_READ
|
1233 NTCREATEX_SHARE_ACCESS_WRITE
|
1234 NTCREATEX_SHARE_ACCESS_DELETE
,
1235 NTCREATEX_DISP_CREATE
,
1237 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
1238 fname
, smbcli_errstr(cli1
->tree
)));
1240 /* Next open with all access, but add delete on close. */
1241 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname
, 0,
1242 SEC_RIGHTS_FILE_ALL
,
1243 FILE_ATTRIBUTE_NORMAL
,
1244 NTCREATEX_SHARE_ACCESS_READ
|
1245 NTCREATEX_SHARE_ACCESS_WRITE
|
1246 NTCREATEX_SHARE_ACCESS_DELETE
,
1247 NTCREATEX_DISP_OPEN
,
1248 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
1250 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 2 of %s failed (%s)",
1251 fname
, smbcli_errstr(cli2
->tree
)));
1253 /* The delete on close bit is *not* reported as being set. */
1254 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
1255 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, false, __location__
);
1257 smbcli_close(cli1
->tree
, fnum1
);
1259 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, false, __location__
);
1261 smbcli_close(cli2
->tree
, fnum2
);
1263 /* See if the file is deleted - should be.... */
1264 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
, DENY_NONE
);
1265 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s succeeded (should fail) - %s",
1266 fname
, smbcli_errstr(cli1
->tree
)));
1272 /* This is the delete semantics that the cifsfs client depends on when
1273 * trying to delete an open file on a Windows server. It
1274 * opens a file with initial delete on close set, renames it then closes
1275 * all open handles. The file goes away on Windows.
1278 static bool deltest20b(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1282 bool correct
= true;
1284 del_clean_area(cli1
, cli2
);
1288 /* Ensure the file doesn't already exist. */
1289 smbcli_close(cli1
->tree
, fnum1
);
1290 smbcli_close(cli1
->tree
, fnum2
);
1291 smbcli_setatr(cli1
->tree
, fname
, 0, 0);
1292 smbcli_unlink(cli1
->tree
, fname
);
1293 smbcli_setatr(cli1
->tree
, fname_new
, 0, 0);
1294 smbcli_unlink(cli1
->tree
, fname_new
);
1296 /* Firstly open and create with all access */
1297 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
1298 SEC_RIGHTS_FILE_ALL
,
1299 FILE_ATTRIBUTE_NORMAL
,
1300 NTCREATEX_SHARE_ACCESS_READ
|
1301 NTCREATEX_SHARE_ACCESS_WRITE
|
1302 NTCREATEX_SHARE_ACCESS_DELETE
,
1303 NTCREATEX_DISP_CREATE
,
1305 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
1306 fname
, smbcli_errstr(cli1
->tree
)));
1308 /* And close - just to create the file. */
1309 smbcli_close(cli1
->tree
, fnum1
);
1311 /* Firstly open and create with all access */
1312 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
1313 SEC_RIGHTS_FILE_ALL
,
1314 FILE_ATTRIBUTE_NORMAL
,
1315 NTCREATEX_SHARE_ACCESS_READ
|
1316 NTCREATEX_SHARE_ACCESS_WRITE
|
1317 NTCREATEX_SHARE_ACCESS_DELETE
,
1318 NTCREATEX_DISP_OPEN
,
1320 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open - 1 of %s failed (%s)",
1321 fname
, smbcli_errstr(cli1
->tree
)));
1323 /* Next open with all access, but add delete on close. */
1324 fnum2
= smbcli_nt_create_full(cli2
->tree
, fname
, 0,
1325 SEC_RIGHTS_FILE_ALL
,
1326 FILE_ATTRIBUTE_NORMAL
,
1327 NTCREATEX_SHARE_ACCESS_READ
|
1328 NTCREATEX_SHARE_ACCESS_WRITE
|
1329 NTCREATEX_SHARE_ACCESS_DELETE
,
1330 NTCREATEX_DISP_OPEN
,
1331 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
, 0);
1333 torture_assert(tctx
, fnum2
!= -1, talloc_asprintf(tctx
, "open - 2 of %s failed (%s)",
1334 fname
, smbcli_errstr(cli2
->tree
)));
1336 /* The delete on close bit is *not* reported as being set. */
1337 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, false, __location__
);
1338 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, false, __location__
);
1340 smbcli_close(cli1
->tree
, fnum1
);
1342 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname
, false, __location__
);
1344 /* Rename the file by handle. */
1347 union smb_setfileinfo sfinfo
;
1350 memset(&sfinfo
, '\0', sizeof(sfinfo
));
1351 sfinfo
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1352 sfinfo
.generic
.in
.file
.fnum
= fnum2
;
1353 sfinfo
.rename_information
.in
.root_fid
= 0;
1354 /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
1355 sfinfo
.rename_information
.in
.new_name
= fname_new
+ 1;
1356 sfinfo
.rename_information
.in
.overwrite
= 1;
1358 status
= smb_raw_setfileinfo(cli2
->tree
, &sfinfo
);
1360 torture_assert_ntstatus_equal(tctx
,status
,NT_STATUS_OK
,talloc_asprintf(tctx
, "rename of %s to %s failed (%s)",
1361 fname
, fname_new
, smbcli_errstr(cli2
->tree
)));
1364 correct
&= check_delete_on_close(tctx
, cli2
, fnum2
, fname_new
, false, __location__
);
1366 smbcli_close(cli2
->tree
, fnum2
);
1368 /* See if the file is deleted - should be.... */
1369 fnum1
= smbcli_open(cli1
->tree
, fname
, O_RDWR
, DENY_NONE
);
1370 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s succeeded (should fail) - %s",
1371 fname
, smbcli_errstr(cli1
->tree
)));
1372 fnum1
= smbcli_open(cli1
->tree
, fname_new
, O_RDWR
, DENY_NONE
);
1373 torture_assert(tctx
, fnum1
== -1, talloc_asprintf(tctx
, "open of %s succeeded (should fail) - %s",
1374 fname_new
, smbcli_errstr(cli1
->tree
)));
1381 static bool deltest21(struct torture_context
*tctx
)
1384 struct smbcli_state
*cli1
;
1385 struct smbcli_state
*cli2
;
1386 bool correct
= true;
1388 if (!torture_open_connection(&cli1
, tctx
, 0))
1391 if (!torture_open_connection(&cli2
, tctx
, 1))
1394 del_clean_area(cli1
, cli2
);
1396 /* Test 21 -- Test removal of file after socket close. */
1398 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
1399 SEC_RIGHTS_FILE_ALL
,
1400 FILE_ATTRIBUTE_NORMAL
, NTCREATEX_SHARE_ACCESS_NONE
,
1401 NTCREATEX_DISP_OVERWRITE_IF
, 0, 0);
1403 torture_assert(tctx
, fnum1
!= -1, talloc_asprintf(tctx
, "open of %s failed (%s)",
1404 fname
, smbcli_errstr(cli1
->tree
)));
1406 torture_assert_ntstatus_ok(tctx
,
1407 smbcli_nt_delete_on_close(cli1
->tree
, fnum1
, true),
1408 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
1409 smbcli_errstr(cli1
->tree
)));
1411 /* Ensure delete on close is set. */
1412 correct
&= check_delete_on_close(tctx
, cli1
, fnum1
, fname
, true, __location__
);
1414 /* Now yank the rug from under cli1. */
1415 smbcli_transport_dead(cli1
->transport
, NT_STATUS_LOCAL_DISCONNECT
);
1419 if (!torture_open_connection(&cli1
, tctx
, 0)) {
1423 /* On slow build farm machines it might happen that they are not fast
1424 * enogh to delete the file for this test */
1427 /* File should not be there. */
1428 fnum1
= smbcli_nt_create_full(cli1
->tree
, fname
, 0,
1429 SEC_RIGHTS_FILE_READ
,
1430 FILE_ATTRIBUTE_NORMAL
,
1431 NTCREATEX_SHARE_ACCESS_READ
|
1432 NTCREATEX_SHARE_ACCESS_WRITE
|
1433 NTCREATEX_SHARE_ACCESS_DELETE
,
1434 NTCREATEX_DISP_OPEN
,
1437 CHECK_STATUS(cli1
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1445 * Test whether a second *directory* handle inhibits delete if the first has
1446 * del-on-close set and is closed
1448 static bool deltest22(struct torture_context
*tctx
)
1452 struct smbcli_state
*cli1
;
1453 bool correct
= true;
1455 if (!torture_open_connection(&cli1
, tctx
, 0))
1458 smbcli_deltree(cli1
->tree
, dname
);
1460 torture_assert_ntstatus_ok(
1461 tctx
, smbcli_mkdir(cli1
->tree
, dname
),
1462 talloc_asprintf(tctx
, "smbcli_mdir failed: (%s)\n",
1463 smbcli_errstr(cli1
->tree
)));
1465 dnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1467 SEC_FILE_WRITE_DATA
|
1469 FILE_ATTRIBUTE_DIRECTORY
,
1470 NTCREATEX_SHARE_ACCESS_READ
|
1471 NTCREATEX_SHARE_ACCESS_WRITE
|
1472 NTCREATEX_SHARE_ACCESS_DELETE
,
1473 NTCREATEX_DISP_OPEN
,
1474 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1476 torture_assert(tctx
, dnum1
!= -1,
1477 talloc_asprintf(tctx
, "open of %s failed: %s!",
1478 dname
, smbcli_errstr(cli1
->tree
)));
1480 dnum2
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1482 SEC_FILE_WRITE_DATA
,
1483 FILE_ATTRIBUTE_DIRECTORY
,
1484 NTCREATEX_SHARE_ACCESS_READ
|
1485 NTCREATEX_SHARE_ACCESS_WRITE
|
1486 NTCREATEX_SHARE_ACCESS_DELETE
,
1487 NTCREATEX_DISP_OPEN
,
1488 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1490 torture_assert(tctx
, dnum2
!= -1,
1491 talloc_asprintf(tctx
, "open of %s failed: %s!",
1492 dname
, smbcli_errstr(cli1
->tree
)));
1494 torture_assert_ntstatus_ok(
1495 tctx
, smbcli_nt_delete_on_close(cli1
->tree
, dnum1
, true),
1496 talloc_asprintf(tctx
, "setting delete_on_close failed (%s)",
1497 smbcli_errstr(cli1
->tree
)));
1499 smbcli_close(cli1
->tree
, dnum1
);
1501 dnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1503 SEC_FILE_WRITE_DATA
|
1505 FILE_ATTRIBUTE_DIRECTORY
,
1506 NTCREATEX_SHARE_ACCESS_READ
|
1507 NTCREATEX_SHARE_ACCESS_WRITE
|
1508 NTCREATEX_SHARE_ACCESS_DELETE
,
1509 NTCREATEX_DISP_OPEN
,
1510 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1512 torture_assert(tctx
, dnum1
== -1,
1513 talloc_asprintf(tctx
, "open of %s succeeded!\n",
1516 CHECK_STATUS(cli1
, NT_STATUS_DELETE_PENDING
);
1518 smbcli_close(cli1
->tree
, dnum2
);
1519 CHECK_STATUS(cli1
, NT_STATUS_OK
);
1524 /* Test 23 - Second directory open fails when delete is pending. */
1525 static bool deltest23(struct torture_context
*tctx
,
1526 struct smbcli_state
*cli1
,
1527 struct smbcli_state
*cli2
)
1531 bool correct
= true;
1534 del_clean_area(cli1
, cli2
);
1536 /* Test 23 -- Basic delete on close for directories. */
1538 /* Open a directory */
1539 dnum1
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1541 SEC_FILE_WRITE_DATA
|
1543 FILE_ATTRIBUTE_DIRECTORY
,
1544 NTCREATEX_SHARE_ACCESS_READ
|
1545 NTCREATEX_SHARE_ACCESS_WRITE
|
1546 NTCREATEX_SHARE_ACCESS_DELETE
,
1547 NTCREATEX_DISP_CREATE
,
1548 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1550 torture_assert(tctx
, dnum1
!= -1, talloc_asprintf(tctx
,
1551 "open of %s failed: %s!",
1552 dname
, smbcli_errstr(cli1
->tree
)));
1554 correct
&= check_delete_on_close(tctx
, cli1
, dnum1
, dname
, false,
1557 /* Set delete on close */
1558 status
= smbcli_nt_delete_on_close(cli1
->tree
, dnum1
, true);
1560 /* Attempt opening the directory again. It should fail. */
1561 dnum2
= smbcli_nt_create_full(cli1
->tree
, dname
, 0,
1563 SEC_FILE_WRITE_DATA
|
1565 FILE_ATTRIBUTE_DIRECTORY
,
1566 NTCREATEX_SHARE_ACCESS_READ
|
1567 NTCREATEX_SHARE_ACCESS_WRITE
|
1568 NTCREATEX_SHARE_ACCESS_DELETE
,
1569 NTCREATEX_DISP_OPEN
,
1570 NTCREATEX_OPTIONS_DIRECTORY
, 0);
1572 torture_assert(tctx
, dnum2
== -1, talloc_asprintf(tctx
,
1573 "open of %s succeeded: %s. It should have failed "
1574 "with NT_STATUS_DELETE_PENDING",
1575 dname
, smbcli_errstr(cli1
->tree
)));
1577 torture_assert_ntstatus_equal(tctx
, smbcli_nt_error(cli1
->tree
),
1578 NT_STATUS_DELETE_PENDING
, "smbcli_open failed");
1584 Test delete on close semantics.
1586 struct torture_suite
*torture_test_delete(void)
1588 struct torture_suite
*suite
= torture_suite_create(
1589 talloc_autofree_context(), "delete");
1591 torture_suite_add_2smb_test(suite
, "deltest1", deltest1
);
1592 torture_suite_add_2smb_test(suite
, "deltest2", deltest2
);
1593 torture_suite_add_2smb_test(suite
, "deltest3", deltest3
);
1594 torture_suite_add_2smb_test(suite
, "deltest4", deltest4
);
1595 torture_suite_add_2smb_test(suite
, "deltest5", deltest5
);
1596 torture_suite_add_2smb_test(suite
, "deltest6", deltest6
);
1597 torture_suite_add_2smb_test(suite
, "deltest7", deltest7
);
1598 torture_suite_add_2smb_test(suite
, "deltest8", deltest8
);
1599 torture_suite_add_2smb_test(suite
, "deltest9", deltest9
);
1600 torture_suite_add_2smb_test(suite
, "deltest10", deltest10
);
1601 torture_suite_add_2smb_test(suite
, "deltest11", deltest11
);
1602 torture_suite_add_2smb_test(suite
, "deltest12", deltest12
);
1603 torture_suite_add_2smb_test(suite
, "deltest13", deltest13
);
1604 torture_suite_add_2smb_test(suite
, "deltest14", deltest14
);
1605 torture_suite_add_2smb_test(suite
, "deltest15", deltest15
);
1606 torture_suite_add_2smb_test(suite
, "deltest16", deltest16
);
1607 torture_suite_add_2smb_test(suite
, "deltest17", deltest17
);
1608 torture_suite_add_2smb_test(suite
, "deltest18", deltest18
);
1609 torture_suite_add_2smb_test(suite
, "deltest19", deltest19
);
1610 torture_suite_add_2smb_test(suite
, "deltest20", deltest20
);
1611 torture_suite_add_2smb_test(suite
, "deltest20a", deltest20a
);
1612 torture_suite_add_2smb_test(suite
, "deltest20b", deltest20b
);
1613 torture_suite_add_simple_test(suite
, "deltest21", deltest21
);
1614 torture_suite_add_simple_test(suite
, "deltest22", deltest22
);
1615 torture_suite_add_2smb_test(suite
, "deltest23", deltest23
);