2 Unix SMB/CIFS implementation.
4 SMB2 dir list test suite
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Zachary Loafman 2009
8 Copyright (C) Aravind Srinivasan 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb_composite/smb_composite.h"
28 #include "libcli/raw/libcliraw.h"
29 #include "libcli/raw/raw_proto.h"
30 #include "libcli/libcli.h"
32 #include "torture/torture.h"
33 #include "torture/smb2/proto.h"
34 #include "torture/util.h"
36 #include "system/filesys.h"
38 #define CHECK_STATUS(status, correct) do { \
39 if (!NT_STATUS_EQUAL(status, correct)) { \
40 torture_result(tctx, TORTURE_FAIL, __location__": \
41 Incorrect status %s - should be %s", \
42 nt_errstr(status), nt_errstr(correct)); \
47 #define CHECK_VALUE(v, correct) torture_assert_int_equal(tctx, (v), \
48 (correct), "incorrect value");
50 #define DNAME "smb2_dir"
58 static NTSTATUS populate_tree(struct torture_context *tctx,
60 struct smb2_tree *tree,
61 struct file_elem *files,
63 struct smb2_handle *h_out)
65 struct smb2_create create;
70 smb2_deltree(tree, DNAME);
73 create.in.desired_access = SEC_RIGHTS_DIR_ALL;
74 create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
75 create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
76 create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
77 NTCREATEX_SHARE_ACCESS_WRITE |
78 NTCREATEX_SHARE_ACCESS_DELETE;
79 create.in.create_disposition = NTCREATEX_DISP_CREATE;
80 create.in.fname = DNAME;
82 status = smb2_create(tree, mem_ctx, &create);
83 CHECK_STATUS(status, NT_STATUS_OK);
84 *h_out = create.out.file.handle;
87 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
88 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
89 create.in.create_disposition = NTCREATEX_DISP_CREATE;
91 for (i = 0; i < nfiles; i++) {
92 files[i].name = generate_random_str(tctx, 8);
93 create.in.fname = talloc_asprintf(mem_ctx, "%s\\%s",
94 DNAME, files[i].name);
95 status = smb2_create(tree, mem_ctx, &create);
96 CHECK_STATUS(status, NT_STATUS_OK);
97 smb2_util_close(tree, create.out.file.handle);
107 static bool test_find(struct torture_context *tctx,
108 struct smb2_tree *tree)
110 TALLOC_CTX *mem_ctx = talloc_new(tctx);
111 struct smb2_handle h;
113 union smb_search_data *d;
114 struct file_elem files[NFILES] = {};
118 int i, j, file_count = 0;
120 status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h);
123 f.in.file.handle = h;
125 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
126 f.in.max_response_size = 0x100;
127 f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
130 status = smb2_find_level(tree, tree, &f, &count, &d);
131 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
133 CHECK_STATUS(status, NT_STATUS_OK);
135 for (i = 0; i < count; i++) {
137 const char *found = d[i].both_directory_info.name.s;
139 if (!strcmp(found, ".") || !strcmp(found, ".."))
143 for (j = 0; j < NFILES; j++) {
144 if (!strcmp(files[j].name, found)) {
145 files[j].found = true;
154 torture_result(tctx, TORTURE_FAIL,
155 "(%s): didn't expect %s\n",
156 __location__, found);
161 file_count = file_count + i;
162 f.in.continue_flags = 0;
163 f.in.max_response_size = 4096;
164 } while (count != 0);
166 CHECK_VALUE(file_count, NFILES + 2);
168 for (i = 0; i < NFILES; i++) {
172 torture_result(tctx, TORTURE_FAIL,
173 "(%s): expected to find %s, but didn't\n",
174 __location__, files[j].name);
180 smb2_deltree(tree, DNAME);
181 talloc_free(mem_ctx);
187 test fixed enumeration
190 static bool test_fixed(struct torture_context *tctx,
191 struct smb2_tree *tree)
193 TALLOC_CTX *mem_ctx = talloc_new(tctx);
194 struct smb2_create create;
195 struct smb2_handle h, h2;
197 union smb_search_data *d;
198 struct file_elem files[NFILES] = {};
204 status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h);
207 create.in.desired_access = SEC_RIGHTS_DIR_ALL;
208 create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
209 create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
210 create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
211 NTCREATEX_SHARE_ACCESS_WRITE |
212 NTCREATEX_SHARE_ACCESS_DELETE;
213 create.in.create_disposition = NTCREATEX_DISP_OPEN;
214 create.in.fname = DNAME;
216 status = smb2_create(tree, mem_ctx, &create);
217 CHECK_STATUS(status, NT_STATUS_OK);
218 h2 = create.out.file.handle;
221 f.in.file.handle = h;
223 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
224 f.in.max_response_size = 0x100;
225 f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
227 /* Start enumeration on h, then delete all from h2 */
228 status = smb2_find_level(tree, tree, &f, &count, &d);
229 CHECK_STATUS(status, NT_STATUS_OK);
231 f.in.file.handle = h2;
234 status = smb2_find_level(tree, tree, &f, &count, &d);
235 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
237 CHECK_STATUS(status, NT_STATUS_OK);
239 for (i = 0; i < count; i++) {
240 const char *found = d[i].both_directory_info.name.s;
241 char *path = talloc_asprintf(mem_ctx, "%s\\%s",
244 if (!strcmp(found, ".") || !strcmp(found, ".."))
247 status = smb2_util_unlink(tree, path);
248 CHECK_STATUS(status, NT_STATUS_OK);
253 f.in.continue_flags = 0;
254 f.in.max_response_size = 4096;
255 } while (count != 0);
257 /* Now finish h enumeration. */
258 f.in.file.handle = h;
261 status = smb2_find_level(tree, tree, &f, &count, &d);
262 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
264 CHECK_STATUS(status, NT_STATUS_OK);
266 for (i = 0; i < count; i++) {
267 const char *found = d[i].both_directory_info.name.s;
269 if (!strcmp(found, ".") || !strcmp(found, ".."))
272 torture_result(tctx, TORTURE_FAIL,
273 "(%s): didn't expect %s\n",
274 __location__, found);
279 f.in.continue_flags = 0;
280 f.in.max_response_size = 4096;
281 } while (count != 0);
284 smb2_util_close(tree, h);
285 smb2_util_close(tree, h2);
286 smb2_deltree(tree, DNAME);
287 talloc_free(mem_ctx);
295 enum smb_search_data_level data_level;
297 int resume_key_offset;
298 uint32_t capability_mask;
300 union smb_search_data data;
302 {"SMB2_FIND_DIRECTORY_INFO",
303 SMB2_FIND_DIRECTORY_INFO, RAW_SEARCH_DATA_DIRECTORY_INFO,
304 offsetof(union smb_search_data, directory_info.name.s),
305 offsetof(union smb_search_data, directory_info.file_index),
307 {"SMB2_FIND_FULL_DIRECTORY_INFO",
308 SMB2_FIND_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
309 offsetof(union smb_search_data, full_directory_info.name.s),
310 offsetof(union smb_search_data, full_directory_info.file_index),
312 {"SMB2_FIND_NAME_INFO",
313 SMB2_FIND_NAME_INFO, RAW_SEARCH_DATA_NAME_INFO,
314 offsetof(union smb_search_data, name_info.name.s),
315 offsetof(union smb_search_data, name_info.file_index),
317 {"SMB2_FIND_BOTH_DIRECTORY_INFO",
318 SMB2_FIND_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
319 offsetof(union smb_search_data, both_directory_info.name.s),
320 offsetof(union smb_search_data, both_directory_info.file_index),
322 {"SMB2_FIND_ID_FULL_DIRECTORY_INFO",
323 SMB2_FIND_ID_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO,
324 offsetof(union smb_search_data, id_full_directory_info.name.s),
325 offsetof(union smb_search_data, id_full_directory_info.file_index),
327 {"SMB2_FIND_ID_BOTH_DIRECTORY_INFO",
328 SMB2_FIND_ID_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO,
329 offsetof(union smb_search_data, id_both_directory_info.name.s),
330 offsetof(union smb_search_data, id_both_directory_info.file_index),
335 extract the name from a smb_data structure and level
337 static const char *extract_name(union smb_search_data *data,
339 enum smb_search_data_level data_level)
342 for (i=0;i<ARRAY_SIZE(levels);i++) {
343 if (level == levels[i].level &&
344 data_level == levels[i].data_level) {
345 return *(const char **)(levels[i].name_offset + (char *)data);
351 /* find a level in the table by name */
352 static union smb_search_data *find(const char *name)
355 for (i=0;i<ARRAY_SIZE(levels);i++) {
356 if (NT_STATUS_IS_OK(levels[i].status) &&
357 strcmp(levels[i].name, name) == 0) {
358 return &levels[i].data;
364 static bool fill_level_data(TALLOC_CTX *mem_ctx,
365 union smb_search_data *data,
366 union smb_search_data *d,
369 enum smb_search_data_level data_level)
372 const char *sname = NULL;
373 for (i=0; i < count ; i++) {
374 sname = extract_name(&d[i], level, data_level);
377 if (!strcmp(sname, ".") || !strcmp(sname, ".."))
385 NTSTATUS torture_single_file_search(struct smb2_tree *tree,
389 enum smb_search_data_level data_level,
391 union smb_search_data *d,
393 struct smb2_handle *h)
399 f.in.file.handle = *h;
400 f.in.pattern = pattern;
401 f.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART;
402 f.in.max_response_size = 0x100;
405 status = smb2_find_level(tree, tree, &f, count, &d);
406 if (NT_STATUS_IS_OK(status))
407 fill_level_data(mem_ctx, &levels[index].data, d, *count, level,
413 basic testing of all File Information Classes using a single file
415 static bool test_one_file(struct torture_context *tctx,
416 struct smb2_tree *tree)
418 TALLOC_CTX *mem_ctx = talloc_new(tctx);
420 const char *fname = "torture_search.txt";
424 union smb_fileinfo all_info2, alt_info, internal_info;
425 union smb_search_data *s;
426 union smb_search_data d;
427 struct smb2_handle h, h2;
429 status = torture_smb2_testdir(tree, DNAME, &h);
430 CHECK_STATUS(status, NT_STATUS_OK);
432 status = smb2_create_complex_file(tree, DNAME "\\torture_search.txt",
434 CHECK_STATUS(status, NT_STATUS_OK);
436 /* call all the File Information Classes */
437 for (i=0;i<ARRAY_SIZE(levels);i++) {
438 torture_comment(tctx, "testing %s %d\n", levels[i].name,
441 levels[i].status = torture_single_file_search(tree, mem_ctx,
442 fname, levels[i].level, levels[i].data_level,
444 CHECK_STATUS(levels[i].status, NT_STATUS_OK);
447 /* get the all_info file into to check against */
448 all_info2.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
449 all_info2.generic.in.file.handle = h2;
450 status = smb2_getinfo_file(tree, tctx, &all_info2);
451 torture_assert_ntstatus_ok(tctx, status,
452 "RAW_FILEINFO_ALL_INFO failed");
454 alt_info.generic.level = RAW_FILEINFO_ALT_NAME_INFORMATION;
455 alt_info.generic.in.file.handle = h2;
456 status = smb2_getinfo_file(tree, tctx, &alt_info);
457 torture_assert_ntstatus_ok(tctx, status,
458 "RAW_FILEINFO_ALT_NAME_INFO failed");
460 internal_info.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
461 internal_info.generic.in.file.handle = h2;
462 status = smb2_getinfo_file(tree, tctx, &internal_info);
463 torture_assert_ntstatus_ok(tctx, status,
464 "RAW_FILEINFO_INTERNAL_INFORMATION failed");
466 #define CHECK_VAL(name, sname1, field1, v, sname2, field2) do { \
469 if ((s->sname1.field1) != (v.sname2.out.field2)) { \
470 printf("(%s) %s/%s [0x%x] != %s/%s [0x%x]\n", \
472 #sname1, #field1, (int)s->sname1.field1, \
473 #sname2, #field2, (int)v.sname2.out.field2); \
478 #define CHECK_TIME(name, sname1, field1, v, sname2, field2) do { \
481 if (s->sname1.field1 != \
482 (~1 & nt_time_to_unix(v.sname2.out.field2))) { \
483 printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
486 timestring(tctx, s->sname1.field1), \
488 nt_time_string(tctx, v.sname2.out.field2)); \
493 #define CHECK_NTTIME(name, sname1, field1, v, sname2, field2) do { \
496 if (s->sname1.field1 != v.sname2.out.field2) { \
497 printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
500 nt_time_string(tctx, s->sname1.field1), \
502 nt_time_string(tctx, v.sname2.out.field2)); \
507 #define CHECK_STR(name, sname1, field1, v, sname2, field2) do { \
510 if (!s->sname1.field1 || \
511 strcmp(s->sname1.field1, v.sname2.out.field2.s)) { \
512 printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
514 #sname1, #field1, s->sname1.field1, \
515 #sname2, #field2, v.sname2.out.field2.s); \
520 #define CHECK_WSTR(name, sname1, field1, v, sname2, field2, flags) do { \
523 if (!s->sname1.field1.s || \
524 strcmp(s->sname1.field1.s, v.sname2.out.field2.s)) { \
525 printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
527 #sname1, #field1, s->sname1.field1.s, \
528 #sname2, #field2, v.sname2.out.field2.s); \
533 #define CHECK_NAME(name, sname1, field1, fname, flags) do { \
536 if (!s->sname1.field1.s || \
537 strcmp(s->sname1.field1.s, fname)) { \
538 printf("(%s) %s/%s [%s] != %s\n", \
540 #sname1, #field1, s->sname1.field1.s, \
546 #define CHECK_UNIX_NAME(name, sname1, field1, fname, flags) do { \
549 if (!s->sname1.field1 || \
550 strcmp(s->sname1.field1, fname)) { \
551 printf("(%s) %s/%s [%s] != %s\n", \
553 #sname1, #field1, s->sname1.field1, \
559 /* check that all the results are as expected */
560 CHECK_VAL("SMB2_FIND_DIRECTORY_INFO", directory_info, attrib, all_info2, all_info2, attrib);
561 CHECK_VAL("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, attrib, all_info2, all_info2, attrib);
562 CHECK_VAL("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, attrib, all_info2, all_info2, attrib);
563 CHECK_VAL("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, attrib, all_info2, all_info2, attrib);
564 CHECK_VAL("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, attrib, all_info2, all_info2, attrib);
566 CHECK_NTTIME("SMB2_FIND_DIRECTORY_INFO", directory_info, write_time, all_info2, all_info2, write_time);
567 CHECK_NTTIME("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, write_time, all_info2, all_info2, write_time);
568 CHECK_NTTIME("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, write_time, all_info2, all_info2, write_time);
569 CHECK_NTTIME("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, write_time, all_info2, all_info2, write_time);
570 CHECK_NTTIME("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, write_time, all_info2, all_info2, write_time);
572 CHECK_NTTIME("SMB2_FIND_DIRECTORY_INFO", directory_info, create_time, all_info2, all_info2, create_time);
573 CHECK_NTTIME("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, create_time, all_info2, all_info2, create_time);
574 CHECK_NTTIME("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, create_time, all_info2, all_info2, create_time);
575 CHECK_NTTIME("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, create_time, all_info2, all_info2, create_time);
576 CHECK_NTTIME("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, create_time, all_info2, all_info2, create_time);
577 CHECK_NTTIME("SMB2_FIND_DIRECTORY_INFO", directory_info, access_time, all_info2, all_info2, access_time);
578 CHECK_NTTIME("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, access_time, all_info2, all_info2, access_time);
579 CHECK_NTTIME("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, access_time, all_info2, all_info2, access_time);
580 CHECK_NTTIME("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, access_time, all_info2, all_info2, access_time);
581 CHECK_NTTIME("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, access_time, all_info2, all_info2, access_time);
583 CHECK_NTTIME("SMB2_FIND_DIRECTORY_INFO", directory_info, change_time, all_info2, all_info2, change_time);
584 CHECK_NTTIME("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, change_time, all_info2, all_info2, change_time);
585 CHECK_NTTIME("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, change_time, all_info2, all_info2, change_time);
586 CHECK_NTTIME("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, change_time, all_info2, all_info2, change_time);
587 CHECK_NTTIME("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, change_time, all_info2, all_info2, change_time);
589 CHECK_VAL("SMB2_FIND_DIRECTORY_INFO", directory_info, size, all_info2, all_info2, size);
590 CHECK_VAL("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, size, all_info2, all_info2, size);
591 CHECK_VAL("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, size, all_info2, all_info2, size);
592 CHECK_VAL("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, size, all_info2, all_info2, size);
593 CHECK_VAL("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, size, all_info2, all_info2, size);
595 CHECK_VAL("SMB2_FIND_DIRECTORY_INFO", directory_info, alloc_size, all_info2, all_info2, alloc_size);
596 CHECK_VAL("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, alloc_size, all_info2, all_info2, alloc_size);
597 CHECK_VAL("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, alloc_size, all_info2, all_info2, alloc_size);
598 CHECK_VAL("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, alloc_size, all_info2, all_info2, alloc_size);
599 CHECK_VAL("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, alloc_size, all_info2, all_info2, alloc_size);
601 CHECK_VAL("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, ea_size, all_info2, all_info2, ea_size);
602 CHECK_VAL("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, ea_size, all_info2, all_info2, ea_size);
603 CHECK_VAL("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, ea_size, all_info2, all_info2, ea_size);
604 CHECK_VAL("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, ea_size, all_info2, all_info2, ea_size);
606 CHECK_WSTR("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, short_name, alt_info, alt_name_info, fname, STR_UNICODE);
608 CHECK_NAME("SMB2_FIND_DIRECTORY_INFO", directory_info, name, fname, STR_TERMINATE_ASCII);
609 CHECK_NAME("SMB2_FIND_FULL_DIRECTORY_INFO", full_directory_info, name, fname, STR_TERMINATE_ASCII);
610 CHECK_NAME("SMB2_FIND_NAME_INFO", name_info, name, fname, STR_TERMINATE_ASCII);
611 CHECK_NAME("SMB2_FIND_BOTH_DIRECTORY_INFO", both_directory_info, name, fname, STR_TERMINATE_ASCII);
612 CHECK_NAME("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, name, fname, STR_TERMINATE_ASCII);
613 CHECK_NAME("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, name, fname, STR_TERMINATE_ASCII);
614 CHECK_VAL("SMB2_FIND_ID_FULL_DIRECTORY_INFO", id_full_directory_info, file_id, internal_info, internal_information, file_id);
616 CHECK_VAL("SMB2_FIND_ID_BOTH_DIRECTORY_INFO", id_both_directory_info, file_id, internal_info, internal_information, file_id);
619 smb2_util_close(tree, h);
620 smb2_util_unlink(tree, fname);
621 talloc_free(mem_ctx);
627 struct multiple_result {
630 union smb_search_data *list;
633 bool fill_result(void *private_data,
634 union smb_search_data *file,
637 enum smb_search_data_level data_level)
641 struct multiple_result *data = (struct multiple_result *)private_data;
643 for (i=0; i<count; i++) {
644 sname = extract_name(&file[i], level, data_level);
645 if (!strcmp(sname, ".") || !(strcmp(sname, "..")))
648 data->list = talloc_realloc(data->tctx,
650 union smb_search_data,
652 data->list[data->count-1] = file[i];
657 enum continue_type {CONT_SINGLE, CONT_INDEX, CONT_RESTART};
659 static NTSTATUS multiple_smb2_search(struct smb2_tree *tree,
663 enum smb_search_data_level data_level,
664 enum continue_type cont_type,
666 struct smb2_handle *h)
671 union smb_search_data *d;
673 struct multiple_result *result = (struct multiple_result *)data;
676 f.in.file.handle = *h;
677 f.in.pattern = pattern;
678 f.in.max_response_size = 0x1000;
681 /* The search should start from the beginning everytime */
682 f.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART;
685 status = smb2_find_level(tree, tree, &f, &count, &d);
686 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
688 CHECK_STATUS(status, NT_STATUS_OK);
689 if (!fill_result(result, d, count, level, data_level)) {
690 return NT_STATUS_UNSUCCESSFUL;
694 * After the first iteration is complete set the CONTINUE
695 * FLAGS appropriately
699 f.in.continue_flags = SMB2_CONTINUE_FLAG_INDEX;
702 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
706 /* we should prevent staying in the loop forever */
707 f.in.continue_flags = 0;
710 } while (count != 0);
716 static enum smb_search_data_level compare_data_level;
719 static int search_compare(union smb_search_data *d1,
720 union smb_search_data *d2)
724 s1 = extract_name(d1, level_sort, compare_data_level);
725 s2 = extract_name(d2, level_sort, compare_data_level);
726 return strcmp_safe(s1, s2);
730 basic testing of search calls using many files
732 static bool test_many_files(struct torture_context *tctx,
733 struct smb2_tree *tree)
735 TALLOC_CTX *mem_ctx = talloc_new(tctx);
736 const int num_files = 700;
741 struct multiple_result result;
742 struct smb2_create create;
743 struct smb2_handle h;
746 const char *cont_name;
748 enum smb_search_data_level data_level;
749 enum continue_type cont_type;
751 {"SMB2_FIND_BOTH_DIRECTORY_INFO", "SINGLE", SMB2_FIND_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, CONT_SINGLE},
752 {"SMB2_FIND_BOTH_DIRECTORY_INFO", "INDEX", SMB2_FIND_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, CONT_INDEX},
753 {"SMB2_FIND_BOTH_DIRECTORY_INFO", "RESTART", SMB2_FIND_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, CONT_RESTART},
754 {"SMB2_FIND_DIRECTORY_INFO", "SINGLE", SMB2_FIND_DIRECTORY_INFO, RAW_SEARCH_DATA_DIRECTORY_INFO, CONT_SINGLE},
755 {"SMB2_FIND_DIRECTORY_INFO", "INDEX", SMB2_FIND_DIRECTORY_INFO, RAW_SEARCH_DATA_DIRECTORY_INFO, CONT_INDEX},
756 {"SMB2_FIND_DIRECTORY_INFO", "RESTART", SMB2_FIND_DIRECTORY_INFO, RAW_SEARCH_DATA_DIRECTORY_INFO, CONT_RESTART},
757 {"SMB2_FIND_FULL_DIRECTORY_INFO", "SINGLE", SMB2_FIND_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_FULL_DIRECTORY_INFO, CONT_SINGLE},
758 {"SMB2_FIND_FULL_DIRECTORY_INFO", "INDEX", SMB2_FIND_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_FULL_DIRECTORY_INFO, CONT_INDEX},
759 {"SMB2_FIND_FULL_DIRECTORY_INFO", "RESTART", SMB2_FIND_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_FULL_DIRECTORY_INFO, CONT_RESTART},
760 {"SMB2_FIND_ID_FULL_DIRECTORY_INFO", "SINGLE", SMB2_FIND_ID_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO, CONT_SINGLE},
761 {"SMB2_FIND_ID_FULL_DIRECTORY_INFO", "INDEX", SMB2_FIND_ID_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO, CONT_INDEX},
762 {"SMB2_FIND_ID_FULL_DIRECTORY_INFO", "RESTART", SMB2_FIND_ID_FULL_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO, CONT_RESTART},
763 {"SMB2_FIND_ID_BOTH_DIRECTORY_INFO", "SINGLE", SMB2_FIND_ID_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO, CONT_SINGLE},
764 {"SMB2_FIND_ID_BOTH_DIRECTORY_INFO", "INDEX", SMB2_FIND_ID_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO, CONT_INDEX},
765 {"SMB2_FIND_ID_BOTH_DIRECTORY_INFO", "RESTART", SMB2_FIND_ID_BOTH_DIRECTORY_INFO, RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO, CONT_RESTART}
768 smb2_deltree(tree, DNAME);
769 status = torture_smb2_testdir(tree, DNAME, &h);
770 CHECK_STATUS(status, NT_STATUS_OK);
772 torture_comment(tctx, "Testing with %d files\n", num_files);
774 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
775 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
776 create.in.create_disposition = NTCREATEX_DISP_CREATE;
778 for (i=num_files-1;i>=0;i--) {
779 fname = talloc_asprintf(mem_ctx, DNAME "\\t%03d-%d.txt", i, i);
780 create.in.fname = talloc_asprintf(mem_ctx, "%s", fname);
781 status = smb2_create(tree, mem_ctx, &create);
782 CHECK_STATUS(status, NT_STATUS_OK);
783 smb2_util_close(tree, create.out.file.handle);
787 for (t=0;t<ARRAY_SIZE(search_types);t++) {
789 result.tctx = talloc_new(tctx);
791 torture_comment(tctx,
792 "Continue %s via %s\n", search_types[t].name,
793 search_types[t].cont_name);
794 status = multiple_smb2_search(tree, tctx, "*",
795 search_types[t].level,
796 search_types[t].data_level,
797 search_types[t].cont_type,
800 CHECK_VALUE(result.count, num_files);
802 compare_data_level = search_types[t].data_level;
803 level_sort = search_types[t].level;
805 qsort(result.list, result.count, sizeof(result.list[0]),
806 QSORT_CAST search_compare);
808 for (i=0;i<result.count;i++) {
810 enum smb_search_level level;
811 level = RAW_SEARCH_SMB2;
812 s = extract_name(&result.list[i],
813 search_types[t].level,
815 fname = talloc_asprintf(mem_ctx, "t%03d-%d.txt", i, i);
816 torture_assert_str_equal(tctx, fname, s,
820 talloc_free(result.tctx);
824 smb2_util_close(tree, h);
825 smb2_deltree(tree, DNAME);
826 talloc_free(mem_ctx);
832 check a individual file result
834 static bool check_result(struct multiple_result *result,
840 for (i=0;i<result->count;i++) {
842 result->list[i].both_directory_info.name.s) == 0) {
846 if (i == result->count) {
848 printf("failed: '%s' should exist with attribute %s\n",
849 name, attrib_string(result->list, attrib));
856 printf("failed: '%s' should NOT exist (has attribute %s)\n",
857 name, attrib_string(result->list,
858 result->list[i].both_directory_info.attrib));
862 if ((result->list[i].both_directory_info.attrib&0xFFF) != attrib) {
863 printf("failed: '%s' should have attribute 0x%x (has 0x%x)\n",
865 attrib, result->list[i].both_directory_info.attrib);
872 test what happens when the directory is modified during a search
874 static bool test_modify_search(struct torture_context *tctx,
875 struct smb2_tree *tree)
878 struct multiple_result result;
879 union smb_setfileinfo sfinfo;
880 TALLOC_CTX *mem_ctx = talloc_new(tctx);
881 struct smb2_create create;
882 struct smb2_handle h;
884 union smb_search_data *d;
885 struct file_elem files[700] = {};
891 smb2_deltree(tree, DNAME);
893 status = torture_smb2_testdir(tree, DNAME, &h);
894 CHECK_STATUS(status, NT_STATUS_OK);
896 printf("Creating %d files\n", num_files);
899 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
900 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
901 create.in.create_disposition = NTCREATEX_DISP_CREATE;
903 for (i = num_files-1; i >= 0; i--) {
904 files[i].name = talloc_asprintf(mem_ctx, "t%03d-%d.txt", i, i);
905 create.in.fname = talloc_asprintf(mem_ctx, "%s\\%s",
906 DNAME, files[i].name);
907 status = smb2_create(tree, mem_ctx, &create);
908 CHECK_STATUS(status, NT_STATUS_OK);
909 smb2_util_close(tree, create.out.file.handle);
912 printf("pulling the first two files\n");
914 result.tctx = talloc_new(tctx);
917 f.in.file.handle = h;
919 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
920 f.in.max_response_size = 0x100;
921 f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
924 status = smb2_find_level(tree, tree, &f, &count, &d);
925 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
927 CHECK_STATUS(status, NT_STATUS_OK);
928 if (!fill_result(&result, d, count, f.in.level,
929 RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO)) {
933 }while(result.count < 2);
935 printf("Changing attributes and deleting\n");
938 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
939 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
940 create.in.create_disposition = NTCREATEX_DISP_CREATE;
942 files[num_files].name = talloc_asprintf(mem_ctx, "T003-03.txt.2");
943 create.in.fname = talloc_asprintf(mem_ctx, "%s\\%s", DNAME,
944 files[num_files].name);
945 status = smb2_create(tree, mem_ctx, &create);
946 CHECK_STATUS(status, NT_STATUS_OK);
947 smb2_util_close(tree, create.out.file.handle);
950 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
951 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
952 create.in.create_disposition = NTCREATEX_DISP_CREATE;
954 files[num_files + 1].name = talloc_asprintf(mem_ctx, "T013-13.txt.2");
955 create.in.fname = talloc_asprintf(mem_ctx, "%s\\%s", DNAME,
956 files[num_files + 1].name);
957 status = smb2_create(tree, mem_ctx, &create);
958 CHECK_STATUS(status, NT_STATUS_OK);
959 smb2_util_close(tree, create.out.file.handle);
961 files[num_files + 2].name = talloc_asprintf(mem_ctx, "T013-13.txt.3");
962 status = smb2_create_complex_file(tree, DNAME "\\T013-13.txt.3", &h);
963 CHECK_STATUS(status, NT_STATUS_OK);
965 smb2_util_unlink(tree, DNAME "\\T014-14.txt");
966 smb2_util_setatr(tree, DNAME "\\T015-15.txt", FILE_ATTRIBUTE_HIDDEN);
967 smb2_util_setatr(tree, DNAME "\\T016-16.txt", FILE_ATTRIBUTE_NORMAL);
968 smb2_util_setatr(tree, DNAME "\\T017-17.txt", FILE_ATTRIBUTE_SYSTEM);
969 smb2_util_setatr(tree, DNAME "\\T018-18.txt", 0);
970 smb2_util_setatr(tree, DNAME "\\T039-39.txt", FILE_ATTRIBUTE_HIDDEN);
971 smb2_util_setatr(tree, DNAME "\\T000-0.txt", FILE_ATTRIBUTE_HIDDEN);
972 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
973 sfinfo.generic.in.file.path = DNAME "\\T013-13.txt.3";
974 sfinfo.disposition_info.in.delete_on_close = 1;
975 status = smb2_composite_setpathinfo(tree, &sfinfo);
976 CHECK_STATUS(status, NT_STATUS_OK);
978 /* Reset the numfiles to include the new files and start the
979 * search from the beginning */
980 num_files = num_files + 2;
982 f.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART;
986 status = smb2_find_level(tree, tree, &f, &count, &d);
987 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
989 CHECK_STATUS(status, NT_STATUS_OK);
990 if (!fill_result(&result, d, count, f.in.level,
991 RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO)) {
995 f.in.continue_flags = 0;
996 f.in.max_response_size = 4096;
997 } while (count != 0);
1000 ret &= check_result(&result, "t039-39.txt", true, FILE_ATTRIBUTE_HIDDEN);
1001 ret &= check_result(&result, "t000-0.txt", true, FILE_ATTRIBUTE_HIDDEN);
1002 ret &= check_result(&result, "t014-14.txt", false, 0);
1003 ret &= check_result(&result, "t015-15.txt", true, FILE_ATTRIBUTE_HIDDEN);
1004 ret &= check_result(&result, "t016-16.txt", true, FILE_ATTRIBUTE_NORMAL);
1005 ret &= check_result(&result, "t017-17.txt", true, FILE_ATTRIBUTE_SYSTEM);
1006 ret &= check_result(&result, "t018-18.txt", true, FILE_ATTRIBUTE_ARCHIVE);
1007 ret &= check_result(&result, "t019-19.txt", true, FILE_ATTRIBUTE_ARCHIVE);
1008 ret &= check_result(&result, "T013-13.txt.2", true, FILE_ATTRIBUTE_ARCHIVE);
1009 ret &= check_result(&result, "T003-3.txt.2", false, 0);
1010 ret &= check_result(&result, "T013-13.txt.3", true, FILE_ATTRIBUTE_NORMAL);
1013 for (i=0;i<result.count;i++) {
1014 printf("%s %s (0x%x)\n",
1015 result.list[i].both_directory_info.name.s,
1017 result.list[i].both_directory_info.attrib),
1018 result.list[i].both_directory_info.attrib);
1022 smb2_util_close(tree, h);
1023 smb2_deltree(tree, DNAME);
1024 talloc_free(mem_ctx);
1030 testing if directories always come back sorted
1032 static bool test_sorted(struct torture_context *tctx,
1033 struct smb2_tree *tree)
1035 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1036 const int num_files = 700;
1038 struct file_elem files[700] = {};
1041 struct multiple_result result;
1042 struct smb2_handle h;
1044 printf("Testing if directories always come back sorted\n");
1045 status = populate_tree(tctx, mem_ctx, tree, files, num_files, &h);
1046 CHECK_STATUS(status, NT_STATUS_OK);
1048 ZERO_STRUCT(result);
1051 status = multiple_smb2_search(tree, tctx, "*",
1052 SMB2_FIND_BOTH_DIRECTORY_INFO,
1053 RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
1054 SMB2_CONTINUE_FLAG_SINGLE,
1057 CHECK_VALUE(result.count, num_files);
1059 for (i=0;i<num_files-1;i++) {
1060 const char *name1, *name2;
1061 name1 = result.list[i].both_directory_info.name.s;
1062 name2 = result.list[i+1].both_directory_info.name.s;
1063 if (strcasecmp_m(name1, name2) > 0) {
1064 printf("non-alphabetical order at entry %d '%s' '%s'"
1065 "\n", i, name1, name2);
1066 torture_comment(tctx,
1067 "Server does not produce sorted directory listings"
1068 "(not an error)\n");
1072 talloc_free(result.list);
1074 smb2_util_close(tree, h);
1075 smb2_deltree(tree, DNAME);
1076 talloc_free(mem_ctx);
1081 /* test the behavior of file_index field in the SMB2_FIND struct */
1083 static bool test_file_index(struct torture_context *tctx,
1084 struct smb2_tree *tree)
1086 TALLOC_CTX *mem_ctx = talloc_new(mem_ctx);
1087 const int num_files = 100;
1088 int resume_index = 4;
1093 struct multiple_result result;
1094 struct smb2_create create;
1096 struct smb2_handle h;
1097 union smb_search_data *d;
1100 smb2_deltree(tree, DNAME);
1102 status = torture_smb2_testdir(tree, DNAME, &h);
1103 CHECK_STATUS(status, NT_STATUS_OK);
1105 printf("Testing the behavior of file_index flag\n");
1107 ZERO_STRUCT(create);
1108 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
1109 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1110 create.in.create_disposition = NTCREATEX_DISP_CREATE;
1111 for (i = num_files-1; i >= 0; i--) {
1112 fname = talloc_asprintf(mem_ctx, DNAME "\\file%u.txt", i);
1113 create.in.fname = fname;
1114 status = smb2_create(tree, mem_ctx, &create);
1115 CHECK_STATUS(status, NT_STATUS_OK);
1117 smb2_util_close(tree, create.out.file.handle);
1120 ZERO_STRUCT(result);
1124 f.in.file.handle = h;
1126 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
1127 f.in.max_response_size = 0x1000;
1128 f.in.level = SMB2_FIND_FULL_DIRECTORY_INFO;
1131 status = smb2_find_level(tree, tree, &f, &count, &d);
1132 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
1134 CHECK_STATUS(status, NT_STATUS_OK);
1135 if (!fill_result(&result, d, count, f.in.level,
1136 RAW_SEARCH_DATA_FULL_DIRECTORY_INFO)) {
1140 } while(result.count < 10);
1142 if (result.list[0].full_directory_info.file_index == 0) {
1143 torture_comment(tctx,
1144 "Talking to a server that doesn't provide a "
1145 "file index.\nWindows servers using NTFS do "
1146 "not provide a file_index. Skipping test\n");
1149 /* We are not talking to a Windows based server. Windows
1150 * servers using NTFS do not provide a file_index. Windows
1151 * server using FAT do provide a file index, however in both
1152 * cases they do not honor a file index on a resume request.
1153 * See MS-FSCC <62> and MS-SMB2 <54> for more information. */
1155 /* Set the file_index flag to point to the fifth file from the
1156 * previous enumeration and try to start the subsequent
1157 * searches from that point */
1159 result.list[resume_index].full_directory_info.file_index;
1160 f.in.continue_flags = SMB2_CONTINUE_FLAG_INDEX;
1162 /* get the name of the next expected file */
1163 fname = talloc_asprintf(mem_ctx, DNAME "\\%s",
1164 result.list[resume_index].full_directory_info.name.s);
1166 ZERO_STRUCT(result);
1168 status = smb2_find_level(tree, tree, &f, &count, &d);
1169 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
1171 CHECK_STATUS(status, NT_STATUS_OK);
1172 if (!fill_result(&result, d, count, f.in.level,
1173 RAW_SEARCH_DATA_FULL_DIRECTORY_INFO)) {
1178 result.list[0].full_directory_info.name.s)) {
1179 printf("next expected file: %s but the server "
1180 "returned %s\n", fname,
1181 result.list[0].full_directory_info.name.s);
1182 torture_comment(tctx,
1183 "Not an error. Resuming using a file "
1184 "index is an optional feature of the "
1190 smb2_util_close(tree, h);
1191 smb2_deltree(tree, DNAME);
1192 talloc_free(mem_ctx);
1198 * Tests directory enumeration in a directory containing >1000 files with
1199 * names of varying lengths.
1201 static bool test_large_files(struct torture_context *tctx,
1202 struct smb2_tree *tree)
1204 TALLOC_CTX *mem_ctx = talloc_new(mem_ctx);
1205 const int num_files = 2000;
1206 int i, j = 1, retry_count = 0;
1207 struct file_elem files[2000] = {};
1210 struct smb2_create create;
1212 struct smb2_handle h;
1213 union smb_search_data *d;
1214 int count, file_count = 0;
1216 torture_comment(tctx,
1217 "Testing directory enumeration in a directory with >1000 files\n");
1219 smb2_deltree(tree, DNAME);
1221 ZERO_STRUCT(create);
1222 create.in.desired_access = SEC_RIGHTS_DIR_ALL;
1223 create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1224 create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1225 create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1226 NTCREATEX_SHARE_ACCESS_WRITE |
1227 NTCREATEX_SHARE_ACCESS_DELETE;
1228 create.in.create_disposition = NTCREATEX_DISP_CREATE;
1229 create.in.fname = DNAME;
1231 status = smb2_create(tree, mem_ctx, &create);
1232 CHECK_STATUS(status, NT_STATUS_OK);
1233 h = create.out.file.handle;
1235 ZERO_STRUCT(create);
1236 create.in.desired_access = SEC_RIGHTS_FILE_ALL;
1237 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1238 create.in.create_disposition = NTCREATEX_DISP_CREATE;
1240 for (i = 0; i < num_files; i++) {
1241 files[i].name = generate_random_str(tctx, j);
1242 create.in.fname = talloc_asprintf(mem_ctx, "%s\\%s",
1243 DNAME, files[i].name);
1244 status = smb2_create(tree, mem_ctx, &create);
1245 CHECK_STATUS(status, NT_STATUS_OK);
1246 smb2_util_close(tree, create.out.file.handle);
1253 f.in.file.handle = h;
1255 f.in.max_response_size = 0x100;
1256 f.in.level = SMB2_FIND_BOTH_DIRECTORY_INFO;
1259 status = smb2_find_level(tree, tree, &f, &count, &d);
1260 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
1262 CHECK_STATUS(status, NT_STATUS_OK);
1264 for (i = 0; i < count; i++) {
1266 const char *found = d[i].both_directory_info.name.s;
1268 if (!strcmp(found, ".") || !strcmp(found, ".."))
1272 for (j = 0; j < 2000; j++) {
1273 if (!strcmp(files[j].name, found)) {
1274 files[j].found = true;
1283 torture_result(tctx, TORTURE_FAIL,
1284 "(%s): didn't expect %s\n",
1285 __location__, found);
1289 file_count = file_count + i;
1290 f.in.continue_flags = 0;
1291 f.in.max_response_size = 4096;
1292 } while (count != 0);
1294 CHECK_VALUE(file_count, num_files + 2);
1296 for (i = 0; i < num_files; i++) {
1300 torture_result(tctx, TORTURE_FAIL,
1301 "(%s): expected to find %s, but didn't\n",
1302 __location__, files[j].name);
1307 smb2_util_close(tree, h);
1308 smb2_deltree(tree, DNAME);
1309 talloc_free(mem_ctx);
1314 struct torture_suite *torture_smb2_dir_init(void)
1316 struct torture_suite *suite =
1317 torture_suite_create(talloc_autofree_context(), "DIR");
1319 torture_suite_add_1smb2_test(suite, "FIND", test_find);
1320 torture_suite_add_1smb2_test(suite, "FIXED", test_fixed);
1321 torture_suite_add_1smb2_test(suite, "ONE", test_one_file);
1322 torture_suite_add_1smb2_test(suite, "MANY", test_many_files);
1323 torture_suite_add_1smb2_test(suite, "MODIFY", test_modify_search);
1324 torture_suite_add_1smb2_test(suite, "SORTED", test_sorted);
1325 torture_suite_add_1smb2_test(suite, "FILE-INDEX", test_file_index);
1326 torture_suite_add_1smb2_test(suite, "LARGE-FILES", test_large_files);
1327 suite->description = talloc_strdup(suite, "SMB2-DIR tests");