lib: tevent: Use system <tevent.h>, not internal header path (except in self-test).
[Samba.git] / source4 / torture / smb2 / rename.c
blob5055cf24344d68582a3c9750130f18ddb85bcef3
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 rename test suite
6 Copyright (C) Christian Ambach 2012
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include <tevent.h>
26 #include "lib/util/tevent_ntstatus.h"
28 #include "torture/torture.h"
29 #include "torture/smb2/proto.h"
31 #include "librpc/gen_ndr/security.h"
33 #define CHECK_STATUS(status, correct) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 torture_result(torture, TORTURE_FAIL, \
36 "(%s) Incorrect status %s - should be %s\n", \
37 __location__, nt_errstr(status), nt_errstr(correct)); \
38 ret = false; \
39 goto done; \
40 }} while (0)
42 #define BASEDIR "test_rename"
45 * basic testing of rename: open file with DELETE access
46 * this should pass
49 static bool torture_smb2_rename_simple(struct torture_context *torture,
50 struct smb2_tree *tree1)
52 bool ret = true;
53 NTSTATUS status;
54 union smb_open io;
55 union smb_close cl;
56 union smb_setfileinfo sinfo;
57 union smb_fileinfo fi;
58 struct smb2_handle h1;
60 ZERO_STRUCT(h1);
62 smb2_deltree(tree1, BASEDIR);
63 smb2_util_rmdir(tree1, BASEDIR);
65 torture_comment(torture, "Creating base directory\n");
67 smb2_util_mkdir(tree1, BASEDIR);
70 torture_comment(torture, "Creating test file\n");
72 ZERO_STRUCT(io.smb2);
73 io.generic.level = RAW_OPEN_SMB2;
74 io.smb2.in.create_flags = 0;
75 io.smb2.in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE;
76 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
77 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
78 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
79 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
80 io.smb2.in.alloc_size = 0;
81 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
82 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
83 io.smb2.in.security_flags = 0;
84 io.smb2.in.fname = BASEDIR "\\file.txt";
86 status = smb2_create(tree1, torture, &(io.smb2));
87 CHECK_STATUS(status, NT_STATUS_OK);
88 h1 = io.smb2.out.file.handle;
90 torture_comment(torture, "Renaming test file\n");
92 ZERO_STRUCT(sinfo);
93 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
94 sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
95 sinfo.rename_information.in.overwrite = 0;
96 sinfo.rename_information.in.root_fid = 0;
97 sinfo.rename_information.in.new_name =
98 BASEDIR "\\newname.txt";
99 status = smb2_setinfo_file(tree1, &sinfo);
100 CHECK_STATUS(status, NT_STATUS_OK);
102 torture_comment(torture, "Checking for new filename\n");
104 ZERO_STRUCT(fi);
105 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
106 fi.generic.in.file.handle = h1;
107 status = smb2_getinfo_file(tree1, torture, &fi);
108 CHECK_STATUS(status, NT_STATUS_OK);
111 torture_comment(torture, "Closing test file\n");
113 ZERO_STRUCT(cl.smb2);
114 cl.smb2.level = RAW_CLOSE_SMB2;
115 cl.smb2.in.file.handle = h1;
116 status = smb2_close(tree1, &(cl.smb2));
117 CHECK_STATUS(status, NT_STATUS_OK);
119 ZERO_STRUCT(h1);
121 done:
123 torture_comment(torture, "Cleaning up\n");
125 if (h1.data[0] || h1.data[1]) {
126 ZERO_STRUCT(cl.smb2);
127 cl.smb2.level = RAW_CLOSE_SMB2;
128 cl.smb2.in.file.handle = h1;
129 status = smb2_close(tree1, &(cl.smb2));
131 smb2_deltree(tree1, BASEDIR);
132 return ret;
136 * basic testing of rename, this time do not request DELETE access
137 * for the file, this should fail
140 static bool torture_smb2_rename_simple2(struct torture_context *torture,
141 struct smb2_tree *tree1)
143 bool ret = true;
144 NTSTATUS status;
145 union smb_open io;
146 union smb_close cl;
147 union smb_setfileinfo sinfo;
148 struct smb2_handle h1;
150 ZERO_STRUCT(h1);
152 smb2_deltree(tree1, BASEDIR);
153 smb2_util_rmdir(tree1, BASEDIR);
155 torture_comment(torture, "Creating base directory\n");
157 smb2_util_mkdir(tree1, BASEDIR);
160 torture_comment(torture, "Creating test file\n");
162 ZERO_STRUCT(io.smb2);
163 io.generic.level = RAW_OPEN_SMB2;
164 io.smb2.in.create_flags = 0;
165 io.smb2.in.desired_access = SEC_FILE_ALL;
166 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
167 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
168 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
169 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
170 io.smb2.in.alloc_size = 0;
171 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
172 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
173 io.smb2.in.security_flags = 0;
174 io.smb2.in.fname = BASEDIR "\\file.txt";
176 status = smb2_create(tree1, torture, &(io.smb2));
177 CHECK_STATUS(status, NT_STATUS_OK);
178 h1 = io.smb2.out.file.handle;
180 torture_comment(torture, "Renaming test file\n");
182 ZERO_STRUCT(sinfo);
183 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
184 sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
185 sinfo.rename_information.in.overwrite = 0;
186 sinfo.rename_information.in.root_fid = 0;
187 sinfo.rename_information.in.new_name =
188 BASEDIR "\\newname.txt";
189 status = smb2_setinfo_file(tree1, &sinfo);
190 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
192 torture_comment(torture, "Closing test file\n");
194 ZERO_STRUCT(cl.smb2);
195 cl.smb2.level = RAW_CLOSE_SMB2;
196 cl.smb2.in.file.handle = h1;
197 status = smb2_close(tree1, &(cl.smb2));
198 CHECK_STATUS(status, NT_STATUS_OK);
200 ZERO_STRUCT(h1);
202 done:
204 torture_comment(torture, "Cleaning up\n");
206 if (h1.data[0] || h1.data[1]) {
207 ZERO_STRUCT(cl.smb2);
208 cl.smb2.level = RAW_CLOSE_SMB2;
209 cl.smb2.in.file.handle = h1;
210 status = smb2_close(tree1, &(cl.smb2));
212 smb2_deltree(tree1, BASEDIR);
213 return ret;
218 * testing of rename with no sharing allowed on file
219 * this should work
222 static bool torture_smb2_rename_no_sharemode(struct torture_context *torture,
223 struct smb2_tree *tree1)
225 bool ret = true;
226 NTSTATUS status;
227 union smb_open io;
228 union smb_close cl;
229 union smb_setfileinfo sinfo;
230 union smb_fileinfo fi;
231 struct smb2_handle h1;
233 ZERO_STRUCT(h1);
235 smb2_deltree(tree1, BASEDIR);
236 smb2_util_rmdir(tree1, BASEDIR);
238 torture_comment(torture, "Creating base directory\n");
240 smb2_util_mkdir(tree1, BASEDIR);
243 torture_comment(torture, "Creating test file\n");
245 ZERO_STRUCT(io.smb2);
246 io.generic.level = RAW_OPEN_SMB2;
247 io.smb2.in.create_flags = 0;
248 io.smb2.in.desired_access = 0x0017019f;
249 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
250 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
251 io.smb2.in.share_access = 0;
252 io.smb2.in.alloc_size = 0;
253 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
254 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
255 io.smb2.in.security_flags = 0;
256 io.smb2.in.fname = BASEDIR "\\file.txt";
258 status = smb2_create(tree1, torture, &(io.smb2));
259 CHECK_STATUS(status, NT_STATUS_OK);
260 h1 = io.smb2.out.file.handle;
262 torture_comment(torture, "Renaming test file\n");
264 ZERO_STRUCT(sinfo);
265 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
266 sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
267 sinfo.rename_information.in.overwrite = 0;
268 sinfo.rename_information.in.root_fid = 0;
269 sinfo.rename_information.in.new_name =
270 BASEDIR "\\newname.txt";
271 status = smb2_setinfo_file(tree1, &sinfo);
272 CHECK_STATUS(status, NT_STATUS_OK);
274 torture_comment(torture, "Checking for new filename\n");
276 ZERO_STRUCT(fi);
277 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
278 fi.generic.in.file.handle = h1;
279 status = smb2_getinfo_file(tree1, torture, &fi);
280 CHECK_STATUS(status, NT_STATUS_OK);
283 torture_comment(torture, "Closing test file\n");
285 ZERO_STRUCT(cl.smb2);
286 cl.smb2.level = RAW_CLOSE_SMB2;
287 cl.smb2.in.file.handle = h1;
288 status = smb2_close(tree1, &(cl.smb2));
289 CHECK_STATUS(status, NT_STATUS_OK);
291 ZERO_STRUCT(h1);
293 done:
295 torture_comment(torture, "Cleaning up\n");
297 if (h1.data[0] || h1.data[1]) {
298 ZERO_STRUCT(cl.smb2);
299 cl.smb2.level = RAW_CLOSE_SMB2;
300 cl.smb2.in.file.handle = h1;
301 status = smb2_close(tree1, &(cl.smb2));
303 smb2_deltree(tree1, BASEDIR);
304 return ret;
308 * testing of rename when opening parent dir with delete access and delete
309 * sharing allowed
310 * should result in sharing violation
313 static bool torture_smb2_rename_with_delete_access(struct torture_context *torture,
314 struct smb2_tree *tree1)
316 bool ret = true;
317 NTSTATUS status;
318 union smb_open io;
319 union smb_close cl;
320 union smb_setfileinfo sinfo;
321 struct smb2_handle fh, dh;
323 ZERO_STRUCT(fh);
324 ZERO_STRUCT(dh);
326 smb2_deltree(tree1, BASEDIR);
327 smb2_util_rmdir(tree1, BASEDIR);
329 torture_comment(torture, "Creating base directory\n");
331 smb2_util_mkdir(tree1, BASEDIR);
333 torture_comment(torture, "Opening parent directory\n");
335 ZERO_STRUCT(io.smb2);
336 io.generic.level = RAW_OPEN_SMB2;
337 io.smb2.in.create_flags = 0;
338 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
339 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
340 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
341 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
342 SEC_FILE_WRITE_DATA;
343 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
344 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
345 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
346 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
347 io.smb2.in.alloc_size = 0;
348 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
349 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
350 io.smb2.in.security_flags = 0;
351 io.smb2.in.fname = BASEDIR;
353 status = smb2_create(tree1, torture, &(io.smb2));
354 CHECK_STATUS(status, NT_STATUS_OK);
355 dh = io.smb2.out.file.handle;
358 torture_comment(torture, "Creating test file\n");
360 ZERO_STRUCT(io.smb2);
361 io.generic.level = RAW_OPEN_SMB2;
362 io.smb2.in.create_flags = 0;
363 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
364 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
365 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
366 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
367 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
368 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
369 io.smb2.in.share_access = 0;
370 io.smb2.in.alloc_size = 0;
371 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
372 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
373 io.smb2.in.security_flags = 0;
374 io.smb2.in.fname = BASEDIR "\\file.txt";
376 status = smb2_create(tree1, torture, &(io.smb2));
377 CHECK_STATUS(status, NT_STATUS_OK);
378 fh = io.smb2.out.file.handle;
380 torture_comment(torture, "Renaming test file\n");
382 ZERO_STRUCT(sinfo);
383 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
384 sinfo.rename_information.in.file.handle = fh;
385 sinfo.rename_information.in.overwrite = 0;
386 sinfo.rename_information.in.root_fid = 0;
387 sinfo.rename_information.in.new_name =
388 BASEDIR "\\newname.txt";
389 status = smb2_setinfo_file(tree1, &sinfo);
390 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
392 torture_comment(torture, "Closing test file\n");
394 ZERO_STRUCT(cl.smb2);
395 cl.smb2.level = RAW_CLOSE_SMB2;
396 cl.smb2.in.file.handle = fh;
397 status = smb2_close(tree1, &(cl.smb2));
398 CHECK_STATUS(status, NT_STATUS_OK);
400 ZERO_STRUCT(fh);
402 torture_comment(torture, "Closing directory\n");
404 ZERO_STRUCT(cl.smb2);
405 cl.smb2.level = RAW_CLOSE_SMB2;
406 cl.smb2.in.file.handle = dh;
407 status = smb2_close(tree1, &(cl.smb2));
408 CHECK_STATUS(status, NT_STATUS_OK);
410 ZERO_STRUCT(dh);
413 done:
415 torture_comment(torture, "Cleaning up\n");
417 if (fh.data[0] || fh.data[1]) {
418 ZERO_STRUCT(cl.smb2);
419 cl.smb2.level = RAW_CLOSE_SMB2;
420 cl.smb2.in.file.handle = fh;
421 status = smb2_close(tree1, &(cl.smb2));
423 if (dh.data[0] || dh.data[1]) {
424 ZERO_STRUCT(cl.smb2);
425 cl.smb2.level = RAW_CLOSE_SMB2;
426 cl.smb2.in.file.handle = dh;
427 status = smb2_close(tree1, &(cl.smb2));
430 smb2_deltree(tree1, BASEDIR);
431 return ret;
436 * testing of rename with delete access on parent dir
437 * this is a variation of the test above: parent dir is opened
438 * without share_delete, so rename must fail
441 static bool torture_smb2_rename_with_delete_access2(struct torture_context *torture,
442 struct smb2_tree *tree1)
444 bool ret = true;
445 NTSTATUS status;
446 union smb_open io;
447 union smb_close cl;
448 union smb_setfileinfo sinfo;
449 struct smb2_handle fh, dh;
451 ZERO_STRUCT(fh);
452 ZERO_STRUCT(dh);
454 smb2_deltree(tree1, BASEDIR);
455 smb2_util_rmdir(tree1, BASEDIR);
457 torture_comment(torture, "Creating base directory\n");
459 smb2_util_mkdir(tree1, BASEDIR);
461 torture_comment(torture, "Opening parent directory\n");
463 ZERO_STRUCT(io.smb2);
464 io.generic.level = RAW_OPEN_SMB2;
465 io.smb2.in.create_flags = 0;
466 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
467 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
468 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
469 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
470 SEC_FILE_WRITE_DATA;
471 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
472 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
473 io.smb2.in.share_access = 0;
474 io.smb2.in.alloc_size = 0;
475 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
476 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
477 io.smb2.in.security_flags = 0;
478 io.smb2.in.fname = BASEDIR;
480 status = smb2_create(tree1, torture, &(io.smb2));
481 CHECK_STATUS(status, NT_STATUS_OK);
482 dh = io.smb2.out.file.handle;
485 torture_comment(torture, "Creating test file\n");
487 ZERO_STRUCT(io.smb2);
488 io.generic.level = RAW_OPEN_SMB2;
489 io.smb2.in.create_flags = 0;
490 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
491 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
492 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
493 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
494 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
495 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
496 io.smb2.in.share_access = 0;
497 io.smb2.in.alloc_size = 0;
498 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
499 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
500 io.smb2.in.security_flags = 0;
501 io.smb2.in.fname = BASEDIR "\\file.txt";
503 status = smb2_create(tree1, torture, &(io.smb2));
504 CHECK_STATUS(status, NT_STATUS_OK);
505 fh = io.smb2.out.file.handle;
507 torture_comment(torture, "Renaming test file\n");
509 ZERO_STRUCT(sinfo);
510 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
511 sinfo.rename_information.in.file.handle = fh;
512 sinfo.rename_information.in.overwrite = 0;
513 sinfo.rename_information.in.root_fid = 0;
514 sinfo.rename_information.in.new_name =
515 BASEDIR "\\newname.txt";
516 status = smb2_setinfo_file(tree1, &sinfo);
517 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
519 torture_comment(torture, "Closing test file\n");
521 ZERO_STRUCT(cl.smb2);
522 cl.smb2.level = RAW_CLOSE_SMB2;
523 cl.smb2.in.file.handle = fh;
524 status = smb2_close(tree1, &(cl.smb2));
525 CHECK_STATUS(status, NT_STATUS_OK);
527 ZERO_STRUCT(fh);
529 torture_comment(torture, "Closing directory\n");
531 ZERO_STRUCT(cl.smb2);
532 cl.smb2.level = RAW_CLOSE_SMB2;
533 cl.smb2.in.file.handle = dh;
534 status = smb2_close(tree1, &(cl.smb2));
535 CHECK_STATUS(status, NT_STATUS_OK);
537 ZERO_STRUCT(dh);
540 done:
542 torture_comment(torture, "Cleaning up\n");
544 if (fh.data[0] || fh.data[1]) {
545 ZERO_STRUCT(cl.smb2);
546 cl.smb2.level = RAW_CLOSE_SMB2;
547 cl.smb2.in.file.handle = fh;
548 status = smb2_close(tree1, &(cl.smb2));
550 if (dh.data[0] || dh.data[1]) {
551 ZERO_STRUCT(cl.smb2);
552 cl.smb2.level = RAW_CLOSE_SMB2;
553 cl.smb2.in.file.handle = dh;
554 status = smb2_close(tree1, &(cl.smb2));
557 smb2_deltree(tree1, BASEDIR);
558 return ret;
562 * testing of rename when opening parent dir with no delete access and delete
563 * sharing allowed
564 * this should pass
567 static bool torture_smb2_rename_no_delete_access(struct torture_context *torture,
568 struct smb2_tree *tree1)
570 bool ret = true;
571 NTSTATUS status;
572 union smb_open io;
573 union smb_close cl;
574 union smb_setfileinfo sinfo;
575 union smb_fileinfo fi;
576 struct smb2_handle fh, dh;
578 ZERO_STRUCT(fh);
579 ZERO_STRUCT(dh);
581 smb2_deltree(tree1, BASEDIR);
582 smb2_util_rmdir(tree1, BASEDIR);
584 torture_comment(torture, "Creating base directory\n");
586 smb2_util_mkdir(tree1, BASEDIR);
588 torture_comment(torture, "Opening parent directory\n");
590 ZERO_STRUCT(io.smb2);
591 io.generic.level = RAW_OPEN_SMB2;
592 io.smb2.in.create_flags = 0;
593 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
594 SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
595 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
596 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
597 SEC_FILE_WRITE_DATA;
598 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
599 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
600 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
601 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
602 io.smb2.in.alloc_size = 0;
603 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
604 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
605 io.smb2.in.security_flags = 0;
606 io.smb2.in.fname = BASEDIR;
608 status = smb2_create(tree1, torture, &(io.smb2));
609 CHECK_STATUS(status, NT_STATUS_OK);
610 dh = io.smb2.out.file.handle;
613 torture_comment(torture, "Creating test file\n");
615 ZERO_STRUCT(io.smb2);
616 io.generic.level = RAW_OPEN_SMB2;
617 io.smb2.in.create_flags = 0;
618 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
619 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
620 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
621 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
622 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
623 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
624 io.smb2.in.share_access = 0;
625 io.smb2.in.alloc_size = 0;
626 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
627 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
628 io.smb2.in.security_flags = 0;
629 io.smb2.in.fname = BASEDIR "\\file.txt";
631 status = smb2_create(tree1, torture, &(io.smb2));
632 CHECK_STATUS(status, NT_STATUS_OK);
633 fh = io.smb2.out.file.handle;
635 torture_comment(torture, "Renaming test file\n");
637 ZERO_STRUCT(sinfo);
638 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
639 sinfo.rename_information.in.file.handle = fh;
640 sinfo.rename_information.in.overwrite = 0;
641 sinfo.rename_information.in.root_fid = 0;
642 sinfo.rename_information.in.new_name =
643 BASEDIR "\\newname.txt";
644 status = smb2_setinfo_file(tree1, &sinfo);
645 CHECK_STATUS(status, NT_STATUS_OK);
647 torture_comment(torture, "Checking for new filename\n");
649 ZERO_STRUCT(fi);
650 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
651 fi.generic.in.file.handle = fh;
652 status = smb2_getinfo_file(tree1, torture, &fi);
653 CHECK_STATUS(status, NT_STATUS_OK);
656 torture_comment(torture, "Closing test file\n");
658 ZERO_STRUCT(cl.smb2);
659 cl.smb2.level = RAW_CLOSE_SMB2;
660 cl.smb2.in.file.handle = fh;
661 status = smb2_close(tree1, &(cl.smb2));
662 CHECK_STATUS(status, NT_STATUS_OK);
664 ZERO_STRUCT(fh);
666 torture_comment(torture, "Closing directory\n");
668 ZERO_STRUCT(cl.smb2);
669 cl.smb2.level = RAW_CLOSE_SMB2;
670 cl.smb2.in.file.handle = dh;
671 status = smb2_close(tree1, &(cl.smb2));
672 CHECK_STATUS(status, NT_STATUS_OK);
674 ZERO_STRUCT(dh);
677 done:
679 torture_comment(torture, "Cleaning up\n");
681 if (fh.data[0] || fh.data[1]) {
682 ZERO_STRUCT(cl.smb2);
683 cl.smb2.level = RAW_CLOSE_SMB2;
684 cl.smb2.in.file.handle = fh;
685 status = smb2_close(tree1, &(cl.smb2));
687 if (dh.data[0] || dh.data[1]) {
688 ZERO_STRUCT(cl.smb2);
689 cl.smb2.level = RAW_CLOSE_SMB2;
690 cl.smb2.in.file.handle = dh;
691 status = smb2_close(tree1, &(cl.smb2));
694 smb2_deltree(tree1, BASEDIR);
695 return ret;
700 * testing of rename with no delete access on parent dir
701 * this is the negative case of the test above: parent dir is opened
702 * without share_delete, so rename must fail
705 static bool torture_smb2_rename_no_delete_access2(struct torture_context *torture,
706 struct smb2_tree *tree1)
708 bool ret = true;
709 NTSTATUS status;
710 union smb_open io;
711 union smb_close cl;
712 union smb_setfileinfo sinfo;
713 struct smb2_handle fh, dh;
715 ZERO_STRUCT(fh);
716 ZERO_STRUCT(dh);
718 smb2_deltree(tree1, BASEDIR);
719 smb2_util_rmdir(tree1, BASEDIR);
721 torture_comment(torture, "Creating base directory\n");
723 smb2_util_mkdir(tree1, BASEDIR);
725 torture_comment(torture, "Opening parent directory\n");
727 ZERO_STRUCT(io.smb2);
728 io.generic.level = RAW_OPEN_SMB2;
729 io.smb2.in.create_flags = 0;
730 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
731 SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
732 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
733 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
734 SEC_FILE_WRITE_DATA;
735 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
736 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
737 io.smb2.in.share_access = 0;
738 io.smb2.in.alloc_size = 0;
739 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
740 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
741 io.smb2.in.security_flags = 0;
742 io.smb2.in.fname = BASEDIR;
744 status = smb2_create(tree1, torture, &(io.smb2));
745 CHECK_STATUS(status, NT_STATUS_OK);
746 dh = io.smb2.out.file.handle;
749 torture_comment(torture, "Creating test file\n");
751 ZERO_STRUCT(io.smb2);
752 io.generic.level = RAW_OPEN_SMB2;
753 io.smb2.in.create_flags = 0;
754 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
755 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
756 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
757 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
758 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
759 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
760 io.smb2.in.share_access = 0;
761 io.smb2.in.alloc_size = 0;
762 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
763 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
764 io.smb2.in.security_flags = 0;
765 io.smb2.in.fname = BASEDIR "\\file.txt";
767 status = smb2_create(tree1, torture, &(io.smb2));
768 CHECK_STATUS(status, NT_STATUS_OK);
769 fh = io.smb2.out.file.handle;
771 torture_comment(torture, "Renaming test file\n");
773 ZERO_STRUCT(sinfo);
774 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
775 sinfo.rename_information.in.file.handle = fh;
776 sinfo.rename_information.in.overwrite = 0;
777 sinfo.rename_information.in.root_fid = 0;
778 sinfo.rename_information.in.new_name =
779 BASEDIR "\\newname.txt";
780 status = smb2_setinfo_file(tree1, &sinfo);
781 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
783 torture_comment(torture, "Closing test file\n");
785 ZERO_STRUCT(cl.smb2);
786 cl.smb2.level = RAW_CLOSE_SMB2;
787 cl.smb2.in.file.handle = fh;
788 status = smb2_close(tree1, &(cl.smb2));
789 CHECK_STATUS(status, NT_STATUS_OK);
791 ZERO_STRUCT(fh);
793 torture_comment(torture, "Closing directory\n");
795 ZERO_STRUCT(cl.smb2);
796 cl.smb2.level = RAW_CLOSE_SMB2;
797 cl.smb2.in.file.handle = dh;
798 status = smb2_close(tree1, &(cl.smb2));
799 CHECK_STATUS(status, NT_STATUS_OK);
801 ZERO_STRUCT(dh);
804 done:
806 torture_comment(torture, "Cleaning up\n");
808 if (fh.data[0] || fh.data[1]) {
809 ZERO_STRUCT(cl.smb2);
810 cl.smb2.level = RAW_CLOSE_SMB2;
811 cl.smb2.in.file.handle = fh;
812 status = smb2_close(tree1, &(cl.smb2));
814 if (dh.data[0] || dh.data[1]) {
815 ZERO_STRUCT(cl.smb2);
816 cl.smb2.level = RAW_CLOSE_SMB2;
817 cl.smb2.in.file.handle = dh;
818 status = smb2_close(tree1, &(cl.smb2));
821 smb2_deltree(tree1, BASEDIR);
822 return ret;
826 * this is a replay of how Word 2010 saves a file
827 * this should pass
830 static bool torture_smb2_rename_msword(struct torture_context *torture,
831 struct smb2_tree *tree1)
833 bool ret = true;
834 NTSTATUS status;
835 union smb_open io;
836 union smb_close cl;
837 union smb_setfileinfo sinfo;
838 union smb_fileinfo fi;
839 struct smb2_handle fh, dh;
841 ZERO_STRUCT(fh);
842 ZERO_STRUCT(dh);
844 smb2_deltree(tree1, BASEDIR);
845 smb2_util_rmdir(tree1, BASEDIR);
847 torture_comment(torture, "Creating base directory\n");
849 smb2_util_mkdir(tree1, BASEDIR);
851 torture_comment(torture, "Creating test file\n");
853 ZERO_STRUCT(io.smb2);
854 io.generic.level = RAW_OPEN_SMB2;
855 io.smb2.in.create_flags = 0;
856 io.smb2.in.desired_access = 0x0017019f;
857 io.smb2.in.create_options = 0x60;
858 io.smb2.in.file_attributes = 0;
859 io.smb2.in.share_access = 0;
860 io.smb2.in.alloc_size = 0;
861 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
862 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
863 io.smb2.in.security_flags = 0;
864 io.smb2.in.fname = BASEDIR "\\file.txt";
866 status = smb2_create(tree1, torture, &(io.smb2));
867 CHECK_STATUS(status, NT_STATUS_OK);
868 fh = io.smb2.out.file.handle;
870 torture_comment(torture, "Opening parent directory\n");
872 ZERO_STRUCT(io.smb2);
873 io.generic.level = RAW_OPEN_SMB2;
874 io.smb2.in.create_flags = 0;
875 io.smb2.in.desired_access = 0x00100080;
876 io.smb2.in.create_options = 0x00800021;
877 io.smb2.in.file_attributes = 0;
878 io.smb2.in.share_access = 0;
879 io.smb2.in.alloc_size = 0;
880 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
881 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
882 io.smb2.in.security_flags = 0;
883 io.smb2.in.fname = BASEDIR;
885 status = smb2_create(tree1, torture, &(io.smb2));
886 CHECK_STATUS(status, NT_STATUS_OK);
887 dh = io.smb2.out.file.handle;
889 torture_comment(torture, "Renaming test file\n");
891 ZERO_STRUCT(sinfo);
892 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
893 sinfo.rename_information.in.file.handle = fh;
894 sinfo.rename_information.in.overwrite = 0;
895 sinfo.rename_information.in.root_fid = 0;
896 sinfo.rename_information.in.new_name =
897 BASEDIR "\\newname.txt";
898 status = smb2_setinfo_file(tree1, &sinfo);
899 CHECK_STATUS(status, NT_STATUS_OK);
901 torture_comment(torture, "Checking for new filename\n");
903 ZERO_STRUCT(fi);
904 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
905 fi.generic.in.file.handle = fh;
906 status = smb2_getinfo_file(tree1, torture, &fi);
907 CHECK_STATUS(status, NT_STATUS_OK);
910 torture_comment(torture, "Closing test file\n");
912 ZERO_STRUCT(cl.smb2);
913 cl.smb2.level = RAW_CLOSE_SMB2;
914 cl.smb2.in.file.handle = fh;
915 status = smb2_close(tree1, &(cl.smb2));
916 CHECK_STATUS(status, NT_STATUS_OK);
918 ZERO_STRUCT(fh);
920 torture_comment(torture, "Closing directory\n");
922 ZERO_STRUCT(cl.smb2);
923 cl.smb2.level = RAW_CLOSE_SMB2;
924 cl.smb2.in.file.handle = dh;
925 status = smb2_close(tree1, &(cl.smb2));
926 CHECK_STATUS(status, NT_STATUS_OK);
928 ZERO_STRUCT(dh);
931 done:
933 torture_comment(torture, "Cleaning up\n");
935 if (fh.data[0] || fh.data[1]) {
936 ZERO_STRUCT(cl.smb2);
937 cl.smb2.level = RAW_CLOSE_SMB2;
938 cl.smb2.in.file.handle = fh;
939 status = smb2_close(tree1, &(cl.smb2));
941 if (dh.data[0] || dh.data[1]) {
942 ZERO_STRUCT(cl.smb2);
943 cl.smb2.level = RAW_CLOSE_SMB2;
944 cl.smb2.in.file.handle = dh;
945 status = smb2_close(tree1, &(cl.smb2));
948 smb2_deltree(tree1, BASEDIR);
949 return ret;
952 static bool torture_smb2_rename_dir_openfile(struct torture_context *torture,
953 struct smb2_tree *tree1)
955 bool ret = true;
956 NTSTATUS status;
957 union smb_open io;
958 union smb_close cl;
959 union smb_setfileinfo sinfo;
960 struct smb2_handle d1, h1;
962 ZERO_STRUCT(d1);
963 ZERO_STRUCT(h1);
965 smb2_deltree(tree1, BASEDIR);
966 smb2_util_rmdir(tree1, BASEDIR);
968 torture_comment(torture, "Creating base directory\n");
970 ZERO_STRUCT(io.smb2);
971 io.generic.level = RAW_OPEN_SMB2;
972 io.smb2.in.create_flags = 0;
973 io.smb2.in.desired_access = 0x0017019f;
974 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
975 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
976 io.smb2.in.share_access = 0;
977 io.smb2.in.alloc_size = 0;
978 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
979 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
980 io.smb2.in.security_flags = 0;
981 io.smb2.in.fname = BASEDIR;
983 status = smb2_create(tree1, torture, &(io.smb2));
984 CHECK_STATUS(status, NT_STATUS_OK);
985 d1 = io.smb2.out.file.handle;
987 torture_comment(torture, "Creating test file\n");
989 ZERO_STRUCT(io.smb2);
990 io.generic.level = RAW_OPEN_SMB2;
991 io.smb2.in.create_flags = 0;
992 io.smb2.in.desired_access = 0x0017019f;
993 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
994 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
995 io.smb2.in.share_access = 0;
996 io.smb2.in.alloc_size = 0;
997 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
998 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
999 io.smb2.in.security_flags = 0;
1000 io.smb2.in.fname = BASEDIR "\\file.txt";
1002 status = smb2_create(tree1, torture, &(io.smb2));
1003 CHECK_STATUS(status, NT_STATUS_OK);
1004 h1 = io.smb2.out.file.handle;
1006 torture_comment(torture, "Renaming directory\n");
1008 ZERO_STRUCT(sinfo);
1009 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1010 sinfo.rename_information.in.file.handle = d1;
1011 sinfo.rename_information.in.overwrite = 0;
1012 sinfo.rename_information.in.root_fid = 0;
1013 sinfo.rename_information.in.new_name =
1014 BASEDIR "-new";
1015 status = smb2_setinfo_file(tree1, &sinfo);
1016 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1018 torture_comment(torture, "Closing directory\n");
1020 ZERO_STRUCT(cl.smb2);
1021 cl.smb2.level = RAW_CLOSE_SMB2;
1022 cl.smb2.in.file.handle = d1;
1023 status = smb2_close(tree1, &(cl.smb2));
1024 CHECK_STATUS(status, NT_STATUS_OK);
1025 ZERO_STRUCT(d1);
1027 torture_comment(torture, "Closing test file\n");
1029 cl.smb2.in.file.handle = h1;
1030 status = smb2_close(tree1, &(cl.smb2));
1031 CHECK_STATUS(status, NT_STATUS_OK);
1032 ZERO_STRUCT(h1);
1034 done:
1036 torture_comment(torture, "Cleaning up\n");
1038 if (h1.data[0] || h1.data[1]) {
1039 ZERO_STRUCT(cl.smb2);
1040 cl.smb2.level = RAW_CLOSE_SMB2;
1041 cl.smb2.in.file.handle = h1;
1042 status = smb2_close(tree1, &(cl.smb2));
1044 smb2_deltree(tree1, BASEDIR);
1045 return ret;
1048 struct rename_one_dir_cycle_state {
1049 struct tevent_context *ev;
1050 struct smb2_tree *tree;
1051 struct smb2_handle file;
1052 const char *base_name;
1053 char *new_name;
1054 unsigned *rename_counter;
1056 unsigned current;
1057 unsigned max;
1058 union smb_setfileinfo sinfo;
1061 static void rename_one_dir_cycle_done(struct smb2_request *subreq);
1063 static struct tevent_req *rename_one_dir_cycle_send(TALLOC_CTX *mem_ctx,
1064 struct tevent_context *ev,
1065 struct smb2_tree *tree,
1066 struct smb2_handle file,
1067 unsigned max_renames,
1068 const char *base_name,
1069 unsigned *rename_counter)
1071 struct tevent_req *req;
1072 struct rename_one_dir_cycle_state *state;
1073 struct smb2_request *subreq;
1075 req = tevent_req_create(mem_ctx, &state,
1076 struct rename_one_dir_cycle_state);
1077 if (req == NULL) {
1078 return NULL;
1080 state->ev = ev;
1081 state->tree = tree;
1082 state->file = file;
1083 state->base_name = base_name;
1084 state->rename_counter = rename_counter;
1085 state->current = 0;
1086 state->max = max_renames;
1088 ZERO_STRUCT(state->sinfo);
1089 state->sinfo.rename_information.level =
1090 RAW_SFILEINFO_RENAME_INFORMATION;
1091 state->sinfo.rename_information.in.file.handle = state->file;
1092 state->sinfo.rename_information.in.overwrite = 0;
1093 state->sinfo.rename_information.in.root_fid = 0;
1095 state->new_name = talloc_asprintf(
1096 state, "%s-%u", state->base_name, state->current);
1097 if (tevent_req_nomem(state->new_name, req)) {
1098 return tevent_req_post(req, ev);
1100 state->sinfo.rename_information.in.new_name = state->new_name;
1102 subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1103 if (tevent_req_nomem(subreq, req)) {
1104 return tevent_req_post(req, ev);
1106 subreq->async.fn = rename_one_dir_cycle_done;
1107 subreq->async.private_data = req;
1108 return req;
1111 static void rename_one_dir_cycle_done(struct smb2_request *subreq)
1113 struct tevent_req *req = talloc_get_type_abort(
1114 subreq->async.private_data, struct tevent_req);
1115 struct rename_one_dir_cycle_state *state = tevent_req_data(
1116 req, struct rename_one_dir_cycle_state);
1117 NTSTATUS status;
1119 status = smb2_setinfo_recv(subreq);
1120 if (tevent_req_nterror(req, status)) {
1121 return;
1123 TALLOC_FREE(state->new_name);
1125 *state->rename_counter += 1;
1127 state->current += 1;
1128 if (state->current >= state->max) {
1129 tevent_req_done(req);
1130 return;
1133 ZERO_STRUCT(state->sinfo);
1134 state->sinfo.rename_information.level =
1135 RAW_SFILEINFO_RENAME_INFORMATION;
1136 state->sinfo.rename_information.in.file.handle = state->file;
1137 state->sinfo.rename_information.in.overwrite = 0;
1138 state->sinfo.rename_information.in.root_fid = 0;
1140 state->new_name = talloc_asprintf(
1141 state, "%s-%u", state->base_name, state->current);
1142 if (tevent_req_nomem(state->new_name, req)) {
1143 return;
1145 state->sinfo.rename_information.in.new_name = state->new_name;
1147 subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1148 if (tevent_req_nomem(subreq, req)) {
1149 return;
1151 subreq->async.fn = rename_one_dir_cycle_done;
1152 subreq->async.private_data = req;
1155 static NTSTATUS rename_one_dir_cycle_recv(struct tevent_req *req)
1157 return tevent_req_simple_recv_ntstatus(req);
1160 struct rename_dir_bench_state {
1161 struct tevent_context *ev;
1162 struct smb2_tree *tree;
1163 const char *base_name;
1164 unsigned max_renames;
1165 unsigned *rename_counter;
1167 struct smb2_create io;
1168 union smb_setfileinfo sinfo;
1169 struct smb2_close cl;
1171 struct smb2_handle file;
1174 static void rename_dir_bench_opened(struct smb2_request *subreq);
1175 static void rename_dir_bench_renamed(struct tevent_req *subreq);
1176 static void rename_dir_bench_set_doc(struct smb2_request *subreq);
1177 static void rename_dir_bench_closed(struct smb2_request *subreq);
1179 static struct tevent_req *rename_dir_bench_send(TALLOC_CTX *mem_ctx,
1180 struct tevent_context *ev,
1181 struct smb2_tree *tree,
1182 const char *base_name,
1183 unsigned max_renames,
1184 unsigned *rename_counter)
1186 struct tevent_req *req;
1187 struct rename_dir_bench_state *state;
1188 struct smb2_request *subreq;
1190 req = tevent_req_create(mem_ctx, &state,
1191 struct rename_dir_bench_state);
1192 if (req == NULL) {
1193 return NULL;
1195 state->ev = ev;
1196 state->tree = tree;
1197 state->base_name = base_name;
1198 state->max_renames = max_renames;
1199 state->rename_counter = rename_counter;
1201 ZERO_STRUCT(state->io);
1202 state->io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1203 state->io.in.share_access =
1204 NTCREATEX_SHARE_ACCESS_READ|
1205 NTCREATEX_SHARE_ACCESS_WRITE;
1206 state->io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1207 state->io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1208 state->io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1209 state->io.in.fname = state->base_name;
1211 subreq = smb2_create_send(state->tree, &state->io);
1212 if (tevent_req_nomem(subreq, req)) {
1213 return tevent_req_post(req, ev);
1215 subreq->async.fn = rename_dir_bench_opened;
1216 subreq->async.private_data = req;
1217 return req;
1220 static void rename_dir_bench_opened(struct smb2_request *subreq)
1222 struct tevent_req *req = talloc_get_type_abort(
1223 subreq->async.private_data, struct tevent_req);
1224 struct rename_dir_bench_state *state = tevent_req_data(
1225 req, struct rename_dir_bench_state);
1226 struct smb2_create *io;
1227 struct tevent_req *subreq2;
1228 NTSTATUS status;
1230 io = talloc(state, struct smb2_create);
1231 if (tevent_req_nomem(io, req)) {
1232 return;
1235 status = smb2_create_recv(subreq, io, io);
1236 if (tevent_req_nterror(req, status)) {
1237 return;
1239 state->file = io->out.file.handle;
1240 TALLOC_FREE(io);
1242 subreq2 = rename_one_dir_cycle_send(
1243 state, state->ev, state->tree, state->file,
1244 state->max_renames, state->base_name,
1245 state->rename_counter);
1246 if (tevent_req_nomem(subreq2, req)) {
1247 return;
1249 tevent_req_set_callback(subreq2, rename_dir_bench_renamed, req);
1252 static void rename_dir_bench_renamed(struct tevent_req *subreq)
1254 struct tevent_req *req = tevent_req_callback_data(
1255 subreq, struct tevent_req);
1256 struct rename_dir_bench_state *state = tevent_req_data(
1257 req, struct rename_dir_bench_state);
1258 struct smb2_request *subreq2;
1259 NTSTATUS status;
1261 status = rename_one_dir_cycle_recv(subreq);
1262 TALLOC_FREE(subreq);
1263 if (tevent_req_nterror(req, status)) {
1264 return;
1267 ZERO_STRUCT(state->sinfo);
1268 state->sinfo.disposition_info.level =
1269 RAW_SFILEINFO_DISPOSITION_INFORMATION;
1270 state->sinfo.disposition_info.in.file.handle = state->file;
1271 state->sinfo.disposition_info.in.delete_on_close = true;
1273 subreq2 = smb2_setinfo_file_send(state->tree, &state->sinfo);
1274 if (tevent_req_nomem(subreq2, req)) {
1275 return;
1277 subreq2->async.fn = rename_dir_bench_set_doc;
1278 subreq2->async.private_data = req;
1281 static void rename_dir_bench_set_doc(struct smb2_request *subreq)
1283 struct tevent_req *req = talloc_get_type_abort(
1284 subreq->async.private_data, struct tevent_req);
1285 struct rename_dir_bench_state *state = tevent_req_data(
1286 req, struct rename_dir_bench_state);
1287 NTSTATUS status;
1289 status = smb2_setinfo_recv(subreq);
1290 if (tevent_req_nterror(req, status)) {
1291 return;
1294 ZERO_STRUCT(state->cl);
1295 state->cl.in.file.handle = state->file;
1297 subreq = smb2_close_send(state->tree, &state->cl);
1298 if (tevent_req_nomem(subreq, req)) {
1299 return;
1301 subreq->async.fn = rename_dir_bench_closed;
1302 subreq->async.private_data = req;
1305 static void rename_dir_bench_closed(struct smb2_request *subreq)
1307 struct tevent_req *req = talloc_get_type_abort(
1308 subreq->async.private_data, struct tevent_req);
1309 struct smb2_close cl;
1310 NTSTATUS status;
1312 status = smb2_close_recv(subreq, &cl);
1313 if (tevent_req_nterror(req, status)) {
1314 return;
1316 tevent_req_done(req);
1319 static NTSTATUS rename_dir_bench_recv(struct tevent_req *req)
1321 return tevent_req_simple_recv_ntstatus(req);
1324 struct rename_dirs_bench_state {
1325 unsigned num_reqs;
1326 unsigned num_done;
1329 static void rename_dirs_bench_done(struct tevent_req *subreq);
1331 static struct tevent_req *rename_dirs_bench_send(TALLOC_CTX *mem_ctx,
1332 struct tevent_context *ev,
1333 struct smb2_tree *tree,
1334 const char *base_name,
1335 unsigned num_parallel,
1336 unsigned max_renames,
1337 unsigned *rename_counter)
1339 struct tevent_req *req;
1340 struct rename_dirs_bench_state *state;
1341 unsigned i;
1343 req = tevent_req_create(mem_ctx, &state,
1344 struct rename_dirs_bench_state);
1345 if (req == NULL) {
1346 return NULL;
1348 state->num_reqs = num_parallel;
1349 state->num_done = 0;
1351 for (i=0; i<num_parallel; i++) {
1352 struct tevent_req *subreq;
1353 char *sub_base;
1355 sub_base = talloc_asprintf(state, "%s-%u", base_name, i);
1356 if (tevent_req_nomem(sub_base, req)) {
1357 return tevent_req_post(req, ev);
1360 subreq = rename_dir_bench_send(state, ev, tree, sub_base,
1361 max_renames, rename_counter);
1362 if (tevent_req_nomem(subreq, req)) {
1363 return tevent_req_post(req, ev);
1365 tevent_req_set_callback(subreq, rename_dirs_bench_done, req);
1367 return req;
1370 static void rename_dirs_bench_done(struct tevent_req *subreq)
1372 struct tevent_req *req = tevent_req_callback_data(
1373 subreq, struct tevent_req);
1374 struct rename_dirs_bench_state *state = tevent_req_data(
1375 req, struct rename_dirs_bench_state);
1376 NTSTATUS status;
1378 status = rename_dir_bench_recv(subreq);
1379 TALLOC_FREE(subreq);
1380 if (tevent_req_nterror(req, status)) {
1381 return;
1384 state->num_done += 1;
1385 if (state->num_done >= state->num_reqs) {
1386 tevent_req_done(req);
1390 static NTSTATUS rename_dirs_bench_recv(struct tevent_req *req)
1392 return tevent_req_simple_recv_ntstatus(req);
1395 static bool torture_smb2_rename_dir_bench(struct torture_context *tctx,
1396 struct smb2_tree *tree)
1398 struct tevent_req *req;
1399 NTSTATUS status;
1400 unsigned counter = 0;
1401 bool ret;
1403 req = rename_dirs_bench_send(tctx, tctx->ev, tree, "dir", 3, 10,
1404 &counter);
1405 torture_assert(tctx, req != NULL, "rename_dirs_bench_send failed");
1407 ret = tevent_req_poll(req, tctx->ev);
1408 torture_assert(tctx, ret, "tevent_req_poll failed");
1410 status = rename_dirs_bench_recv(req);
1411 torture_comment(tctx, "rename_dirs_bench returned %s\n",
1412 nt_errstr(status));
1413 TALLOC_FREE(req);
1414 torture_assert_ntstatus_ok(tctx, status, "bench failed");
1415 return true;
1420 basic testing of SMB2 rename
1422 struct torture_suite *torture_smb2_rename_init(TALLOC_CTX *ctx)
1424 struct torture_suite *suite =
1425 torture_suite_create(ctx, "rename");
1427 torture_suite_add_1smb2_test(suite, "simple",
1428 torture_smb2_rename_simple);
1430 torture_suite_add_1smb2_test(suite, "simple_nodelete",
1431 torture_smb2_rename_simple2);
1433 torture_suite_add_1smb2_test(suite, "no_sharing",
1434 torture_smb2_rename_no_sharemode);
1436 torture_suite_add_1smb2_test(suite,
1437 "share_delete_and_delete_access",
1438 torture_smb2_rename_with_delete_access);
1440 torture_suite_add_1smb2_test(suite,
1441 "no_share_delete_but_delete_access",
1442 torture_smb2_rename_with_delete_access2);
1444 torture_suite_add_1smb2_test(suite,
1445 "share_delete_no_delete_access",
1446 torture_smb2_rename_no_delete_access);
1448 torture_suite_add_1smb2_test(suite,
1449 "no_share_delete_no_delete_access",
1450 torture_smb2_rename_no_delete_access2);
1452 torture_suite_add_1smb2_test(suite,
1453 "msword",
1454 torture_smb2_rename_msword);
1456 torture_suite_add_1smb2_test(
1457 suite, "rename_dir_openfile",
1458 torture_smb2_rename_dir_openfile);
1460 torture_suite_add_1smb2_test(suite,
1461 "rename_dir_bench",
1462 torture_smb2_rename_dir_bench);
1464 suite->description = talloc_strdup(suite, "smb2.rename tests");
1466 return suite;