doc: clarify "winbind max clients"
[Samba.git] / source4 / torture / smb2 / rename.c
blob07bdabd691d0e67c4da56b830f078d5e9f8dc661
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 "lib/tevent/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 smb2_deltree(tree1, BASEDIR);
61 smb2_util_rmdir(tree1, BASEDIR);
63 torture_comment(torture, "Creating base directory\n");
65 smb2_util_mkdir(tree1, BASEDIR);
68 torture_comment(torture, "Creating test file\n");
70 ZERO_STRUCT(io.smb2);
71 io.generic.level = RAW_OPEN_SMB2;
72 io.smb2.in.create_flags = 0;
73 io.smb2.in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE;
74 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
75 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
76 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
77 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
78 io.smb2.in.alloc_size = 0;
79 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
80 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
81 io.smb2.in.security_flags = 0;
82 io.smb2.in.fname = BASEDIR "\\file.txt";
84 status = smb2_create(tree1, torture, &(io.smb2));
85 CHECK_STATUS(status, NT_STATUS_OK);
86 h1 = io.smb2.out.file.handle;
88 torture_comment(torture, "Renaming test file\n");
90 ZERO_STRUCT(sinfo);
91 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
92 sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
93 sinfo.rename_information.in.overwrite = 0;
94 sinfo.rename_information.in.root_fid = 0;
95 sinfo.rename_information.in.new_name =
96 BASEDIR "\\newname.txt";
97 status = smb2_setinfo_file(tree1, &sinfo);
98 CHECK_STATUS(status, NT_STATUS_OK);
100 torture_comment(torture, "Checking for new filename\n");
102 ZERO_STRUCT(fi);
103 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
104 fi.generic.in.file.handle = h1;
105 status = smb2_getinfo_file(tree1, torture, &fi);
106 CHECK_STATUS(status, NT_STATUS_OK);
109 torture_comment(torture, "Closing test file\n");
111 ZERO_STRUCT(cl.smb2);
112 cl.smb2.level = RAW_CLOSE_SMB2;
113 cl.smb2.in.file.handle = h1;
114 status = smb2_close(tree1, &(cl.smb2));
115 CHECK_STATUS(status, NT_STATUS_OK);
117 ZERO_STRUCT(h1);
119 done:
121 torture_comment(torture, "Cleaning up\n");
123 if (h1.data) {
124 ZERO_STRUCT(cl.smb2);
125 cl.smb2.level = RAW_CLOSE_SMB2;
126 cl.smb2.in.file.handle = h1;
127 status = smb2_close(tree1, &(cl.smb2));
129 smb2_deltree(tree1, BASEDIR);
130 return ret;
134 * basic testing of rename, this time do not request DELETE access
135 * for the file, this should fail
138 static bool torture_smb2_rename_simple2(struct torture_context *torture,
139 struct smb2_tree *tree1)
141 bool ret = true;
142 NTSTATUS status;
143 union smb_open io;
144 union smb_close cl;
145 union smb_setfileinfo sinfo;
146 struct smb2_handle h1;
148 smb2_deltree(tree1, BASEDIR);
149 smb2_util_rmdir(tree1, BASEDIR);
151 torture_comment(torture, "Creating base directory\n");
153 smb2_util_mkdir(tree1, BASEDIR);
156 torture_comment(torture, "Creating test file\n");
158 ZERO_STRUCT(io.smb2);
159 io.generic.level = RAW_OPEN_SMB2;
160 io.smb2.in.create_flags = 0;
161 io.smb2.in.desired_access = SEC_FILE_ALL;
162 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
163 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
164 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
165 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
166 io.smb2.in.alloc_size = 0;
167 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
168 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
169 io.smb2.in.security_flags = 0;
170 io.smb2.in.fname = BASEDIR "\\file.txt";
172 status = smb2_create(tree1, torture, &(io.smb2));
173 CHECK_STATUS(status, NT_STATUS_OK);
174 h1 = io.smb2.out.file.handle;
176 torture_comment(torture, "Renaming test file\n");
178 ZERO_STRUCT(sinfo);
179 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
180 sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
181 sinfo.rename_information.in.overwrite = 0;
182 sinfo.rename_information.in.root_fid = 0;
183 sinfo.rename_information.in.new_name =
184 BASEDIR "\\newname.txt";
185 status = smb2_setinfo_file(tree1, &sinfo);
186 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
188 torture_comment(torture, "Closing test file\n");
190 ZERO_STRUCT(cl.smb2);
191 cl.smb2.level = RAW_CLOSE_SMB2;
192 cl.smb2.in.file.handle = h1;
193 status = smb2_close(tree1, &(cl.smb2));
194 CHECK_STATUS(status, NT_STATUS_OK);
196 ZERO_STRUCT(h1);
198 done:
200 torture_comment(torture, "Cleaning up\n");
202 if (h1.data) {
203 ZERO_STRUCT(cl.smb2);
204 cl.smb2.level = RAW_CLOSE_SMB2;
205 cl.smb2.in.file.handle = h1;
206 status = smb2_close(tree1, &(cl.smb2));
208 smb2_deltree(tree1, BASEDIR);
209 return ret;
214 * testing of rename with no sharing allowed on file
215 * this should work
218 static bool torture_smb2_rename_no_sharemode(struct torture_context *torture,
219 struct smb2_tree *tree1)
221 bool ret = true;
222 NTSTATUS status;
223 union smb_open io;
224 union smb_close cl;
225 union smb_setfileinfo sinfo;
226 union smb_fileinfo fi;
227 struct smb2_handle h1;
229 smb2_deltree(tree1, BASEDIR);
230 smb2_util_rmdir(tree1, BASEDIR);
232 torture_comment(torture, "Creating base directory\n");
234 smb2_util_mkdir(tree1, BASEDIR);
237 torture_comment(torture, "Creating test file\n");
239 ZERO_STRUCT(io.smb2);
240 io.generic.level = RAW_OPEN_SMB2;
241 io.smb2.in.create_flags = 0;
242 io.smb2.in.desired_access = 0x0017019f;
243 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
244 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
245 io.smb2.in.share_access = 0;
246 io.smb2.in.alloc_size = 0;
247 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
248 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
249 io.smb2.in.security_flags = 0;
250 io.smb2.in.fname = BASEDIR "\\file.txt";
252 status = smb2_create(tree1, torture, &(io.smb2));
253 CHECK_STATUS(status, NT_STATUS_OK);
254 h1 = io.smb2.out.file.handle;
256 torture_comment(torture, "Renaming test file\n");
258 ZERO_STRUCT(sinfo);
259 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
260 sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
261 sinfo.rename_information.in.overwrite = 0;
262 sinfo.rename_information.in.root_fid = 0;
263 sinfo.rename_information.in.new_name =
264 BASEDIR "\\newname.txt";
265 status = smb2_setinfo_file(tree1, &sinfo);
266 CHECK_STATUS(status, NT_STATUS_OK);
268 torture_comment(torture, "Checking for new filename\n");
270 ZERO_STRUCT(fi);
271 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
272 fi.generic.in.file.handle = h1;
273 status = smb2_getinfo_file(tree1, torture, &fi);
274 CHECK_STATUS(status, NT_STATUS_OK);
277 torture_comment(torture, "Closing test file\n");
279 ZERO_STRUCT(cl.smb2);
280 cl.smb2.level = RAW_CLOSE_SMB2;
281 cl.smb2.in.file.handle = h1;
282 status = smb2_close(tree1, &(cl.smb2));
283 CHECK_STATUS(status, NT_STATUS_OK);
285 ZERO_STRUCT(h1);
287 done:
289 torture_comment(torture, "Cleaning up\n");
291 if (h1.data) {
292 ZERO_STRUCT(cl.smb2);
293 cl.smb2.level = RAW_CLOSE_SMB2;
294 cl.smb2.in.file.handle = h1;
295 status = smb2_close(tree1, &(cl.smb2));
297 smb2_deltree(tree1, BASEDIR);
298 return ret;
302 * testing of rename when opening parent dir with delete access and delete
303 * sharing allowed
304 * should result in sharing violation
307 static bool torture_smb2_rename_with_delete_access(struct torture_context *torture,
308 struct smb2_tree *tree1)
310 bool ret = true;
311 NTSTATUS status;
312 union smb_open io;
313 union smb_close cl;
314 union smb_setfileinfo sinfo;
315 struct smb2_handle fh, dh;
317 smb2_deltree(tree1, BASEDIR);
318 smb2_util_rmdir(tree1, BASEDIR);
320 torture_comment(torture, "Creating base directory\n");
322 smb2_util_mkdir(tree1, BASEDIR);
324 torture_comment(torture, "Opening parent directory\n");
326 ZERO_STRUCT(io.smb2);
327 io.generic.level = RAW_OPEN_SMB2;
328 io.smb2.in.create_flags = 0;
329 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
330 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
331 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
332 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
333 SEC_FILE_WRITE_DATA;
334 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
335 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
336 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
337 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
338 io.smb2.in.alloc_size = 0;
339 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
340 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
341 io.smb2.in.security_flags = 0;
342 io.smb2.in.fname = BASEDIR;
344 status = smb2_create(tree1, torture, &(io.smb2));
345 CHECK_STATUS(status, NT_STATUS_OK);
346 dh = io.smb2.out.file.handle;
349 torture_comment(torture, "Creating test file\n");
351 ZERO_STRUCT(io.smb2);
352 io.generic.level = RAW_OPEN_SMB2;
353 io.smb2.in.create_flags = 0;
354 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
355 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
356 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
357 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
358 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
359 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
360 io.smb2.in.share_access = 0;
361 io.smb2.in.alloc_size = 0;
362 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
363 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
364 io.smb2.in.security_flags = 0;
365 io.smb2.in.fname = BASEDIR "\\file.txt";
367 status = smb2_create(tree1, torture, &(io.smb2));
368 CHECK_STATUS(status, NT_STATUS_OK);
369 fh = io.smb2.out.file.handle;
371 torture_comment(torture, "Renaming test file\n");
373 ZERO_STRUCT(sinfo);
374 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
375 sinfo.rename_information.in.file.handle = fh;
376 sinfo.rename_information.in.overwrite = 0;
377 sinfo.rename_information.in.root_fid = 0;
378 sinfo.rename_information.in.new_name =
379 BASEDIR "\\newname.txt";
380 status = smb2_setinfo_file(tree1, &sinfo);
381 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
383 torture_comment(torture, "Closing test file\n");
385 ZERO_STRUCT(cl.smb2);
386 cl.smb2.level = RAW_CLOSE_SMB2;
387 cl.smb2.in.file.handle = fh;
388 status = smb2_close(tree1, &(cl.smb2));
389 CHECK_STATUS(status, NT_STATUS_OK);
391 ZERO_STRUCT(fh);
393 torture_comment(torture, "Closing directory\n");
395 ZERO_STRUCT(cl.smb2);
396 cl.smb2.level = RAW_CLOSE_SMB2;
397 cl.smb2.in.file.handle = dh;
398 status = smb2_close(tree1, &(cl.smb2));
399 CHECK_STATUS(status, NT_STATUS_OK);
401 ZERO_STRUCT(dh);
404 done:
406 torture_comment(torture, "Cleaning up\n");
408 if (fh.data) {
409 ZERO_STRUCT(cl.smb2);
410 cl.smb2.level = RAW_CLOSE_SMB2;
411 cl.smb2.in.file.handle = fh;
412 status = smb2_close(tree1, &(cl.smb2));
414 if (dh.data) {
415 ZERO_STRUCT(cl.smb2);
416 cl.smb2.level = RAW_CLOSE_SMB2;
417 cl.smb2.in.file.handle = dh;
418 status = smb2_close(tree1, &(cl.smb2));
421 smb2_deltree(tree1, BASEDIR);
422 return ret;
427 * testing of rename with delete access on parent dir
428 * this is a variation of the test above: parent dir is opened
429 * without share_delete, so rename must fail
432 static bool torture_smb2_rename_with_delete_access2(struct torture_context *torture,
433 struct smb2_tree *tree1)
435 bool ret = true;
436 NTSTATUS status;
437 union smb_open io;
438 union smb_close cl;
439 union smb_setfileinfo sinfo;
440 struct smb2_handle fh, dh;
442 smb2_deltree(tree1, BASEDIR);
443 smb2_util_rmdir(tree1, BASEDIR);
445 torture_comment(torture, "Creating base directory\n");
447 smb2_util_mkdir(tree1, BASEDIR);
449 torture_comment(torture, "Opening parent directory\n");
451 ZERO_STRUCT(io.smb2);
452 io.generic.level = RAW_OPEN_SMB2;
453 io.smb2.in.create_flags = 0;
454 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
455 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
456 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
457 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
458 SEC_FILE_WRITE_DATA;
459 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
460 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
461 io.smb2.in.share_access = 0;
462 io.smb2.in.alloc_size = 0;
463 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
464 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
465 io.smb2.in.security_flags = 0;
466 io.smb2.in.fname = BASEDIR;
468 status = smb2_create(tree1, torture, &(io.smb2));
469 CHECK_STATUS(status, NT_STATUS_OK);
470 dh = io.smb2.out.file.handle;
473 torture_comment(torture, "Creating test file\n");
475 ZERO_STRUCT(io.smb2);
476 io.generic.level = RAW_OPEN_SMB2;
477 io.smb2.in.create_flags = 0;
478 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
479 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
480 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
481 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
482 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
483 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
484 io.smb2.in.share_access = 0;
485 io.smb2.in.alloc_size = 0;
486 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
487 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
488 io.smb2.in.security_flags = 0;
489 io.smb2.in.fname = BASEDIR "\\file.txt";
491 status = smb2_create(tree1, torture, &(io.smb2));
492 CHECK_STATUS(status, NT_STATUS_OK);
493 fh = io.smb2.out.file.handle;
495 torture_comment(torture, "Renaming test file\n");
497 ZERO_STRUCT(sinfo);
498 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
499 sinfo.rename_information.in.file.handle = fh;
500 sinfo.rename_information.in.overwrite = 0;
501 sinfo.rename_information.in.root_fid = 0;
502 sinfo.rename_information.in.new_name =
503 BASEDIR "\\newname.txt";
504 status = smb2_setinfo_file(tree1, &sinfo);
505 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
507 torture_comment(torture, "Closing test file\n");
509 ZERO_STRUCT(cl.smb2);
510 cl.smb2.level = RAW_CLOSE_SMB2;
511 cl.smb2.in.file.handle = fh;
512 status = smb2_close(tree1, &(cl.smb2));
513 CHECK_STATUS(status, NT_STATUS_OK);
515 ZERO_STRUCT(fh);
517 torture_comment(torture, "Closing directory\n");
519 ZERO_STRUCT(cl.smb2);
520 cl.smb2.level = RAW_CLOSE_SMB2;
521 cl.smb2.in.file.handle = dh;
522 status = smb2_close(tree1, &(cl.smb2));
523 CHECK_STATUS(status, NT_STATUS_OK);
525 ZERO_STRUCT(dh);
528 done:
530 torture_comment(torture, "Cleaning up\n");
532 if (fh.data) {
533 ZERO_STRUCT(cl.smb2);
534 cl.smb2.level = RAW_CLOSE_SMB2;
535 cl.smb2.in.file.handle = fh;
536 status = smb2_close(tree1, &(cl.smb2));
538 if (dh.data) {
539 ZERO_STRUCT(cl.smb2);
540 cl.smb2.level = RAW_CLOSE_SMB2;
541 cl.smb2.in.file.handle = dh;
542 status = smb2_close(tree1, &(cl.smb2));
545 smb2_deltree(tree1, BASEDIR);
546 return ret;
550 * testing of rename when opening parent dir with no delete access and delete
551 * sharing allowed
552 * this should pass
555 static bool torture_smb2_rename_no_delete_access(struct torture_context *torture,
556 struct smb2_tree *tree1)
558 bool ret = true;
559 NTSTATUS status;
560 union smb_open io;
561 union smb_close cl;
562 union smb_setfileinfo sinfo;
563 union smb_fileinfo fi;
564 struct smb2_handle fh, dh;
566 smb2_deltree(tree1, BASEDIR);
567 smb2_util_rmdir(tree1, BASEDIR);
569 torture_comment(torture, "Creating base directory\n");
571 smb2_util_mkdir(tree1, BASEDIR);
573 torture_comment(torture, "Opening parent directory\n");
575 ZERO_STRUCT(io.smb2);
576 io.generic.level = RAW_OPEN_SMB2;
577 io.smb2.in.create_flags = 0;
578 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
579 SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
580 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
581 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
582 SEC_FILE_WRITE_DATA;
583 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
584 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
585 io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
586 NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
587 io.smb2.in.alloc_size = 0;
588 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
589 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
590 io.smb2.in.security_flags = 0;
591 io.smb2.in.fname = BASEDIR;
593 status = smb2_create(tree1, torture, &(io.smb2));
594 CHECK_STATUS(status, NT_STATUS_OK);
595 dh = io.smb2.out.file.handle;
598 torture_comment(torture, "Creating test file\n");
600 ZERO_STRUCT(io.smb2);
601 io.generic.level = RAW_OPEN_SMB2;
602 io.smb2.in.create_flags = 0;
603 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
604 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
605 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
606 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
607 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
608 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
609 io.smb2.in.share_access = 0;
610 io.smb2.in.alloc_size = 0;
611 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
612 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
613 io.smb2.in.security_flags = 0;
614 io.smb2.in.fname = BASEDIR "\\file.txt";
616 status = smb2_create(tree1, torture, &(io.smb2));
617 CHECK_STATUS(status, NT_STATUS_OK);
618 fh = io.smb2.out.file.handle;
620 torture_comment(torture, "Renaming test file\n");
622 ZERO_STRUCT(sinfo);
623 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
624 sinfo.rename_information.in.file.handle = fh;
625 sinfo.rename_information.in.overwrite = 0;
626 sinfo.rename_information.in.root_fid = 0;
627 sinfo.rename_information.in.new_name =
628 BASEDIR "\\newname.txt";
629 status = smb2_setinfo_file(tree1, &sinfo);
630 CHECK_STATUS(status, NT_STATUS_OK);
632 torture_comment(torture, "Checking for new filename\n");
634 ZERO_STRUCT(fi);
635 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
636 fi.generic.in.file.handle = fh;
637 status = smb2_getinfo_file(tree1, torture, &fi);
638 CHECK_STATUS(status, NT_STATUS_OK);
641 torture_comment(torture, "Closing test file\n");
643 ZERO_STRUCT(cl.smb2);
644 cl.smb2.level = RAW_CLOSE_SMB2;
645 cl.smb2.in.file.handle = fh;
646 status = smb2_close(tree1, &(cl.smb2));
647 CHECK_STATUS(status, NT_STATUS_OK);
649 ZERO_STRUCT(fh);
651 torture_comment(torture, "Closing directory\n");
653 ZERO_STRUCT(cl.smb2);
654 cl.smb2.level = RAW_CLOSE_SMB2;
655 cl.smb2.in.file.handle = dh;
656 status = smb2_close(tree1, &(cl.smb2));
657 CHECK_STATUS(status, NT_STATUS_OK);
659 ZERO_STRUCT(dh);
662 done:
664 torture_comment(torture, "Cleaning up\n");
666 if (fh.data) {
667 ZERO_STRUCT(cl.smb2);
668 cl.smb2.level = RAW_CLOSE_SMB2;
669 cl.smb2.in.file.handle = fh;
670 status = smb2_close(tree1, &(cl.smb2));
672 if (dh.data) {
673 ZERO_STRUCT(cl.smb2);
674 cl.smb2.level = RAW_CLOSE_SMB2;
675 cl.smb2.in.file.handle = dh;
676 status = smb2_close(tree1, &(cl.smb2));
679 smb2_deltree(tree1, BASEDIR);
680 return ret;
685 * testing of rename with no delete access on parent dir
686 * this is the negative case of the test above: parent dir is opened
687 * without share_delete, so rename must fail
690 static bool torture_smb2_rename_no_delete_access2(struct torture_context *torture,
691 struct smb2_tree *tree1)
693 bool ret = true;
694 NTSTATUS status;
695 union smb_open io;
696 union smb_close cl;
697 union smb_setfileinfo sinfo;
698 struct smb2_handle fh, dh;
700 smb2_deltree(tree1, BASEDIR);
701 smb2_util_rmdir(tree1, BASEDIR);
703 torture_comment(torture, "Creating base directory\n");
705 smb2_util_mkdir(tree1, BASEDIR);
707 torture_comment(torture, "Opening parent directory\n");
709 ZERO_STRUCT(io.smb2);
710 io.generic.level = RAW_OPEN_SMB2;
711 io.smb2.in.create_flags = 0;
712 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
713 SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
714 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
715 SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
716 SEC_FILE_WRITE_DATA;
717 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
718 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
719 io.smb2.in.share_access = 0;
720 io.smb2.in.alloc_size = 0;
721 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
722 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
723 io.smb2.in.security_flags = 0;
724 io.smb2.in.fname = BASEDIR;
726 status = smb2_create(tree1, torture, &(io.smb2));
727 CHECK_STATUS(status, NT_STATUS_OK);
728 dh = io.smb2.out.file.handle;
731 torture_comment(torture, "Creating test file\n");
733 ZERO_STRUCT(io.smb2);
734 io.generic.level = RAW_OPEN_SMB2;
735 io.smb2.in.create_flags = 0;
736 io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
737 SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
738 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
739 SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
740 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
741 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
742 io.smb2.in.share_access = 0;
743 io.smb2.in.alloc_size = 0;
744 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
745 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
746 io.smb2.in.security_flags = 0;
747 io.smb2.in.fname = BASEDIR "\\file.txt";
749 status = smb2_create(tree1, torture, &(io.smb2));
750 CHECK_STATUS(status, NT_STATUS_OK);
751 fh = io.smb2.out.file.handle;
753 torture_comment(torture, "Renaming test file\n");
755 ZERO_STRUCT(sinfo);
756 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
757 sinfo.rename_information.in.file.handle = fh;
758 sinfo.rename_information.in.overwrite = 0;
759 sinfo.rename_information.in.root_fid = 0;
760 sinfo.rename_information.in.new_name =
761 BASEDIR "\\newname.txt";
762 status = smb2_setinfo_file(tree1, &sinfo);
763 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
765 torture_comment(torture, "Closing test file\n");
767 ZERO_STRUCT(cl.smb2);
768 cl.smb2.level = RAW_CLOSE_SMB2;
769 cl.smb2.in.file.handle = fh;
770 status = smb2_close(tree1, &(cl.smb2));
771 CHECK_STATUS(status, NT_STATUS_OK);
773 ZERO_STRUCT(fh);
775 torture_comment(torture, "Closing directory\n");
777 ZERO_STRUCT(cl.smb2);
778 cl.smb2.level = RAW_CLOSE_SMB2;
779 cl.smb2.in.file.handle = dh;
780 status = smb2_close(tree1, &(cl.smb2));
781 CHECK_STATUS(status, NT_STATUS_OK);
783 ZERO_STRUCT(dh);
786 done:
788 torture_comment(torture, "Cleaning up\n");
790 if (fh.data) {
791 ZERO_STRUCT(cl.smb2);
792 cl.smb2.level = RAW_CLOSE_SMB2;
793 cl.smb2.in.file.handle = fh;
794 status = smb2_close(tree1, &(cl.smb2));
796 if (dh.data) {
797 ZERO_STRUCT(cl.smb2);
798 cl.smb2.level = RAW_CLOSE_SMB2;
799 cl.smb2.in.file.handle = dh;
800 status = smb2_close(tree1, &(cl.smb2));
803 smb2_deltree(tree1, BASEDIR);
804 return ret;
808 * this is a replay of how Word 2010 saves a file
809 * this should pass
812 static bool torture_smb2_rename_msword(struct torture_context *torture,
813 struct smb2_tree *tree1)
815 bool ret = true;
816 NTSTATUS status;
817 union smb_open io;
818 union smb_close cl;
819 union smb_setfileinfo sinfo;
820 union smb_fileinfo fi;
821 struct smb2_handle fh, dh;
823 smb2_deltree(tree1, BASEDIR);
824 smb2_util_rmdir(tree1, BASEDIR);
826 torture_comment(torture, "Creating base directory\n");
828 smb2_util_mkdir(tree1, BASEDIR);
830 torture_comment(torture, "Creating test file\n");
832 ZERO_STRUCT(io.smb2);
833 io.generic.level = RAW_OPEN_SMB2;
834 io.smb2.in.create_flags = 0;
835 io.smb2.in.desired_access = 0x0017019f;
836 io.smb2.in.create_options = 0x60;
837 io.smb2.in.file_attributes = 0;
838 io.smb2.in.share_access = 0;
839 io.smb2.in.alloc_size = 0;
840 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
841 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
842 io.smb2.in.security_flags = 0;
843 io.smb2.in.fname = BASEDIR "\\file.txt";
845 status = smb2_create(tree1, torture, &(io.smb2));
846 CHECK_STATUS(status, NT_STATUS_OK);
847 fh = io.smb2.out.file.handle;
849 torture_comment(torture, "Opening parent directory\n");
851 ZERO_STRUCT(io.smb2);
852 io.generic.level = RAW_OPEN_SMB2;
853 io.smb2.in.create_flags = 0;
854 io.smb2.in.desired_access = 0x00100080;
855 io.smb2.in.create_options = 0x00800021;
856 io.smb2.in.file_attributes = 0;
857 io.smb2.in.share_access = 0;
858 io.smb2.in.alloc_size = 0;
859 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
860 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
861 io.smb2.in.security_flags = 0;
862 io.smb2.in.fname = BASEDIR;
864 status = smb2_create(tree1, torture, &(io.smb2));
865 CHECK_STATUS(status, NT_STATUS_OK);
866 dh = io.smb2.out.file.handle;
868 torture_comment(torture, "Renaming test file\n");
870 ZERO_STRUCT(sinfo);
871 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
872 sinfo.rename_information.in.file.handle = fh;
873 sinfo.rename_information.in.overwrite = 0;
874 sinfo.rename_information.in.root_fid = 0;
875 sinfo.rename_information.in.new_name =
876 BASEDIR "\\newname.txt";
877 status = smb2_setinfo_file(tree1, &sinfo);
878 CHECK_STATUS(status, NT_STATUS_OK);
880 torture_comment(torture, "Checking for new filename\n");
882 ZERO_STRUCT(fi);
883 fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
884 fi.generic.in.file.handle = fh;
885 status = smb2_getinfo_file(tree1, torture, &fi);
886 CHECK_STATUS(status, NT_STATUS_OK);
889 torture_comment(torture, "Closing test file\n");
891 ZERO_STRUCT(cl.smb2);
892 cl.smb2.level = RAW_CLOSE_SMB2;
893 cl.smb2.in.file.handle = fh;
894 status = smb2_close(tree1, &(cl.smb2));
895 CHECK_STATUS(status, NT_STATUS_OK);
897 ZERO_STRUCT(fh);
899 torture_comment(torture, "Closing directory\n");
901 ZERO_STRUCT(cl.smb2);
902 cl.smb2.level = RAW_CLOSE_SMB2;
903 cl.smb2.in.file.handle = dh;
904 status = smb2_close(tree1, &(cl.smb2));
905 CHECK_STATUS(status, NT_STATUS_OK);
907 ZERO_STRUCT(dh);
910 done:
912 torture_comment(torture, "Cleaning up\n");
914 if (fh.data) {
915 ZERO_STRUCT(cl.smb2);
916 cl.smb2.level = RAW_CLOSE_SMB2;
917 cl.smb2.in.file.handle = fh;
918 status = smb2_close(tree1, &(cl.smb2));
920 if (dh.data) {
921 ZERO_STRUCT(cl.smb2);
922 cl.smb2.level = RAW_CLOSE_SMB2;
923 cl.smb2.in.file.handle = dh;
924 status = smb2_close(tree1, &(cl.smb2));
927 smb2_deltree(tree1, BASEDIR);
928 return ret;
931 static bool torture_smb2_rename_dir_openfile(struct torture_context *torture,
932 struct smb2_tree *tree1)
934 bool ret = true;
935 NTSTATUS status;
936 union smb_open io;
937 union smb_close cl;
938 union smb_setfileinfo sinfo;
939 struct smb2_handle d1, h1;
941 smb2_deltree(tree1, BASEDIR);
942 smb2_util_rmdir(tree1, BASEDIR);
944 torture_comment(torture, "Creating base directory\n");
946 ZERO_STRUCT(io.smb2);
947 io.generic.level = RAW_OPEN_SMB2;
948 io.smb2.in.create_flags = 0;
949 io.smb2.in.desired_access = 0x0017019f;
950 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
951 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
952 io.smb2.in.share_access = 0;
953 io.smb2.in.alloc_size = 0;
954 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
955 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
956 io.smb2.in.security_flags = 0;
957 io.smb2.in.fname = BASEDIR;
959 status = smb2_create(tree1, torture, &(io.smb2));
960 CHECK_STATUS(status, NT_STATUS_OK);
961 d1 = io.smb2.out.file.handle;
963 torture_comment(torture, "Creating test file\n");
965 ZERO_STRUCT(io.smb2);
966 io.generic.level = RAW_OPEN_SMB2;
967 io.smb2.in.create_flags = 0;
968 io.smb2.in.desired_access = 0x0017019f;
969 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
970 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
971 io.smb2.in.share_access = 0;
972 io.smb2.in.alloc_size = 0;
973 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
974 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
975 io.smb2.in.security_flags = 0;
976 io.smb2.in.fname = BASEDIR "\\file.txt";
978 status = smb2_create(tree1, torture, &(io.smb2));
979 CHECK_STATUS(status, NT_STATUS_OK);
980 h1 = io.smb2.out.file.handle;
982 torture_comment(torture, "Renaming directory\n");
984 ZERO_STRUCT(sinfo);
985 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
986 sinfo.rename_information.in.file.handle = d1;
987 sinfo.rename_information.in.overwrite = 0;
988 sinfo.rename_information.in.root_fid = 0;
989 sinfo.rename_information.in.new_name =
990 BASEDIR "-new";
991 status = smb2_setinfo_file(tree1, &sinfo);
992 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
994 torture_comment(torture, "Closing directory\n");
996 ZERO_STRUCT(cl.smb2);
997 cl.smb2.level = RAW_CLOSE_SMB2;
998 cl.smb2.in.file.handle = d1;
999 status = smb2_close(tree1, &(cl.smb2));
1000 CHECK_STATUS(status, NT_STATUS_OK);
1001 ZERO_STRUCT(d1);
1003 torture_comment(torture, "Closing test file\n");
1005 cl.smb2.in.file.handle = h1;
1006 status = smb2_close(tree1, &(cl.smb2));
1007 CHECK_STATUS(status, NT_STATUS_OK);
1008 ZERO_STRUCT(h1);
1010 done:
1012 torture_comment(torture, "Cleaning up\n");
1014 if (h1.data) {
1015 ZERO_STRUCT(cl.smb2);
1016 cl.smb2.level = RAW_CLOSE_SMB2;
1017 cl.smb2.in.file.handle = h1;
1018 status = smb2_close(tree1, &(cl.smb2));
1020 smb2_deltree(tree1, BASEDIR);
1021 return ret;
1024 struct rename_one_dir_cycle_state {
1025 struct tevent_context *ev;
1026 struct smb2_tree *tree;
1027 struct smb2_handle file;
1028 const char *base_name;
1029 char *new_name;
1030 unsigned *rename_counter;
1032 unsigned current;
1033 unsigned max;
1034 union smb_setfileinfo sinfo;
1037 static void rename_one_dir_cycle_done(struct smb2_request *subreq);
1039 static struct tevent_req *rename_one_dir_cycle_send(TALLOC_CTX *mem_ctx,
1040 struct tevent_context *ev,
1041 struct smb2_tree *tree,
1042 struct smb2_handle file,
1043 unsigned max_renames,
1044 const char *base_name,
1045 unsigned *rename_counter)
1047 struct tevent_req *req;
1048 struct rename_one_dir_cycle_state *state;
1049 struct smb2_request *subreq;
1051 req = tevent_req_create(mem_ctx, &state,
1052 struct rename_one_dir_cycle_state);
1053 if (req == NULL) {
1054 return NULL;
1056 state->ev = ev;
1057 state->tree = tree;
1058 state->file = file;
1059 state->base_name = base_name;
1060 state->rename_counter = rename_counter;
1061 state->current = 0;
1062 state->max = max_renames;
1064 ZERO_STRUCT(state->sinfo);
1065 state->sinfo.rename_information.level =
1066 RAW_SFILEINFO_RENAME_INFORMATION;
1067 state->sinfo.rename_information.in.file.handle = state->file;
1068 state->sinfo.rename_information.in.overwrite = 0;
1069 state->sinfo.rename_information.in.root_fid = 0;
1071 state->new_name = talloc_asprintf(
1072 state, "%s-%u", state->base_name, state->current);
1073 if (tevent_req_nomem(state->new_name, req)) {
1074 return tevent_req_post(req, ev);
1076 state->sinfo.rename_information.in.new_name = state->new_name;
1078 subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1079 if (tevent_req_nomem(subreq, req)) {
1080 return tevent_req_post(req, ev);
1082 subreq->async.fn = rename_one_dir_cycle_done;
1083 subreq->async.private_data = req;
1084 return req;
1087 static void rename_one_dir_cycle_done(struct smb2_request *subreq)
1089 struct tevent_req *req = talloc_get_type_abort(
1090 subreq->async.private_data, struct tevent_req);
1091 struct rename_one_dir_cycle_state *state = tevent_req_data(
1092 req, struct rename_one_dir_cycle_state);
1093 NTSTATUS status;
1095 status = smb2_setinfo_recv(subreq);
1096 if (tevent_req_nterror(req, status)) {
1097 return;
1099 TALLOC_FREE(state->new_name);
1101 *state->rename_counter += 1;
1103 state->current += 1;
1104 if (state->current >= state->max) {
1105 tevent_req_done(req);
1106 return;
1109 ZERO_STRUCT(state->sinfo);
1110 state->sinfo.rename_information.level =
1111 RAW_SFILEINFO_RENAME_INFORMATION;
1112 state->sinfo.rename_information.in.file.handle = state->file;
1113 state->sinfo.rename_information.in.overwrite = 0;
1114 state->sinfo.rename_information.in.root_fid = 0;
1116 state->new_name = talloc_asprintf(
1117 state, "%s-%u", state->base_name, state->current);
1118 if (tevent_req_nomem(state->new_name, req)) {
1119 return;
1121 state->sinfo.rename_information.in.new_name = state->new_name;
1123 subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1124 if (tevent_req_nomem(subreq, req)) {
1125 return;
1127 subreq->async.fn = rename_one_dir_cycle_done;
1128 subreq->async.private_data = req;
1131 static NTSTATUS rename_one_dir_cycle_recv(struct tevent_req *req)
1133 return tevent_req_simple_recv_ntstatus(req);
1136 struct rename_dir_bench_state {
1137 struct tevent_context *ev;
1138 struct smb2_tree *tree;
1139 const char *base_name;
1140 unsigned max_renames;
1141 unsigned *rename_counter;
1143 struct smb2_create io;
1144 union smb_setfileinfo sinfo;
1145 struct smb2_close cl;
1147 struct smb2_handle file;
1150 static void rename_dir_bench_opened(struct smb2_request *subreq);
1151 static void rename_dir_bench_renamed(struct tevent_req *subreq);
1152 static void rename_dir_bench_set_doc(struct smb2_request *subreq);
1153 static void rename_dir_bench_closed(struct smb2_request *subreq);
1155 static struct tevent_req *rename_dir_bench_send(TALLOC_CTX *mem_ctx,
1156 struct tevent_context *ev,
1157 struct smb2_tree *tree,
1158 const char *base_name,
1159 unsigned max_renames,
1160 unsigned *rename_counter)
1162 struct tevent_req *req;
1163 struct rename_dir_bench_state *state;
1164 struct smb2_request *subreq;
1166 req = tevent_req_create(mem_ctx, &state,
1167 struct rename_dir_bench_state);
1168 if (req == NULL) {
1169 return NULL;
1171 state->ev = ev;
1172 state->tree = tree;
1173 state->base_name = base_name;
1174 state->max_renames = max_renames;
1175 state->rename_counter = rename_counter;
1177 ZERO_STRUCT(state->io);
1178 state->io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1179 state->io.in.share_access =
1180 NTCREATEX_SHARE_ACCESS_READ|
1181 NTCREATEX_SHARE_ACCESS_WRITE;
1182 state->io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1183 state->io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1184 state->io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1185 state->io.in.fname = state->base_name;
1187 subreq = smb2_create_send(state->tree, &state->io);
1188 if (tevent_req_nomem(subreq, req)) {
1189 return tevent_req_post(req, ev);
1191 subreq->async.fn = rename_dir_bench_opened;
1192 subreq->async.private_data = req;
1193 return req;
1196 static void rename_dir_bench_opened(struct smb2_request *subreq)
1198 struct tevent_req *req = talloc_get_type_abort(
1199 subreq->async.private_data, struct tevent_req);
1200 struct rename_dir_bench_state *state = tevent_req_data(
1201 req, struct rename_dir_bench_state);
1202 struct smb2_create *io;
1203 struct tevent_req *subreq2;
1204 NTSTATUS status;
1206 io = talloc(state, struct smb2_create);
1207 if (tevent_req_nomem(io, req)) {
1208 return;
1211 status = smb2_create_recv(subreq, io, io);
1212 if (tevent_req_nterror(req, status)) {
1213 return;
1215 state->file = io->out.file.handle;
1216 TALLOC_FREE(io);
1218 subreq2 = rename_one_dir_cycle_send(
1219 state, state->ev, state->tree, state->file,
1220 state->max_renames, state->base_name,
1221 state->rename_counter);
1222 if (tevent_req_nomem(subreq2, req)) {
1223 return;
1225 tevent_req_set_callback(subreq2, rename_dir_bench_renamed, req);
1228 static void rename_dir_bench_renamed(struct tevent_req *subreq)
1230 struct tevent_req *req = tevent_req_callback_data(
1231 subreq, struct tevent_req);
1232 struct rename_dir_bench_state *state = tevent_req_data(
1233 req, struct rename_dir_bench_state);
1234 struct smb2_request *subreq2;
1235 NTSTATUS status;
1237 status = rename_one_dir_cycle_recv(subreq);
1238 TALLOC_FREE(subreq);
1239 if (tevent_req_nterror(req, status)) {
1240 return;
1243 ZERO_STRUCT(state->sinfo);
1244 state->sinfo.disposition_info.level =
1245 RAW_SFILEINFO_DISPOSITION_INFORMATION;
1246 state->sinfo.disposition_info.in.file.handle = state->file;
1247 state->sinfo.disposition_info.in.delete_on_close = true;
1249 subreq2 = smb2_setinfo_file_send(state->tree, &state->sinfo);
1250 if (tevent_req_nomem(subreq2, req)) {
1251 return;
1253 subreq2->async.fn = rename_dir_bench_set_doc;
1254 subreq2->async.private_data = req;
1257 static void rename_dir_bench_set_doc(struct smb2_request *subreq)
1259 struct tevent_req *req = talloc_get_type_abort(
1260 subreq->async.private_data, struct tevent_req);
1261 struct rename_dir_bench_state *state = tevent_req_data(
1262 req, struct rename_dir_bench_state);
1263 NTSTATUS status;
1265 status = smb2_setinfo_recv(subreq);
1266 if (tevent_req_nterror(req, status)) {
1267 return;
1270 ZERO_STRUCT(state->cl);
1271 state->cl.in.file.handle = state->file;
1273 subreq = smb2_close_send(state->tree, &state->cl);
1274 if (tevent_req_nomem(subreq, req)) {
1275 return;
1277 subreq->async.fn = rename_dir_bench_closed;
1278 subreq->async.private_data = req;
1281 static void rename_dir_bench_closed(struct smb2_request *subreq)
1283 struct tevent_req *req = talloc_get_type_abort(
1284 subreq->async.private_data, struct tevent_req);
1285 struct smb2_close cl;
1286 NTSTATUS status;
1288 status = smb2_close_recv(subreq, &cl);
1289 if (tevent_req_nterror(req, status)) {
1290 return;
1292 tevent_req_done(req);
1295 static NTSTATUS rename_dir_bench_recv(struct tevent_req *req)
1297 return tevent_req_simple_recv_ntstatus(req);
1300 struct rename_dirs_bench_state {
1301 unsigned num_reqs;
1302 unsigned num_done;
1305 static void rename_dirs_bench_done(struct tevent_req *subreq);
1307 static struct tevent_req *rename_dirs_bench_send(TALLOC_CTX *mem_ctx,
1308 struct tevent_context *ev,
1309 struct smb2_tree *tree,
1310 const char *base_name,
1311 unsigned num_parallel,
1312 unsigned max_renames,
1313 unsigned *rename_counter)
1315 struct tevent_req *req;
1316 struct rename_dirs_bench_state *state;
1317 unsigned i;
1319 req = tevent_req_create(mem_ctx, &state,
1320 struct rename_dirs_bench_state);
1321 if (req == NULL) {
1322 return NULL;
1324 state->num_reqs = num_parallel;
1325 state->num_done = 0;
1327 for (i=0; i<num_parallel; i++) {
1328 struct tevent_req *subreq;
1329 char *sub_base;
1331 sub_base = talloc_asprintf(state, "%s-%u", base_name, i);
1332 if (tevent_req_nomem(sub_base, req)) {
1333 return tevent_req_post(req, ev);
1336 subreq = rename_dir_bench_send(state, ev, tree, sub_base,
1337 max_renames, rename_counter);
1338 if (tevent_req_nomem(subreq, req)) {
1339 return tevent_req_post(req, ev);
1341 tevent_req_set_callback(subreq, rename_dirs_bench_done, req);
1343 return req;
1346 static void rename_dirs_bench_done(struct tevent_req *subreq)
1348 struct tevent_req *req = tevent_req_callback_data(
1349 subreq, struct tevent_req);
1350 struct rename_dirs_bench_state *state = tevent_req_data(
1351 req, struct rename_dirs_bench_state);
1352 NTSTATUS status;
1354 status = rename_dir_bench_recv(subreq);
1355 TALLOC_FREE(subreq);
1356 if (tevent_req_nterror(req, status)) {
1357 return;
1360 state->num_done += 1;
1361 if (state->num_done >= state->num_reqs) {
1362 tevent_req_done(req);
1366 static NTSTATUS rename_dirs_bench_recv(struct tevent_req *req)
1368 return tevent_req_simple_recv_ntstatus(req);
1371 static bool torture_smb2_rename_dir_bench(struct torture_context *tctx,
1372 struct smb2_tree *tree)
1374 struct tevent_req *req;
1375 NTSTATUS status;
1376 unsigned counter = 0;
1377 bool ret;
1379 req = rename_dirs_bench_send(tctx, tctx->ev, tree, "dir", 3, 10,
1380 &counter);
1381 torture_assert(tctx, req != NULL, "rename_dirs_bench_send failed");
1383 ret = tevent_req_poll(req, tctx->ev);
1384 torture_assert(tctx, ret, "tevent_req_poll failed");
1386 status = rename_dirs_bench_recv(req);
1387 torture_comment(tctx, "rename_dirs_bench returned %s\n",
1388 nt_errstr(status));
1389 TALLOC_FREE(req);
1390 torture_assert_ntstatus_ok(tctx, status, "bench failed");
1391 return true;
1396 basic testing of SMB2 rename
1398 struct torture_suite *torture_smb2_rename_init(void)
1400 struct torture_suite *suite =
1401 torture_suite_create(talloc_autofree_context(), "rename");
1403 torture_suite_add_1smb2_test(suite, "simple",
1404 torture_smb2_rename_simple);
1406 torture_suite_add_1smb2_test(suite, "simple_nodelete)",
1407 torture_smb2_rename_simple2);
1409 torture_suite_add_1smb2_test(suite, "no_sharing",
1410 torture_smb2_rename_no_sharemode);
1412 torture_suite_add_1smb2_test(suite,
1413 "share_delete_and_delete_access",
1414 torture_smb2_rename_with_delete_access);
1416 torture_suite_add_1smb2_test(suite,
1417 "no_share_delete_but_delete_access",
1418 torture_smb2_rename_with_delete_access2);
1420 torture_suite_add_1smb2_test(suite,
1421 "share_delete_no_delete_access",
1422 torture_smb2_rename_no_delete_access);
1424 torture_suite_add_1smb2_test(suite,
1425 "no_share_delete_no_delete_access",
1426 torture_smb2_rename_no_delete_access2);
1428 torture_suite_add_1smb2_test(suite,
1429 "msword",
1430 torture_smb2_rename_msword);
1432 torture_suite_add_1smb2_test(
1433 suite, "rename_dir_openfile",
1434 torture_smb2_rename_dir_openfile);
1436 torture_suite_add_1smb2_test(suite,
1437 "rename_dir_bench",
1438 torture_smb2_rename_dir_bench);
1440 suite->description = talloc_strdup(suite, "smb2.rename tests");
1442 return suite;