Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : delete on close testing
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "libcli/libcli.h"
24 : #include "torture/util.h"
25 : #include "system/filesys.h"
26 : #include "libcli/raw/raw_proto.h"
27 :
28 : #include "torture/raw/proto.h"
29 : #include "torture/basic/proto.h"
30 :
31 609 : static bool check_delete_on_close(struct torture_context *tctx,
32 : struct smbcli_state *cli, int fnum,
33 : const char *fname, bool expect_it,
34 : const char *where)
35 : {
36 87 : union smb_search_data data;
37 87 : NTSTATUS status;
38 :
39 87 : time_t c_time, a_time, m_time;
40 87 : size_t size;
41 87 : uint16_t mode;
42 :
43 609 : status = torture_single_search(cli, tctx,
44 : fname,
45 : RAW_SEARCH_TRANS2,
46 : RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
47 : FILE_ATTRIBUTE_DIRECTORY,
48 : &data);
49 609 : torture_assert_ntstatus_ok(tctx, status,
50 : talloc_asprintf(tctx, "single_search failed (%s)", where));
51 :
52 609 : if (fnum != -1) {
53 76 : union smb_fileinfo io;
54 532 : int nlink = expect_it ? 0 : 1;
55 :
56 532 : io.all_info.level = RAW_FILEINFO_ALL_INFO;
57 532 : io.all_info.in.file.fnum = fnum;
58 :
59 532 : status = smb_raw_fileinfo(cli->tree, tctx, &io);
60 532 : torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx,
61 : "qfileinfo failed (%s)", where));
62 :
63 532 : torture_assert(tctx, expect_it == io.all_info.out.delete_pending,
64 : talloc_asprintf(tctx,
65 : "%s - Expected del_on_close flag %d, qfileinfo/all_info gave %d",
66 : where, expect_it, io.all_info.out.delete_pending));
67 :
68 515 : torture_assert(tctx, nlink == io.all_info.out.nlink,
69 : talloc_asprintf(tctx,
70 : "%s - Expected nlink %d, qfileinfo/all_info gave %d",
71 : where, nlink, io.all_info.out.nlink));
72 :
73 515 : io.standard_info.level = RAW_FILEINFO_STANDARD_INFO;
74 515 : io.standard_info.in.file.fnum = fnum;
75 :
76 515 : status = smb_raw_fileinfo(cli->tree, tctx, &io);
77 515 : torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
78 :
79 515 : 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));
82 :
83 515 : 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));
86 : }
87 :
88 592 : status = smbcli_qpathinfo(cli->tree, fname,
89 : &c_time, &a_time, &m_time,
90 : &size, &mode);
91 :
92 592 : if (expect_it) {
93 142 : torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
94 : "qpathinfo did not give correct error code");
95 : } else {
96 450 : torture_assert_ntstatus_ok(tctx, status,
97 : talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
98 : }
99 :
100 502 : return true;
101 : }
102 :
103 : #define CHECK_STATUS(_cli, _expected) \
104 : torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
105 : "Incorrect status")
106 :
107 : static const char *fname = "\\delete.file";
108 : static const char *fname_new = "\\delete.new";
109 : static const char *dname = "\\delete.dir";
110 :
111 259 : static void del_clean_area(struct smbcli_state *cli1, struct smbcli_state *cli2)
112 : {
113 259 : smb_raw_exit(cli1->session);
114 259 : smb_raw_exit(cli2->session);
115 :
116 259 : smbcli_deltree(cli1->tree, dname);
117 259 : smbcli_setatr(cli1->tree, fname, 0, 0);
118 259 : smbcli_unlink(cli1->tree, fname);
119 259 : smbcli_setatr(cli1->tree, fname_new, 0, 0);
120 259 : smbcli_unlink(cli1->tree, fname_new);
121 259 : }
122 :
123 : /* Test 1 - this should delete the file on close. */
124 :
125 7 : static bool deltest1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
126 : {
127 7 : int fnum1 = -1;
128 :
129 7 : del_clean_area(cli1, cli2);
130 :
131 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
132 : SEC_RIGHTS_FILE_ALL,
133 : FILE_ATTRIBUTE_NORMAL,
134 : NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF,
135 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
136 :
137 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
138 : fname, smbcli_errstr(cli1->tree)));
139 :
140 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
141 : talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli1->tree)));
142 :
143 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
144 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
145 : fname));
146 :
147 6 : return true;
148 : }
149 :
150 : /* Test 2 - this should delete the file on close. */
151 7 : static bool deltest2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
152 : {
153 7 : int fnum1 = -1;
154 :
155 7 : del_clean_area(cli1, cli2);
156 :
157 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
158 : SEC_RIGHTS_FILE_ALL,
159 : FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
160 : NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
161 :
162 7 : torture_assert(tctx, fnum1 != -1,
163 : talloc_asprintf(tctx, "open of %s failed (%s)",
164 : fname, smbcli_errstr(cli1->tree)));
165 :
166 7 : 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)));
169 :
170 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
171 : talloc_asprintf(tctx, "close failed (%s)",
172 : smbcli_errstr(cli1->tree)));
173 :
174 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
175 7 : if (fnum1 != -1) {
176 0 : printf("(%s) open of %s succeeded should have been deleted on close !\n",
177 : __location__, fname);
178 0 : if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
179 0 : printf("(%s) close failed (%s)\n",
180 : __location__, smbcli_errstr(cli1->tree));
181 0 : return false;
182 : }
183 0 : smbcli_unlink(cli1->tree, fname);
184 : }
185 6 : return true;
186 : }
187 :
188 : /* Test 3 - ... */
189 7 : static bool deltest3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
190 : {
191 7 : int fnum1 = -1;
192 7 : int fnum2 = -1;
193 :
194 7 : del_clean_area(cli1, cli2);
195 :
196 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
197 : SEC_RIGHTS_FILE_ALL,
198 : FILE_ATTRIBUTE_NORMAL,
199 : NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
200 : NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
201 :
202 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
203 : fname, smbcli_errstr(cli1->tree)));
204 :
205 : /* This should fail with a sharing violation - open for delete is only compatible
206 : with SHARE_DELETE. */
207 :
208 7 : 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);
213 :
214 7 : torture_assert(tctx, fnum2 == -1,
215 : talloc_asprintf(tctx, "open - 2 of %s succeeded - should have failed.",
216 : fname));
217 :
218 : /* This should succeed. */
219 :
220 7 : 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);
225 :
226 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
227 : fname, smbcli_errstr(cli1->tree)));
228 :
229 7 : 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)));
233 :
234 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
235 : talloc_asprintf(tctx, "close 1 failed (%s)",
236 : smbcli_errstr(cli1->tree)));
237 :
238 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum2),
239 : talloc_asprintf(tctx, "close 2 failed (%s)",
240 : smbcli_errstr(cli1->tree)));
241 :
242 : /* This should fail - file should no longer be there. */
243 :
244 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
245 7 : if (fnum1 != -1) {
246 0 : printf("(%s) open of %s succeeded should have been deleted on close !\n",
247 : __location__, fname);
248 0 : if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
249 0 : printf("(%s) close failed (%s)\n",
250 : __location__, smbcli_errstr(cli1->tree));
251 : }
252 0 : smbcli_unlink(cli1->tree, fname);
253 0 : return false;
254 : }
255 6 : return true;
256 : }
257 :
258 : /* Test 4 ... */
259 7 : static bool deltest4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
260 : {
261 7 : int fnum1 = -1;
262 7 : int fnum2 = -1;
263 7 : bool correct = true;
264 :
265 7 : del_clean_area(cli1, cli2);
266 :
267 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
268 : SEC_FILE_READ_DATA |
269 : SEC_FILE_WRITE_DATA |
270 : SEC_STD_DELETE,
271 : FILE_ATTRIBUTE_NORMAL,
272 : NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE,
273 : NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
274 :
275 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
276 : fname, smbcli_errstr(cli1->tree)));
277 :
278 : /* This should succeed. */
279 7 : 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 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
287 : fname, smbcli_errstr(cli1->tree)));
288 :
289 7 : torture_assert_ntstatus_ok(tctx,
290 : smbcli_close(cli1->tree, fnum2),
291 : talloc_asprintf(tctx, "close - 1 failed (%s)",
292 : smbcli_errstr(cli1->tree)));
293 :
294 7 : 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)));
298 :
299 : /* This should fail - no more opens once delete on close set. */
300 7 : 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 7 : torture_assert(tctx, fnum2 == -1,
306 : talloc_asprintf(tctx, "open - 3 of %s succeeded ! Should have failed.",
307 : fname ));
308 :
309 7 : CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
310 :
311 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
312 : talloc_asprintf(tctx, "close - 2 failed (%s)",
313 : smbcli_errstr(cli1->tree)));
314 :
315 7 : return correct;
316 : }
317 :
318 : /* Test 5 ... */
319 7 : static bool deltest5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
320 : {
321 7 : int fnum1 = -1;
322 :
323 7 : del_clean_area(cli1, cli2);
324 :
325 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
326 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
327 : fname, smbcli_errstr(cli1->tree)));
328 :
329 : /* This should fail - only allowed on NT opens with DELETE access. */
330 :
331 7 : 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 !");
333 :
334 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
335 : talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
336 :
337 7 : return true;
338 : }
339 :
340 : /* Test 6 ... */
341 7 : static bool deltest6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
342 : {
343 7 : int fnum1 = -1;
344 :
345 7 : del_clean_area(cli1, cli2);
346 :
347 7 : 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);
354 :
355 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
356 : fname, smbcli_errstr(cli1->tree)));
357 :
358 : /* This should fail - only allowed on NT opens with DELETE access. */
359 :
360 7 : torture_assert(tctx,
361 : !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, true)),
362 : "setting delete_on_close on file with no delete access succeeded - should fail !");
363 :
364 7 : 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)));
369 :
370 7 : return true;
371 : }
372 :
373 : /* Test 7 ... */
374 7 : static bool deltest7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
375 : {
376 7 : int fnum1 = -1;
377 7 : bool correct = true;
378 :
379 7 : del_clean_area(cli1, cli2);
380 :
381 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
382 : SEC_FILE_READ_DATA |
383 : SEC_FILE_WRITE_DATA |
384 : SEC_STD_DELETE,
385 : FILE_ATTRIBUTE_NORMAL, 0,
386 : NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
387 :
388 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
389 : fname, smbcli_errstr(cli1->tree)));
390 :
391 7 : torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
392 : "setting delete_on_close on file failed !");
393 :
394 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
395 :
396 7 : torture_assert_ntstatus_ok(tctx,
397 : smbcli_nt_delete_on_close(cli1->tree, fnum1, false),
398 : "unsetting delete_on_close on file failed !");
399 :
400 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
401 :
402 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
403 : talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
404 :
405 : /* This next open should succeed - we reset the flag. */
406 :
407 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
408 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
409 : fname, smbcli_errstr(cli1->tree)));
410 :
411 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
412 : talloc_asprintf(tctx, "close - 2 failed (%s)",
413 : smbcli_errstr(cli1->tree)));
414 :
415 7 : return correct;
416 : }
417 :
418 : /* Test 8 ... */
419 7 : static bool deltest8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
420 : {
421 7 : int fnum1 = -1;
422 7 : int fnum2 = -1;
423 7 : bool correct = true;
424 :
425 7 : del_clean_area(cli1, cli2);
426 :
427 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
428 : SEC_FILE_READ_DATA|
429 : SEC_FILE_WRITE_DATA|
430 : SEC_STD_DELETE,
431 : FILE_ATTRIBUTE_NORMAL,
432 : NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
433 : NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
434 :
435 7 : torture_assert(tctx, fnum1 != -1,
436 : talloc_asprintf(tctx, "open of %s failed (%s)",
437 : fname, smbcli_errstr(cli1->tree)));
438 :
439 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
440 : SEC_FILE_READ_DATA|
441 : SEC_FILE_WRITE_DATA|
442 : SEC_STD_DELETE,
443 : FILE_ATTRIBUTE_NORMAL,
444 : NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
445 : NTCREATEX_DISP_OPEN, 0, 0);
446 :
447 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
448 : fname, smbcli_errstr(cli1->tree)));
449 :
450 7 : torture_assert_ntstatus_ok(tctx,
451 : smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
452 : "setting delete_on_close on file failed !");
453 :
454 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
455 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
456 :
457 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
458 : talloc_asprintf(tctx, "close - 1 failed (%s)",
459 : smbcli_errstr(cli1->tree)));
460 :
461 7 : correct &= check_delete_on_close(tctx, cli1, -1, fname, true, __location__);
462 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
463 :
464 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
465 : talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli2->tree)));
466 :
467 : /* This should fail.. */
468 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
469 7 : torture_assert(tctx, fnum1 == -1,
470 : talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !\n", fname));
471 :
472 6 : return correct;
473 : }
474 :
475 : /* Test 9 ... */
476 7 : static bool deltest9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
477 : {
478 7 : int fnum1 = -1;
479 1 : NTSTATUS status;
480 7 : uint32_t disps[4] = {
481 : NTCREATEX_DISP_SUPERSEDE,
482 : NTCREATEX_DISP_OVERWRITE_IF,
483 : NTCREATEX_DISP_CREATE,
484 : NTCREATEX_DISP_OPEN_IF};
485 1 : unsigned int i;
486 :
487 7 : del_clean_area(cli1, cli2);
488 :
489 36 : for (i = 0; i < sizeof(disps)/sizeof(disps[0]); i++) {
490 : /* This should fail - we need to set DELETE_ACCESS. */
491 :
492 : /*
493 : * A file or directory create with DELETE_ON_CLOSE but
494 : * without DELETE_ACCESS should fail with
495 : * NT_STATUS_INVALID_PARAMETER.
496 : */
497 :
498 28 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
499 : SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
500 : FILE_ATTRIBUTE_NORMAL,
501 : NTCREATEX_SHARE_ACCESS_NONE,
502 : disps[i],
503 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
504 :
505 28 : torture_assert(tctx, fnum1 == -1,
506 : talloc_asprintf(tctx, "open of %s succeeded "
507 : "should have failed!",
508 : fname));
509 :
510 : /* Must fail with NT_STATUS_INVALID_PARAMETER. */
511 28 : status = smbcli_nt_error(cli1->tree);
512 28 : torture_assert_ntstatus_equal(tctx,
513 : status,
514 : NT_STATUS_INVALID_PARAMETER,
515 : talloc_asprintf(tctx, "create of %s should return "
516 : "NT_STATUS_INVALID_PARAMETER, got %s",
517 : fname,
518 : smbcli_errstr(cli1->tree)));
519 :
520 : /* This should fail - the file should not have been created. */
521 28 : status = smbcli_getatr(cli1->tree, fname, NULL, NULL, NULL);
522 28 : torture_assert_ntstatus_equal(tctx,
523 : status,
524 : NT_STATUS_OBJECT_NAME_NOT_FOUND,
525 : talloc_asprintf(tctx, "getattr of %s succeeded should "
526 : "not have been created !",
527 : fname));
528 : }
529 :
530 6 : return true;
531 : }
532 :
533 : /* Test 9a ... */
534 7 : static bool deltest9a(struct torture_context *tctx,
535 : struct smbcli_state *cli1,
536 : struct smbcli_state *cli2)
537 : {
538 7 : int fnum1 = -1;
539 1 : NTSTATUS status;
540 7 : uint32_t disps[4] = {
541 : NTCREATEX_DISP_OVERWRITE_IF,
542 : NTCREATEX_DISP_OPEN,
543 : NTCREATEX_DISP_OVERWRITE,
544 : NTCREATEX_DISP_OPEN_IF};
545 :
546 1 : unsigned int i;
547 :
548 7 : del_clean_area(cli1, cli2);
549 :
550 : /* Create the file, and try with open calls. */
551 7 : fnum1 = smbcli_open(cli1->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
552 7 : torture_assert(tctx,
553 : fnum1 != -1,
554 : talloc_asprintf(tctx, "open of %s failed (%s)",
555 : fname,
556 : smbcli_errstr(cli1->tree)));
557 7 : status = smbcli_close(cli1->tree, fnum1);
558 7 : torture_assert_ntstatus_ok(tctx,
559 : status,
560 : talloc_asprintf(tctx, "close failed"));
561 :
562 35 : for (i = 0; i < sizeof(disps)/sizeof(disps[0]); i++) {
563 28 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
564 : SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
565 : FILE_ATTRIBUTE_NORMAL,
566 : NTCREATEX_SHARE_ACCESS_NONE,
567 : disps[i],
568 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
569 :
570 28 : torture_assert(tctx, fnum1 == -1,
571 : talloc_asprintf(tctx, "open of %s succeeded "
572 : "should have failed!",
573 : fname));
574 :
575 : /* Must fail with NT_STATUS_INVALID_PARAMETER. */
576 28 : status = smbcli_nt_error(cli1->tree);
577 28 : torture_assert_ntstatus_equal(tctx,
578 : status,
579 : NT_STATUS_INVALID_PARAMETER,
580 : talloc_asprintf(tctx, "create of %s should return "
581 : "NT_STATUS_INVALID_PARAMETER, got %s",
582 : fname,
583 : smbcli_errstr(cli1->tree)));
584 :
585 : /*
586 : * This should succeed - the file should not have been deleted.
587 : */
588 28 : status = smbcli_getatr(cli1->tree, fname, NULL, NULL, NULL);
589 28 : torture_assert_ntstatus_ok(tctx,
590 : status,
591 : talloc_asprintf(tctx, "getattr of %s failed %s",
592 : fname,
593 : smbcli_errstr(cli1->tree)));
594 : }
595 :
596 7 : del_clean_area(cli1, cli2);
597 7 : return true;
598 : }
599 :
600 : /* Test 10 ... */
601 7 : static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
602 : {
603 7 : int fnum1 = -1;
604 :
605 7 : del_clean_area(cli1, cli2);
606 :
607 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
608 : SEC_FILE_READ_DATA|
609 : SEC_FILE_WRITE_DATA|
610 : SEC_STD_DELETE,
611 : FILE_ATTRIBUTE_NORMAL,
612 : NTCREATEX_SHARE_ACCESS_NONE,
613 : NTCREATEX_DISP_OVERWRITE_IF,
614 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
615 7 : torture_assert(tctx, fnum1 != -1,
616 : talloc_asprintf(tctx, "open of %s failed (%s)",
617 : fname, smbcli_errstr(cli1->tree)));
618 :
619 : /* This should delete the file. */
620 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
621 : talloc_asprintf(tctx, "close failed (%s)",
622 : smbcli_errstr(cli1->tree)));
623 :
624 : /* This should fail.. */
625 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
626 7 : torture_assert(tctx, fnum1 == -1,
627 : talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
628 : fname));
629 6 : return true;
630 : }
631 :
632 : /* Test 11 ... */
633 7 : static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
634 : {
635 7 : int fnum1 = -1;
636 1 : NTSTATUS status;
637 :
638 7 : del_clean_area(cli1, cli2);
639 :
640 : /* test 11 - does having read only attribute still allow delete on close. */
641 :
642 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
643 : SEC_RIGHTS_FILE_ALL,
644 : FILE_ATTRIBUTE_READONLY,
645 : NTCREATEX_SHARE_ACCESS_NONE,
646 : NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
647 :
648 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
649 : fname, smbcli_errstr(cli1->tree)));
650 :
651 7 : status = smbcli_nt_delete_on_close(cli1->tree, fnum1, true);
652 :
653 7 : 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)));
655 :
656 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
657 : talloc_asprintf(tctx, "close failed (%s)",
658 : smbcli_errstr(cli1->tree)));
659 :
660 7 : return true;
661 : }
662 :
663 : /* Test 12 ... */
664 7 : static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
665 : {
666 7 : int fnum1 = -1;
667 1 : NTSTATUS status;
668 :
669 7 : del_clean_area(cli1, cli2);
670 :
671 : /* test 12 - does having read only attribute still allow delete on
672 : * close at time of open. */
673 :
674 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
675 : SEC_RIGHTS_FILE_ALL,
676 : FILE_ATTRIBUTE_READONLY,
677 : NTCREATEX_SHARE_ACCESS_DELETE,
678 : NTCREATEX_DISP_OVERWRITE_IF,
679 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
680 :
681 7 : torture_assert(tctx, fnum1 == -1,
682 : talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
683 : "NT_STATUS_CANNOT_DELETE.\n", fname));
684 :
685 7 : status = smbcli_nt_error(cli1->tree);
686 7 : torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE,
687 : talloc_asprintf(tctx, "setting delete_on_close on open should "
688 : "fail with NT_STATUS_CANNOT_DELETE. Got %s "
689 : "instead)",
690 : smbcli_errstr(cli1->tree)));
691 :
692 6 : return true;
693 : }
694 :
695 : /* Test 13 ... */
696 7 : static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
697 : {
698 7 : int fnum1 = -1;
699 7 : int fnum2 = -1;
700 7 : bool correct = true;
701 :
702 7 : del_clean_area(cli1, cli2);
703 :
704 : /* Test 13: Does resetting the delete on close flag affect a second
705 : * fd? */
706 :
707 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
708 : SEC_FILE_READ_DATA|
709 : SEC_FILE_WRITE_DATA|
710 : SEC_STD_DELETE,
711 : FILE_ATTRIBUTE_NORMAL,
712 : NTCREATEX_SHARE_ACCESS_READ|
713 : NTCREATEX_SHARE_ACCESS_WRITE|
714 : NTCREATEX_SHARE_ACCESS_DELETE,
715 : NTCREATEX_DISP_OVERWRITE_IF,
716 : 0, 0);
717 :
718 7 : torture_assert(tctx, fnum1 != -1,
719 : talloc_asprintf(tctx, "open of %s failed (%s)",
720 : fname, smbcli_errstr(cli1->tree)));
721 :
722 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
723 : SEC_FILE_READ_DATA|
724 : SEC_FILE_WRITE_DATA|
725 : SEC_STD_DELETE,
726 : FILE_ATTRIBUTE_NORMAL,
727 : NTCREATEX_SHARE_ACCESS_READ|
728 : NTCREATEX_SHARE_ACCESS_WRITE|
729 : NTCREATEX_SHARE_ACCESS_DELETE,
730 : NTCREATEX_DISP_OPEN, 0, 0);
731 :
732 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
733 : "open of %s failed (%s)",
734 : fname, smbcli_errstr(cli2->tree)));
735 :
736 7 : torture_assert_ntstatus_ok(tctx,
737 : smbcli_nt_delete_on_close(cli1->tree, fnum1,
738 : true),
739 : "setting delete_on_close on file failed !");
740 :
741 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
742 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
743 :
744 7 : torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
745 : false),
746 : "unsetting delete_on_close on file failed !");
747 :
748 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
749 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
750 :
751 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
752 : talloc_asprintf(tctx, "close - 1 failed (%s)",
753 : smbcli_errstr(cli1->tree)));
754 :
755 7 : torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
756 : talloc_asprintf(tctx, "close - 2 failed (%s)",
757 : smbcli_errstr(cli2->tree)));
758 :
759 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
760 :
761 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!",
762 : fname));
763 :
764 7 : smbcli_close(cli1->tree, fnum1);
765 :
766 7 : return correct;
767 : }
768 :
769 : /* Test 14 ... */
770 7 : static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
771 : {
772 7 : int dnum1 = -1;
773 7 : bool correct = true;
774 :
775 7 : del_clean_area(cli1, cli2);
776 :
777 : /* Test 14 -- directory */
778 :
779 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
780 : SEC_FILE_READ_DATA|
781 : SEC_FILE_WRITE_DATA|
782 : SEC_STD_DELETE,
783 : FILE_ATTRIBUTE_DIRECTORY,
784 : NTCREATEX_SHARE_ACCESS_READ|
785 : NTCREATEX_SHARE_ACCESS_WRITE|
786 : NTCREATEX_SHARE_ACCESS_DELETE,
787 : NTCREATEX_DISP_CREATE, 0, 0);
788 7 : torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
789 : dname, smbcli_errstr(cli1->tree)));
790 :
791 7 : correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
792 7 : torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
793 : "setting delete_on_close on file failed !");
794 7 : correct &= check_delete_on_close(tctx, cli1, dnum1, dname, true, __location__);
795 7 : smbcli_close(cli1->tree, dnum1);
796 :
797 : /* Now it should be gone... */
798 :
799 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
800 : SEC_FILE_READ_DATA|
801 : SEC_FILE_WRITE_DATA|
802 : SEC_STD_DELETE,
803 : FILE_ATTRIBUTE_DIRECTORY,
804 : NTCREATEX_SHARE_ACCESS_READ|
805 : NTCREATEX_SHARE_ACCESS_WRITE|
806 : NTCREATEX_SHARE_ACCESS_DELETE,
807 : NTCREATEX_DISP_OPEN, 0, 0);
808 7 : torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
809 :
810 6 : return correct;
811 : }
812 :
813 : /* Test 15 ... */
814 7 : static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
815 : {
816 7 : int fnum1 = -1;
817 7 : bool correct = true;
818 7 : int fnum2 = -1;
819 1 : NTSTATUS status;
820 :
821 7 : del_clean_area(cli1, cli2);
822 :
823 : /* Test 15: delete on close under rename */
824 :
825 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
826 7 : smbcli_unlink(cli1->tree, fname);
827 7 : smbcli_unlink(cli1->tree, fname_new);
828 :
829 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
830 : SEC_FILE_READ_DATA,
831 : FILE_ATTRIBUTE_NORMAL,
832 : NTCREATEX_SHARE_ACCESS_READ|
833 : NTCREATEX_SHARE_ACCESS_WRITE|
834 : NTCREATEX_SHARE_ACCESS_DELETE,
835 : NTCREATEX_DISP_OVERWRITE_IF,
836 : 0, 0);
837 :
838 7 : torture_assert(tctx, fnum1 != -1,
839 : talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
840 :
841 7 : status = smbcli_rename(cli2->tree, fname, fname_new);
842 :
843 7 : torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
844 :
845 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0,
846 : SEC_GENERIC_ALL,
847 : FILE_ATTRIBUTE_NORMAL,
848 : NTCREATEX_SHARE_ACCESS_READ|
849 : NTCREATEX_SHARE_ACCESS_WRITE|
850 : NTCREATEX_SHARE_ACCESS_DELETE,
851 : NTCREATEX_DISP_OVERWRITE_IF,
852 : 0, 0);
853 :
854 7 : torture_assert(tctx, fnum2 != -1,
855 : talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
856 : fname_new, smbcli_errstr(cli1->tree)));
857 :
858 7 : status = smbcli_nt_delete_on_close(cli2->tree, fnum2, true);
859 :
860 7 : torture_assert_ntstatus_ok(tctx, status,
861 : "setting delete_on_close on file failed !");
862 :
863 7 : smbcli_close(cli2->tree, fnum2);
864 :
865 : /* The file should be around under the new name, there's a second
866 : * handle open */
867 :
868 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, true, __location__);
869 :
870 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
871 : SEC_GENERIC_ALL,
872 : FILE_ATTRIBUTE_NORMAL,
873 : NTCREATEX_SHARE_ACCESS_READ|
874 : NTCREATEX_SHARE_ACCESS_WRITE|
875 : NTCREATEX_SHARE_ACCESS_DELETE,
876 : NTCREATEX_DISP_OVERWRITE_IF,
877 : 0, 0);
878 :
879 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
880 : fname, smbcli_errstr(cli1->tree)));
881 :
882 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
883 :
884 7 : smbcli_close(cli2->tree, fnum2);
885 7 : smbcli_close(cli1->tree, fnum1);
886 :
887 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
888 : SEC_FILE_READ_EA,
889 : FILE_ATTRIBUTE_NORMAL,
890 : NTCREATEX_SHARE_ACCESS_READ|
891 : NTCREATEX_SHARE_ACCESS_WRITE|
892 : NTCREATEX_SHARE_ACCESS_DELETE,
893 : NTCREATEX_DISP_OPEN,
894 : 0, 0);
895 :
896 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
897 : fname, smbcli_errstr(cli1->tree)));
898 :
899 7 : smbcli_close(cli1->tree, fnum1);
900 :
901 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0,
902 : SEC_FILE_READ_EA,
903 : FILE_ATTRIBUTE_NORMAL,
904 : NTCREATEX_SHARE_ACCESS_READ|
905 : NTCREATEX_SHARE_ACCESS_WRITE|
906 : NTCREATEX_SHARE_ACCESS_DELETE,
907 : NTCREATEX_DISP_OPEN,
908 : 0, 0);
909 :
910 7 : torture_assert(tctx, fnum1 == -1,
911 : "smbcli_open succeeded, should have "
912 : "failed");
913 :
914 6 : return correct;
915 : }
916 :
917 : /* Test 16 ... */
918 7 : static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
919 : {
920 7 : int fnum1 = -1;
921 7 : int fnum2 = -1;
922 7 : bool correct = true;
923 :
924 7 : del_clean_area(cli1, cli2);
925 :
926 : /* Test 16. */
927 :
928 : /* Ensure the file doesn't already exist. */
929 7 : smbcli_close(cli1->tree, fnum1);
930 7 : smbcli_close(cli1->tree, fnum2);
931 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
932 7 : smbcli_unlink(cli1->tree, fname);
933 :
934 : /* Firstly create with all access, but delete on close. */
935 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
936 : SEC_RIGHTS_FILE_ALL,
937 : FILE_ATTRIBUTE_NORMAL,
938 : NTCREATEX_SHARE_ACCESS_READ|
939 : NTCREATEX_SHARE_ACCESS_WRITE|
940 : NTCREATEX_SHARE_ACCESS_DELETE,
941 : NTCREATEX_DISP_CREATE,
942 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
943 :
944 7 : torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
945 :
946 : /* The delete on close bit is *not* reported as being set. */
947 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
948 :
949 : /* The delete on close bit is *not* reported as being set. */
950 7 : correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
951 7 : correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
952 :
953 : /* Now try opening again for read-only. */
954 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
955 : SEC_RIGHTS_FILE_READ,
956 : FILE_ATTRIBUTE_NORMAL,
957 : NTCREATEX_SHARE_ACCESS_READ|
958 : NTCREATEX_SHARE_ACCESS_WRITE|
959 : NTCREATEX_SHARE_ACCESS_DELETE,
960 : NTCREATEX_DISP_OPEN,
961 : 0, 0);
962 :
963 : /* Should work. */
964 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
965 : fname, smbcli_errstr(cli1->tree)));
966 :
967 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
968 7 : correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
969 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
970 7 : correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
971 :
972 7 : smbcli_close(cli1->tree, fnum1);
973 :
974 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
975 7 : correct &= check_delete_on_close(tctx, cli2, -1, fname, true, __location__);
976 :
977 7 : smbcli_close(cli2->tree, fnum2);
978 :
979 : /* And the file should be deleted ! */
980 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
981 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
982 : fname));
983 :
984 7 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
985 :
986 6 : return correct;
987 : }
988 :
989 : /* Test 16 ... */
990 7 : static bool deltest16a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
991 : {
992 7 : int fnum1 = -1;
993 7 : int fnum2 = -1;
994 7 : bool correct = true;
995 :
996 7 : del_clean_area(cli1, cli2);
997 :
998 : /* Test 16. */
999 :
1000 : /* Ensure the file doesn't already exist. */
1001 7 : smbcli_close(cli1->tree, fnum1);
1002 7 : smbcli_close(cli1->tree, fnum2);
1003 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1004 7 : smbcli_unlink(cli1->tree, fname);
1005 :
1006 : /* Firstly open and create with all access */
1007 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1008 : SEC_RIGHTS_FILE_ALL,
1009 : FILE_ATTRIBUTE_NORMAL,
1010 : NTCREATEX_SHARE_ACCESS_READ|
1011 : NTCREATEX_SHARE_ACCESS_WRITE|
1012 : NTCREATEX_SHARE_ACCESS_DELETE,
1013 : NTCREATEX_DISP_CREATE,
1014 : 0, 0);
1015 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1016 : fname, smbcli_errstr(cli1->tree)));
1017 :
1018 : /* And close - just to create the file. */
1019 7 : smbcli_close(cli1->tree, fnum1);
1020 :
1021 : /* Firstly create with all access, but delete on close. */
1022 7 : 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);
1030 :
1031 7 : torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1032 :
1033 : /* The delete on close bit is *not* reported as being set. */
1034 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1035 :
1036 : /* The delete on close bit is *not* reported as being set. */
1037 7 : correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
1038 7 : correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
1039 :
1040 : /* Now try opening again for read-only. */
1041 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1042 : SEC_RIGHTS_FILE_READ,
1043 : FILE_ATTRIBUTE_NORMAL,
1044 : NTCREATEX_SHARE_ACCESS_READ|
1045 : NTCREATEX_SHARE_ACCESS_WRITE|
1046 : NTCREATEX_SHARE_ACCESS_DELETE,
1047 : NTCREATEX_DISP_OPEN,
1048 : 0, 0);
1049 :
1050 : /* Should work. */
1051 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1052 : fname, smbcli_errstr(cli1->tree)));
1053 :
1054 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1055 7 : correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
1056 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1057 7 : correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
1058 :
1059 7 : smbcli_close(cli1->tree, fnum1);
1060 :
1061 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1062 7 : correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
1063 :
1064 7 : smbcli_close(cli2->tree, fnum2);
1065 :
1066 : /* And the file should be deleted ! */
1067 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1068 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
1069 : fname, smbcli_errstr(cli1->tree)));
1070 :
1071 2 : smbcli_close(cli1->tree, fnum1);
1072 2 : smbcli_setatr(cli1->tree, fname, 0, 0);
1073 2 : smbcli_unlink(cli1->tree, fname);
1074 :
1075 2 : return correct;
1076 : }
1077 :
1078 : /* Test 17 ... */
1079 7 : static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1080 : {
1081 7 : int fnum1 = -1;
1082 7 : int fnum2 = -1;
1083 7 : bool correct = true;
1084 :
1085 7 : del_clean_area(cli1, cli2);
1086 :
1087 : /* Test 17. */
1088 :
1089 : /* Ensure the file doesn't already exist. */
1090 7 : smbcli_close(cli1->tree, fnum1);
1091 7 : smbcli_close(cli1->tree, fnum2);
1092 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1093 7 : smbcli_unlink(cli1->tree, fname);
1094 :
1095 : /* Firstly open and create with all access */
1096 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1097 : SEC_RIGHTS_FILE_ALL,
1098 : FILE_ATTRIBUTE_NORMAL,
1099 : NTCREATEX_SHARE_ACCESS_READ|
1100 : NTCREATEX_SHARE_ACCESS_WRITE|
1101 : NTCREATEX_SHARE_ACCESS_DELETE,
1102 : NTCREATEX_DISP_CREATE,
1103 : 0, 0);
1104 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1105 : fname, smbcli_errstr(cli1->tree)));
1106 :
1107 : /* And close - just to create the file. */
1108 7 : smbcli_close(cli1->tree, fnum1);
1109 :
1110 : /* Next open with all access, but add delete on close. */
1111 7 : 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);
1119 :
1120 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1121 : fname, smbcli_errstr(cli1->tree)));
1122 :
1123 : /* The delete on close bit is *not* reported as being set. */
1124 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1125 :
1126 : /* Now try opening again for read-only. */
1127 7 : fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1128 : SEC_RIGHTS_FILE_READ|
1129 : SEC_STD_DELETE,
1130 : FILE_ATTRIBUTE_NORMAL,
1131 : NTCREATEX_SHARE_ACCESS_READ|
1132 : NTCREATEX_SHARE_ACCESS_WRITE|
1133 : NTCREATEX_SHARE_ACCESS_DELETE,
1134 : NTCREATEX_DISP_OPEN,
1135 : 0, 0);
1136 :
1137 : /* Should work. */
1138 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1139 : fname, smbcli_errstr(cli1->tree)));
1140 :
1141 : /* still not reported as being set on either */
1142 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1143 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1144 :
1145 7 : smbcli_close(cli1->tree, fnum1);
1146 :
1147 : /* After the first close, the files has the delete on close bit set. */
1148 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1149 :
1150 7 : smbcli_close(cli1->tree, fnum2);
1151 :
1152 : /* Make sure the file has been deleted */
1153 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1154 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
1155 : fname, smbcli_errstr(cli1->tree)));
1156 :
1157 5 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1158 :
1159 4 : return correct;
1160 : }
1161 :
1162 : /* Test 17a - like 17, but the delete on close handle is closed last */
1163 7 : static bool deltest17a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1164 : {
1165 7 : int fnum1 = -1;
1166 7 : int fnum2 = -1;
1167 7 : bool correct = true;
1168 :
1169 7 : del_clean_area(cli1, cli2);
1170 :
1171 : /* Ensure the file doesn't already exist. */
1172 7 : smbcli_close(cli1->tree, fnum1);
1173 7 : smbcli_close(cli1->tree, fnum2);
1174 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1175 7 : smbcli_unlink(cli1->tree, fname);
1176 :
1177 : /* Firstly open and create with all access */
1178 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1179 : SEC_RIGHTS_FILE_ALL,
1180 : FILE_ATTRIBUTE_NORMAL,
1181 : NTCREATEX_SHARE_ACCESS_READ|
1182 : NTCREATEX_SHARE_ACCESS_WRITE|
1183 : NTCREATEX_SHARE_ACCESS_DELETE,
1184 : NTCREATEX_DISP_CREATE,
1185 : 0, 0);
1186 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1187 : fname, smbcli_errstr(cli1->tree)));
1188 :
1189 : /* And close - just to create the file. */
1190 7 : smbcli_close(cli1->tree, fnum1);
1191 :
1192 : /* Next open with all access, but add delete on close. */
1193 7 : 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);
1201 :
1202 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1203 : fname, smbcli_errstr(cli1->tree)));
1204 :
1205 : /* The delete on close bit is *not* reported as being set. */
1206 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1207 :
1208 : /* Now try opening again for read-only. */
1209 7 : fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1210 : SEC_RIGHTS_FILE_READ|
1211 : SEC_STD_DELETE,
1212 : FILE_ATTRIBUTE_NORMAL,
1213 : NTCREATEX_SHARE_ACCESS_READ|
1214 : NTCREATEX_SHARE_ACCESS_WRITE|
1215 : NTCREATEX_SHARE_ACCESS_DELETE,
1216 : NTCREATEX_DISP_OPEN,
1217 : 0, 0);
1218 :
1219 : /* Should work. */
1220 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1221 : fname, smbcli_errstr(cli1->tree)));
1222 :
1223 : /* still not reported as being set on either */
1224 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1225 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1226 :
1227 7 : smbcli_close(cli1->tree, fnum2);
1228 :
1229 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1230 :
1231 7 : smbcli_close(cli1->tree, fnum1);
1232 :
1233 : /*
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
1237 : */
1238 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1239 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1240 : fname, smbcli_errstr(cli1->tree)));
1241 :
1242 2 : smbcli_close(cli1->tree, fnum1);
1243 2 : smbcli_setatr(cli1->tree, fname, 0, 0);
1244 2 : smbcli_unlink(cli1->tree, fname);
1245 :
1246 2 : return correct;
1247 : }
1248 :
1249 : /* Test 17b - like 17a, but the initial delete on close is set on the second handle */
1250 7 : static bool deltest17b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1251 : {
1252 7 : int fnum1 = -1;
1253 7 : int fnum2 = -1;
1254 7 : bool correct = true;
1255 :
1256 7 : del_clean_area(cli1, cli2);
1257 :
1258 : /* Ensure the file doesn't already exist. */
1259 7 : smbcli_close(cli1->tree, fnum1);
1260 7 : smbcli_close(cli1->tree, fnum2);
1261 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1262 7 : smbcli_unlink(cli1->tree, fname);
1263 :
1264 : /* Firstly open and create with all access */
1265 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1266 : SEC_RIGHTS_FILE_ALL,
1267 : FILE_ATTRIBUTE_NORMAL,
1268 : NTCREATEX_SHARE_ACCESS_READ|
1269 : NTCREATEX_SHARE_ACCESS_WRITE|
1270 : NTCREATEX_SHARE_ACCESS_DELETE,
1271 : NTCREATEX_DISP_CREATE,
1272 : 0, 0);
1273 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1274 : fname, smbcli_errstr(cli1->tree)));
1275 :
1276 : /* And close - just to create the file. */
1277 7 : smbcli_close(cli1->tree, fnum1);
1278 :
1279 : /* Next open with all access, but add delete on close. */
1280 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1281 : SEC_RIGHTS_FILE_ALL,
1282 : FILE_ATTRIBUTE_NORMAL,
1283 : NTCREATEX_SHARE_ACCESS_READ|
1284 : NTCREATEX_SHARE_ACCESS_WRITE|
1285 : NTCREATEX_SHARE_ACCESS_DELETE,
1286 : NTCREATEX_DISP_OPEN,
1287 : 0, 0);
1288 :
1289 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1290 : fname, smbcli_errstr(cli1->tree)));
1291 :
1292 : /* The delete on close bit is *not* reported as being set. */
1293 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1294 :
1295 : /* Now try opening again for read-only. */
1296 7 : fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1297 : SEC_RIGHTS_FILE_READ|
1298 : SEC_STD_DELETE,
1299 : FILE_ATTRIBUTE_NORMAL,
1300 : NTCREATEX_SHARE_ACCESS_READ|
1301 : NTCREATEX_SHARE_ACCESS_WRITE|
1302 : NTCREATEX_SHARE_ACCESS_DELETE,
1303 : NTCREATEX_DISP_OPEN,
1304 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1305 :
1306 : /* Should work. */
1307 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1308 : fname, smbcli_errstr(cli1->tree)));
1309 :
1310 : /* still not reported as being set on either */
1311 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1312 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1313 :
1314 7 : smbcli_close(cli1->tree, fnum1);
1315 :
1316 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1317 :
1318 7 : smbcli_close(cli1->tree, fnum2);
1319 :
1320 : /* Make sure the file has been deleted */
1321 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1322 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1323 : fname));
1324 :
1325 5 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1326 :
1327 4 : return correct;
1328 : }
1329 :
1330 : /* Test 17c - like 17, but the initial delete on close is set on the second handle */
1331 7 : static bool deltest17c(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1332 : {
1333 7 : int fnum1 = -1;
1334 7 : int fnum2 = -1;
1335 7 : bool correct = true;
1336 :
1337 7 : del_clean_area(cli1, cli2);
1338 :
1339 : /* Ensure the file doesn't already exist. */
1340 7 : smbcli_close(cli1->tree, fnum1);
1341 7 : smbcli_close(cli1->tree, fnum2);
1342 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1343 7 : smbcli_unlink(cli1->tree, fname);
1344 :
1345 : /* Firstly open and create with all access */
1346 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1347 : SEC_RIGHTS_FILE_ALL,
1348 : FILE_ATTRIBUTE_NORMAL,
1349 : NTCREATEX_SHARE_ACCESS_READ|
1350 : NTCREATEX_SHARE_ACCESS_WRITE|
1351 : NTCREATEX_SHARE_ACCESS_DELETE,
1352 : NTCREATEX_DISP_CREATE,
1353 : 0, 0);
1354 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1355 : fname, smbcli_errstr(cli1->tree)));
1356 :
1357 : /* And close - just to create the file. */
1358 7 : smbcli_close(cli1->tree, fnum1);
1359 :
1360 : /* Next open with all access, but add delete on close. */
1361 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1362 : SEC_RIGHTS_FILE_ALL,
1363 : FILE_ATTRIBUTE_NORMAL,
1364 : NTCREATEX_SHARE_ACCESS_READ|
1365 : NTCREATEX_SHARE_ACCESS_WRITE|
1366 : NTCREATEX_SHARE_ACCESS_DELETE,
1367 : NTCREATEX_DISP_OPEN,
1368 : 0, 0);
1369 :
1370 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1371 : fname, smbcli_errstr(cli1->tree)));
1372 :
1373 : /* The delete on close bit is *not* reported as being set. */
1374 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1375 :
1376 : /* Now try opening again for read-only. */
1377 7 : fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1378 : SEC_RIGHTS_FILE_READ|
1379 : SEC_STD_DELETE,
1380 : FILE_ATTRIBUTE_NORMAL,
1381 : NTCREATEX_SHARE_ACCESS_READ|
1382 : NTCREATEX_SHARE_ACCESS_WRITE|
1383 : NTCREATEX_SHARE_ACCESS_DELETE,
1384 : NTCREATEX_DISP_OPEN,
1385 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1386 :
1387 : /* Should work. */
1388 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1389 : fname, smbcli_errstr(cli1->tree)));
1390 :
1391 : /* still not reported as being set on either */
1392 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1393 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1394 :
1395 7 : smbcli_close(cli1->tree, fnum2);
1396 :
1397 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
1398 :
1399 7 : fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1400 7 : torture_assert(tctx, fnum2 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1401 : fname));
1402 :
1403 7 : CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1404 :
1405 5 : smbcli_close(cli1->tree, fnum1);
1406 :
1407 : /* Make sure the file has been deleted */
1408 5 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1409 5 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1410 : fname));
1411 :
1412 5 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1413 :
1414 4 : return correct;
1415 : }
1416 :
1417 : /* Test 17d - like 17a, but the first delete-on-close opener creates the file */
1418 7 : static bool deltest17d(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1419 : {
1420 7 : int fnum1 = -1;
1421 7 : int fnum2 = -1;
1422 7 : bool correct = true;
1423 :
1424 7 : del_clean_area(cli1, cli2);
1425 :
1426 : /* Ensure the file doesn't already exist. */
1427 7 : smbcli_close(cli1->tree, fnum1);
1428 7 : smbcli_close(cli1->tree, fnum2);
1429 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1430 7 : smbcli_unlink(cli1->tree, fname);
1431 :
1432 :
1433 : /* Create the file with delete on close. */
1434 7 : 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);
1442 :
1443 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1444 : fname, smbcli_errstr(cli1->tree)));
1445 :
1446 : /* The delete on close bit is *not* reported as being set. */
1447 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1448 :
1449 : /* Now try opening again for read-only. */
1450 7 : fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1451 : SEC_RIGHTS_FILE_READ|
1452 : SEC_STD_DELETE,
1453 : FILE_ATTRIBUTE_NORMAL,
1454 : NTCREATEX_SHARE_ACCESS_READ|
1455 : NTCREATEX_SHARE_ACCESS_WRITE|
1456 : NTCREATEX_SHARE_ACCESS_DELETE,
1457 : NTCREATEX_DISP_OPEN,
1458 : 0, 0);
1459 :
1460 : /* Should work. */
1461 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1462 : fname, smbcli_errstr(cli1->tree)));
1463 :
1464 : /* still not reported as being set on either */
1465 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1466 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1467 :
1468 7 : smbcli_close(cli1->tree, fnum2);
1469 :
1470 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1471 :
1472 7 : smbcli_close(cli1->tree, fnum1);
1473 :
1474 : /*
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
1478 : */
1479 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1480 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeed (should fail)",
1481 : fname));
1482 :
1483 7 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1484 :
1485 6 : return correct;
1486 : }
1487 :
1488 7 : static bool deltest17e(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1489 : {
1490 7 : int fnum1 = -1;
1491 7 : int fnum2 = -1;
1492 7 : int fnum3 = -1;
1493 7 : bool correct = true;
1494 :
1495 7 : del_clean_area(cli1, cli2);
1496 :
1497 : /* Ensure the file doesn't already exist. */
1498 7 : smbcli_close(cli1->tree, fnum1);
1499 7 : smbcli_close(cli1->tree, fnum2);
1500 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1501 7 : smbcli_unlink(cli1->tree, fname);
1502 :
1503 : /* Firstly open and create with all access */
1504 7 : fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1505 : SEC_RIGHTS_FILE_ALL,
1506 : FILE_ATTRIBUTE_NORMAL,
1507 : NTCREATEX_SHARE_ACCESS_READ|
1508 : NTCREATEX_SHARE_ACCESS_WRITE|
1509 : NTCREATEX_SHARE_ACCESS_DELETE,
1510 : NTCREATEX_DISP_CREATE,
1511 : 0, 0);
1512 7 : torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1513 : fname, smbcli_errstr(cli1->tree)));
1514 :
1515 : /* Next open with all access, but add delete on close. */
1516 7 : 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);
1524 :
1525 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1526 : fname, smbcli_errstr(cli1->tree)));
1527 :
1528 : /* The delete on close bit is *not* reported as being set. */
1529 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1530 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1531 :
1532 : /* Now try opening again for read-only. */
1533 7 : fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1534 : SEC_RIGHTS_FILE_READ|
1535 : SEC_STD_DELETE,
1536 : FILE_ATTRIBUTE_NORMAL,
1537 : NTCREATEX_SHARE_ACCESS_READ|
1538 : NTCREATEX_SHARE_ACCESS_WRITE|
1539 : NTCREATEX_SHARE_ACCESS_DELETE,
1540 : NTCREATEX_DISP_OPEN,
1541 : 0, 0);
1542 :
1543 : /* Should work. */
1544 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1545 : fname, smbcli_errstr(cli1->tree)));
1546 :
1547 : /* still not reported as being set on either */
1548 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1549 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1550 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1551 :
1552 7 : smbcli_close(cli1->tree, fnum1);
1553 :
1554 : /*
1555 : * closing the handle that has delete_on_close set
1556 : * inherits the flag to the global context
1557 : */
1558 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1559 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1560 :
1561 7 : smbcli_close(cli1->tree, fnum2);
1562 :
1563 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1564 :
1565 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1566 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1567 : fname));
1568 :
1569 7 : CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1570 :
1571 5 : smbcli_close(cli1->tree, fnum3);
1572 :
1573 5 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1574 5 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1575 : fname));
1576 :
1577 5 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1578 :
1579 4 : return correct;
1580 : }
1581 :
1582 7 : static bool deltest17f(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1583 : {
1584 7 : int fnum1 = -1;
1585 7 : int fnum2 = -1;
1586 7 : int fnum3 = -1;
1587 7 : bool correct = true;
1588 1 : NTSTATUS status;
1589 :
1590 7 : del_clean_area(cli1, cli2);
1591 :
1592 : /* Ensure the file doesn't already exist. */
1593 7 : smbcli_close(cli1->tree, fnum1);
1594 7 : smbcli_close(cli1->tree, fnum2);
1595 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1596 7 : smbcli_unlink(cli1->tree, fname);
1597 :
1598 : /* Firstly open and create with all access */
1599 7 : 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 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1608 : fname, smbcli_errstr(cli1->tree)));
1609 :
1610 : /* The delete on close bit is *not* reported as being set. */
1611 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1612 :
1613 : /* Next open with all access, but add delete on close. */
1614 7 : 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);
1622 :
1623 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1624 : fname, smbcli_errstr(cli1->tree)));
1625 :
1626 : /* still not reported as being set on either */
1627 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1628 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1629 :
1630 : /* Now try opening again for read-only. */
1631 7 : fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1632 : SEC_RIGHTS_FILE_READ|
1633 : SEC_STD_DELETE,
1634 : FILE_ATTRIBUTE_NORMAL,
1635 : NTCREATEX_SHARE_ACCESS_READ|
1636 : NTCREATEX_SHARE_ACCESS_WRITE|
1637 : NTCREATEX_SHARE_ACCESS_DELETE,
1638 : NTCREATEX_DISP_OPEN,
1639 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1640 :
1641 : /* Should work. */
1642 7 : torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1643 : fname, smbcli_errstr(cli1->tree)));
1644 :
1645 : /* still not reported as being set on either */
1646 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1647 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1648 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1649 :
1650 7 : smbcli_close(cli1->tree, fnum1);
1651 :
1652 : /*
1653 : * closing the handle that has delete_on_close set
1654 : * inherits the flag to the global context
1655 : */
1656 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1657 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1658 :
1659 :
1660 7 : status = smbcli_nt_delete_on_close(cli1->tree, fnum2, false);
1661 7 : torture_assert_ntstatus_ok(tctx, status,
1662 : "clearing delete_on_close on file failed !");
1663 :
1664 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1665 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1666 :
1667 7 : smbcli_close(cli1->tree, fnum2);
1668 :
1669 7 : correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1670 :
1671 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1672 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1673 : fname));
1674 :
1675 7 : CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1676 :
1677 5 : smbcli_close(cli1->tree, fnum3);
1678 :
1679 5 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1680 5 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1681 : fname));
1682 :
1683 5 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1684 :
1685 4 : return correct;
1686 : }
1687 :
1688 : /* Test 18 ... */
1689 7 : static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1690 : {
1691 7 : int fnum1 = -1;
1692 7 : int fnum2 = -1;
1693 7 : bool correct = true;
1694 :
1695 7 : del_clean_area(cli1, cli2);
1696 :
1697 : /* Test 18. With directories. */
1698 :
1699 : /* Ensure the file doesn't already exist. */
1700 7 : smbcli_close(cli1->tree, fnum1);
1701 7 : smbcli_close(cli1->tree, fnum2);
1702 :
1703 7 : smbcli_deltree(cli1->tree, dname);
1704 :
1705 : /* Firstly create with all access, but delete on close. */
1706 7 : fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1707 : SEC_FILE_READ_DATA|
1708 : SEC_FILE_WRITE_DATA|
1709 : SEC_STD_DELETE,
1710 : FILE_ATTRIBUTE_DIRECTORY,
1711 : NTCREATEX_SHARE_ACCESS_READ|
1712 : NTCREATEX_SHARE_ACCESS_WRITE|
1713 : NTCREATEX_SHARE_ACCESS_DELETE,
1714 : NTCREATEX_DISP_CREATE,
1715 : NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1716 :
1717 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1718 : dname, smbcli_errstr(cli1->tree)));
1719 :
1720 : /*
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.
1725 : */
1726 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1727 :
1728 : /* Now try opening again for read-only. */
1729 7 : 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);
1737 :
1738 :
1739 : /* Should work. */
1740 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1741 : dname, smbcli_errstr(cli1->tree)));
1742 :
1743 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1744 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, dname, false, __location__);
1745 :
1746 7 : smbcli_close(cli1->tree, fnum1);
1747 :
1748 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1749 :
1750 7 : smbcli_close(cli1->tree, fnum2);
1751 :
1752 : /* And the directory should be deleted ! */
1753 7 : 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 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)",
1762 : dname));
1763 :
1764 6 : return correct;
1765 : }
1766 :
1767 : /* Test 19 ... */
1768 7 : static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1769 : {
1770 7 : int fnum1 = -1;
1771 7 : int fnum2 = -1;
1772 7 : bool correct = true;
1773 :
1774 7 : del_clean_area(cli1, cli2);
1775 :
1776 : /* Test 19. */
1777 :
1778 7 : smbcli_deltree(cli1->tree, dname);
1779 :
1780 : /* Firstly open and create with all access */
1781 7 : fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1782 : SEC_FILE_READ_DATA|
1783 : SEC_FILE_WRITE_DATA|
1784 : SEC_STD_DELETE,
1785 : FILE_ATTRIBUTE_DIRECTORY,
1786 : NTCREATEX_SHARE_ACCESS_READ|
1787 : NTCREATEX_SHARE_ACCESS_WRITE|
1788 : NTCREATEX_SHARE_ACCESS_DELETE,
1789 : NTCREATEX_DISP_CREATE,
1790 : NTCREATEX_OPTIONS_DIRECTORY, 0);
1791 :
1792 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1793 : dname, smbcli_errstr(cli1->tree)));
1794 :
1795 : /* And close - just to create the directory. */
1796 7 : smbcli_close(cli1->tree, fnum1);
1797 :
1798 : /* Next open with all access, but add delete on close. */
1799 7 : fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1800 : SEC_FILE_READ_DATA|
1801 : SEC_FILE_WRITE_DATA|
1802 : SEC_STD_DELETE,
1803 : FILE_ATTRIBUTE_DIRECTORY,
1804 : NTCREATEX_SHARE_ACCESS_READ|
1805 : NTCREATEX_SHARE_ACCESS_WRITE|
1806 : NTCREATEX_SHARE_ACCESS_DELETE,
1807 : NTCREATEX_DISP_OPEN,
1808 : NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1809 :
1810 7 : torture_assert(tctx, fnum1 != -1,
1811 : talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1812 :
1813 : /*
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.
1818 : */
1819 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1820 :
1821 : /* Now try opening again for read-only. */
1822 7 : 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);
1830 :
1831 : /* Should work. */
1832 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1833 : dname, smbcli_errstr(cli1->tree)));
1834 :
1835 7 : smbcli_close(cli1->tree, fnum1);
1836 :
1837 7 : correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1838 :
1839 7 : smbcli_close(cli1->tree, fnum2);
1840 :
1841 : /* See if the file is deleted - for a directory this seems to be true ! */
1842 7 : 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);
1850 :
1851 7 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1852 :
1853 7 : torture_assert(tctx, fnum1 == -1,
1854 : talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1855 :
1856 6 : return correct;
1857 : }
1858 :
1859 : /* Test 20 ... */
1860 7 : static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1861 : {
1862 7 : int fnum1 = -1;
1863 7 : int dnum1 = -1;
1864 7 : bool correct = true;
1865 1 : NTSTATUS status;
1866 1 : int ret;
1867 :
1868 7 : if (geteuid() == 0) {
1869 0 : torture_skip(tctx, "This test doesn't work as user root.");
1870 : }
1871 :
1872 7 : del_clean_area(cli1, cli2);
1873 :
1874 : /* Test 20 -- non-empty directory hardest to get right... */
1875 :
1876 7 : smbcli_deltree(cli1->tree, dname);
1877 :
1878 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1879 : SEC_FILE_READ_DATA|
1880 : SEC_FILE_WRITE_DATA|
1881 : SEC_STD_DELETE,
1882 : FILE_ATTRIBUTE_DIRECTORY,
1883 : NTCREATEX_SHARE_ACCESS_READ|
1884 : NTCREATEX_SHARE_ACCESS_WRITE|
1885 : NTCREATEX_SHARE_ACCESS_DELETE,
1886 : NTCREATEX_DISP_CREATE,
1887 : NTCREATEX_OPTIONS_DIRECTORY, 0);
1888 7 : torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!",
1889 : dname, smbcli_errstr(cli1->tree)));
1890 :
1891 7 : correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
1892 7 : status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1893 :
1894 : {
1895 1 : char *fullname;
1896 7 : ret = asprintf(&fullname, "\\%s%s", dname, fname);
1897 7 : torture_assert(tctx, ret != -1, "asprintf failed");
1898 7 : fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1899 : DENY_NONE);
1900 7 : torture_assert(tctx, fnum1 == -1,
1901 : "smbcli_open succeeded, should have "
1902 : "failed with NT_STATUS_DELETE_PENDING"
1903 : );
1904 :
1905 7 : torture_assert_ntstatus_equal(tctx,
1906 : smbcli_nt_error(cli1->tree),
1907 : NT_STATUS_DELETE_PENDING,
1908 : "smbcli_open failed");
1909 : }
1910 :
1911 7 : status = smbcli_nt_delete_on_close(cli1->tree, dnum1, false);
1912 7 : torture_assert_ntstatus_ok(tctx, status,
1913 : "unsetting delete_on_close on file failed !");
1914 :
1915 : {
1916 1 : char *fullname;
1917 7 : ret = asprintf(&fullname, "\\%s%s", dname, fname);
1918 7 : torture_assert(tctx, ret != -1, "asprintf failed");
1919 7 : fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1920 : DENY_NONE);
1921 7 : torture_assert(tctx, fnum1 != -1,
1922 : talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1923 : smbcli_errstr(cli1->tree)));
1924 7 : smbcli_close(cli1->tree, fnum1);
1925 : }
1926 :
1927 7 : status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1928 :
1929 7 : torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1930 : "setting delete_on_close failed");
1931 7 : smbcli_close(cli1->tree, dnum1);
1932 :
1933 7 : return correct;
1934 : }
1935 :
1936 : /* Test 20a ... */
1937 7 : static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1938 : {
1939 7 : int fnum1 = -1;
1940 7 : int fnum2 = -1;
1941 7 : bool correct = true;
1942 :
1943 7 : del_clean_area(cli1, cli2);
1944 :
1945 : /* Test 20a. */
1946 :
1947 : /* Ensure the file doesn't already exist. */
1948 7 : smbcli_close(cli1->tree, fnum1);
1949 7 : smbcli_close(cli1->tree, fnum2);
1950 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
1951 7 : smbcli_unlink(cli1->tree, fname);
1952 :
1953 : /* Firstly open and create with all access */
1954 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1955 : SEC_RIGHTS_FILE_ALL,
1956 : FILE_ATTRIBUTE_NORMAL,
1957 : NTCREATEX_SHARE_ACCESS_READ|
1958 : NTCREATEX_SHARE_ACCESS_WRITE|
1959 : NTCREATEX_SHARE_ACCESS_DELETE,
1960 : NTCREATEX_DISP_CREATE,
1961 : 0, 0);
1962 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1963 : fname, smbcli_errstr(cli1->tree)));
1964 :
1965 : /* Next open with all access, but add delete on close. */
1966 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
1967 : SEC_RIGHTS_FILE_ALL,
1968 : FILE_ATTRIBUTE_NORMAL,
1969 : NTCREATEX_SHARE_ACCESS_READ|
1970 : NTCREATEX_SHARE_ACCESS_WRITE|
1971 : NTCREATEX_SHARE_ACCESS_DELETE,
1972 : NTCREATEX_DISP_OPEN,
1973 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1974 :
1975 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1976 : fname, smbcli_errstr(cli2->tree)));
1977 :
1978 : /* The delete on close bit is *not* reported as being set. */
1979 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1980 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1981 :
1982 7 : smbcli_close(cli1->tree, fnum1);
1983 :
1984 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1985 :
1986 7 : smbcli_close(cli2->tree, fnum2);
1987 :
1988 : /* See if the file is deleted - should be.... */
1989 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1990 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
1991 : fname, smbcli_errstr(cli1->tree)));
1992 :
1993 4 : return correct;
1994 : }
1995 :
1996 : /* Test 20b ... */
1997 : /* This is the delete semantics that the cifsfs client depends on when
1998 : * trying to delete an open file on a Windows server. It
1999 : * opens a file with initial delete on close set, renames it then closes
2000 : * all open handles. The file goes away on Windows.
2001 : */
2002 :
2003 7 : static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2004 : {
2005 7 : int fnum1 = -1;
2006 7 : int fnum2 = -1;
2007 7 : bool correct = true;
2008 :
2009 7 : del_clean_area(cli1, cli2);
2010 :
2011 : /* Test 20b. */
2012 :
2013 : /* Ensure the file doesn't already exist. */
2014 7 : smbcli_close(cli1->tree, fnum1);
2015 7 : smbcli_close(cli1->tree, fnum2);
2016 7 : smbcli_setatr(cli1->tree, fname, 0, 0);
2017 7 : smbcli_unlink(cli1->tree, fname);
2018 7 : smbcli_setatr(cli1->tree, fname_new, 0, 0);
2019 7 : smbcli_unlink(cli1->tree, fname_new);
2020 :
2021 : /* Firstly open and create with all access */
2022 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2023 : SEC_RIGHTS_FILE_ALL,
2024 : FILE_ATTRIBUTE_NORMAL,
2025 : NTCREATEX_SHARE_ACCESS_READ|
2026 : NTCREATEX_SHARE_ACCESS_WRITE|
2027 : NTCREATEX_SHARE_ACCESS_DELETE,
2028 : NTCREATEX_DISP_CREATE,
2029 : 0, 0);
2030 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
2031 : fname, smbcli_errstr(cli1->tree)));
2032 :
2033 : /* And close - just to create the file. */
2034 7 : smbcli_close(cli1->tree, fnum1);
2035 :
2036 : /* Firstly open and create with all access */
2037 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2038 : SEC_RIGHTS_FILE_ALL,
2039 : FILE_ATTRIBUTE_NORMAL,
2040 : NTCREATEX_SHARE_ACCESS_READ|
2041 : NTCREATEX_SHARE_ACCESS_WRITE|
2042 : NTCREATEX_SHARE_ACCESS_DELETE,
2043 : NTCREATEX_DISP_OPEN,
2044 : 0, 0);
2045 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
2046 : fname, smbcli_errstr(cli1->tree)));
2047 :
2048 : /* Next open with all access, but add delete on close. */
2049 7 : fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
2050 : SEC_RIGHTS_FILE_ALL,
2051 : FILE_ATTRIBUTE_NORMAL,
2052 : NTCREATEX_SHARE_ACCESS_READ|
2053 : NTCREATEX_SHARE_ACCESS_WRITE|
2054 : NTCREATEX_SHARE_ACCESS_DELETE,
2055 : NTCREATEX_DISP_OPEN,
2056 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2057 :
2058 7 : torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
2059 : fname, smbcli_errstr(cli2->tree)));
2060 :
2061 : /* The delete on close bit is *not* reported as being set. */
2062 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
2063 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
2064 :
2065 7 : smbcli_close(cli1->tree, fnum1);
2066 :
2067 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
2068 :
2069 : /* Rename the file by handle. */
2070 :
2071 : {
2072 1 : union smb_setfileinfo sfinfo;
2073 1 : NTSTATUS status;
2074 :
2075 7 : memset(&sfinfo, '\0', sizeof(sfinfo));
2076 7 : sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
2077 7 : sfinfo.generic.in.file.fnum = fnum2;
2078 7 : sfinfo.rename_information.in.root_fid = 0;
2079 : /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
2080 7 : sfinfo.rename_information.in.new_name = fname_new + 1;
2081 7 : sfinfo.rename_information.in.overwrite = 1;
2082 :
2083 7 : status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
2084 :
2085 7 : torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
2086 : fname, fname_new, smbcli_errstr(cli2->tree)));
2087 : }
2088 :
2089 7 : correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, false, __location__);
2090 :
2091 7 : smbcli_close(cli2->tree, fnum2);
2092 :
2093 : /* See if the file is deleted - should be.... */
2094 7 : fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
2095 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
2096 : fname, smbcli_errstr(cli1->tree)));
2097 7 : fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
2098 7 : torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s",
2099 : fname_new, smbcli_errstr(cli1->tree)));
2100 :
2101 4 : return correct;
2102 : }
2103 :
2104 : /* Test 20c */
2105 : /* Along the lines of deltest20 we try to open a non-empty directory with delete
2106 : * on close set and subsequent close to verify its presence in the tree.
2107 : */
2108 7 : static bool deltest20c(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
2109 : {
2110 7 : int fnum1 = -1;
2111 7 : int dnum1 = -1;
2112 1 : int ret;
2113 1 : char *fullname;
2114 :
2115 7 : del_clean_area(cli1, cli2);
2116 :
2117 7 : smbcli_deltree(cli1->tree, dname);
2118 :
2119 : /* Firstly open and create with all access */
2120 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2121 : SEC_FILE_READ_DATA|
2122 : SEC_FILE_WRITE_DATA|
2123 : SEC_STD_DELETE,
2124 : FILE_ATTRIBUTE_DIRECTORY,
2125 : NTCREATEX_SHARE_ACCESS_READ|
2126 : NTCREATEX_SHARE_ACCESS_WRITE|
2127 : NTCREATEX_SHARE_ACCESS_DELETE,
2128 : NTCREATEX_DISP_CREATE,
2129 : NTCREATEX_OPTIONS_DIRECTORY, 0);
2130 7 : torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s",
2131 : dname, smbcli_errstr(cli1->tree)));
2132 :
2133 : /* And close - just to create the directory */
2134 7 : smbcli_close(cli1->tree, dnum1);
2135 :
2136 7 : ret = asprintf(&fullname, "\\%s%s", dname, fname);
2137 7 : torture_assert(tctx, ret != -1, "asprintf failed");
2138 :
2139 : /* Open and create with all access */
2140 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fullname, 0,
2141 : SEC_RIGHTS_FILE_ALL,
2142 : FILE_ATTRIBUTE_NORMAL,
2143 : NTCREATEX_SHARE_ACCESS_READ|
2144 : NTCREATEX_SHARE_ACCESS_WRITE|
2145 : NTCREATEX_SHARE_ACCESS_DELETE,
2146 : NTCREATEX_DISP_CREATE,
2147 : 0, 0);
2148 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s",
2149 : fname, smbcli_errstr(cli1->tree)));
2150 :
2151 : /* And close - just to create the file. */
2152 7 : smbcli_close(cli1->tree, fnum1);
2153 :
2154 : /* Open with all access, but add delete on close */
2155 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2156 : SEC_FILE_READ_DATA|
2157 : SEC_FILE_WRITE_DATA|
2158 : SEC_STD_DELETE,
2159 : FILE_ATTRIBUTE_DIRECTORY,
2160 : NTCREATEX_SHARE_ACCESS_READ|
2161 : NTCREATEX_SHARE_ACCESS_WRITE|
2162 : NTCREATEX_SHARE_ACCESS_DELETE,
2163 : NTCREATEX_DISP_OPEN,
2164 : NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2165 : /* Should work */
2166 7 : torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s",
2167 : dname, smbcli_errstr(cli1->tree)));
2168 :
2169 7 : smbcli_close(cli1->tree, dnum1);
2170 :
2171 : /* Try to open again */
2172 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2173 : SEC_FILE_READ_DATA|
2174 : SEC_FILE_WRITE_DATA|
2175 : SEC_STD_DELETE,
2176 : FILE_ATTRIBUTE_DIRECTORY,
2177 : NTCREATEX_SHARE_ACCESS_READ|
2178 : NTCREATEX_SHARE_ACCESS_WRITE|
2179 : NTCREATEX_SHARE_ACCESS_DELETE,
2180 : NTCREATEX_DISP_OPEN,
2181 : NTCREATEX_OPTIONS_DIRECTORY, 0);
2182 : /* Directory should be still present*/
2183 7 : torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s",
2184 : dname, smbcli_errstr(cli1->tree)));
2185 :
2186 7 : smbcli_close(cli1->tree, dnum1);
2187 :
2188 7 : return true;
2189 : }
2190 :
2191 : /* Test 21 ... */
2192 7 : static bool deltest21(struct torture_context *tctx)
2193 : {
2194 7 : int fnum1 = -1;
2195 1 : struct smbcli_state *cli1;
2196 1 : struct smbcli_state *cli2;
2197 7 : bool correct = true;
2198 :
2199 7 : if (!torture_open_connection(&cli1, tctx, 0))
2200 0 : return false;
2201 :
2202 7 : if (!torture_open_connection(&cli2, tctx, 1))
2203 0 : return false;
2204 :
2205 7 : del_clean_area(cli1, cli2);
2206 :
2207 : /* Test 21 -- Test removal of file after socket close. */
2208 :
2209 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2210 : SEC_RIGHTS_FILE_ALL,
2211 : FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE,
2212 : NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2213 :
2214 7 : torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
2215 : fname, smbcli_errstr(cli1->tree)));
2216 :
2217 7 : torture_assert_ntstatus_ok(tctx,
2218 : smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
2219 : talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2220 : smbcli_errstr(cli1->tree)));
2221 :
2222 : /* Ensure delete on close is set. */
2223 7 : correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
2224 :
2225 : /* Now yank the rug from under cli1. */
2226 7 : smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
2227 :
2228 7 : fnum1 = -1;
2229 :
2230 7 : if (!torture_open_connection(&cli1, tctx, 0)) {
2231 0 : return false;
2232 : }
2233 :
2234 : /* On slow build farm machines it might happen that they are not fast
2235 : * enough to delete the file for this test */
2236 7 : smb_msleep(200);
2237 :
2238 : /* File should not be there. */
2239 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2240 : SEC_RIGHTS_FILE_READ,
2241 : FILE_ATTRIBUTE_NORMAL,
2242 : NTCREATEX_SHARE_ACCESS_READ|
2243 : NTCREATEX_SHARE_ACCESS_WRITE|
2244 : NTCREATEX_SHARE_ACCESS_DELETE,
2245 : NTCREATEX_DISP_OPEN,
2246 : 0, 0);
2247 :
2248 7 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2249 :
2250 6 : return correct;
2251 : }
2252 :
2253 : /* Test 22 ... */
2254 :
2255 : /*
2256 : * Test whether a second *directory* handle inhibits delete if the first has
2257 : * del-on-close set and is closed
2258 : */
2259 7 : static bool deltest22(struct torture_context *tctx)
2260 : {
2261 7 : int dnum1 = -1;
2262 7 : int dnum2 = -1;
2263 1 : struct smbcli_state *cli1;
2264 7 : bool correct = true;
2265 :
2266 7 : if (!torture_open_connection(&cli1, tctx, 0))
2267 0 : return false;
2268 :
2269 7 : smbcli_deltree(cli1->tree, dname);
2270 :
2271 7 : torture_assert_ntstatus_ok(
2272 : tctx, smbcli_mkdir(cli1->tree, dname),
2273 : talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
2274 : smbcli_errstr(cli1->tree)));
2275 :
2276 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2277 : SEC_FILE_READ_DATA|
2278 : SEC_FILE_WRITE_DATA|
2279 : SEC_STD_DELETE,
2280 : FILE_ATTRIBUTE_DIRECTORY,
2281 : NTCREATEX_SHARE_ACCESS_READ|
2282 : NTCREATEX_SHARE_ACCESS_WRITE|
2283 : NTCREATEX_SHARE_ACCESS_DELETE,
2284 : NTCREATEX_DISP_OPEN,
2285 : NTCREATEX_OPTIONS_DIRECTORY, 0);
2286 :
2287 7 : torture_assert(tctx, dnum1 != -1,
2288 : talloc_asprintf(tctx, "open of %s failed: %s!",
2289 : dname, smbcli_errstr(cli1->tree)));
2290 :
2291 7 : dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2292 : SEC_FILE_READ_DATA|
2293 : SEC_FILE_WRITE_DATA,
2294 : FILE_ATTRIBUTE_DIRECTORY,
2295 : NTCREATEX_SHARE_ACCESS_READ|
2296 : NTCREATEX_SHARE_ACCESS_WRITE|
2297 : NTCREATEX_SHARE_ACCESS_DELETE,
2298 : NTCREATEX_DISP_OPEN,
2299 : NTCREATEX_OPTIONS_DIRECTORY, 0);
2300 :
2301 7 : torture_assert(tctx, dnum2 != -1,
2302 : talloc_asprintf(tctx, "open of %s failed: %s!",
2303 : dname, smbcli_errstr(cli1->tree)));
2304 :
2305 7 : torture_assert_ntstatus_ok(
2306 : tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
2307 : talloc_asprintf(tctx, "setting delete_on_close failed (%s)",
2308 : smbcli_errstr(cli1->tree)));
2309 :
2310 7 : smbcli_close(cli1->tree, dnum1);
2311 :
2312 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2313 : SEC_FILE_READ_DATA|
2314 : SEC_FILE_WRITE_DATA|
2315 : SEC_STD_DELETE,
2316 : FILE_ATTRIBUTE_DIRECTORY,
2317 : NTCREATEX_SHARE_ACCESS_READ|
2318 : NTCREATEX_SHARE_ACCESS_WRITE|
2319 : NTCREATEX_SHARE_ACCESS_DELETE,
2320 : NTCREATEX_DISP_OPEN,
2321 : NTCREATEX_OPTIONS_DIRECTORY, 0);
2322 :
2323 7 : torture_assert(tctx, dnum1 == -1,
2324 : talloc_asprintf(tctx, "open of %s succeeded!\n",
2325 : dname));
2326 :
2327 7 : CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
2328 :
2329 7 : smbcli_close(cli1->tree, dnum2);
2330 7 : CHECK_STATUS(cli1, NT_STATUS_OK);
2331 :
2332 6 : return correct;
2333 : }
2334 :
2335 : /* Test 23 - Second directory open fails when delete is pending. */
2336 7 : static bool deltest23(struct torture_context *tctx,
2337 : struct smbcli_state *cli1,
2338 : struct smbcli_state *cli2)
2339 : {
2340 7 : int dnum1 = -1;
2341 7 : int dnum2 = -1;
2342 7 : bool correct = true;
2343 :
2344 7 : del_clean_area(cli1, cli2);
2345 :
2346 : /* Test 23 -- Basic delete on close for directories. */
2347 :
2348 : /* Open a directory */
2349 7 : dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2350 : SEC_FILE_READ_DATA|
2351 : SEC_FILE_WRITE_DATA|
2352 : SEC_STD_DELETE,
2353 : FILE_ATTRIBUTE_DIRECTORY,
2354 : NTCREATEX_SHARE_ACCESS_READ|
2355 : NTCREATEX_SHARE_ACCESS_WRITE|
2356 : NTCREATEX_SHARE_ACCESS_DELETE,
2357 : NTCREATEX_DISP_CREATE,
2358 : NTCREATEX_OPTIONS_DIRECTORY, 0);
2359 :
2360 7 : torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx,
2361 : "open of %s failed: %s!",
2362 : dname, smbcli_errstr(cli1->tree)));
2363 :
2364 7 : correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false,
2365 : __location__);
2366 :
2367 : /* Set delete on close */
2368 7 : (void)smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
2369 :
2370 : /* Attempt opening the directory again. It should fail. */
2371 7 : dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2372 : SEC_FILE_READ_DATA|
2373 : SEC_FILE_WRITE_DATA|
2374 : SEC_STD_DELETE,
2375 : FILE_ATTRIBUTE_DIRECTORY,
2376 : NTCREATEX_SHARE_ACCESS_READ|
2377 : NTCREATEX_SHARE_ACCESS_WRITE|
2378 : NTCREATEX_SHARE_ACCESS_DELETE,
2379 : NTCREATEX_DISP_OPEN,
2380 : NTCREATEX_OPTIONS_DIRECTORY, 0);
2381 :
2382 7 : torture_assert(tctx, dnum2 == -1, talloc_asprintf(tctx,
2383 : "open of %s succeeded: %s. It should have failed "
2384 : "with NT_STATUS_DELETE_PENDING",
2385 : dname, smbcli_errstr(cli1->tree)));
2386 :
2387 7 : torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree),
2388 : NT_STATUS_DELETE_PENDING, "smbcli_open failed");
2389 :
2390 7 : return correct;
2391 : }
2392 :
2393 : /* Test 24 ... */
2394 :
2395 : /*
2396 : * Test whether unsetting delete-on-close before the close has any effect.
2397 : * It should be ignored.
2398 : */
2399 7 : static bool deltest24(struct torture_context *tctx)
2400 : {
2401 7 : int fnum1 = -1;
2402 1 : struct smbcli_state *cli1;
2403 7 : bool correct = true;
2404 :
2405 7 : if (!torture_open_connection(&cli1, tctx, 0))
2406 0 : return false;
2407 :
2408 7 : smbcli_deltree(cli1->tree, fname);
2409 :
2410 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2411 : SEC_FILE_READ_DATA|
2412 : SEC_FILE_WRITE_DATA|
2413 : SEC_STD_DELETE,
2414 : FILE_ATTRIBUTE_NORMAL,
2415 : NTCREATEX_SHARE_ACCESS_READ|
2416 : NTCREATEX_SHARE_ACCESS_WRITE|
2417 : NTCREATEX_SHARE_ACCESS_DELETE,
2418 : NTCREATEX_DISP_CREATE,
2419 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2420 :
2421 7 : torture_assert(tctx, fnum1 != -1,
2422 : talloc_asprintf(tctx, "open of %s failed: %s!",
2423 : fname, smbcli_errstr(cli1->tree)));
2424 :
2425 : /* Now, unset Delete-On-Close, but it should have no effect */
2426 7 : torture_assert_ntstatus_ok(
2427 : tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, false),
2428 : talloc_asprintf(tctx, "unsetting delete_on_close failed (%s)",
2429 : smbcli_errstr(cli1->tree)));
2430 :
2431 7 : smbcli_close(cli1->tree, fnum1);
2432 :
2433 : /* File should not be there. */
2434 7 : fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
2435 : SEC_RIGHTS_FILE_READ,
2436 : FILE_ATTRIBUTE_NORMAL,
2437 : NTCREATEX_SHARE_ACCESS_READ|
2438 : NTCREATEX_SHARE_ACCESS_WRITE|
2439 : NTCREATEX_SHARE_ACCESS_DELETE,
2440 : NTCREATEX_DISP_OPEN,
2441 : 0, 0);
2442 :
2443 7 : CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2444 :
2445 6 : return correct;
2446 : }
2447 :
2448 : /* Test 25 ... */
2449 7 : static bool deltest25(struct torture_context *tctx,
2450 : struct smbcli_state *cli1,
2451 : struct smbcli_state *cli2)
2452 : {
2453 7 : int fnum1 = -1;
2454 1 : NTSTATUS status;
2455 7 : uint32_t disps[4] = {
2456 : NTCREATEX_DISP_SUPERSEDE,
2457 : NTCREATEX_DISP_OVERWRITE_IF,
2458 : NTCREATEX_DISP_CREATE,
2459 : NTCREATEX_DISP_OPEN_IF};
2460 1 : unsigned int i;
2461 :
2462 7 : del_clean_area(cli1, cli2);
2463 :
2464 36 : for (i = 0; i < sizeof(disps)/sizeof(disps[0]); i++) {
2465 : /* This should fail - we need to set DELETE_ACCESS. */
2466 :
2467 : /*
2468 : * A file or directory create with DELETE_ON_CLOSE but
2469 : * without DELETE_ACCESS should fail with
2470 : * NT_STATUS_INVALID_PARAMETER.
2471 : */
2472 :
2473 28 : fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2474 : SEC_FILE_READ_DATA,
2475 : FILE_ATTRIBUTE_DIRECTORY,
2476 : NTCREATEX_SHARE_ACCESS_NONE,
2477 : disps[i],
2478 : NTCREATEX_OPTIONS_DIRECTORY|
2479 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2480 :
2481 28 : torture_assert(tctx, fnum1 == -1,
2482 : talloc_asprintf(tctx, "open of %s succeeded "
2483 : "should have failed!",
2484 : dname));
2485 :
2486 : /* Must fail with NT_STATUS_INVALID_PARAMETER. */
2487 28 : status = smbcli_nt_error(cli1->tree);
2488 28 : torture_assert_ntstatus_equal(tctx,
2489 : status,
2490 : NT_STATUS_INVALID_PARAMETER,
2491 : talloc_asprintf(tctx, "create of %s should return "
2492 : "NT_STATUS_INVALID_PARAMETER, got %s",
2493 : dname,
2494 : smbcli_errstr(cli1->tree)));
2495 :
2496 : /*
2497 : * This should fail - the directory
2498 : * should not have been created.
2499 : */
2500 28 : status = smbcli_getatr(cli1->tree, dname, NULL, NULL, NULL);
2501 28 : torture_assert_ntstatus_equal(tctx,
2502 : status,
2503 : NT_STATUS_OBJECT_NAME_NOT_FOUND,
2504 : talloc_asprintf(tctx, "getattr of %s succeeded should "
2505 : "not have been created !",
2506 : dname));
2507 : }
2508 :
2509 6 : return true;
2510 : }
2511 :
2512 : /* Test 25a... */
2513 7 : static bool deltest25a(struct torture_context *tctx,
2514 : struct smbcli_state *cli1,
2515 : struct smbcli_state *cli2)
2516 : {
2517 7 : int fnum1 = -1;
2518 1 : NTSTATUS status;
2519 7 : uint32_t disps[4] = {
2520 : NTCREATEX_DISP_OVERWRITE_IF,
2521 : NTCREATEX_DISP_OPEN,
2522 : NTCREATEX_DISP_OVERWRITE,
2523 : NTCREATEX_DISP_OPEN_IF};
2524 :
2525 1 : unsigned int i;
2526 :
2527 7 : del_clean_area(cli1, cli2);
2528 :
2529 : /* Create the directory, and try with open calls. */
2530 7 : status = smbcli_mkdir(cli1->tree, dname);
2531 7 : torture_assert_ntstatus_ok(tctx,
2532 : status,
2533 : talloc_asprintf(tctx, "mkdir of %s failed %s",
2534 : dname,
2535 : smbcli_errstr(cli1->tree)));
2536 :
2537 35 : for (i = 0; i < sizeof(disps)/sizeof(disps[0]); i++) {
2538 28 : fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2539 : SEC_FILE_READ_DATA,
2540 : FILE_ATTRIBUTE_DIRECTORY,
2541 : NTCREATEX_SHARE_ACCESS_NONE,
2542 : disps[i],
2543 : NTCREATEX_OPTIONS_DIRECTORY|
2544 : NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
2545 :
2546 28 : torture_assert(tctx, fnum1 == -1,
2547 : talloc_asprintf(tctx, "open of %s succeeded "
2548 : "should have failed!",
2549 : dname));
2550 :
2551 : /* Must fail with NT_STATUS_INVALID_PARAMETER. */
2552 28 : status = smbcli_nt_error(cli1->tree);
2553 28 : torture_assert_ntstatus_equal(tctx,
2554 : status,
2555 : NT_STATUS_INVALID_PARAMETER,
2556 : talloc_asprintf(tctx, "create of %s should return "
2557 : "NT_STATUS_INVALID_PARAMETER, got %s",
2558 : dname,
2559 : smbcli_errstr(cli1->tree)));
2560 :
2561 : /*
2562 : * This should succeed - the directory
2563 : * should not have been deleted.
2564 : */
2565 28 : status = smbcli_getatr(cli1->tree, dname, NULL, NULL, NULL);
2566 28 : torture_assert_ntstatus_ok(tctx,
2567 : status,
2568 : talloc_asprintf(tctx, "getattr of %s failed %s",
2569 : fname,
2570 : smbcli_errstr(cli1->tree)));
2571 : }
2572 :
2573 7 : del_clean_area(cli1, cli2);
2574 7 : return true;
2575 : }
2576 :
2577 : /*
2578 : Test delete on close semantics.
2579 : */
2580 2354 : struct torture_suite *torture_test_delete(TALLOC_CTX *ctx)
2581 : {
2582 2354 : struct torture_suite *suite = torture_suite_create(
2583 : ctx, "delete");
2584 :
2585 2354 : torture_suite_add_2smb_test(suite, "deltest1", deltest1);
2586 2354 : torture_suite_add_2smb_test(suite, "deltest2", deltest2);
2587 2354 : torture_suite_add_2smb_test(suite, "deltest3", deltest3);
2588 2354 : torture_suite_add_2smb_test(suite, "deltest4", deltest4);
2589 2354 : torture_suite_add_2smb_test(suite, "deltest5", deltest5);
2590 2354 : torture_suite_add_2smb_test(suite, "deltest6", deltest6);
2591 2354 : torture_suite_add_2smb_test(suite, "deltest7", deltest7);
2592 2354 : torture_suite_add_2smb_test(suite, "deltest8", deltest8);
2593 2354 : torture_suite_add_2smb_test(suite, "deltest9", deltest9);
2594 2354 : torture_suite_add_2smb_test(suite, "deltest9a", deltest9a);
2595 2354 : torture_suite_add_2smb_test(suite, "deltest10", deltest10);
2596 2354 : torture_suite_add_2smb_test(suite, "deltest11", deltest11);
2597 2354 : torture_suite_add_2smb_test(suite, "deltest12", deltest12);
2598 2354 : torture_suite_add_2smb_test(suite, "deltest13", deltest13);
2599 2354 : torture_suite_add_2smb_test(suite, "deltest14", deltest14);
2600 2354 : torture_suite_add_2smb_test(suite, "deltest15", deltest15);
2601 2354 : torture_suite_add_2smb_test(suite, "deltest16", deltest16);
2602 2354 : torture_suite_add_2smb_test(suite, "deltest16a", deltest16a);
2603 2354 : torture_suite_add_2smb_test(suite, "deltest17", deltest17);
2604 2354 : torture_suite_add_2smb_test(suite, "deltest17a", deltest17a);
2605 2354 : torture_suite_add_2smb_test(suite, "deltest17b", deltest17b);
2606 2354 : torture_suite_add_2smb_test(suite, "deltest17c", deltest17c);
2607 2354 : torture_suite_add_2smb_test(suite, "deltest17d", deltest17d);
2608 2354 : torture_suite_add_2smb_test(suite, "deltest17e", deltest17e);
2609 2354 : torture_suite_add_2smb_test(suite, "deltest17f", deltest17f);
2610 2354 : torture_suite_add_2smb_test(suite, "deltest18", deltest18);
2611 2354 : torture_suite_add_2smb_test(suite, "deltest19", deltest19);
2612 2354 : torture_suite_add_2smb_test(suite, "deltest20", deltest20);
2613 2354 : torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
2614 2354 : torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
2615 2354 : torture_suite_add_2smb_test(suite, "deltest20c", deltest20c);
2616 2354 : torture_suite_add_simple_test(suite, "deltest21", deltest21);
2617 2354 : torture_suite_add_simple_test(suite, "deltest22", deltest22);
2618 2354 : torture_suite_add_2smb_test(suite, "deltest23", deltest23);
2619 2354 : torture_suite_add_simple_test(suite, "deltest24", deltest24);
2620 2354 : torture_suite_add_2smb_test(suite, "deltest25", deltest25);
2621 2354 : torture_suite_add_2smb_test(suite, "deltest25a", deltest25a);
2622 :
2623 2354 : return suite;
2624 : }
|