1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 | RAW_SEARCH_* individual test suite
|
---|
4 | Copyright (C) Andrew Tridgell 2003
|
---|
5 |
|
---|
6 | This program is free software; you can redistribute it and/or modify
|
---|
7 | it under the terms of the GNU General Public License as published by
|
---|
8 | the Free Software Foundation; either version 3 of the License, or
|
---|
9 | (at your option) any later version.
|
---|
10 |
|
---|
11 | This program is distributed in the hope that it will be useful,
|
---|
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | GNU General Public License for more details.
|
---|
15 |
|
---|
16 | You should have received a copy of the GNU General Public License
|
---|
17 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
18 | */
|
---|
19 |
|
---|
20 | #include "includes.h"
|
---|
21 | #include "system/filesys.h"
|
---|
22 | #include "libcli/raw/libcliraw.h"
|
---|
23 | #include "libcli/raw/raw_proto.h"
|
---|
24 | #include "libcli/libcli.h"
|
---|
25 | #include "torture/util.h"
|
---|
26 | #include "lib/util/tsort.h"
|
---|
27 |
|
---|
28 |
|
---|
29 | #define BASEDIR "\\testsearch"
|
---|
30 |
|
---|
31 | #define CHECK_STATUS_LEVEL(__tctx, __status, __level, __supp) \
|
---|
32 | do { \
|
---|
33 | if (NT_STATUS_EQUAL(__status, \
|
---|
34 | NT_STATUS_NOT_SUPPORTED) || \
|
---|
35 | NT_STATUS_EQUAL(__status, \
|
---|
36 | NT_STATUS_NOT_IMPLEMENTED)) { \
|
---|
37 | torture_warning(__tctx, "(%s) Info " \
|
---|
38 | "level "#__level" is %s", \
|
---|
39 | __location__, nt_errstr(__status)); \
|
---|
40 | __supp = false; \
|
---|
41 | } else { \
|
---|
42 | torture_assert_ntstatus_ok_goto(__tctx, \
|
---|
43 | __status, ret, done, #__level" failed"); \
|
---|
44 | __supp = true; \
|
---|
45 | } \
|
---|
46 | } while (0)
|
---|
47 |
|
---|
48 | /*
|
---|
49 | callback function for single_search
|
---|
50 | */
|
---|
51 | static bool single_search_callback(void *private_data, const union smb_search_data *file)
|
---|
52 | {
|
---|
53 | union smb_search_data *data = (union smb_search_data *)private_data;
|
---|
54 |
|
---|
55 | *data = *file;
|
---|
56 |
|
---|
57 | return true;
|
---|
58 | }
|
---|
59 |
|
---|
60 | /*
|
---|
61 | do a single file (non-wildcard) search
|
---|
62 | */
|
---|
63 | NTSTATUS torture_single_search(struct smbcli_state *cli,
|
---|
64 | TALLOC_CTX *tctx,
|
---|
65 | const char *pattern,
|
---|
66 | enum smb_search_level level,
|
---|
67 | enum smb_search_data_level data_level,
|
---|
68 | uint16_t attrib,
|
---|
69 | union smb_search_data *data)
|
---|
70 | {
|
---|
71 | union smb_search_first io;
|
---|
72 | union smb_search_close c;
|
---|
73 | NTSTATUS status;
|
---|
74 |
|
---|
75 | switch (level) {
|
---|
76 | case RAW_SEARCH_SEARCH:
|
---|
77 | case RAW_SEARCH_FFIRST:
|
---|
78 | case RAW_SEARCH_FUNIQUE:
|
---|
79 | io.search_first.level = level;
|
---|
80 | io.search_first.data_level = RAW_SEARCH_DATA_SEARCH;
|
---|
81 | io.search_first.in.max_count = 1;
|
---|
82 | io.search_first.in.search_attrib = attrib;
|
---|
83 | io.search_first.in.pattern = pattern;
|
---|
84 | break;
|
---|
85 |
|
---|
86 | case RAW_SEARCH_TRANS2:
|
---|
87 | io.t2ffirst.level = RAW_SEARCH_TRANS2;
|
---|
88 | io.t2ffirst.data_level = data_level;
|
---|
89 | io.t2ffirst.in.search_attrib = attrib;
|
---|
90 | io.t2ffirst.in.max_count = 1;
|
---|
91 | io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
|
---|
92 | io.t2ffirst.in.storage_type = 0;
|
---|
93 | io.t2ffirst.in.pattern = pattern;
|
---|
94 | break;
|
---|
95 |
|
---|
96 | case RAW_SEARCH_SMB2:
|
---|
97 | return NT_STATUS_INVALID_LEVEL;
|
---|
98 | }
|
---|
99 |
|
---|
100 | status = smb_raw_search_first(cli->tree, tctx,
|
---|
101 | &io, (void *)data, single_search_callback);
|
---|
102 |
|
---|
103 | if (NT_STATUS_IS_OK(status) && level == RAW_SEARCH_FFIRST) {
|
---|
104 | c.fclose.level = RAW_FINDCLOSE_FCLOSE;
|
---|
105 | c.fclose.in.max_count = 1;
|
---|
106 | c.fclose.in.search_attrib = 0;
|
---|
107 | c.fclose.in.id = data->search.id;
|
---|
108 | status = smb_raw_search_close(cli->tree, &c);
|
---|
109 | }
|
---|
110 |
|
---|
111 | return status;
|
---|
112 | }
|
---|
113 |
|
---|
114 |
|
---|
115 | static struct {
|
---|
116 | const char *name;
|
---|
117 | enum smb_search_level level;
|
---|
118 | enum smb_search_data_level data_level;
|
---|
119 | int name_offset;
|
---|
120 | int resume_key_offset;
|
---|
121 | uint32_t capability_mask;
|
---|
122 | NTSTATUS status;
|
---|
123 | union smb_search_data data;
|
---|
124 | } levels[] = {
|
---|
125 | {"FFIRST",
|
---|
126 | RAW_SEARCH_FFIRST, RAW_SEARCH_DATA_SEARCH,
|
---|
127 | offsetof(union smb_search_data, search.name),
|
---|
128 | -1,
|
---|
129 | },
|
---|
130 | {"FUNIQUE",
|
---|
131 | RAW_SEARCH_FUNIQUE, RAW_SEARCH_DATA_SEARCH,
|
---|
132 | offsetof(union smb_search_data, search.name),
|
---|
133 | -1,
|
---|
134 | },
|
---|
135 | {"SEARCH",
|
---|
136 | RAW_SEARCH_SEARCH, RAW_SEARCH_DATA_SEARCH,
|
---|
137 | offsetof(union smb_search_data, search.name),
|
---|
138 | -1,
|
---|
139 | },
|
---|
140 | {"STANDARD",
|
---|
141 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_STANDARD,
|
---|
142 | offsetof(union smb_search_data, standard.name.s),
|
---|
143 | offsetof(union smb_search_data, standard.resume_key),
|
---|
144 | },
|
---|
145 | {"EA_SIZE",
|
---|
146 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_EA_SIZE,
|
---|
147 | offsetof(union smb_search_data, ea_size.name.s),
|
---|
148 | offsetof(union smb_search_data, ea_size.resume_key),
|
---|
149 | },
|
---|
150 | {"DIRECTORY_INFO",
|
---|
151 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_DIRECTORY_INFO,
|
---|
152 | offsetof(union smb_search_data, directory_info.name.s),
|
---|
153 | offsetof(union smb_search_data, directory_info.file_index),
|
---|
154 | },
|
---|
155 | {"FULL_DIRECTORY_INFO",
|
---|
156 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
|
---|
157 | offsetof(union smb_search_data, full_directory_info.name.s),
|
---|
158 | offsetof(union smb_search_data, full_directory_info.file_index),
|
---|
159 | },
|
---|
160 | {"NAME_INFO",
|
---|
161 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_NAME_INFO,
|
---|
162 | offsetof(union smb_search_data, name_info.name.s),
|
---|
163 | offsetof(union smb_search_data, name_info.file_index),
|
---|
164 | },
|
---|
165 | {"BOTH_DIRECTORY_INFO",
|
---|
166 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
|
---|
167 | offsetof(union smb_search_data, both_directory_info.name.s),
|
---|
168 | offsetof(union smb_search_data, both_directory_info.file_index),
|
---|
169 | },
|
---|
170 | {"ID_FULL_DIRECTORY_INFO",
|
---|
171 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO,
|
---|
172 | offsetof(union smb_search_data, id_full_directory_info.name.s),
|
---|
173 | offsetof(union smb_search_data, id_full_directory_info.file_index),
|
---|
174 | },
|
---|
175 | {"ID_BOTH_DIRECTORY_INFO",
|
---|
176 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO,
|
---|
177 | offsetof(union smb_search_data, id_both_directory_info.name.s),
|
---|
178 | offsetof(union smb_search_data, id_both_directory_info.file_index),
|
---|
179 | },
|
---|
180 | {"UNIX_INFO",
|
---|
181 | RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_UNIX_INFO,
|
---|
182 | offsetof(union smb_search_data, unix_info.name),
|
---|
183 | offsetof(union smb_search_data, unix_info.file_index),
|
---|
184 | CAP_UNIX}
|
---|
185 | };
|
---|
186 |
|
---|
187 |
|
---|
188 | /*
|
---|
189 | return level name
|
---|
190 | */
|
---|
191 | static const char *level_name(enum smb_search_level level,
|
---|
192 | enum smb_search_data_level data_level)
|
---|
193 | {
|
---|
194 | int i;
|
---|
195 | for (i=0;i<ARRAY_SIZE(levels);i++) {
|
---|
196 | if (level == levels[i].level &&
|
---|
197 | data_level == levels[i].data_level) {
|
---|
198 | return levels[i].name;
|
---|
199 | }
|
---|
200 | }
|
---|
201 | return NULL;
|
---|
202 | }
|
---|
203 |
|
---|
204 | /*
|
---|
205 | extract the name from a smb_data structure and level
|
---|
206 | */
|
---|
207 | static const char *extract_name(void *data, enum smb_search_level level,
|
---|
208 | enum smb_search_data_level data_level)
|
---|
209 | {
|
---|
210 | int i;
|
---|
211 | for (i=0;i<ARRAY_SIZE(levels);i++) {
|
---|
212 | if (level == levels[i].level &&
|
---|
213 | data_level == levels[i].data_level) {
|
---|
214 | return *(const char **)(levels[i].name_offset + (char *)data);
|
---|
215 | }
|
---|
216 | }
|
---|
217 | return NULL;
|
---|
218 | }
|
---|
219 |
|
---|
220 | /*
|
---|
221 | extract the name from a smb_data structure and level
|
---|
222 | */
|
---|
223 | static uint32_t extract_resume_key(void *data, enum smb_search_level level,
|
---|
224 | enum smb_search_data_level data_level)
|
---|
225 | {
|
---|
226 | int i;
|
---|
227 | for (i=0;i<ARRAY_SIZE(levels);i++) {
|
---|
228 | if (level == levels[i].level &&
|
---|
229 | data_level == levels[i].data_level) {
|
---|
230 | return *(uint32_t *)(levels[i].resume_key_offset + (char *)data);
|
---|
231 | }
|
---|
232 | }
|
---|
233 | return 0;
|
---|
234 | }
|
---|
235 |
|
---|
236 | /* find a level in the table by name */
|
---|
237 | static union smb_search_data *find(const char *name)
|
---|
238 | {
|
---|
239 | int i;
|
---|
240 | for (i=0;i<ARRAY_SIZE(levels);i++) {
|
---|
241 | if (NT_STATUS_IS_OK(levels[i].status) &&
|
---|
242 | strcmp(levels[i].name, name) == 0) {
|
---|
243 | return &levels[i].data;
|
---|
244 | }
|
---|
245 | }
|
---|
246 | return NULL;
|
---|
247 | }
|
---|
248 |
|
---|
249 | /*
|
---|
250 | basic testing of all RAW_SEARCH_* calls using a single file
|
---|
251 | */
|
---|
252 | static bool test_one_file(struct torture_context *tctx,
|
---|
253 | struct smbcli_state *cli)
|
---|
254 | {
|
---|
255 | bool ret = true;
|
---|
256 | int fnum;
|
---|
257 | const char *fname = "\\torture_search.txt";
|
---|
258 | const char *fname2 = "\\torture_search-NOTEXIST.txt";
|
---|
259 | NTSTATUS status;
|
---|
260 | int i;
|
---|
261 | union smb_fileinfo all_info, alt_info, name_info, internal_info;
|
---|
262 | bool all_info_supported, alt_info_supported, name_info_supported,
|
---|
263 | internal_info_supported;
|
---|
264 | union smb_search_data *s;
|
---|
265 |
|
---|
266 | fnum = create_complex_file(cli, tctx, fname);
|
---|
267 | if (fnum == -1) {
|
---|
268 | printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
|
---|
269 | ret = false;
|
---|
270 | goto done;
|
---|
271 | }
|
---|
272 |
|
---|
273 | /* call all the levels */
|
---|
274 | for (i=0;i<ARRAY_SIZE(levels);i++) {
|
---|
275 | NTSTATUS expected_status;
|
---|
276 | uint32_t cap = cli->transport->negotiate.capabilities;
|
---|
277 |
|
---|
278 | torture_comment(tctx, "Testing %s\n", levels[i].name);
|
---|
279 |
|
---|
280 | levels[i].status = torture_single_search(cli, tctx, fname,
|
---|
281 | levels[i].level,
|
---|
282 | levels[i].data_level,
|
---|
283 | 0,
|
---|
284 | &levels[i].data);
|
---|
285 |
|
---|
286 | /* see if this server claims to support this level */
|
---|
287 | if (((cap & levels[i].capability_mask) != levels[i].capability_mask)
|
---|
288 | || NT_STATUS_EQUAL(levels[i].status, NT_STATUS_NOT_SUPPORTED)) {
|
---|
289 | printf("search level %s(%d) not supported by server\n",
|
---|
290 | levels[i].name, (int)levels[i].level);
|
---|
291 | continue;
|
---|
292 | }
|
---|
293 |
|
---|
294 | if (!NT_STATUS_IS_OK(levels[i].status)) {
|
---|
295 | printf("search level %s(%d) failed - %s\n",
|
---|
296 | levels[i].name, (int)levels[i].level,
|
---|
297 | nt_errstr(levels[i].status));
|
---|
298 | ret = false;
|
---|
299 | continue;
|
---|
300 | }
|
---|
301 |
|
---|
302 | status = torture_single_search(cli, tctx, fname2,
|
---|
303 | levels[i].level,
|
---|
304 | levels[i].data_level,
|
---|
305 | 0,
|
---|
306 | &levels[i].data);
|
---|
307 |
|
---|
308 | expected_status = NT_STATUS_NO_SUCH_FILE;
|
---|
309 | if (levels[i].level == RAW_SEARCH_SEARCH ||
|
---|
310 | levels[i].level == RAW_SEARCH_FFIRST ||
|
---|
311 | levels[i].level == RAW_SEARCH_FUNIQUE) {
|
---|
312 | expected_status = STATUS_NO_MORE_FILES;
|
---|
313 | }
|
---|
314 | if (!NT_STATUS_EQUAL(status, expected_status)) {
|
---|
315 | printf("search level %s(%d) should fail with %s - %s\n",
|
---|
316 | levels[i].name, (int)levels[i].level,
|
---|
317 | nt_errstr(expected_status),
|
---|
318 | nt_errstr(status));
|
---|
319 | ret = false;
|
---|
320 | }
|
---|
321 | }
|
---|
322 |
|
---|
323 | /* get the all_info file into to check against */
|
---|
324 | all_info.generic.level = RAW_FILEINFO_ALL_INFO;
|
---|
325 | all_info.generic.in.file.path = fname;
|
---|
326 | status = smb_raw_pathinfo(cli->tree, tctx, &all_info);
|
---|
327 | CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_ALL_INFO",
|
---|
328 | all_info_supported);
|
---|
329 |
|
---|
330 | alt_info.generic.level = RAW_FILEINFO_ALT_NAME_INFO;
|
---|
331 | alt_info.generic.in.file.path = fname;
|
---|
332 | status = smb_raw_pathinfo(cli->tree, tctx, &alt_info);
|
---|
333 | CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_ALT_NAME_INFO",
|
---|
334 | alt_info_supported);
|
---|
335 |
|
---|
336 | internal_info.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
|
---|
337 | internal_info.generic.in.file.path = fname;
|
---|
338 | status = smb_raw_pathinfo(cli->tree, tctx, &internal_info);
|
---|
339 | CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_INTERNAL_INFORMATION",
|
---|
340 | internal_info_supported);
|
---|
341 |
|
---|
342 | name_info.generic.level = RAW_FILEINFO_NAME_INFO;
|
---|
343 | name_info.generic.in.file.path = fname;
|
---|
344 | status = smb_raw_pathinfo(cli->tree, tctx, &name_info);
|
---|
345 | CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_NAME_INFO",
|
---|
346 | name_info_supported);
|
---|
347 |
|
---|
348 | #define CHECK_VAL(name, sname1, field1, v, sname2, field2) do { \
|
---|
349 | s = find(name); \
|
---|
350 | if (s) { \
|
---|
351 | if ((s->sname1.field1) != (v.sname2.out.field2)) { \
|
---|
352 | printf("(%s) %s/%s [0x%x] != %s/%s [0x%x]\n", \
|
---|
353 | __location__, \
|
---|
354 | #sname1, #field1, (int)s->sname1.field1, \
|
---|
355 | #sname2, #field2, (int)v.sname2.out.field2); \
|
---|
356 | ret = false; \
|
---|
357 | } \
|
---|
358 | }} while (0)
|
---|
359 |
|
---|
360 | #define CHECK_TIME(name, sname1, field1, v, sname2, field2) do { \
|
---|
361 | s = find(name); \
|
---|
362 | if (s) { \
|
---|
363 | if (s->sname1.field1 != (~1 & nt_time_to_unix(v.sname2.out.field2))) { \
|
---|
364 | printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
|
---|
365 | __location__, \
|
---|
366 | #sname1, #field1, timestring(tctx, s->sname1.field1), \
|
---|
367 | #sname2, #field2, nt_time_string(tctx, v.sname2.out.field2)); \
|
---|
368 | ret = false; \
|
---|
369 | } \
|
---|
370 | }} while (0)
|
---|
371 |
|
---|
372 | #define CHECK_NTTIME(name, sname1, field1, v, sname2, field2) do { \
|
---|
373 | s = find(name); \
|
---|
374 | if (s) { \
|
---|
375 | if (s->sname1.field1 != v.sname2.out.field2) { \
|
---|
376 | printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
|
---|
377 | __location__, \
|
---|
378 | #sname1, #field1, nt_time_string(tctx, s->sname1.field1), \
|
---|
379 | #sname2, #field2, nt_time_string(tctx, v.sname2.out.field2)); \
|
---|
380 | ret = false; \
|
---|
381 | } \
|
---|
382 | }} while (0)
|
---|
383 |
|
---|
384 | #define CHECK_STR(name, sname1, field1, v, sname2, field2) do { \
|
---|
385 | s = find(name); \
|
---|
386 | if (s) { \
|
---|
387 | if (!s->sname1.field1 || strcmp(s->sname1.field1, v.sname2.out.field2.s)) { \
|
---|
388 | printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
|
---|
389 | __location__, \
|
---|
390 | #sname1, #field1, s->sname1.field1, \
|
---|
391 | #sname2, #field2, v.sname2.out.field2.s); \
|
---|
392 | ret = false; \
|
---|
393 | } \
|
---|
394 | }} while (0)
|
---|
395 |
|
---|
396 | #define CHECK_WSTR(name, sname1, field1, v, sname2, field2, flags) do { \
|
---|
397 | s = find(name); \
|
---|
398 | if (s) { \
|
---|
399 | if (!s->sname1.field1.s || \
|
---|
400 | strcmp(s->sname1.field1.s, v.sname2.out.field2.s) || \
|
---|
401 | wire_bad_flags(&s->sname1.field1, flags, cli->transport)) { \
|
---|
402 | printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
|
---|
403 | __location__, \
|
---|
404 | #sname1, #field1, s->sname1.field1.s, \
|
---|
405 | #sname2, #field2, v.sname2.out.field2.s); \
|
---|
406 | ret = false; \
|
---|
407 | } \
|
---|
408 | }} while (0)
|
---|
409 |
|
---|
410 | #define CHECK_NAME(name, sname1, field1, fname, flags) do { \
|
---|
411 | s = find(name); \
|
---|
412 | if (s) { \
|
---|
413 | if (!s->sname1.field1.s || \
|
---|
414 | strcmp(s->sname1.field1.s, fname) || \
|
---|
415 | wire_bad_flags(&s->sname1.field1, flags, cli->transport)) { \
|
---|
416 | printf("(%s) %s/%s [%s] != %s\n", \
|
---|
417 | __location__, \
|
---|
418 | #sname1, #field1, s->sname1.field1.s, \
|
---|
419 | fname); \
|
---|
420 | ret = false; \
|
---|
421 | } \
|
---|
422 | }} while (0)
|
---|
423 |
|
---|
424 | #define CHECK_UNIX_NAME(name, sname1, field1, fname, flags) do { \
|
---|
425 | s = find(name); \
|
---|
426 | if (s) { \
|
---|
427 | if (!s->sname1.field1 || \
|
---|
428 | strcmp(s->sname1.field1, fname)) { \
|
---|
429 | printf("(%s) %s/%s [%s] != %s\n", \
|
---|
430 | __location__, \
|
---|
431 | #sname1, #field1, s->sname1.field1, \
|
---|
432 | fname); \
|
---|
433 | ret = false; \
|
---|
434 | } \
|
---|
435 | }} while (0)
|
---|
436 |
|
---|
437 | /* check that all the results are as expected */
|
---|
438 | CHECK_VAL("SEARCH", search, attrib, all_info, all_info, attrib&0xFFF);
|
---|
439 | CHECK_VAL("STANDARD", standard, attrib, all_info, all_info, attrib&0xFFF);
|
---|
440 | CHECK_VAL("EA_SIZE", ea_size, attrib, all_info, all_info, attrib&0xFFF);
|
---|
441 | CHECK_VAL("DIRECTORY_INFO", directory_info, attrib, all_info, all_info, attrib);
|
---|
442 | CHECK_VAL("FULL_DIRECTORY_INFO", full_directory_info, attrib, all_info, all_info, attrib);
|
---|
443 | CHECK_VAL("BOTH_DIRECTORY_INFO", both_directory_info, attrib, all_info, all_info, attrib);
|
---|
444 | CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info, attrib, all_info, all_info, attrib);
|
---|
445 | CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, attrib, all_info, all_info, attrib);
|
---|
446 |
|
---|
447 | CHECK_TIME("SEARCH", search, write_time, all_info, all_info, write_time);
|
---|
448 | CHECK_TIME("STANDARD", standard, write_time, all_info, all_info, write_time);
|
---|
449 | CHECK_TIME("EA_SIZE", ea_size, write_time, all_info, all_info, write_time);
|
---|
450 | CHECK_TIME("STANDARD", standard, create_time, all_info, all_info, create_time);
|
---|
451 | CHECK_TIME("EA_SIZE", ea_size, create_time, all_info, all_info, create_time);
|
---|
452 | CHECK_TIME("STANDARD", standard, access_time, all_info, all_info, access_time);
|
---|
453 | CHECK_TIME("EA_SIZE", ea_size, access_time, all_info, all_info, access_time);
|
---|
454 |
|
---|
455 | CHECK_NTTIME("DIRECTORY_INFO", directory_info, write_time, all_info, all_info, write_time);
|
---|
456 | CHECK_NTTIME("FULL_DIRECTORY_INFO", full_directory_info, write_time, all_info, all_info, write_time);
|
---|
457 | CHECK_NTTIME("BOTH_DIRECTORY_INFO", both_directory_info, write_time, all_info, all_info, write_time);
|
---|
458 | CHECK_NTTIME("ID_FULL_DIRECTORY_INFO", id_full_directory_info, write_time, all_info, all_info, write_time);
|
---|
459 | CHECK_NTTIME("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, write_time, all_info, all_info, write_time);
|
---|
460 |
|
---|
461 | CHECK_NTTIME("DIRECTORY_INFO", directory_info, create_time, all_info, all_info, create_time);
|
---|
462 | CHECK_NTTIME("FULL_DIRECTORY_INFO", full_directory_info, create_time, all_info, all_info, create_time);
|
---|
463 | CHECK_NTTIME("BOTH_DIRECTORY_INFO", both_directory_info, create_time, all_info, all_info, create_time);
|
---|
464 | CHECK_NTTIME("ID_FULL_DIRECTORY_INFO", id_full_directory_info, create_time, all_info, all_info, create_time);
|
---|
465 | CHECK_NTTIME("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, create_time, all_info, all_info, create_time);
|
---|
466 |
|
---|
467 | CHECK_NTTIME("DIRECTORY_INFO", directory_info, access_time, all_info, all_info, access_time);
|
---|
468 | CHECK_NTTIME("FULL_DIRECTORY_INFO", full_directory_info, access_time, all_info, all_info, access_time);
|
---|
469 | CHECK_NTTIME("BOTH_DIRECTORY_INFO", both_directory_info, access_time, all_info, all_info, access_time);
|
---|
470 | CHECK_NTTIME("ID_FULL_DIRECTORY_INFO", id_full_directory_info, access_time, all_info, all_info, access_time);
|
---|
471 | CHECK_NTTIME("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, access_time, all_info, all_info, access_time);
|
---|
472 |
|
---|
473 | CHECK_NTTIME("DIRECTORY_INFO", directory_info, change_time, all_info, all_info, change_time);
|
---|
474 | CHECK_NTTIME("FULL_DIRECTORY_INFO", full_directory_info, change_time, all_info, all_info, change_time);
|
---|
475 | CHECK_NTTIME("BOTH_DIRECTORY_INFO", both_directory_info, change_time, all_info, all_info, change_time);
|
---|
476 | CHECK_NTTIME("ID_FULL_DIRECTORY_INFO", id_full_directory_info, change_time, all_info, all_info, change_time);
|
---|
477 | CHECK_NTTIME("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, change_time, all_info, all_info, change_time);
|
---|
478 |
|
---|
479 | CHECK_VAL("SEARCH", search, size, all_info, all_info, size);
|
---|
480 | CHECK_VAL("STANDARD", standard, size, all_info, all_info, size);
|
---|
481 | CHECK_VAL("EA_SIZE", ea_size, size, all_info, all_info, size);
|
---|
482 | CHECK_VAL("DIRECTORY_INFO", directory_info, size, all_info, all_info, size);
|
---|
483 | CHECK_VAL("FULL_DIRECTORY_INFO", full_directory_info, size, all_info, all_info, size);
|
---|
484 | CHECK_VAL("BOTH_DIRECTORY_INFO", both_directory_info, size, all_info, all_info, size);
|
---|
485 | CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info, size, all_info, all_info, size);
|
---|
486 | CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, size, all_info, all_info, size);
|
---|
487 | CHECK_VAL("UNIX_INFO", unix_info, size, all_info, all_info, size);
|
---|
488 |
|
---|
489 | CHECK_VAL("STANDARD", standard, alloc_size, all_info, all_info, alloc_size);
|
---|
490 | CHECK_VAL("EA_SIZE", ea_size, alloc_size, all_info, all_info, alloc_size);
|
---|
491 | CHECK_VAL("DIRECTORY_INFO", directory_info, alloc_size, all_info, all_info, alloc_size);
|
---|
492 | CHECK_VAL("FULL_DIRECTORY_INFO", full_directory_info, alloc_size, all_info, all_info, alloc_size);
|
---|
493 | CHECK_VAL("BOTH_DIRECTORY_INFO", both_directory_info, alloc_size, all_info, all_info, alloc_size);
|
---|
494 | CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info, alloc_size, all_info, all_info, alloc_size);
|
---|
495 | CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, alloc_size, all_info, all_info, alloc_size);
|
---|
496 | CHECK_VAL("UNIX_INFO", unix_info, alloc_size, all_info, all_info, alloc_size);
|
---|
497 |
|
---|
498 | CHECK_VAL("EA_SIZE", ea_size, ea_size, all_info, all_info, ea_size);
|
---|
499 | CHECK_VAL("FULL_DIRECTORY_INFO", full_directory_info, ea_size, all_info, all_info, ea_size);
|
---|
500 | CHECK_VAL("BOTH_DIRECTORY_INFO", both_directory_info, ea_size, all_info, all_info, ea_size);
|
---|
501 | CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info, ea_size, all_info, all_info, ea_size);
|
---|
502 | CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, ea_size, all_info, all_info, ea_size);
|
---|
503 |
|
---|
504 | if (alt_info_supported) {
|
---|
505 | CHECK_STR("SEARCH", search, name, alt_info, alt_name_info,
|
---|
506 | fname);
|
---|
507 | CHECK_WSTR("BOTH_DIRECTORY_INFO", both_directory_info,
|
---|
508 | short_name, alt_info, alt_name_info, fname, STR_UNICODE);
|
---|
509 | }
|
---|
510 |
|
---|
511 | CHECK_NAME("STANDARD", standard, name, fname+1, 0);
|
---|
512 | CHECK_NAME("EA_SIZE", ea_size, name, fname+1, 0);
|
---|
513 | CHECK_NAME("DIRECTORY_INFO", directory_info, name, fname+1, STR_TERMINATE_ASCII);
|
---|
514 | CHECK_NAME("FULL_DIRECTORY_INFO", full_directory_info, name, fname+1, STR_TERMINATE_ASCII);
|
---|
515 |
|
---|
516 | if (name_info_supported) {
|
---|
517 | CHECK_NAME("NAME_INFO", name_info, name, fname+1,
|
---|
518 | STR_TERMINATE_ASCII);
|
---|
519 | }
|
---|
520 |
|
---|
521 | CHECK_NAME("BOTH_DIRECTORY_INFO", both_directory_info, name, fname+1, STR_TERMINATE_ASCII);
|
---|
522 | CHECK_NAME("ID_FULL_DIRECTORY_INFO", id_full_directory_info, name, fname+1, STR_TERMINATE_ASCII);
|
---|
523 | CHECK_NAME("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, name, fname+1, STR_TERMINATE_ASCII);
|
---|
524 | CHECK_UNIX_NAME("UNIX_INFO", unix_info, name, fname+1, STR_TERMINATE_ASCII);
|
---|
525 |
|
---|
526 | if (internal_info_supported) {
|
---|
527 | CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info,
|
---|
528 | file_id, internal_info, internal_information, file_id);
|
---|
529 | CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info,
|
---|
530 | file_id, internal_info, internal_information, file_id);
|
---|
531 | }
|
---|
532 |
|
---|
533 | done:
|
---|
534 | smb_raw_exit(cli->session);
|
---|
535 | smbcli_unlink(cli->tree, fname);
|
---|
536 |
|
---|
537 | return ret;
|
---|
538 | }
|
---|
539 |
|
---|
540 |
|
---|
541 | struct multiple_result {
|
---|
542 | TALLOC_CTX *tctx;
|
---|
543 | int count;
|
---|
544 | union smb_search_data *list;
|
---|
545 | };
|
---|
546 |
|
---|
547 | /*
|
---|
548 | callback function for multiple_search
|
---|
549 | */
|
---|
550 | static bool multiple_search_callback(void *private_data, const union smb_search_data *file)
|
---|
551 | {
|
---|
552 | struct multiple_result *data = (struct multiple_result *)private_data;
|
---|
553 |
|
---|
554 |
|
---|
555 | data->count++;
|
---|
556 | data->list = talloc_realloc(data->tctx,
|
---|
557 | data->list,
|
---|
558 | union smb_search_data,
|
---|
559 | data->count);
|
---|
560 |
|
---|
561 | data->list[data->count-1] = *file;
|
---|
562 |
|
---|
563 | return true;
|
---|
564 | }
|
---|
565 |
|
---|
566 | enum continue_type {CONT_FLAGS, CONT_NAME, CONT_RESUME_KEY};
|
---|
567 |
|
---|
568 | /*
|
---|
569 | do a single file (non-wildcard) search
|
---|
570 | */
|
---|
571 | static NTSTATUS multiple_search(struct smbcli_state *cli,
|
---|
572 | TALLOC_CTX *tctx,
|
---|
573 | const char *pattern,
|
---|
574 | enum smb_search_data_level data_level,
|
---|
575 | enum continue_type cont_type,
|
---|
576 | void *data)
|
---|
577 | {
|
---|
578 | union smb_search_first io;
|
---|
579 | union smb_search_next io2;
|
---|
580 | NTSTATUS status;
|
---|
581 | const int per_search = 100;
|
---|
582 | struct multiple_result *result = (struct multiple_result *)data;
|
---|
583 |
|
---|
584 | if (data_level == RAW_SEARCH_DATA_SEARCH) {
|
---|
585 | io.search_first.level = RAW_SEARCH_SEARCH;
|
---|
586 | io.search_first.data_level = RAW_SEARCH_DATA_SEARCH;
|
---|
587 | io.search_first.in.max_count = per_search;
|
---|
588 | io.search_first.in.search_attrib = 0;
|
---|
589 | io.search_first.in.pattern = pattern;
|
---|
590 | } else {
|
---|
591 | io.t2ffirst.level = RAW_SEARCH_TRANS2;
|
---|
592 | io.t2ffirst.data_level = data_level;
|
---|
593 | io.t2ffirst.in.search_attrib = 0;
|
---|
594 | io.t2ffirst.in.max_count = per_search;
|
---|
595 | io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE_IF_END;
|
---|
596 | io.t2ffirst.in.storage_type = 0;
|
---|
597 | io.t2ffirst.in.pattern = pattern;
|
---|
598 | if (cont_type == CONT_RESUME_KEY) {
|
---|
599 | io.t2ffirst.in.flags |= FLAG_TRANS2_FIND_REQUIRE_RESUME |
|
---|
600 | FLAG_TRANS2_FIND_BACKUP_INTENT;
|
---|
601 | }
|
---|
602 | }
|
---|
603 |
|
---|
604 | status = smb_raw_search_first(cli->tree, tctx,
|
---|
605 | &io, data, multiple_search_callback);
|
---|
606 |
|
---|
607 |
|
---|
608 | while (NT_STATUS_IS_OK(status)) {
|
---|
609 | if (data_level == RAW_SEARCH_DATA_SEARCH) {
|
---|
610 | io2.search_next.level = RAW_SEARCH_SEARCH;
|
---|
611 | io2.search_next.data_level = RAW_SEARCH_DATA_SEARCH;
|
---|
612 | io2.search_next.in.max_count = per_search;
|
---|
613 | io2.search_next.in.search_attrib = 0;
|
---|
614 | io2.search_next.in.id = result->list[result->count-1].search.id;
|
---|
615 | } else {
|
---|
616 | io2.t2fnext.level = RAW_SEARCH_TRANS2;
|
---|
617 | io2.t2fnext.data_level = data_level;
|
---|
618 | io2.t2fnext.in.handle = io.t2ffirst.out.handle;
|
---|
619 | io2.t2fnext.in.max_count = per_search;
|
---|
620 | io2.t2fnext.in.resume_key = 0;
|
---|
621 | io2.t2fnext.in.flags = FLAG_TRANS2_FIND_CLOSE_IF_END;
|
---|
622 | io2.t2fnext.in.last_name = "";
|
---|
623 | switch (cont_type) {
|
---|
624 | case CONT_RESUME_KEY:
|
---|
625 | io2.t2fnext.in.resume_key = extract_resume_key(&result->list[result->count-1],
|
---|
626 | io2.t2fnext.level, io2.t2fnext.data_level);
|
---|
627 | if (io2.t2fnext.in.resume_key == 0) {
|
---|
628 | printf("Server does not support resume by key for level %s\n",
|
---|
629 | level_name(io2.t2fnext.level, io2.t2fnext.data_level));
|
---|
630 | return NT_STATUS_NOT_SUPPORTED;
|
---|
631 | }
|
---|
632 | io2.t2fnext.in.flags |= FLAG_TRANS2_FIND_REQUIRE_RESUME |
|
---|
633 | FLAG_TRANS2_FIND_BACKUP_INTENT;
|
---|
634 | break;
|
---|
635 | case CONT_NAME:
|
---|
636 | io2.t2fnext.in.last_name = extract_name(&result->list[result->count-1],
|
---|
637 | io2.t2fnext.level, io2.t2fnext.data_level);
|
---|
638 | break;
|
---|
639 | case CONT_FLAGS:
|
---|
640 | io2.t2fnext.in.flags |= FLAG_TRANS2_FIND_CONTINUE;
|
---|
641 | break;
|
---|
642 | }
|
---|
643 | }
|
---|
644 |
|
---|
645 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
646 | &io2, data, multiple_search_callback);
|
---|
647 | if (!NT_STATUS_IS_OK(status)) {
|
---|
648 | break;
|
---|
649 | }
|
---|
650 | if (data_level == RAW_SEARCH_DATA_SEARCH) {
|
---|
651 | if (io2.search_next.out.count == 0) {
|
---|
652 | break;
|
---|
653 | }
|
---|
654 | } else if (io2.t2fnext.out.count == 0 ||
|
---|
655 | io2.t2fnext.out.end_of_search) {
|
---|
656 | break;
|
---|
657 | }
|
---|
658 | }
|
---|
659 |
|
---|
660 | return status;
|
---|
661 | }
|
---|
662 |
|
---|
663 | #define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status")
|
---|
664 |
|
---|
665 | #define CHECK_VALUE(v, correct) torture_assert_int_equal(tctx, (v), (correct), "incorrect value");
|
---|
666 |
|
---|
667 | #define CHECK_STRING(v, correct) torture_assert_casestr_equal(tctx, v, correct, "incorrect value");
|
---|
668 |
|
---|
669 |
|
---|
670 | static enum smb_search_data_level compare_data_level;
|
---|
671 |
|
---|
672 | static int search_compare(union smb_search_data *d1, union smb_search_data *d2)
|
---|
673 | {
|
---|
674 | const char *s1, *s2;
|
---|
675 | enum smb_search_level level;
|
---|
676 |
|
---|
677 | if (compare_data_level == RAW_SEARCH_DATA_SEARCH) {
|
---|
678 | level = RAW_SEARCH_SEARCH;
|
---|
679 | } else {
|
---|
680 | level = RAW_SEARCH_TRANS2;
|
---|
681 | }
|
---|
682 |
|
---|
683 | s1 = extract_name(d1, level, compare_data_level);
|
---|
684 | s2 = extract_name(d2, level, compare_data_level);
|
---|
685 | return strcmp_safe(s1, s2);
|
---|
686 | }
|
---|
687 |
|
---|
688 |
|
---|
689 |
|
---|
690 | /*
|
---|
691 | basic testing of search calls using many files
|
---|
692 | */
|
---|
693 | static bool test_many_files(struct torture_context *tctx,
|
---|
694 | struct smbcli_state *cli)
|
---|
695 | {
|
---|
696 | const int num_files = 700;
|
---|
697 | int i, fnum, t;
|
---|
698 | char *fname;
|
---|
699 | bool ret = true;
|
---|
700 | NTSTATUS status;
|
---|
701 | struct multiple_result result;
|
---|
702 | struct {
|
---|
703 | const char *name;
|
---|
704 | const char *cont_name;
|
---|
705 | enum smb_search_data_level data_level;
|
---|
706 | enum continue_type cont_type;
|
---|
707 | } search_types[] = {
|
---|
708 | {"SEARCH", "ID", RAW_SEARCH_DATA_SEARCH, CONT_RESUME_KEY},
|
---|
709 | {"BOTH_DIRECTORY_INFO", "NAME", RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, CONT_NAME},
|
---|
710 | {"BOTH_DIRECTORY_INFO", "FLAGS", RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, CONT_FLAGS},
|
---|
711 | {"BOTH_DIRECTORY_INFO", "KEY", RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, CONT_RESUME_KEY},
|
---|
712 | {"STANDARD", "FLAGS", RAW_SEARCH_DATA_STANDARD, CONT_FLAGS},
|
---|
713 | {"STANDARD", "KEY", RAW_SEARCH_DATA_STANDARD, CONT_RESUME_KEY},
|
---|
714 | {"STANDARD", "NAME", RAW_SEARCH_DATA_STANDARD, CONT_NAME},
|
---|
715 | {"EA_SIZE", "FLAGS", RAW_SEARCH_DATA_EA_SIZE, CONT_FLAGS},
|
---|
716 | {"EA_SIZE", "KEY", RAW_SEARCH_DATA_EA_SIZE, CONT_RESUME_KEY},
|
---|
717 | {"EA_SIZE", "NAME", RAW_SEARCH_DATA_EA_SIZE, CONT_NAME},
|
---|
718 | {"DIRECTORY_INFO", "FLAGS", RAW_SEARCH_DATA_DIRECTORY_INFO, CONT_FLAGS},
|
---|
719 | {"DIRECTORY_INFO", "KEY", RAW_SEARCH_DATA_DIRECTORY_INFO, CONT_RESUME_KEY},
|
---|
720 | {"DIRECTORY_INFO", "NAME", RAW_SEARCH_DATA_DIRECTORY_INFO, CONT_NAME},
|
---|
721 | {"FULL_DIRECTORY_INFO", "FLAGS", RAW_SEARCH_DATA_FULL_DIRECTORY_INFO, CONT_FLAGS},
|
---|
722 | {"FULL_DIRECTORY_INFO", "KEY", RAW_SEARCH_DATA_FULL_DIRECTORY_INFO, CONT_RESUME_KEY},
|
---|
723 | {"FULL_DIRECTORY_INFO", "NAME", RAW_SEARCH_DATA_FULL_DIRECTORY_INFO, CONT_NAME},
|
---|
724 | {"ID_FULL_DIRECTORY_INFO", "FLAGS", RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO, CONT_FLAGS},
|
---|
725 | {"ID_FULL_DIRECTORY_INFO", "KEY", RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO, CONT_RESUME_KEY},
|
---|
726 | {"ID_FULL_DIRECTORY_INFO", "NAME", RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO, CONT_NAME},
|
---|
727 | {"ID_BOTH_DIRECTORY_INFO", "NAME", RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO, CONT_NAME},
|
---|
728 | {"ID_BOTH_DIRECTORY_INFO", "FLAGS", RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO, CONT_FLAGS},
|
---|
729 | {"ID_BOTH_DIRECTORY_INFO", "KEY", RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO, CONT_RESUME_KEY}
|
---|
730 | };
|
---|
731 |
|
---|
732 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
733 | return false;
|
---|
734 | }
|
---|
735 |
|
---|
736 | torture_comment(tctx, "Testing with %d files\n", num_files);
|
---|
737 |
|
---|
738 | for (i=0;i<num_files;i++) {
|
---|
739 | fname = talloc_asprintf(cli, BASEDIR "\\t%03d-%d.txt", i, i);
|
---|
740 | fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
741 | torture_assert(tctx, fnum != -1, "Failed to create");
|
---|
742 | talloc_free(fname);
|
---|
743 | smbcli_close(cli->tree, fnum);
|
---|
744 | }
|
---|
745 |
|
---|
746 |
|
---|
747 | for (t=0;t<ARRAY_SIZE(search_types);t++) {
|
---|
748 | ZERO_STRUCT(result);
|
---|
749 |
|
---|
750 | if ((search_types[t].cont_type == CONT_RESUME_KEY) &&
|
---|
751 | (search_types[t].data_level != RAW_SEARCH_DATA_SEARCH) &&
|
---|
752 | !torture_setting_bool(tctx, "resume_key_support", true)) {
|
---|
753 | torture_comment(tctx,
|
---|
754 | "SKIP: Continue %s via %s\n",
|
---|
755 | search_types[t].name, search_types[t].cont_name);
|
---|
756 | continue;
|
---|
757 | }
|
---|
758 |
|
---|
759 | result.tctx = talloc_new(tctx);
|
---|
760 |
|
---|
761 | torture_comment(tctx,
|
---|
762 | "Continue %s via %s\n", search_types[t].name, search_types[t].cont_name);
|
---|
763 |
|
---|
764 | status = multiple_search(cli, tctx, BASEDIR "\\*.*",
|
---|
765 | search_types[t].data_level,
|
---|
766 | search_types[t].cont_type,
|
---|
767 | &result);
|
---|
768 | if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
|
---|
769 | torture_warning(tctx, "search level %s not supported "
|
---|
770 | "by server",
|
---|
771 | search_types[t].name);
|
---|
772 | continue;
|
---|
773 | }
|
---|
774 | torture_assert_ntstatus_ok(tctx, status, "search failed");
|
---|
775 | CHECK_VALUE(result.count, num_files);
|
---|
776 |
|
---|
777 | compare_data_level = search_types[t].data_level;
|
---|
778 |
|
---|
779 | TYPESAFE_QSORT(result.list, result.count, search_compare);
|
---|
780 |
|
---|
781 | for (i=0;i<result.count;i++) {
|
---|
782 | const char *s;
|
---|
783 | enum smb_search_level level;
|
---|
784 | if (compare_data_level == RAW_SEARCH_DATA_SEARCH) {
|
---|
785 | level = RAW_SEARCH_SEARCH;
|
---|
786 | } else {
|
---|
787 | level = RAW_SEARCH_TRANS2;
|
---|
788 | }
|
---|
789 | s = extract_name(&result.list[i], level, compare_data_level);
|
---|
790 | fname = talloc_asprintf(cli, "t%03d-%d.txt", i, i);
|
---|
791 | torture_assert_str_equal(tctx, fname, s, "Incorrect name");
|
---|
792 | talloc_free(fname);
|
---|
793 | }
|
---|
794 | talloc_free(result.tctx);
|
---|
795 | }
|
---|
796 |
|
---|
797 | smb_raw_exit(cli->session);
|
---|
798 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
799 |
|
---|
800 | return ret;
|
---|
801 | }
|
---|
802 |
|
---|
803 | /*
|
---|
804 | check a individual file result
|
---|
805 | */
|
---|
806 | static bool check_result(struct multiple_result *result, const char *name, bool exist, uint32_t attrib)
|
---|
807 | {
|
---|
808 | int i;
|
---|
809 | for (i=0;i<result->count;i++) {
|
---|
810 | if (strcmp(name, result->list[i].both_directory_info.name.s) == 0) break;
|
---|
811 | }
|
---|
812 | if (i == result->count) {
|
---|
813 | if (exist) {
|
---|
814 | printf("failed: '%s' should exist with attribute %s\n",
|
---|
815 | name, attrib_string(result->list, attrib));
|
---|
816 | return false;
|
---|
817 | }
|
---|
818 | return true;
|
---|
819 | }
|
---|
820 |
|
---|
821 | if (!exist) {
|
---|
822 | printf("failed: '%s' should NOT exist (has attribute %s)\n",
|
---|
823 | name, attrib_string(result->list, result->list[i].both_directory_info.attrib));
|
---|
824 | return false;
|
---|
825 | }
|
---|
826 |
|
---|
827 | if ((result->list[i].both_directory_info.attrib&0xFFF) != attrib) {
|
---|
828 | printf("failed: '%s' should have attribute 0x%x (has 0x%x)\n",
|
---|
829 | name,
|
---|
830 | attrib, result->list[i].both_directory_info.attrib);
|
---|
831 | return false;
|
---|
832 | }
|
---|
833 | return true;
|
---|
834 | }
|
---|
835 |
|
---|
836 | /*
|
---|
837 | test what happens when the directory is modified during a search
|
---|
838 | */
|
---|
839 | static bool test_modify_search(struct torture_context *tctx,
|
---|
840 | struct smbcli_state *cli)
|
---|
841 | {
|
---|
842 | const int num_files = 20;
|
---|
843 | int i, fnum;
|
---|
844 | char *fname;
|
---|
845 | bool ret = true;
|
---|
846 | NTSTATUS status;
|
---|
847 | struct multiple_result result;
|
---|
848 | union smb_search_first io;
|
---|
849 | union smb_search_next io2;
|
---|
850 | union smb_setfileinfo sfinfo;
|
---|
851 |
|
---|
852 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
853 | return false;
|
---|
854 | }
|
---|
855 |
|
---|
856 | printf("Creating %d files\n", num_files);
|
---|
857 |
|
---|
858 | for (i=num_files-1;i>=0;i--) {
|
---|
859 | fname = talloc_asprintf(cli, BASEDIR "\\t%03d-%d.txt", i, i);
|
---|
860 | fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
861 | if (fnum == -1) {
|
---|
862 | printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
|
---|
863 | ret = false;
|
---|
864 | goto done;
|
---|
865 | }
|
---|
866 | talloc_free(fname);
|
---|
867 | smbcli_close(cli->tree, fnum);
|
---|
868 | }
|
---|
869 |
|
---|
870 | printf("pulling the first file\n");
|
---|
871 | ZERO_STRUCT(result);
|
---|
872 | result.tctx = talloc_new(tctx);
|
---|
873 |
|
---|
874 | io.t2ffirst.level = RAW_SEARCH_TRANS2;
|
---|
875 | io.t2ffirst.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
|
---|
876 | io.t2ffirst.in.search_attrib = 0;
|
---|
877 | io.t2ffirst.in.max_count = 0;
|
---|
878 | io.t2ffirst.in.flags = 0;
|
---|
879 | io.t2ffirst.in.storage_type = 0;
|
---|
880 | io.t2ffirst.in.pattern = BASEDIR "\\*.*";
|
---|
881 |
|
---|
882 | status = smb_raw_search_first(cli->tree, tctx,
|
---|
883 | &io, &result, multiple_search_callback);
|
---|
884 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
885 | CHECK_VALUE(result.count, 1);
|
---|
886 |
|
---|
887 | printf("pulling the second file\n");
|
---|
888 | io2.t2fnext.level = RAW_SEARCH_TRANS2;
|
---|
889 | io2.t2fnext.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
|
---|
890 | io2.t2fnext.in.handle = io.t2ffirst.out.handle;
|
---|
891 | io2.t2fnext.in.max_count = 1;
|
---|
892 | io2.t2fnext.in.resume_key = 0;
|
---|
893 | io2.t2fnext.in.flags = 0;
|
---|
894 | io2.t2fnext.in.last_name = result.list[result.count-1].both_directory_info.name.s;
|
---|
895 |
|
---|
896 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
897 | &io2, &result, multiple_search_callback);
|
---|
898 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
899 | CHECK_VALUE(result.count, 2);
|
---|
900 |
|
---|
901 | result.count = 0;
|
---|
902 |
|
---|
903 | printf("Changing attributes and deleting\n");
|
---|
904 | smbcli_open(cli->tree, BASEDIR "\\T003-03.txt.2", O_CREAT|O_RDWR, DENY_NONE);
|
---|
905 | smbcli_open(cli->tree, BASEDIR "\\T013-13.txt.2", O_CREAT|O_RDWR, DENY_NONE);
|
---|
906 | fnum = create_complex_file(cli, tctx, BASEDIR "\\T013-13.txt.3");
|
---|
907 | smbcli_unlink(cli->tree, BASEDIR "\\T014-14.txt");
|
---|
908 | torture_set_file_attribute(cli->tree, BASEDIR "\\T015-15.txt", FILE_ATTRIBUTE_HIDDEN);
|
---|
909 | torture_set_file_attribute(cli->tree, BASEDIR "\\T016-16.txt", FILE_ATTRIBUTE_NORMAL);
|
---|
910 | torture_set_file_attribute(cli->tree, BASEDIR "\\T017-17.txt", FILE_ATTRIBUTE_SYSTEM);
|
---|
911 | torture_set_file_attribute(cli->tree, BASEDIR "\\T018-18.txt", 0);
|
---|
912 | sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
|
---|
913 | sfinfo.generic.in.file.fnum = fnum;
|
---|
914 | sfinfo.disposition_info.in.delete_on_close = 1;
|
---|
915 | status = smb_raw_setfileinfo(cli->tree, &sfinfo);
|
---|
916 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
917 |
|
---|
918 | io2.t2fnext.level = RAW_SEARCH_TRANS2;
|
---|
919 | io2.t2fnext.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
|
---|
920 | io2.t2fnext.in.handle = io.t2ffirst.out.handle;
|
---|
921 | io2.t2fnext.in.max_count = num_files + 3;
|
---|
922 | io2.t2fnext.in.resume_key = 0;
|
---|
923 | io2.t2fnext.in.flags = 0;
|
---|
924 | io2.t2fnext.in.last_name = ".";
|
---|
925 |
|
---|
926 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
927 | &io2, &result, multiple_search_callback);
|
---|
928 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
929 | CHECK_VALUE(result.count, 20);
|
---|
930 |
|
---|
931 | ret &= check_result(&result, "t009-9.txt", true, FILE_ATTRIBUTE_ARCHIVE);
|
---|
932 | ret &= check_result(&result, "t014-14.txt", false, 0);
|
---|
933 | ret &= check_result(&result, "t015-15.txt", false, 0);
|
---|
934 | ret &= check_result(&result, "t016-16.txt", true, FILE_ATTRIBUTE_NORMAL);
|
---|
935 | ret &= check_result(&result, "t017-17.txt", false, 0);
|
---|
936 | ret &= check_result(&result, "t018-18.txt", true, FILE_ATTRIBUTE_ARCHIVE);
|
---|
937 | ret &= check_result(&result, "t019-19.txt", true, FILE_ATTRIBUTE_ARCHIVE);
|
---|
938 | ret &= check_result(&result, "T013-13.txt.2", true, FILE_ATTRIBUTE_ARCHIVE);
|
---|
939 | ret &= check_result(&result, "T003-3.txt.2", false, 0);
|
---|
940 | ret &= check_result(&result, "T013-13.txt.3", true, FILE_ATTRIBUTE_ARCHIVE);
|
---|
941 |
|
---|
942 | if (!ret) {
|
---|
943 | for (i=0;i<result.count;i++) {
|
---|
944 | printf("%s %s (0x%x)\n",
|
---|
945 | result.list[i].both_directory_info.name.s,
|
---|
946 | attrib_string(tctx, result.list[i].both_directory_info.attrib),
|
---|
947 | result.list[i].both_directory_info.attrib);
|
---|
948 | }
|
---|
949 | }
|
---|
950 |
|
---|
951 | done:
|
---|
952 | smb_raw_exit(cli->session);
|
---|
953 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
954 |
|
---|
955 | return ret;
|
---|
956 | }
|
---|
957 |
|
---|
958 |
|
---|
959 | /*
|
---|
960 | testing if directories always come back sorted
|
---|
961 | */
|
---|
962 | static bool test_sorted(struct torture_context *tctx, struct smbcli_state *cli)
|
---|
963 | {
|
---|
964 | const int num_files = 700;
|
---|
965 | int i, fnum;
|
---|
966 | char *fname;
|
---|
967 | bool ret = true;
|
---|
968 | NTSTATUS status;
|
---|
969 | struct multiple_result result;
|
---|
970 |
|
---|
971 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
972 | return false;
|
---|
973 | }
|
---|
974 |
|
---|
975 | printf("Creating %d files\n", num_files);
|
---|
976 |
|
---|
977 | for (i=0;i<num_files;i++) {
|
---|
978 | fname = talloc_asprintf(cli, BASEDIR "\\%s.txt", generate_random_str_list(tctx, 10, "abcdefgh"));
|
---|
979 | fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
980 | if (fnum == -1) {
|
---|
981 | printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
|
---|
982 | ret = false;
|
---|
983 | goto done;
|
---|
984 | }
|
---|
985 | talloc_free(fname);
|
---|
986 | smbcli_close(cli->tree, fnum);
|
---|
987 | }
|
---|
988 |
|
---|
989 |
|
---|
990 | ZERO_STRUCT(result);
|
---|
991 | result.tctx = tctx;
|
---|
992 |
|
---|
993 | status = multiple_search(cli, tctx, BASEDIR "\\*.*",
|
---|
994 | RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
|
---|
995 | CONT_NAME, &result);
|
---|
996 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
997 | CHECK_VALUE(result.count, num_files);
|
---|
998 |
|
---|
999 | for (i=0;i<num_files-1;i++) {
|
---|
1000 | const char *name1, *name2;
|
---|
1001 | name1 = result.list[i].both_directory_info.name.s;
|
---|
1002 | name2 = result.list[i+1].both_directory_info.name.s;
|
---|
1003 | if (strcasecmp_m(name1, name2) > 0) {
|
---|
1004 | printf("non-alphabetical order at entry %d '%s' '%s'\n",
|
---|
1005 | i, name1, name2);
|
---|
1006 | printf("Server does not produce sorted directory listings (not an error)\n");
|
---|
1007 | goto done;
|
---|
1008 | }
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 | talloc_free(result.list);
|
---|
1012 |
|
---|
1013 | done:
|
---|
1014 | smb_raw_exit(cli->session);
|
---|
1015 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1016 |
|
---|
1017 | return ret;
|
---|
1018 | }
|
---|
1019 |
|
---|
1020 |
|
---|
1021 |
|
---|
1022 | /*
|
---|
1023 | basic testing of many old style search calls using separate dirs
|
---|
1024 | */
|
---|
1025 | static bool test_many_dirs(struct torture_context *tctx,
|
---|
1026 | struct smbcli_state *cli)
|
---|
1027 | {
|
---|
1028 | const int num_dirs = 20;
|
---|
1029 | int i, fnum, n;
|
---|
1030 | char *fname, *dname;
|
---|
1031 | bool ret = true;
|
---|
1032 | NTSTATUS status;
|
---|
1033 | union smb_search_data *file, *file2, *file3;
|
---|
1034 |
|
---|
1035 | if (!torture_setting_bool(tctx, "raw_search_search", true)) {
|
---|
1036 | torture_comment(tctx, "Skipping these tests as the server "
|
---|
1037 | "doesn't support old style search calls\n");
|
---|
1038 | return true;
|
---|
1039 | }
|
---|
1040 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1041 | return false;
|
---|
1042 | }
|
---|
1043 |
|
---|
1044 | printf("Creating %d dirs\n", num_dirs);
|
---|
1045 |
|
---|
1046 | for (i=0;i<num_dirs;i++) {
|
---|
1047 | dname = talloc_asprintf(cli, BASEDIR "\\d%d", i);
|
---|
1048 | status = smbcli_mkdir(cli->tree, dname);
|
---|
1049 | if (!NT_STATUS_IS_OK(status)) {
|
---|
1050 | printf("(%s) Failed to create %s - %s\n",
|
---|
1051 | __location__, dname, nt_errstr(status));
|
---|
1052 | ret = false;
|
---|
1053 | goto done;
|
---|
1054 | }
|
---|
1055 |
|
---|
1056 | for (n=0;n<3;n++) {
|
---|
1057 | fname = talloc_asprintf(cli, BASEDIR "\\d%d\\f%d-%d.txt", i, i, n);
|
---|
1058 | fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
1059 | if (fnum == -1) {
|
---|
1060 | printf("(%s) Failed to create %s - %s\n",
|
---|
1061 | __location__, fname, smbcli_errstr(cli->tree));
|
---|
1062 | ret = false;
|
---|
1063 | goto done;
|
---|
1064 | }
|
---|
1065 | talloc_free(fname);
|
---|
1066 | smbcli_close(cli->tree, fnum);
|
---|
1067 | }
|
---|
1068 |
|
---|
1069 | talloc_free(dname);
|
---|
1070 | }
|
---|
1071 |
|
---|
1072 | file = talloc_zero_array(tctx, union smb_search_data, num_dirs);
|
---|
1073 | file2 = talloc_zero_array(tctx, union smb_search_data, num_dirs);
|
---|
1074 | file3 = talloc_zero_array(tctx, union smb_search_data, num_dirs);
|
---|
1075 |
|
---|
1076 | printf("Search first on %d dirs\n", num_dirs);
|
---|
1077 |
|
---|
1078 | for (i=0;i<num_dirs;i++) {
|
---|
1079 | union smb_search_first io;
|
---|
1080 | io.search_first.level = RAW_SEARCH_SEARCH;
|
---|
1081 | io.search_first.data_level = RAW_SEARCH_DATA_SEARCH;
|
---|
1082 | io.search_first.in.max_count = 1;
|
---|
1083 | io.search_first.in.search_attrib = 0;
|
---|
1084 | io.search_first.in.pattern = talloc_asprintf(tctx, BASEDIR "\\d%d\\*.txt", i);
|
---|
1085 | fname = talloc_asprintf(tctx, "f%d-", i);
|
---|
1086 |
|
---|
1087 | io.search_first.out.count = 0;
|
---|
1088 |
|
---|
1089 | status = smb_raw_search_first(cli->tree, tctx,
|
---|
1090 | &io, (void *)&file[i], single_search_callback);
|
---|
1091 | if (io.search_first.out.count != 1) {
|
---|
1092 | printf("(%s) search first gave %d entries for dir %d - %s\n",
|
---|
1093 | __location__, io.search_first.out.count, i, nt_errstr(status));
|
---|
1094 | ret = false;
|
---|
1095 | goto done;
|
---|
1096 | }
|
---|
1097 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1098 | if (strncasecmp(file[i].search.name, fname, strlen(fname)) != 0) {
|
---|
1099 | printf("(%s) incorrect name '%s' expected '%s'[12].txt\n",
|
---|
1100 | __location__, file[i].search.name, fname);
|
---|
1101 | ret = false;
|
---|
1102 | goto done;
|
---|
1103 | }
|
---|
1104 |
|
---|
1105 | talloc_free(fname);
|
---|
1106 | }
|
---|
1107 |
|
---|
1108 | printf("Search next on %d dirs\n", num_dirs);
|
---|
1109 |
|
---|
1110 | for (i=0;i<num_dirs;i++) {
|
---|
1111 | union smb_search_next io2;
|
---|
1112 |
|
---|
1113 | io2.search_next.level = RAW_SEARCH_SEARCH;
|
---|
1114 | io2.search_next.data_level = RAW_SEARCH_DATA_SEARCH;
|
---|
1115 | io2.search_next.in.max_count = 1;
|
---|
1116 | io2.search_next.in.search_attrib = 0;
|
---|
1117 | io2.search_next.in.id = file[i].search.id;
|
---|
1118 | fname = talloc_asprintf(tctx, "f%d-", i);
|
---|
1119 |
|
---|
1120 | io2.search_next.out.count = 0;
|
---|
1121 |
|
---|
1122 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
1123 | &io2, (void *)&file2[i], single_search_callback);
|
---|
1124 | if (io2.search_next.out.count != 1) {
|
---|
1125 | printf("(%s) search next gave %d entries for dir %d - %s\n",
|
---|
1126 | __location__, io2.search_next.out.count, i, nt_errstr(status));
|
---|
1127 | ret = false;
|
---|
1128 | goto done;
|
---|
1129 | }
|
---|
1130 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1131 | if (strncasecmp(file2[i].search.name, fname, strlen(fname)) != 0) {
|
---|
1132 | printf("(%s) incorrect name '%s' expected '%s'[12].txt\n",
|
---|
1133 | __location__, file2[i].search.name, fname);
|
---|
1134 | ret = false;
|
---|
1135 | goto done;
|
---|
1136 | }
|
---|
1137 |
|
---|
1138 | talloc_free(fname);
|
---|
1139 | }
|
---|
1140 |
|
---|
1141 |
|
---|
1142 | printf("Search next (rewind) on %d dirs\n", num_dirs);
|
---|
1143 |
|
---|
1144 | for (i=0;i<num_dirs;i++) {
|
---|
1145 | union smb_search_next io2;
|
---|
1146 |
|
---|
1147 | io2.search_next.level = RAW_SEARCH_SEARCH;
|
---|
1148 | io2.search_next.data_level = RAW_SEARCH_DATA_SEARCH;
|
---|
1149 | io2.search_next.in.max_count = 1;
|
---|
1150 | io2.search_next.in.search_attrib = 0;
|
---|
1151 | io2.search_next.in.id = file[i].search.id;
|
---|
1152 | fname = talloc_asprintf(tctx, "f%d-", i);
|
---|
1153 | io2.search_next.out.count = 0;
|
---|
1154 |
|
---|
1155 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
1156 | &io2, (void *)&file3[i], single_search_callback);
|
---|
1157 | if (io2.search_next.out.count != 1) {
|
---|
1158 | printf("(%s) search next gave %d entries for dir %d - %s\n",
|
---|
1159 | __location__, io2.search_next.out.count, i, nt_errstr(status));
|
---|
1160 | ret = false;
|
---|
1161 | goto done;
|
---|
1162 | }
|
---|
1163 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1164 |
|
---|
1165 | if (strncasecmp(file3[i].search.name, file2[i].search.name, 3) != 0) {
|
---|
1166 | printf("(%s) incorrect name '%s' on rewind at dir %d\n",
|
---|
1167 | __location__, file2[i].search.name, i);
|
---|
1168 | ret = false;
|
---|
1169 | goto done;
|
---|
1170 | }
|
---|
1171 |
|
---|
1172 | if (torture_setting_bool(tctx, "rewind_support", true) &&
|
---|
1173 | strcmp(file3[i].search.name, file2[i].search.name) != 0) {
|
---|
1174 | printf("(%s) server did not rewind - got '%s' expected '%s'\n",
|
---|
1175 | __location__, file3[i].search.name, file2[i].search.name);
|
---|
1176 | ret = false;
|
---|
1177 | goto done;
|
---|
1178 | }
|
---|
1179 |
|
---|
1180 | talloc_free(fname);
|
---|
1181 | }
|
---|
1182 |
|
---|
1183 |
|
---|
1184 | done:
|
---|
1185 | smb_raw_exit(cli->session);
|
---|
1186 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1187 |
|
---|
1188 | return ret;
|
---|
1189 | }
|
---|
1190 |
|
---|
1191 |
|
---|
1192 | /*
|
---|
1193 | testing of OS/2 style delete
|
---|
1194 | */
|
---|
1195 | static bool test_os2_delete(struct torture_context *tctx,
|
---|
1196 | struct smbcli_state *cli)
|
---|
1197 | {
|
---|
1198 | const int num_files = 700;
|
---|
1199 | const int delete_count = 4;
|
---|
1200 | int total_deleted = 0;
|
---|
1201 | int i, fnum;
|
---|
1202 | char *fname;
|
---|
1203 | bool ret = true;
|
---|
1204 | NTSTATUS status;
|
---|
1205 | union smb_search_first io;
|
---|
1206 | union smb_search_next io2;
|
---|
1207 | struct multiple_result result;
|
---|
1208 |
|
---|
1209 | if (!torture_setting_bool(tctx, "search_ea_size", true)){
|
---|
1210 | torture_comment(tctx,
|
---|
1211 | "Server does not support RAW_SEARCH_EA_SIZE "
|
---|
1212 | "level. Skipping this test\n");
|
---|
1213 | return true;
|
---|
1214 | }
|
---|
1215 |
|
---|
1216 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1217 | return false;
|
---|
1218 | }
|
---|
1219 |
|
---|
1220 | printf("Testing OS/2 style delete on %d files\n", num_files);
|
---|
1221 |
|
---|
1222 | for (i=0;i<num_files;i++) {
|
---|
1223 | fname = talloc_asprintf(cli, BASEDIR "\\file%u.txt", i);
|
---|
1224 | fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
1225 | if (fnum == -1) {
|
---|
1226 | printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
|
---|
1227 | ret = false;
|
---|
1228 | goto done;
|
---|
1229 | }
|
---|
1230 | talloc_free(fname);
|
---|
1231 | smbcli_close(cli->tree, fnum);
|
---|
1232 | }
|
---|
1233 |
|
---|
1234 |
|
---|
1235 | ZERO_STRUCT(result);
|
---|
1236 | result.tctx = tctx;
|
---|
1237 |
|
---|
1238 | io.t2ffirst.level = RAW_SEARCH_TRANS2;
|
---|
1239 | io.t2ffirst.data_level = RAW_SEARCH_DATA_EA_SIZE;
|
---|
1240 | io.t2ffirst.in.search_attrib = 0;
|
---|
1241 | io.t2ffirst.in.max_count = 100;
|
---|
1242 | io.t2ffirst.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME;
|
---|
1243 | io.t2ffirst.in.storage_type = 0;
|
---|
1244 | io.t2ffirst.in.pattern = BASEDIR "\\*";
|
---|
1245 |
|
---|
1246 | status = smb_raw_search_first(cli->tree, tctx,
|
---|
1247 | &io, &result, multiple_search_callback);
|
---|
1248 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1249 |
|
---|
1250 | for (i=0;i<MIN(result.count, delete_count);i++) {
|
---|
1251 | fname = talloc_asprintf(cli, BASEDIR "\\%s", result.list[i].ea_size.name.s);
|
---|
1252 | status = smbcli_unlink(cli->tree, fname);
|
---|
1253 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1254 | total_deleted++;
|
---|
1255 | talloc_free(fname);
|
---|
1256 | }
|
---|
1257 |
|
---|
1258 | io2.t2fnext.level = RAW_SEARCH_TRANS2;
|
---|
1259 | io2.t2fnext.data_level = RAW_SEARCH_DATA_EA_SIZE;
|
---|
1260 | io2.t2fnext.in.handle = io.t2ffirst.out.handle;
|
---|
1261 | io2.t2fnext.in.max_count = 100;
|
---|
1262 | io2.t2fnext.in.resume_key = result.list[i-1].ea_size.resume_key;
|
---|
1263 | io2.t2fnext.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME;
|
---|
1264 | io2.t2fnext.in.last_name = result.list[i-1].ea_size.name.s;
|
---|
1265 |
|
---|
1266 | do {
|
---|
1267 | ZERO_STRUCT(result);
|
---|
1268 | result.tctx = tctx;
|
---|
1269 |
|
---|
1270 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
1271 | &io2, &result, multiple_search_callback);
|
---|
1272 | if (!NT_STATUS_IS_OK(status)) {
|
---|
1273 | break;
|
---|
1274 | }
|
---|
1275 |
|
---|
1276 | for (i=0;i<MIN(result.count, delete_count);i++) {
|
---|
1277 | fname = talloc_asprintf(cli, BASEDIR "\\%s", result.list[i].ea_size.name.s);
|
---|
1278 | status = smbcli_unlink(cli->tree, fname);
|
---|
1279 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1280 | total_deleted++;
|
---|
1281 | talloc_free(fname);
|
---|
1282 | }
|
---|
1283 |
|
---|
1284 | if (i>0) {
|
---|
1285 | io2.t2fnext.in.resume_key = result.list[i-1].ea_size.resume_key;
|
---|
1286 | io2.t2fnext.in.last_name = result.list[i-1].ea_size.name.s;
|
---|
1287 | }
|
---|
1288 | } while (NT_STATUS_IS_OK(status) && result.count != 0);
|
---|
1289 |
|
---|
1290 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1291 |
|
---|
1292 | if (total_deleted != num_files) {
|
---|
1293 | printf("error: deleted %d - expected to delete %d\n",
|
---|
1294 | total_deleted, num_files);
|
---|
1295 | ret = false;
|
---|
1296 | }
|
---|
1297 |
|
---|
1298 | done:
|
---|
1299 | smb_raw_exit(cli->session);
|
---|
1300 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1301 |
|
---|
1302 | return ret;
|
---|
1303 | }
|
---|
1304 |
|
---|
1305 |
|
---|
1306 | static int ealist_cmp(union smb_search_data *r1, union smb_search_data *r2)
|
---|
1307 | {
|
---|
1308 | return strcmp(r1->ea_list.name.s, r2->ea_list.name.s);
|
---|
1309 | }
|
---|
1310 |
|
---|
1311 | /*
|
---|
1312 | testing of the rather strange ea_list level
|
---|
1313 | */
|
---|
1314 | static bool test_ea_list(struct torture_context *tctx,
|
---|
1315 | struct smbcli_state *cli)
|
---|
1316 | {
|
---|
1317 | int fnum;
|
---|
1318 | bool ret = true;
|
---|
1319 | NTSTATUS status;
|
---|
1320 | union smb_search_first io;
|
---|
1321 | union smb_search_next nxt;
|
---|
1322 | struct multiple_result result;
|
---|
1323 | union smb_setfileinfo setfile;
|
---|
1324 |
|
---|
1325 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1326 | return false;
|
---|
1327 | }
|
---|
1328 |
|
---|
1329 | printf("Testing RAW_SEARCH_EA_LIST level\n");
|
---|
1330 |
|
---|
1331 | if (!torture_setting_bool(tctx, "search_ea_support", true) ||
|
---|
1332 | !torture_setting_bool(tctx, "ea_support", true)) {
|
---|
1333 | printf("..skipped per target configuration.\n");
|
---|
1334 | return true;
|
---|
1335 | }
|
---|
1336 |
|
---|
1337 | fnum = smbcli_open(cli->tree, BASEDIR "\\file1.txt", O_CREAT|O_RDWR, DENY_NONE);
|
---|
1338 | smbcli_close(cli->tree, fnum);
|
---|
1339 |
|
---|
1340 | fnum = smbcli_open(cli->tree, BASEDIR "\\file2.txt", O_CREAT|O_RDWR, DENY_NONE);
|
---|
1341 | smbcli_close(cli->tree, fnum);
|
---|
1342 |
|
---|
1343 | fnum = smbcli_open(cli->tree, BASEDIR "\\file3.txt", O_CREAT|O_RDWR, DENY_NONE);
|
---|
1344 | smbcli_close(cli->tree, fnum);
|
---|
1345 |
|
---|
1346 | setfile.generic.level = RAW_SFILEINFO_EA_SET;
|
---|
1347 | setfile.generic.in.file.path = BASEDIR "\\file2.txt";
|
---|
1348 | setfile.ea_set.in.num_eas = 2;
|
---|
1349 | setfile.ea_set.in.eas = talloc_array(tctx, struct ea_struct, 2);
|
---|
1350 | setfile.ea_set.in.eas[0].flags = 0;
|
---|
1351 | setfile.ea_set.in.eas[0].name.s = "EA ONE";
|
---|
1352 | setfile.ea_set.in.eas[0].value = data_blob_string_const("VALUE 1");
|
---|
1353 | setfile.ea_set.in.eas[1].flags = 0;
|
---|
1354 | setfile.ea_set.in.eas[1].name.s = "SECOND EA";
|
---|
1355 | setfile.ea_set.in.eas[1].value = data_blob_string_const("Value Two");
|
---|
1356 |
|
---|
1357 | status = smb_raw_setpathinfo(cli->tree, &setfile);
|
---|
1358 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1359 |
|
---|
1360 | setfile.generic.in.file.path = BASEDIR "\\file3.txt";
|
---|
1361 | status = smb_raw_setpathinfo(cli->tree, &setfile);
|
---|
1362 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1363 |
|
---|
1364 | ZERO_STRUCT(result);
|
---|
1365 | result.tctx = tctx;
|
---|
1366 |
|
---|
1367 | io.t2ffirst.level = RAW_SEARCH_TRANS2;
|
---|
1368 | io.t2ffirst.data_level = RAW_SEARCH_DATA_EA_LIST;
|
---|
1369 | io.t2ffirst.in.search_attrib = 0;
|
---|
1370 | io.t2ffirst.in.max_count = 2;
|
---|
1371 | io.t2ffirst.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME;
|
---|
1372 | io.t2ffirst.in.storage_type = 0;
|
---|
1373 | io.t2ffirst.in.pattern = BASEDIR "\\*";
|
---|
1374 | io.t2ffirst.in.num_names = 2;
|
---|
1375 | io.t2ffirst.in.ea_names = talloc_array(tctx, struct ea_name, 2);
|
---|
1376 | io.t2ffirst.in.ea_names[0].name.s = "SECOND EA";
|
---|
1377 | io.t2ffirst.in.ea_names[1].name.s = "THIRD EA";
|
---|
1378 |
|
---|
1379 | status = smb_raw_search_first(cli->tree, tctx,
|
---|
1380 | &io, &result, multiple_search_callback);
|
---|
1381 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1382 | CHECK_VALUE(result.count, 2);
|
---|
1383 |
|
---|
1384 | nxt.t2fnext.level = RAW_SEARCH_TRANS2;
|
---|
1385 | nxt.t2fnext.data_level = RAW_SEARCH_DATA_EA_LIST;
|
---|
1386 | nxt.t2fnext.in.handle = io.t2ffirst.out.handle;
|
---|
1387 | nxt.t2fnext.in.max_count = 2;
|
---|
1388 | nxt.t2fnext.in.resume_key = result.list[1].ea_list.resume_key;
|
---|
1389 | nxt.t2fnext.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME | FLAG_TRANS2_FIND_CONTINUE;
|
---|
1390 | nxt.t2fnext.in.last_name = result.list[1].ea_list.name.s;
|
---|
1391 | nxt.t2fnext.in.num_names = 2;
|
---|
1392 | nxt.t2fnext.in.ea_names = talloc_array(tctx, struct ea_name, 2);
|
---|
1393 | nxt.t2fnext.in.ea_names[0].name.s = "SECOND EA";
|
---|
1394 | nxt.t2fnext.in.ea_names[1].name.s = "THIRD EA";
|
---|
1395 |
|
---|
1396 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
1397 | &nxt, &result, multiple_search_callback);
|
---|
1398 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1399 |
|
---|
1400 | /* we have to sort the result as different servers can return directories
|
---|
1401 | in different orders */
|
---|
1402 | TYPESAFE_QSORT(result.list, result.count, ealist_cmp);
|
---|
1403 |
|
---|
1404 | CHECK_VALUE(result.count, 3);
|
---|
1405 | CHECK_VALUE(result.list[0].ea_list.eas.num_eas, 2);
|
---|
1406 | CHECK_STRING(result.list[0].ea_list.name.s, "file1.txt");
|
---|
1407 | CHECK_STRING(result.list[0].ea_list.eas.eas[0].name.s, "SECOND EA");
|
---|
1408 | CHECK_VALUE(result.list[0].ea_list.eas.eas[0].value.length, 0);
|
---|
1409 | CHECK_STRING(result.list[0].ea_list.eas.eas[1].name.s, "THIRD EA");
|
---|
1410 | CHECK_VALUE(result.list[0].ea_list.eas.eas[1].value.length, 0);
|
---|
1411 |
|
---|
1412 | CHECK_STRING(result.list[1].ea_list.name.s, "file2.txt");
|
---|
1413 | CHECK_STRING(result.list[1].ea_list.eas.eas[0].name.s, "SECOND EA");
|
---|
1414 | CHECK_VALUE(result.list[1].ea_list.eas.eas[0].value.length, 9);
|
---|
1415 | CHECK_STRING((const char *)result.list[1].ea_list.eas.eas[0].value.data, "Value Two");
|
---|
1416 | CHECK_STRING(result.list[1].ea_list.eas.eas[1].name.s, "THIRD EA");
|
---|
1417 | CHECK_VALUE(result.list[1].ea_list.eas.eas[1].value.length, 0);
|
---|
1418 |
|
---|
1419 | CHECK_STRING(result.list[2].ea_list.name.s, "file3.txt");
|
---|
1420 | CHECK_STRING(result.list[2].ea_list.eas.eas[0].name.s, "SECOND EA");
|
---|
1421 | CHECK_VALUE(result.list[2].ea_list.eas.eas[0].value.length, 9);
|
---|
1422 | CHECK_STRING((const char *)result.list[2].ea_list.eas.eas[0].value.data, "Value Two");
|
---|
1423 | CHECK_STRING(result.list[2].ea_list.eas.eas[1].name.s, "THIRD EA");
|
---|
1424 | CHECK_VALUE(result.list[2].ea_list.eas.eas[1].value.length, 0);
|
---|
1425 |
|
---|
1426 | smb_raw_exit(cli->session);
|
---|
1427 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1428 |
|
---|
1429 | return ret;
|
---|
1430 | }
|
---|
1431 |
|
---|
1432 | /*
|
---|
1433 | Test the behavior of max count parameter in TRANS2_FIND_FIRST2 and
|
---|
1434 | TRANS2_FIND_NEXT2 queries
|
---|
1435 | */
|
---|
1436 | static bool test_max_count(struct torture_context *tctx,
|
---|
1437 | struct smbcli_state *cli)
|
---|
1438 | {
|
---|
1439 | const int num_files = 2;
|
---|
1440 | int i, fnum;
|
---|
1441 | char *fname;
|
---|
1442 | bool ret = true;
|
---|
1443 | NTSTATUS status;
|
---|
1444 | struct multiple_result result;
|
---|
1445 | union smb_search_first io;
|
---|
1446 | union smb_search_next io2;
|
---|
1447 |
|
---|
1448 | if (!torture_setup_dir(cli, BASEDIR)) {
|
---|
1449 | return false;
|
---|
1450 | }
|
---|
1451 |
|
---|
1452 | torture_comment(tctx, "Creating %d files\n", num_files);
|
---|
1453 |
|
---|
1454 | for (i=num_files-1;i>=0;i--) {
|
---|
1455 | fname = talloc_asprintf(cli, BASEDIR "\\t%03d-%d.txt", i, i);
|
---|
1456 | fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
|
---|
1457 | if (fnum == -1) {
|
---|
1458 | torture_comment(tctx,
|
---|
1459 | "Failed to create %s - %s\n",
|
---|
1460 | fname, smbcli_errstr(cli->tree));
|
---|
1461 | ret = false;
|
---|
1462 | goto done;
|
---|
1463 | }
|
---|
1464 | talloc_free(fname);
|
---|
1465 | smbcli_close(cli->tree, fnum);
|
---|
1466 | }
|
---|
1467 |
|
---|
1468 | torture_comment(tctx, "Set max_count parameter to 0. "
|
---|
1469 | "This should return 1 entry\n");
|
---|
1470 | ZERO_STRUCT(result);
|
---|
1471 | result.tctx = talloc_new(tctx);
|
---|
1472 |
|
---|
1473 | io.t2ffirst.level = RAW_SEARCH_TRANS2;
|
---|
1474 | io.t2ffirst.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
|
---|
1475 | io.t2ffirst.in.search_attrib = 0;
|
---|
1476 | io.t2ffirst.in.max_count = 0;
|
---|
1477 | io.t2ffirst.in.flags = 0;
|
---|
1478 | io.t2ffirst.in.storage_type = 0;
|
---|
1479 | io.t2ffirst.in.pattern = BASEDIR "\\*.*";
|
---|
1480 |
|
---|
1481 | status = smb_raw_search_first(cli->tree, tctx,
|
---|
1482 | &io, &result, multiple_search_callback);
|
---|
1483 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1484 | CHECK_VALUE(result.count, 1);
|
---|
1485 |
|
---|
1486 | torture_comment(tctx, "Set max_count to 1. This should also "
|
---|
1487 | "return 1 entry\n");
|
---|
1488 | io2.t2fnext.level = RAW_SEARCH_TRANS2;
|
---|
1489 | io2.t2fnext.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
|
---|
1490 | io2.t2fnext.in.handle = io.t2ffirst.out.handle;
|
---|
1491 | io2.t2fnext.in.max_count = 1;
|
---|
1492 | io2.t2fnext.in.resume_key = 0;
|
---|
1493 | io2.t2fnext.in.flags = 0;
|
---|
1494 | io2.t2fnext.in.last_name =
|
---|
1495 | result.list[result.count-1].both_directory_info.name.s;
|
---|
1496 |
|
---|
1497 | status = smb_raw_search_next(cli->tree, tctx,
|
---|
1498 | &io2, &result, multiple_search_callback);
|
---|
1499 | CHECK_STATUS(status, NT_STATUS_OK);
|
---|
1500 | CHECK_VALUE(result.count, 2);
|
---|
1501 | done:
|
---|
1502 | smb_raw_exit(cli->session);
|
---|
1503 | smbcli_deltree(cli->tree, BASEDIR);
|
---|
1504 |
|
---|
1505 | return ret;
|
---|
1506 | }
|
---|
1507 |
|
---|
1508 | /*
|
---|
1509 | basic testing of all RAW_SEARCH_* calls using a single file
|
---|
1510 | */
|
---|
1511 | struct torture_suite *torture_raw_search(TALLOC_CTX *mem_ctx)
|
---|
1512 | {
|
---|
1513 | struct torture_suite *suite = torture_suite_create(mem_ctx, "search");
|
---|
1514 |
|
---|
1515 | torture_suite_add_1smb_test(suite, "one file search", test_one_file);
|
---|
1516 | torture_suite_add_1smb_test(suite, "many files", test_many_files);
|
---|
1517 | torture_suite_add_1smb_test(suite, "sorted", test_sorted);
|
---|
1518 | torture_suite_add_1smb_test(suite, "modify search", test_modify_search);
|
---|
1519 | torture_suite_add_1smb_test(suite, "many dirs", test_many_dirs);
|
---|
1520 | torture_suite_add_1smb_test(suite, "os2 delete", test_os2_delete);
|
---|
1521 | torture_suite_add_1smb_test(suite, "ea list", test_ea_list);
|
---|
1522 | torture_suite_add_1smb_test(suite, "max count", test_max_count);
|
---|
1523 |
|
---|
1524 | return suite;
|
---|
1525 | }
|
---|