~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/raw/search.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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