Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : unlink test suite
4 : Copyright (C) Andrew Tridgell 2003
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "torture/torture.h"
22 : #include "system/filesys.h"
23 : #include "libcli/raw/libcliraw.h"
24 : #include "libcli/raw/raw_proto.h"
25 : #include "libcli/libcli.h"
26 : #include "torture/util.h"
27 : #include "torture/raw/proto.h"
28 :
29 : #define CHECK_STATUS(status, correct) do { \
30 : if (!NT_STATUS_EQUAL(status, correct)) { \
31 : printf("(%s) Incorrect status %s - should be %s\n", \
32 : __location__, nt_errstr(status), nt_errstr(correct)); \
33 : ret = false; \
34 : goto done; \
35 : }} while (0)
36 :
37 : #define BASEDIR "\\testunlink"
38 :
39 : /*
40 : test unlink ops
41 : */
42 5 : static bool test_unlink(struct torture_context *tctx, struct smbcli_state *cli)
43 : {
44 : union smb_unlink io;
45 : NTSTATUS status;
46 5 : bool ret = true;
47 5 : const char *fname = BASEDIR "\\test.txt";
48 :
49 5 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
50 :
51 5 : printf("Trying non-existent file\n");
52 5 : io.unlink.in.pattern = fname;
53 5 : io.unlink.in.attrib = 0;
54 5 : status = smb_raw_unlink(cli->tree, &io);
55 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
56 :
57 5 : smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
58 :
59 5 : io.unlink.in.pattern = fname;
60 5 : io.unlink.in.attrib = 0;
61 5 : status = smb_raw_unlink(cli->tree, &io);
62 5 : CHECK_STATUS(status, NT_STATUS_OK);
63 :
64 5 : printf("Trying a hidden file\n");
65 5 : smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
66 5 : torture_set_file_attribute(cli->tree, fname, FILE_ATTRIBUTE_HIDDEN);
67 :
68 5 : io.unlink.in.pattern = fname;
69 5 : io.unlink.in.attrib = 0;
70 5 : status = smb_raw_unlink(cli->tree, &io);
71 5 : CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
72 :
73 5 : io.unlink.in.pattern = fname;
74 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_HIDDEN;
75 5 : status = smb_raw_unlink(cli->tree, &io);
76 5 : CHECK_STATUS(status, NT_STATUS_OK);
77 :
78 5 : io.unlink.in.pattern = fname;
79 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_HIDDEN;
80 5 : status = smb_raw_unlink(cli->tree, &io);
81 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
82 :
83 5 : printf("Trying a directory\n");
84 5 : io.unlink.in.pattern = BASEDIR;
85 5 : io.unlink.in.attrib = 0;
86 5 : status = smb_raw_unlink(cli->tree, &io);
87 5 : CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
88 :
89 5 : io.unlink.in.pattern = BASEDIR;
90 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
91 5 : status = smb_raw_unlink(cli->tree, &io);
92 5 : CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
93 :
94 5 : printf("Trying a bad path\n");
95 5 : io.unlink.in.pattern = "..";
96 5 : io.unlink.in.attrib = 0;
97 5 : status = smb_raw_unlink(cli->tree, &io);
98 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
99 :
100 5 : io.unlink.in.pattern = "\\..";
101 5 : io.unlink.in.attrib = 0;
102 5 : status = smb_raw_unlink(cli->tree, &io);
103 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
104 :
105 5 : io.unlink.in.pattern = BASEDIR "\\..\\..";
106 5 : io.unlink.in.attrib = 0;
107 5 : status = smb_raw_unlink(cli->tree, &io);
108 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
109 :
110 5 : io.unlink.in.pattern = BASEDIR "\\..";
111 5 : io.unlink.in.attrib = 0;
112 5 : status = smb_raw_unlink(cli->tree, &io);
113 5 : CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
114 :
115 5 : printf("Trying wildcards\n");
116 5 : smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
117 5 : io.unlink.in.pattern = BASEDIR "\\t*.t";
118 5 : io.unlink.in.attrib = 0;
119 5 : status = smb_raw_unlink(cli->tree, &io);
120 5 : CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
121 :
122 5 : io.unlink.in.pattern = BASEDIR "\\z*";
123 5 : io.unlink.in.attrib = 0;
124 5 : status = smb_raw_unlink(cli->tree, &io);
125 5 : CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
126 :
127 5 : io.unlink.in.pattern = BASEDIR "\\z*";
128 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
129 5 : status = smb_raw_unlink(cli->tree, &io);
130 :
131 5 : if (torture_setting_bool(tctx, "samba3", false)) {
132 : /*
133 : * In Samba3 we gave up upon getting the error codes in
134 : * wildcard unlink correct. Trying gentest showed that this is
135 : * irregular beyond our capabilities. So for
136 : * FILE_ATTRIBUTE_DIRECTORY we always return NAME_INVALID.
137 : * Tried by jra and vl. If others feel like solving this
138 : * puzzle, please tell us :-)
139 : */
140 4 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
141 : }
142 : else {
143 1 : CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
144 : }
145 :
146 5 : io.unlink.in.pattern = BASEDIR "\\*";
147 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
148 5 : status = smb_raw_unlink(cli->tree, &io);
149 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
150 :
151 5 : io.unlink.in.pattern = BASEDIR "\\?";
152 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
153 5 : status = smb_raw_unlink(cli->tree, &io);
154 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
155 :
156 5 : io.unlink.in.pattern = BASEDIR "\\t*";
157 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
158 5 : status = smb_raw_unlink(cli->tree, &io);
159 5 : if (torture_setting_bool(tctx, "samba3", false)) {
160 4 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
161 : }
162 : else {
163 1 : CHECK_STATUS(status, NT_STATUS_OK);
164 : }
165 :
166 5 : smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
167 :
168 5 : io.unlink.in.pattern = BASEDIR "\\*.dat";
169 5 : io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
170 5 : status = smb_raw_unlink(cli->tree, &io);
171 5 : if (torture_setting_bool(tctx, "samba3", false)) {
172 4 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
173 : }
174 : else {
175 1 : CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
176 : }
177 :
178 5 : io.unlink.in.pattern = BASEDIR "\\*.tx?";
179 5 : io.unlink.in.attrib = 0;
180 5 : status = smb_raw_unlink(cli->tree, &io);
181 5 : CHECK_STATUS(status, NT_STATUS_OK);
182 :
183 5 : status = smb_raw_unlink(cli->tree, &io);
184 5 : CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
185 :
186 :
187 9 : done:
188 5 : smb_raw_exit(cli->session);
189 5 : smbcli_deltree(cli->tree, BASEDIR);
190 5 : return ret;
191 : }
192 :
193 :
194 : /*
195 : test delete on close
196 : */
197 5 : static bool test_delete_on_close(struct torture_context *tctx,
198 : struct smbcli_state *cli)
199 : {
200 : union smb_open op;
201 : union smb_unlink io;
202 : struct smb_rmdir dio;
203 : NTSTATUS status;
204 5 : bool ret = true;
205 : int fnum, fnum2;
206 5 : const char *fname = BASEDIR "\\test.txt";
207 5 : const char *dname = BASEDIR "\\test.dir";
208 5 : const char *inside = BASEDIR "\\test.dir\\test.txt";
209 : union smb_setfileinfo sfinfo;
210 :
211 5 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
212 :
213 5 : dio.in.path = dname;
214 :
215 5 : io.unlink.in.pattern = fname;
216 5 : io.unlink.in.attrib = 0;
217 5 : status = smb_raw_unlink(cli->tree, &io);
218 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
219 :
220 5 : printf("Testing with delete_on_close 0\n");
221 5 : fnum = create_complex_file(cli, tctx, fname);
222 :
223 5 : sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
224 5 : sfinfo.disposition_info.in.file.fnum = fnum;
225 5 : sfinfo.disposition_info.in.delete_on_close = 0;
226 5 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
227 5 : CHECK_STATUS(status, NT_STATUS_OK);
228 :
229 5 : smbcli_close(cli->tree, fnum);
230 :
231 5 : status = smb_raw_unlink(cli->tree, &io);
232 5 : CHECK_STATUS(status, NT_STATUS_OK);
233 :
234 5 : printf("Testing with delete_on_close 1\n");
235 5 : fnum = create_complex_file(cli, tctx, fname);
236 5 : sfinfo.disposition_info.in.file.fnum = fnum;
237 5 : sfinfo.disposition_info.in.delete_on_close = 1;
238 5 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
239 5 : CHECK_STATUS(status, NT_STATUS_OK);
240 :
241 5 : smbcli_close(cli->tree, fnum);
242 :
243 5 : status = smb_raw_unlink(cli->tree, &io);
244 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
245 :
246 :
247 5 : printf("Testing with directory and delete_on_close 0\n");
248 5 : status = create_directory_handle(cli->tree, dname, &fnum);
249 5 : CHECK_STATUS(status, NT_STATUS_OK);
250 :
251 5 : sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
252 5 : sfinfo.disposition_info.in.file.fnum = fnum;
253 5 : sfinfo.disposition_info.in.delete_on_close = 0;
254 5 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
255 5 : CHECK_STATUS(status, NT_STATUS_OK);
256 :
257 5 : smbcli_close(cli->tree, fnum);
258 :
259 5 : status = smb_raw_rmdir(cli->tree, &dio);
260 5 : CHECK_STATUS(status, NT_STATUS_OK);
261 :
262 5 : printf("Testing with directory delete_on_close 1\n");
263 5 : status = create_directory_handle(cli->tree, dname, &fnum);
264 5 : CHECK_STATUS(status, NT_STATUS_OK);
265 :
266 5 : sfinfo.disposition_info.in.file.fnum = fnum;
267 5 : sfinfo.disposition_info.in.delete_on_close = 1;
268 5 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
269 5 : CHECK_STATUS(status, NT_STATUS_OK);
270 :
271 5 : smbcli_close(cli->tree, fnum);
272 :
273 5 : status = smb_raw_rmdir(cli->tree, &dio);
274 5 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
275 :
276 :
277 5 : if (!torture_setting_bool(tctx, "samba3", false)) {
278 :
279 : /*
280 : * Known deficiency, also skipped in base-delete.
281 : */
282 :
283 1 : printf("Testing with non-empty directory delete_on_close\n");
284 1 : status = create_directory_handle(cli->tree, dname, &fnum);
285 1 : CHECK_STATUS(status, NT_STATUS_OK);
286 :
287 1 : fnum2 = create_complex_file(cli, tctx, inside);
288 :
289 1 : sfinfo.disposition_info.in.file.fnum = fnum;
290 1 : sfinfo.disposition_info.in.delete_on_close = 1;
291 1 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
292 1 : CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
293 :
294 1 : sfinfo.disposition_info.in.file.fnum = fnum2;
295 1 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
296 1 : CHECK_STATUS(status, NT_STATUS_OK);
297 :
298 1 : sfinfo.disposition_info.in.file.fnum = fnum;
299 1 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
300 1 : CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
301 :
302 1 : smbcli_close(cli->tree, fnum2);
303 :
304 1 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
305 1 : CHECK_STATUS(status, NT_STATUS_OK);
306 :
307 1 : smbcli_close(cli->tree, fnum);
308 :
309 1 : status = smb_raw_rmdir(cli->tree, &dio);
310 1 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
311 : }
312 :
313 5 : printf("Testing open dir with delete_on_close\n");
314 5 : status = create_directory_handle(cli->tree, dname, &fnum);
315 5 : CHECK_STATUS(status, NT_STATUS_OK);
316 :
317 5 : smbcli_close(cli->tree, fnum);
318 5 : fnum2 = create_complex_file(cli, tctx, inside);
319 5 : smbcli_close(cli->tree, fnum2);
320 :
321 5 : op.generic.level = RAW_OPEN_NTCREATEX;
322 5 : op.ntcreatex.in.root_fid.fnum = 0;
323 5 : op.ntcreatex.in.flags = 0;
324 5 : op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
325 5 : op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
326 5 : op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
327 5 : op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
328 5 : op.ntcreatex.in.alloc_size = 0;
329 5 : op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
330 5 : op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
331 5 : op.ntcreatex.in.security_flags = 0;
332 5 : op.ntcreatex.in.fname = dname;
333 :
334 5 : status = smb_raw_open(cli->tree, tctx, &op);
335 5 : CHECK_STATUS(status, NT_STATUS_OK);
336 5 : fnum = op.ntcreatex.out.file.fnum;
337 :
338 5 : smbcli_close(cli->tree, fnum);
339 :
340 5 : status = smb_raw_rmdir(cli->tree, &dio);
341 5 : CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
342 :
343 5 : smbcli_deltree(cli->tree, dname);
344 :
345 5 : printf("Testing double open dir with second delete_on_close\n");
346 5 : status = create_directory_handle(cli->tree, dname, &fnum);
347 5 : CHECK_STATUS(status, NT_STATUS_OK);
348 5 : smbcli_close(cli->tree, fnum);
349 :
350 5 : fnum2 = create_complex_file(cli, tctx, inside);
351 5 : smbcli_close(cli->tree, fnum2);
352 :
353 5 : op.generic.level = RAW_OPEN_NTCREATEX;
354 5 : op.ntcreatex.in.root_fid.fnum = 0;
355 5 : op.ntcreatex.in.flags = 0;
356 5 : op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
357 5 : op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
358 5 : op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
359 5 : op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
360 5 : op.ntcreatex.in.alloc_size = 0;
361 5 : op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
362 5 : op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
363 5 : op.ntcreatex.in.security_flags = 0;
364 5 : op.ntcreatex.in.fname = dname;
365 :
366 5 : status = smb_raw_open(cli->tree, tctx, &op);
367 5 : CHECK_STATUS(status, NT_STATUS_OK);
368 5 : fnum2 = op.ntcreatex.out.file.fnum;
369 :
370 5 : smbcli_close(cli->tree, fnum2);
371 :
372 5 : status = smb_raw_rmdir(cli->tree, &dio);
373 5 : CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
374 :
375 5 : smbcli_deltree(cli->tree, dname);
376 :
377 5 : printf("Testing pre-existing open dir with second delete_on_close\n");
378 5 : status = create_directory_handle(cli->tree, dname, &fnum);
379 5 : CHECK_STATUS(status, NT_STATUS_OK);
380 :
381 5 : smbcli_close(cli->tree, fnum);
382 :
383 5 : fnum = create_complex_file(cli, tctx, inside);
384 5 : smbcli_close(cli->tree, fnum);
385 :
386 : /* we have a dir with a file in it, no handles open */
387 :
388 5 : op.generic.level = RAW_OPEN_NTCREATEX;
389 5 : op.ntcreatex.in.root_fid.fnum = 0;
390 5 : op.ntcreatex.in.flags = 0;
391 5 : op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
392 5 : op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
393 5 : op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
394 5 : op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
395 5 : op.ntcreatex.in.alloc_size = 0;
396 5 : op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
397 5 : op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
398 5 : op.ntcreatex.in.security_flags = 0;
399 5 : op.ntcreatex.in.fname = dname;
400 :
401 5 : status = smb_raw_open(cli->tree, tctx, &op);
402 5 : CHECK_STATUS(status, NT_STATUS_OK);
403 5 : fnum = op.ntcreatex.out.file.fnum;
404 :
405 : /* open without delete on close */
406 5 : op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
407 5 : status = smb_raw_open(cli->tree, tctx, &op);
408 5 : CHECK_STATUS(status, NT_STATUS_OK);
409 5 : fnum2 = op.ntcreatex.out.file.fnum;
410 :
411 : /* close 2nd file handle */
412 5 : smbcli_close(cli->tree, fnum2);
413 :
414 5 : status = smb_raw_rmdir(cli->tree, &dio);
415 5 : CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
416 :
417 :
418 5 : smbcli_close(cli->tree, fnum);
419 :
420 5 : status = smb_raw_rmdir(cli->tree, &dio);
421 5 : CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
422 :
423 9 : done:
424 5 : smb_raw_exit(cli->session);
425 5 : smbcli_deltree(cli->tree, BASEDIR);
426 5 : return ret;
427 : }
428 :
429 :
430 : struct unlink_defer_cli_state {
431 : struct torture_context *tctx;
432 : struct smbcli_state *cli1;
433 : };
434 :
435 : /*
436 : * A handler function for oplock break requests. Ack it as a break to none
437 : */
438 5 : static bool oplock_handler_ack_to_none(struct smbcli_transport *transport,
439 : uint16_t tid, uint16_t fnum,
440 : uint8_t level, void *private_data)
441 : {
442 5 : struct unlink_defer_cli_state *ud_cli_state =
443 : (struct unlink_defer_cli_state *)private_data;
444 : union smb_setfileinfo sfinfo;
445 : bool ret;
446 5 : struct smbcli_request *req = NULL;
447 :
448 5 : torture_comment(ud_cli_state->tctx, "delete the file before sending "
449 : "the ack.");
450 :
451 : /* cli1: set delete on close */
452 5 : sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
453 5 : sfinfo.disposition_info.in.file.fnum = fnum;
454 5 : sfinfo.disposition_info.in.delete_on_close = 1;
455 5 : req = smb_raw_setfileinfo_send(ud_cli_state->cli1->tree, &sfinfo);
456 5 : if (!req) {
457 0 : torture_comment(ud_cli_state->tctx, "smb_raw_setfileinfo_send "
458 : "failed.");
459 : }
460 :
461 5 : smbcli_close(ud_cli_state->cli1->tree, fnum);
462 :
463 5 : torture_comment(ud_cli_state->tctx, "Acking the oplock to NONE\n");
464 :
465 5 : ret = smbcli_oplock_ack(ud_cli_state->cli1->tree, fnum,
466 : OPLOCK_BREAK_TO_NONE);
467 :
468 5 : return ret;
469 : }
470 :
471 5 : static bool test_unlink_defer(struct torture_context *tctx,
472 : struct smbcli_state *cli1,
473 : struct smbcli_state *cli2)
474 : {
475 5 : const char *fname = BASEDIR "\\test_unlink_defer.dat";
476 : NTSTATUS status;
477 5 : bool ret = true;
478 : union smb_open io;
479 : union smb_unlink unl;
480 5 : struct unlink_defer_cli_state ud_cli_state = {};
481 :
482 5 : if (!torture_setup_dir(cli1, BASEDIR)) {
483 0 : return false;
484 : }
485 :
486 : /* cleanup */
487 5 : smbcli_unlink(cli1->tree, fname);
488 :
489 5 : ud_cli_state.tctx = tctx;
490 5 : ud_cli_state.cli1 = cli1;
491 :
492 5 : smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none,
493 : &ud_cli_state);
494 :
495 5 : io.generic.level = RAW_OPEN_NTCREATEX;
496 5 : io.ntcreatex.in.root_fid.fnum = 0;
497 5 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
498 5 : io.ntcreatex.in.alloc_size = 0;
499 5 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
500 5 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
501 : NTCREATEX_SHARE_ACCESS_WRITE |
502 : NTCREATEX_SHARE_ACCESS_DELETE;
503 5 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
504 5 : io.ntcreatex.in.create_options = 0;
505 5 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
506 5 : io.ntcreatex.in.security_flags = 0;
507 5 : io.ntcreatex.in.fname = fname;
508 :
509 : /* cli1: open file with a batch oplock. */
510 5 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
511 : NTCREATEX_FLAGS_REQUEST_OPLOCK |
512 : NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
513 :
514 5 : status = smb_raw_open(cli1->tree, tctx, &io);
515 5 : CHECK_STATUS(status, NT_STATUS_OK);
516 :
517 : /* cli2: Try to unlink it, but block on the oplock */
518 5 : torture_comment(tctx, "Try an unlink (should defer the open\n");
519 5 : unl.unlink.in.pattern = fname;
520 5 : unl.unlink.in.attrib = 0;
521 5 : status = smb_raw_unlink(cli2->tree, &unl);
522 :
523 5 : done:
524 5 : smb_raw_exit(cli1->session);
525 5 : smb_raw_exit(cli2->session);
526 5 : smbcli_deltree(cli1->tree, BASEDIR);
527 5 : return ret;
528 : }
529 :
530 : /*
531 : basic testing of unlink calls
532 : */
533 2355 : struct torture_suite *torture_raw_unlink(TALLOC_CTX *mem_ctx)
534 : {
535 2355 : struct torture_suite *suite = torture_suite_create(mem_ctx, "unlink");
536 :
537 2355 : torture_suite_add_1smb_test(suite, "unlink", test_unlink);
538 2355 : torture_suite_add_1smb_test(suite, "delete_on_close", test_delete_on_close);
539 2355 : torture_suite_add_2smb_test(suite, "unlink-defer", test_unlink_defer);
540 :
541 2355 : return suite;
542 : }
|