Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : RAW_FILEINFO_* individual test suite
4 : Copyright (C) Andrew Tridgell 2003
5 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.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 "torture/rpc/torture_rpc.h"
27 : #include "param/param.h"
28 : #include "torture/raw/proto.h"
29 :
30 : static struct {
31 : const char *name;
32 : enum smb_fileinfo_level level;
33 : unsigned int only_paths:1;
34 : unsigned int only_handles:1;
35 : uint32_t capability_mask;
36 : unsigned int expected_ipc_access_denied:1;
37 : NTSTATUS expected_ipc_fnum_status;
38 : NTSTATUS fnum_status, fname_status;
39 : union smb_fileinfo fnum_finfo, fname_finfo;
40 : } levels[] = {
41 : {
42 : .name = "GETATTR",
43 : .level = RAW_FILEINFO_GETATTR,
44 : .only_paths = 1,
45 : .only_handles = 0,
46 : .expected_ipc_access_denied = 1,
47 : },
48 : {
49 : .name ="GETATTRE",
50 : .level = RAW_FILEINFO_GETATTRE,
51 : .only_paths = 0,
52 : .only_handles = 1,
53 : },
54 : {
55 : .name ="STANDARD",
56 : .level = RAW_FILEINFO_STANDARD,
57 : },
58 : {
59 : .name ="EA_SIZE",
60 : .level = RAW_FILEINFO_EA_SIZE,
61 : },
62 : {
63 : .name ="ALL_EAS",
64 : .level = RAW_FILEINFO_ALL_EAS,
65 : .expected_ipc_fnum_status = NT_STATUS_ACCESS_DENIED,
66 : .fnum_status = NT_STATUS_SUCCESS,
67 : .fname_status = NT_STATUS_SUCCESS,
68 : .fnum_finfo = {
69 : .generic = {
70 : .level = 0,
71 : },
72 : },
73 : .fname_finfo = {
74 : .generic = {
75 : .level = 0,
76 : },
77 : },
78 : },
79 : {
80 : .name ="IS_NAME_VALID",
81 : .level = RAW_FILEINFO_IS_NAME_VALID,
82 : .only_paths = 1,
83 : .only_handles = 0,
84 : },
85 : {
86 : .name ="BASIC_INFO",
87 : .level = RAW_FILEINFO_BASIC_INFO,
88 : },
89 : {
90 : .name ="STANDARD_INFO",
91 : .level = RAW_FILEINFO_STANDARD_INFO,
92 : },
93 : {
94 : .name ="EA_INFO",
95 : .level = RAW_FILEINFO_EA_INFO,
96 : },
97 : {
98 : .name ="NAME_INFO",
99 : .level = RAW_FILEINFO_NAME_INFO,
100 : },
101 : {
102 : .name ="ALL_INFO",
103 : .level = RAW_FILEINFO_ALL_INFO,
104 : },
105 : {
106 : .name ="ALT_NAME_INFO",
107 : .level = RAW_FILEINFO_ALT_NAME_INFO,
108 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
109 : .fnum_status = NT_STATUS_SUCCESS,
110 : .fname_status = NT_STATUS_SUCCESS,
111 : .fnum_finfo = {
112 : .generic = {
113 : .level = 0,
114 : },
115 : },
116 : .fname_finfo = {
117 : .generic = {
118 : .level = 0,
119 : },
120 : },
121 : },
122 : {
123 : .name ="STREAM_INFO",
124 : .level = RAW_FILEINFO_STREAM_INFO,
125 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
126 : .fnum_status = NT_STATUS_SUCCESS,
127 : .fname_status = NT_STATUS_SUCCESS,
128 : .fnum_finfo = {
129 : .generic = {
130 : .level = 0,
131 : },
132 : },
133 : .fname_finfo = {
134 : .generic = {
135 : .level = 0,
136 : },
137 : },
138 : },
139 : {
140 : .name ="COMPRESSION_INFO",
141 : .level = RAW_FILEINFO_COMPRESSION_INFO,
142 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
143 : .fnum_status = NT_STATUS_SUCCESS,
144 : .fname_status = NT_STATUS_SUCCESS,
145 : .fnum_finfo = {
146 : .generic = {
147 : .level = 0,
148 : },
149 : },
150 : .fname_finfo = {
151 : .generic = {
152 : .level = 0,
153 : },
154 : },
155 : },
156 : {
157 : .name ="UNIX_BASIC_INFO",
158 : .level = RAW_FILEINFO_UNIX_BASIC,
159 : .only_paths = 0,
160 : .only_handles = 0,
161 : .capability_mask = CAP_UNIX,
162 : },
163 : {
164 : .name ="UNIX_LINK_INFO",
165 : .level = RAW_FILEINFO_UNIX_LINK,
166 : .only_paths = 0,
167 : .only_handles = 0,
168 : .capability_mask = CAP_UNIX,
169 : },
170 : {
171 : .name ="BASIC_INFORMATION",
172 : .level = RAW_FILEINFO_BASIC_INFORMATION,
173 : },
174 : {
175 : .name ="STANDARD_INFORMATION",
176 : .level = RAW_FILEINFO_STANDARD_INFORMATION,
177 : },
178 : {
179 : .name ="INTERNAL_INFORMATION",
180 : .level = RAW_FILEINFO_INTERNAL_INFORMATION,
181 : },
182 : {
183 : .name ="EA_INFORMATION",
184 : .level = RAW_FILEINFO_EA_INFORMATION,
185 : },
186 : {
187 : .name = "ACCESS_INFORMATION",
188 : .level = RAW_FILEINFO_ACCESS_INFORMATION,
189 : },
190 : {
191 : .name = "NAME_INFORMATION",
192 : .level = RAW_FILEINFO_NAME_INFORMATION,
193 : },
194 : {
195 : .name ="POSITION_INFORMATION",
196 : .level = RAW_FILEINFO_POSITION_INFORMATION,
197 : },
198 : {
199 : .name ="MODE_INFORMATION",
200 : .level = RAW_FILEINFO_MODE_INFORMATION,
201 : },
202 : {
203 : .name ="ALIGNMENT_INFORMATION",
204 : .level = RAW_FILEINFO_ALIGNMENT_INFORMATION,
205 : },
206 : {
207 : .name ="ALL_INFORMATION",
208 : .level = RAW_FILEINFO_ALL_INFORMATION,
209 : },
210 : {
211 : .name ="ALT_NAME_INFORMATION",
212 : .level = RAW_FILEINFO_ALT_NAME_INFORMATION,
213 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
214 : .fnum_status = NT_STATUS_SUCCESS,
215 : .fname_status = NT_STATUS_SUCCESS,
216 : .fnum_finfo = {
217 : .generic = {
218 : .level = 0,
219 : },
220 : },
221 : .fname_finfo = {
222 : .generic = {
223 : .level = 0,
224 : },
225 : },
226 : },
227 : {
228 : .name ="STREAM_INFORMATION",
229 : .level = RAW_FILEINFO_STREAM_INFORMATION,
230 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
231 : .fnum_status = NT_STATUS_SUCCESS,
232 : .fname_status = NT_STATUS_SUCCESS,
233 : .fnum_finfo = {
234 : .generic = {
235 : .level = 0,
236 : },
237 : },
238 : .fname_finfo = {
239 : .generic = {
240 : .level = 0,
241 : },
242 : },
243 : },
244 : {
245 : .name = "COMPRESSION_INFORMATION",
246 : .level = RAW_FILEINFO_COMPRESSION_INFORMATION,
247 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
248 : .fnum_status = NT_STATUS_SUCCESS,
249 : .fname_status = NT_STATUS_SUCCESS,
250 : .fnum_finfo = {
251 : .generic = {
252 : .level = 0,
253 : },
254 : },
255 : .fname_finfo = {
256 : .generic = {
257 : .level = 0,
258 : },
259 : },
260 : },
261 : {
262 : .name ="NETWORK_OPEN_INFORMATION",
263 : .level = RAW_FILEINFO_NETWORK_OPEN_INFORMATION,
264 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
265 : .fnum_status = NT_STATUS_SUCCESS,
266 : .fname_status = NT_STATUS_SUCCESS,
267 : .fnum_finfo = {
268 : .generic = {
269 : .level = 0,
270 : },
271 : },
272 : .fname_finfo = {
273 : .generic = {
274 : .level = 0,
275 : },
276 : },
277 : },
278 : {
279 : .name = "ATTRIBUTE_TAG_INFORMATION",
280 : .level = RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION,
281 : .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER,
282 : .fnum_status = NT_STATUS_SUCCESS,
283 : .fname_status = NT_STATUS_SUCCESS,
284 : .fnum_finfo = {
285 : .generic = {
286 : .level = 0,
287 : },
288 : },
289 : .fname_finfo = {
290 : .generic = {
291 : .level = 0,
292 : },
293 : },
294 : },
295 : { .name = NULL, },
296 : };
297 :
298 : /*
299 : compare a dos time (2 second resolution) to a nt time
300 : */
301 25 : static int dos_nt_time_cmp(time_t t, NTTIME nt)
302 : {
303 25 : time_t t2 = nt_time_to_unix(nt);
304 25 : if (labs(t2 - t) <= 2) return 0;
305 0 : return t2 > t ? 1 : -1;
306 : }
307 :
308 :
309 : /*
310 : find a level in the levels[] table
311 : */
312 241 : static union smb_fileinfo *fnum_find(const char *name)
313 : {
314 0 : int i;
315 3511 : for (i=0; levels[i].name; i++) {
316 3482 : if (NT_STATUS_IS_OK(levels[i].fnum_status) &&
317 2936 : strcmp(name, levels[i].name) == 0 &&
318 218 : !levels[i].only_paths) {
319 212 : return &levels[i].fnum_finfo;
320 : }
321 : }
322 29 : return NULL;
323 : }
324 :
325 : /*
326 : find a level in the levels[] table
327 : */
328 213 : static union smb_fileinfo *fname_find(bool is_ipc, const char *name)
329 : {
330 0 : int i;
331 213 : if (is_ipc) {
332 100 : return NULL;
333 : }
334 1773 : for (i=0; levels[i].name; i++) {
335 1767 : if (NT_STATUS_IS_OK(levels[i].fname_status) &&
336 1667 : strcmp(name, levels[i].name) == 0 &&
337 113 : !levels[i].only_handles) {
338 107 : return &levels[i].fname_finfo;
339 : }
340 : }
341 6 : return NULL;
342 : }
343 :
344 : /* local macros to make the code below more readable */
345 : #define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
346 : printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
347 : #n1, #v1, (unsigned int)s1->n1.out.v1, \
348 : #n2, #v2, (unsigned int)s2->n2.out.v2, \
349 : __FILE__, __LINE__); \
350 : ret = false; \
351 : }} while(0)
352 :
353 : #define STR_EQUAL(n1, v1, n2, v2) do {if (strcmp_safe(s1->n1.out.v1.s, s2->n2.out.v2.s) || \
354 : s1->n1.out.v1.private_length != s2->n2.out.v2.private_length) { \
355 : printf("%s/%s [%s/%d] != %s/%s [%s/%d] at %s(%d)\n", \
356 : #n1, #v1, s1->n1.out.v1.s, s1->n1.out.v1.private_length, \
357 : #n2, #v2, s2->n2.out.v2.s, s2->n2.out.v2.private_length, \
358 : __FILE__, __LINE__); \
359 : ret = false; \
360 : }} while(0)
361 :
362 : #define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
363 : printf("%s/%s != %s/%s at %s(%d)\n", \
364 : #n1, #v1, \
365 : #n2, #v2, \
366 : __FILE__, __LINE__); \
367 : ret = false; \
368 : }} while(0)
369 :
370 : /* used to find hints on unknown values - and to make sure
371 : we zero-fill */
372 : #if 0 /* unused */
373 : #define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
374 : printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
375 : #n1, #v1, \
376 : (unsigned int)s1->n1.out.v1, \
377 : (unsigned int)s1->n1.out.v1, \
378 : __FILE__, __LINE__); \
379 : ret = false; \
380 : }} while(0)
381 : #endif
382 :
383 : /* basic testing of all RAW_FILEINFO_* calls
384 : for each call we test that it succeeds, and where possible test
385 : for consistency between the calls.
386 : */
387 2 : static bool torture_raw_qfileinfo_internals(struct torture_context *torture,
388 : TALLOC_CTX *mem_ctx,
389 : struct smbcli_tree *tree,
390 : int fnum, const char *fname,
391 : bool is_ipc)
392 : {
393 0 : size_t i;
394 2 : bool ret = true;
395 0 : size_t count;
396 0 : union smb_fileinfo *s1, *s2;
397 0 : NTTIME correct_time;
398 0 : uint64_t correct_size;
399 0 : uint32_t correct_attrib;
400 0 : const char *correct_name;
401 2 : bool skip_streams = false;
402 :
403 : /* scan all the fileinfo and pathinfo levels */
404 64 : for (i=0; levels[i].name; i++) {
405 62 : if (!levels[i].only_paths) {
406 58 : levels[i].fnum_finfo.generic.level = levels[i].level;
407 58 : levels[i].fnum_finfo.generic.in.file.fnum = fnum;
408 58 : levels[i].fnum_status = smb_raw_fileinfo(tree, mem_ctx,
409 : &levels[i].fnum_finfo);
410 : }
411 :
412 62 : if (!levels[i].only_handles) {
413 60 : levels[i].fname_finfo.generic.level = levels[i].level;
414 60 : levels[i].fname_finfo.generic.in.file.path = talloc_strdup(mem_ctx, fname);
415 60 : levels[i].fname_status = smb_raw_pathinfo(tree, mem_ctx,
416 : &levels[i].fname_finfo);
417 : }
418 : }
419 :
420 : /* check for completely broken levels */
421 64 : for (count=i=0; levels[i].name; i++) {
422 62 : uint32_t cap = tree->session->transport->negotiate.capabilities;
423 : /* see if this server claims to support this level */
424 62 : if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
425 4 : continue;
426 : }
427 :
428 58 : if (is_ipc) {
429 29 : if (levels[i].expected_ipc_access_denied && NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, levels[i].fname_status)) {
430 28 : } else if (!levels[i].only_handles &&
431 27 : NT_STATUS_EQUAL(levels[i].fname_status,
432 : NT_STATUS_NOT_SUPPORTED)) {
433 0 : torture_warning(torture, "fname level %s %s",
434 : levels[i].name,
435 : nt_errstr(levels[i].fname_status));
436 0 : continue;
437 28 : } else if (!levels[i].only_handles && !NT_STATUS_EQUAL(NT_STATUS_INVALID_DEVICE_REQUEST, levels[i].fname_status)) {
438 0 : printf("ERROR: fname level %s failed, expected NT_STATUS_INVALID_DEVICE_REQUEST - %s\n",
439 : levels[i].name, nt_errstr(levels[i].fname_status));
440 0 : count++;
441 : }
442 29 : if (!levels[i].only_paths &&
443 27 : (NT_STATUS_EQUAL(levels[i].fnum_status,
444 27 : NT_STATUS_NOT_SUPPORTED) ||
445 27 : NT_STATUS_EQUAL(levels[i].fnum_status,
446 : NT_STATUS_NOT_IMPLEMENTED))) {
447 0 : torture_warning(torture, "fnum level %s %s",
448 : levels[i].name,
449 : nt_errstr(levels[i].fnum_status));
450 0 : continue;
451 : }
452 29 : if (!levels[i].only_paths && !NT_STATUS_EQUAL(levels[i].expected_ipc_fnum_status, levels[i].fnum_status)) {
453 0 : printf("ERROR: fnum level %s failed, expected %s - %s\n",
454 : levels[i].name, nt_errstr(levels[i].expected_ipc_fnum_status),
455 : nt_errstr(levels[i].fnum_status));
456 0 : count++;
457 : }
458 : } else {
459 29 : if (!levels[i].only_paths &&
460 27 : (NT_STATUS_EQUAL(levels[i].fnum_status,
461 27 : NT_STATUS_NOT_SUPPORTED) ||
462 27 : NT_STATUS_EQUAL(levels[i].fnum_status,
463 : NT_STATUS_NOT_IMPLEMENTED))) {
464 0 : torture_warning(torture, "fnum level %s %s",
465 : levels[i].name,
466 : nt_errstr(levels[i].fnum_status));
467 0 : continue;
468 : }
469 :
470 29 : if (!levels[i].only_handles &&
471 28 : (NT_STATUS_EQUAL(levels[i].fname_status,
472 28 : NT_STATUS_NOT_SUPPORTED) ||
473 28 : NT_STATUS_EQUAL(levels[i].fname_status,
474 : NT_STATUS_NOT_IMPLEMENTED))) {
475 0 : torture_warning(torture, "fname level %s %s",
476 : levels[i].name,
477 : nt_errstr(levels[i].fname_status));
478 0 : continue;
479 : }
480 :
481 29 : if (!levels[i].only_paths && !NT_STATUS_IS_OK(levels[i].fnum_status)) {
482 0 : printf("ERROR: fnum level %s failed - %s\n",
483 : levels[i].name, nt_errstr(levels[i].fnum_status));
484 0 : count++;
485 : }
486 29 : if (!levels[i].only_handles && !NT_STATUS_IS_OK(levels[i].fname_status)) {
487 0 : printf("ERROR: fname level %s failed - %s\n",
488 : levels[i].name, nt_errstr(levels[i].fname_status));
489 0 : count++;
490 : }
491 : }
492 :
493 : }
494 :
495 2 : if (count != 0) {
496 0 : ret = false;
497 0 : printf("%zu levels failed\n", count);
498 0 : if (count > 35) {
499 0 : torture_fail(torture, "too many level failures - giving up");
500 : }
501 : }
502 :
503 : /* see if we can do streams */
504 2 : s1 = fnum_find("STREAM_INFO");
505 2 : if (!s1 || s1->stream_info.out.num_streams == 0) {
506 1 : if (!is_ipc) {
507 0 : printf("STREAM_INFO broken (%d) - skipping streams checks\n",
508 : s1 ? s1->stream_info.out.num_streams : -1);
509 : }
510 1 : skip_streams = true;
511 : }
512 :
513 :
514 : /* this code is incredibly repititive but doesn't lend itself to loops, so
515 : we use lots of macros to make it less painful */
516 :
517 : /* first off we check the levels that are supposed to be aliases. It will be quite rare for
518 : this code to fail, but we need to check it for completeness */
519 :
520 :
521 :
522 : #define ALIAS_CHECK(sname1, sname2) \
523 : do { \
524 : s1 = fnum_find(sname1); s2 = fnum_find(sname2); \
525 : if (s1 && s2) { INFO_CHECK } \
526 : s1 = fname_find(is_ipc, sname1); s2 = fname_find(is_ipc, sname2); \
527 : if (s1 && s2) { INFO_CHECK } \
528 : s1 = fnum_find(sname1); s2 = fname_find(is_ipc, sname2); \
529 : if (s1 && s2) { INFO_CHECK } \
530 : } while (0)
531 :
532 : #define INFO_CHECK \
533 : STRUCT_EQUAL(basic_info, create_time, basic_info, create_time); \
534 : STRUCT_EQUAL(basic_info, access_time, basic_info, access_time); \
535 : STRUCT_EQUAL(basic_info, write_time, basic_info, write_time); \
536 : STRUCT_EQUAL(basic_info, change_time, basic_info, change_time); \
537 : VAL_EQUAL (basic_info, attrib, basic_info, attrib);
538 :
539 2 : ALIAS_CHECK("BASIC_INFO", "BASIC_INFORMATION");
540 :
541 : #undef INFO_CHECK
542 : #define INFO_CHECK \
543 : VAL_EQUAL(standard_info, alloc_size, standard_info, alloc_size); \
544 : VAL_EQUAL(standard_info, size, standard_info, size); \
545 : VAL_EQUAL(standard_info, nlink, standard_info, nlink); \
546 : VAL_EQUAL(standard_info, delete_pending, standard_info, delete_pending); \
547 : VAL_EQUAL(standard_info, directory, standard_info, directory);
548 :
549 2 : ALIAS_CHECK("STANDARD_INFO", "STANDARD_INFORMATION");
550 :
551 : #undef INFO_CHECK
552 : #define INFO_CHECK \
553 : VAL_EQUAL(ea_info, ea_size, ea_info, ea_size);
554 :
555 2 : ALIAS_CHECK("EA_INFO", "EA_INFORMATION");
556 :
557 : #undef INFO_CHECK
558 : #define INFO_CHECK \
559 : STR_EQUAL(name_info, fname, name_info, fname);
560 :
561 2 : ALIAS_CHECK("NAME_INFO", "NAME_INFORMATION");
562 :
563 : #undef INFO_CHECK
564 : #define INFO_CHECK \
565 : STRUCT_EQUAL(all_info, create_time, all_info, create_time); \
566 : STRUCT_EQUAL(all_info, access_time, all_info, access_time); \
567 : STRUCT_EQUAL(all_info, write_time, all_info, write_time); \
568 : STRUCT_EQUAL(all_info, change_time, all_info, change_time); \
569 : VAL_EQUAL(all_info, attrib, all_info, attrib); \
570 : VAL_EQUAL(all_info, alloc_size, all_info, alloc_size); \
571 : VAL_EQUAL(all_info, size, all_info, size); \
572 : VAL_EQUAL(all_info, nlink, all_info, nlink); \
573 : VAL_EQUAL(all_info, delete_pending, all_info, delete_pending); \
574 : VAL_EQUAL(all_info, directory, all_info, directory); \
575 : VAL_EQUAL(all_info, ea_size, all_info, ea_size); \
576 : STR_EQUAL(all_info, fname, all_info, fname);
577 :
578 2 : ALIAS_CHECK("ALL_INFO", "ALL_INFORMATION");
579 :
580 : #undef INFO_CHECK
581 : #define INFO_CHECK \
582 : VAL_EQUAL(compression_info, compressed_size,compression_info, compressed_size); \
583 : VAL_EQUAL(compression_info, format, compression_info, format); \
584 : VAL_EQUAL(compression_info, unit_shift, compression_info, unit_shift); \
585 : VAL_EQUAL(compression_info, chunk_shift, compression_info, chunk_shift); \
586 : VAL_EQUAL(compression_info, cluster_shift, compression_info, cluster_shift);
587 :
588 2 : ALIAS_CHECK("COMPRESSION_INFO", "COMPRESSION_INFORMATION");
589 :
590 :
591 : #undef INFO_CHECK
592 : #define INFO_CHECK \
593 : STR_EQUAL(alt_name_info, fname, alt_name_info, fname);
594 :
595 2 : ALIAS_CHECK("ALT_NAME_INFO", "ALT_NAME_INFORMATION");
596 :
597 :
598 : #define TIME_CHECK_NT(sname, stype, tfield) do { \
599 : s1 = fnum_find(sname); \
600 : if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
601 : printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
602 : nt_time_string(mem_ctx, s1->stype.out.tfield), \
603 : nt_time_string(mem_ctx, correct_time)); \
604 : ret = false; \
605 : } \
606 : s1 = fname_find(is_ipc, sname); \
607 : if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
608 : printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
609 : nt_time_string(mem_ctx, s1->stype.out.tfield), \
610 : nt_time_string(mem_ctx, correct_time)); \
611 : ret = false; \
612 : }} while (0)
613 :
614 : #define TIME_CHECK_DOS(sname, stype, tfield) do { \
615 : s1 = fnum_find(sname); \
616 : if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
617 : printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
618 : timestring(mem_ctx, s1->stype.out.tfield), \
619 : nt_time_string(mem_ctx, correct_time)); \
620 : ret = false; \
621 : } \
622 : s1 = fname_find(is_ipc, sname); \
623 : if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
624 : printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
625 : timestring(mem_ctx, s1->stype.out.tfield), \
626 : nt_time_string(mem_ctx, correct_time)); \
627 : ret = false; \
628 : }} while (0)
629 :
630 : #if 0 /* unused */
631 : #define TIME_CHECK_UNX(sname, stype, tfield) do { \
632 : s1 = fnum_find(sname); \
633 : if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
634 : printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
635 : timestring(mem_ctx, s1->stype.out.tfield), \
636 : nt_time_string(mem_ctx, correct_time)); \
637 : ret = false; \
638 : } \
639 : s1 = fname_find(is_ipc, sname); \
640 : if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
641 : printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
642 : timestring(mem_ctx, s1->stype.out.tfield), \
643 : nt_time_string(mem_ctx, correct_time)); \
644 : ret = false; \
645 : }} while (0)
646 : #endif
647 :
648 : /* now check that all the times that are supposed to be equal are correct */
649 2 : s1 = fnum_find("BASIC_INFO");
650 2 : correct_time = s1->basic_info.out.create_time;
651 2 : torture_comment(torture, "create_time: %s\n", nt_time_string(mem_ctx, correct_time));
652 :
653 2 : TIME_CHECK_NT ("BASIC_INFO", basic_info, create_time);
654 2 : TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, create_time);
655 2 : TIME_CHECK_DOS("GETATTRE", getattre, create_time);
656 2 : TIME_CHECK_DOS("STANDARD", standard, create_time);
657 2 : TIME_CHECK_DOS("EA_SIZE", ea_size, create_time);
658 2 : TIME_CHECK_NT ("ALL_INFO", all_info, create_time);
659 2 : TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, create_time);
660 :
661 2 : s1 = fnum_find("BASIC_INFO");
662 2 : correct_time = s1->basic_info.out.access_time;
663 2 : torture_comment(torture, "access_time: %s\n", nt_time_string(mem_ctx, correct_time));
664 :
665 2 : TIME_CHECK_NT ("BASIC_INFO", basic_info, access_time);
666 2 : TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, access_time);
667 2 : TIME_CHECK_DOS("GETATTRE", getattre, access_time);
668 2 : TIME_CHECK_DOS("STANDARD", standard, access_time);
669 2 : TIME_CHECK_DOS("EA_SIZE", ea_size, access_time);
670 2 : TIME_CHECK_NT ("ALL_INFO", all_info, access_time);
671 2 : TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, access_time);
672 :
673 2 : s1 = fnum_find("BASIC_INFO");
674 2 : correct_time = s1->basic_info.out.write_time;
675 2 : torture_comment(torture, "write_time : %s\n", nt_time_string(mem_ctx, correct_time));
676 :
677 2 : TIME_CHECK_NT ("BASIC_INFO", basic_info, write_time);
678 2 : TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, write_time);
679 2 : TIME_CHECK_DOS("GETATTR", getattr, write_time);
680 2 : TIME_CHECK_DOS("GETATTRE", getattre, write_time);
681 2 : TIME_CHECK_DOS("STANDARD", standard, write_time);
682 2 : TIME_CHECK_DOS("EA_SIZE", ea_size, write_time);
683 2 : TIME_CHECK_NT ("ALL_INFO", all_info, write_time);
684 2 : TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, write_time);
685 :
686 2 : s1 = fnum_find("BASIC_INFO");
687 2 : correct_time = s1->basic_info.out.change_time;
688 2 : torture_comment(torture, "change_time: %s\n", nt_time_string(mem_ctx, correct_time));
689 :
690 2 : TIME_CHECK_NT ("BASIC_INFO", basic_info, change_time);
691 2 : TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, change_time);
692 2 : TIME_CHECK_NT ("ALL_INFO", all_info, change_time);
693 2 : TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, change_time);
694 :
695 :
696 : #define SIZE_CHECK(sname, stype, tfield) do { \
697 : s1 = fnum_find(sname); \
698 : if (s1 && s1->stype.out.tfield != correct_size) { \
699 : printf("(%d) handle %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield, \
700 : (unsigned int)s1->stype.out.tfield, \
701 : (unsigned int)correct_size); \
702 : ret = false; \
703 : } \
704 : s1 = fname_find(is_ipc, sname); \
705 : if (s1 && s1->stype.out.tfield != correct_size) { \
706 : printf("(%d) path %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield, \
707 : (unsigned int)s1->stype.out.tfield, \
708 : (unsigned int)correct_size); \
709 : ret = false; \
710 : }} while (0)
711 :
712 2 : s1 = fnum_find("STANDARD_INFO");
713 2 : correct_size = s1->standard_info.out.size;
714 2 : torture_comment(torture, "size: %u\n", (unsigned int)correct_size);
715 :
716 2 : SIZE_CHECK("GETATTR", getattr, size);
717 2 : SIZE_CHECK("GETATTRE", getattre, size);
718 2 : SIZE_CHECK("STANDARD", standard, size);
719 2 : SIZE_CHECK("EA_SIZE", ea_size, size);
720 2 : SIZE_CHECK("STANDARD_INFO", standard_info, size);
721 2 : SIZE_CHECK("STANDARD_INFORMATION", standard_info, size);
722 2 : SIZE_CHECK("ALL_INFO", all_info, size);
723 2 : SIZE_CHECK("ALL_INFORMATION", all_info, size);
724 2 : SIZE_CHECK("COMPRESSION_INFO", compression_info, compressed_size);
725 2 : SIZE_CHECK("COMPRESSION_INFORMATION", compression_info, compressed_size);
726 2 : SIZE_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, size);
727 2 : if (!skip_streams) {
728 1 : SIZE_CHECK("STREAM_INFO", stream_info, streams[0].size);
729 1 : SIZE_CHECK("STREAM_INFORMATION", stream_info, streams[0].size);
730 : }
731 :
732 :
733 2 : s1 = fnum_find("STANDARD_INFO");
734 2 : correct_size = s1->standard_info.out.alloc_size;
735 2 : torture_comment(torture, "alloc_size: %u\n", (unsigned int)correct_size);
736 :
737 2 : SIZE_CHECK("GETATTRE", getattre, alloc_size);
738 2 : SIZE_CHECK("STANDARD", standard, alloc_size);
739 2 : SIZE_CHECK("EA_SIZE", ea_size, alloc_size);
740 2 : SIZE_CHECK("STANDARD_INFO", standard_info, alloc_size);
741 2 : SIZE_CHECK("STANDARD_INFORMATION", standard_info, alloc_size);
742 2 : SIZE_CHECK("ALL_INFO", all_info, alloc_size);
743 2 : SIZE_CHECK("ALL_INFORMATION", all_info, alloc_size);
744 2 : SIZE_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, alloc_size);
745 2 : if (!skip_streams) {
746 1 : SIZE_CHECK("STREAM_INFO", stream_info, streams[0].alloc_size);
747 1 : SIZE_CHECK("STREAM_INFORMATION", stream_info, streams[0].alloc_size);
748 : }
749 :
750 : #define ATTRIB_CHECK(sname, stype, tfield) do { \
751 : s1 = fnum_find(sname); \
752 : if (s1 && s1->stype.out.tfield != correct_attrib) { \
753 : printf("(%d) handle %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield, \
754 : (unsigned int)s1->stype.out.tfield, \
755 : (unsigned int)correct_attrib); \
756 : ret = false; \
757 : } \
758 : s1 = fname_find(is_ipc, sname); \
759 : if (s1 && s1->stype.out.tfield != correct_attrib) { \
760 : printf("(%d) path %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield, \
761 : (unsigned int)s1->stype.out.tfield, \
762 : (unsigned int)correct_attrib); \
763 : ret = false; \
764 : }} while (0)
765 :
766 2 : s1 = fnum_find("BASIC_INFO");
767 2 : correct_attrib = s1->basic_info.out.attrib;
768 2 : torture_comment(torture, "attrib: 0x%x\n", (unsigned int)correct_attrib);
769 :
770 2 : ATTRIB_CHECK("GETATTR", getattr, attrib);
771 2 : if (!is_ipc) {
772 1 : ATTRIB_CHECK("GETATTRE", getattre, attrib);
773 1 : ATTRIB_CHECK("STANDARD", standard, attrib);
774 1 : ATTRIB_CHECK("EA_SIZE", ea_size, attrib);
775 : }
776 2 : ATTRIB_CHECK("BASIC_INFO", basic_info, attrib);
777 2 : ATTRIB_CHECK("BASIC_INFORMATION", basic_info, attrib);
778 2 : ATTRIB_CHECK("ALL_INFO", all_info, attrib);
779 2 : ATTRIB_CHECK("ALL_INFORMATION", all_info, attrib);
780 2 : ATTRIB_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, attrib);
781 2 : ATTRIB_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
782 :
783 2 : correct_name = fname;
784 2 : torture_comment(torture, "name: %s\n", correct_name);
785 :
786 : #define NAME_CHECK(sname, stype, tfield, flags) do { \
787 : s1 = fnum_find(sname); \
788 : if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
789 : wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
790 : printf("(%d) handle %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \
791 : s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
792 : ret = false; \
793 : } \
794 : s1 = fname_find(is_ipc, sname); \
795 : if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
796 : wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
797 : printf("(%d) path %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \
798 : s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
799 : ret = false; \
800 : }} while (0)
801 :
802 2 : NAME_CHECK("NAME_INFO", name_info, fname, STR_UNICODE);
803 2 : NAME_CHECK("NAME_INFORMATION", name_info, fname, STR_UNICODE);
804 :
805 : /* the ALL_INFO file name is the full path on the filesystem */
806 2 : s1 = fnum_find("ALL_INFO");
807 2 : if (s1 && !s1->all_info.out.fname.s) {
808 0 : torture_fail(torture, "ALL_INFO didn't give a filename");
809 : }
810 2 : if (s1 && s1->all_info.out.fname.s) {
811 2 : char *p = strrchr(s1->all_info.out.fname.s, '\\');
812 2 : if (!p) {
813 0 : printf("Not a full path in all_info/fname? - '%s'\n",
814 : s1->all_info.out.fname.s);
815 0 : ret = false;
816 : } else {
817 2 : if (strcmp_safe(correct_name, p) != 0) {
818 0 : printf("incorrect basename in all_info/fname - '%s'\n",
819 : s1->all_info.out.fname.s);
820 0 : ret = false;
821 : }
822 : }
823 2 : if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE, tree->session->transport)) {
824 0 : printf("Should not null terminate all_info/fname\n");
825 0 : ret = false;
826 : }
827 : }
828 :
829 2 : s1 = fnum_find("ALT_NAME_INFO");
830 2 : if (s1) {
831 1 : correct_name = s1->alt_name_info.out.fname.s;
832 : }
833 :
834 2 : if (!correct_name) {
835 0 : torture_comment(torture, "no alternate name information\n");
836 : } else {
837 2 : torture_comment(torture, "alt_name: %s\n", correct_name);
838 :
839 2 : NAME_CHECK("ALT_NAME_INFO", alt_name_info, fname, STR_UNICODE);
840 2 : NAME_CHECK("ALT_NAME_INFORMATION", alt_name_info, fname, STR_UNICODE);
841 :
842 : /* and make sure we can open by alternate name */
843 2 : smbcli_close(tree, fnum);
844 2 : fnum = smbcli_nt_create_full(tree, correct_name, 0,
845 : SEC_RIGHTS_FILE_ALL,
846 : FILE_ATTRIBUTE_NORMAL,
847 : NTCREATEX_SHARE_ACCESS_DELETE|
848 : NTCREATEX_SHARE_ACCESS_READ|
849 : NTCREATEX_SHARE_ACCESS_WRITE,
850 : NTCREATEX_DISP_OVERWRITE_IF,
851 : 0, 0);
852 2 : if (fnum == -1) {
853 0 : printf("Unable to open by alt_name - %s\n", smbcli_errstr(tree));
854 0 : ret = false;
855 : }
856 :
857 2 : if (!skip_streams) {
858 1 : correct_name = "::$DATA";
859 1 : torture_comment(torture, "stream_name: %s\n", correct_name);
860 :
861 1 : NAME_CHECK("STREAM_INFO", stream_info, streams[0].stream_name, STR_UNICODE);
862 1 : NAME_CHECK("STREAM_INFORMATION", stream_info, streams[0].stream_name, STR_UNICODE);
863 : }
864 : }
865 :
866 : /* make sure the EAs look right */
867 2 : s1 = fnum_find("ALL_EAS");
868 2 : s2 = fnum_find("ALL_INFO");
869 2 : if (s1) {
870 3 : for (i=0;i<s1->all_eas.out.num_eas;i++) {
871 2 : printf(" flags=%d %s=%*.*s\n",
872 2 : s1->all_eas.out.eas[i].flags,
873 2 : s1->all_eas.out.eas[i].name.s,
874 2 : (int)s1->all_eas.out.eas[i].value.length,
875 2 : (int)s1->all_eas.out.eas[i].value.length,
876 2 : s1->all_eas.out.eas[i].value.data);
877 : }
878 : }
879 2 : if (s1 && s2) {
880 1 : if (s1->all_eas.out.num_eas == 0) {
881 0 : if (s2->all_info.out.ea_size != 0) {
882 0 : printf("ERROR: num_eas==0 but fnum all_info.out.ea_size == %d\n",
883 : s2->all_info.out.ea_size);
884 : }
885 : } else {
886 1 : if (s2->all_info.out.ea_size !=
887 1 : ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas)) {
888 0 : printf("ERROR: ea_list_size=%d != fnum all_info.out.ea_size=%d\n",
889 0 : (int)ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas),
890 0 : (int)s2->all_info.out.ea_size);
891 : }
892 : }
893 : }
894 2 : s2 = fname_find(is_ipc, "ALL_EAS");
895 2 : if (s2) {
896 1 : VAL_EQUAL(all_eas, num_eas, all_eas, num_eas);
897 3 : for (i=0;i<s1->all_eas.out.num_eas;i++) {
898 2 : VAL_EQUAL(all_eas, eas[i].flags, all_eas, eas[i].flags);
899 2 : STR_EQUAL(all_eas, eas[i].name, all_eas, eas[i].name);
900 2 : VAL_EQUAL(all_eas, eas[i].value.length, all_eas, eas[i].value.length);
901 : }
902 : }
903 :
904 : #define VAL_CHECK(sname1, stype1, tfield1, sname2, stype2, tfield2) do { \
905 : s1 = fnum_find(sname1); s2 = fnum_find(sname2); \
906 : if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
907 : printf("(%d) handle %s/%s != %s/%s - 0x%x vs 0x%x\n", __LINE__, \
908 : #stype1, #tfield1, #stype2, #tfield2, \
909 : s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
910 : ret = false; \
911 : } \
912 : s1 = fname_find(is_ipc, sname1); s2 = fname_find(is_ipc, sname2); \
913 : if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
914 : printf("(%d) path %s/%s != %s/%s - 0x%x vs 0x%x\n", __LINE__, \
915 : #stype1, #tfield1, #stype2, #tfield2, \
916 : s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
917 : ret = false; \
918 : } \
919 : s1 = fnum_find(sname1); s2 = fname_find(is_ipc, sname2); \
920 : if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
921 : printf("(%d) handle %s/%s != path %s/%s - 0x%x vs 0x%x\n", __LINE__, \
922 : #stype1, #tfield1, #stype2, #tfield2, \
923 : s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
924 : ret = false; \
925 : } \
926 : s1 = fname_find(is_ipc, sname1); s2 = fnum_find(sname2); \
927 : if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
928 : printf("(%d) path %s/%s != handle %s/%s - 0x%x vs 0x%x\n", __LINE__, \
929 : #stype1, #tfield1, #stype2, #tfield2, \
930 : s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
931 : ret = false; \
932 : }} while (0)
933 :
934 2 : VAL_CHECK("STANDARD_INFO", standard_info, delete_pending,
935 : "ALL_INFO", all_info, delete_pending);
936 2 : VAL_CHECK("STANDARD_INFO", standard_info, directory,
937 : "ALL_INFO", all_info, directory);
938 2 : VAL_CHECK("STANDARD_INFO", standard_info, nlink,
939 : "ALL_INFO", all_info, nlink);
940 2 : s1 = fnum_find("BASIC_INFO");
941 2 : if (s1 && is_ipc) {
942 1 : if (s1->basic_info.out.attrib != FILE_ATTRIBUTE_NORMAL) {
943 0 : printf("(%d) attrib basic_info/nlink incorrect - %d should be %d\n", __LINE__, s1->basic_info.out.attrib, (int)FILE_ATTRIBUTE_NORMAL);
944 0 : ret = false;
945 : }
946 : }
947 2 : s1 = fnum_find("STANDARD_INFO");
948 2 : if (s1 && is_ipc) {
949 1 : if (s1->standard_info.out.nlink != 1) {
950 0 : printf("(%d) nlinks standard_info/nlink incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.nlink);
951 0 : ret = false;
952 : }
953 1 : if (s1->standard_info.out.delete_pending != 1) {
954 0 : printf("(%d) nlinks standard_info/delete_pending incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.delete_pending);
955 0 : ret = false;
956 : }
957 : }
958 2 : VAL_CHECK("EA_INFO", ea_info, ea_size,
959 : "ALL_INFO", all_info, ea_size);
960 2 : if (!is_ipc) {
961 1 : VAL_CHECK("EA_SIZE", ea_size, ea_size,
962 : "ALL_INFO", all_info, ea_size);
963 : }
964 :
965 : #define NAME_PATH_CHECK(sname, stype, field) do { \
966 : s1 = fname_find(is_ipc, sname); s2 = fnum_find(sname); \
967 : if (s1 && s2) { \
968 : VAL_EQUAL(stype, field, stype, field); \
969 : } \
970 : } while (0)
971 :
972 :
973 2 : s1 = fnum_find("INTERNAL_INFORMATION");
974 2 : if (s1) {
975 2 : torture_comment(torture, "file_id=%.0f\n", (double)s1->internal_information.out.file_id);
976 : }
977 :
978 2 : NAME_PATH_CHECK("INTERNAL_INFORMATION", internal_information, file_id);
979 2 : NAME_PATH_CHECK("POSITION_INFORMATION", position_information, position);
980 2 : if (s1 && s2) {
981 1 : printf("fnum pos = %.0f, fname pos = %.0f\n",
982 1 : (double)s2->position_information.out.position,
983 1 : (double)s1->position_information.out.position );
984 : }
985 2 : NAME_PATH_CHECK("MODE_INFORMATION", mode_information, mode);
986 2 : NAME_PATH_CHECK("ALIGNMENT_INFORMATION", alignment_information, alignment_requirement);
987 2 : NAME_PATH_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
988 2 : NAME_PATH_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, reparse_tag);
989 :
990 : #if 0
991 : /* these are expected to differ */
992 : NAME_PATH_CHECK("ACCESS_INFORMATION", access_information, access_flags);
993 : #endif
994 :
995 : #if 0 /* unused */
996 : #define UNKNOWN_CHECK(sname, stype, tfield) do { \
997 : s1 = fnum_find(sname); \
998 : if (s1 && s1->stype.out.tfield != 0) { \
999 : printf("(%d) handle %s/%s unknown != 0 (0x%x)\n", __LINE__, \
1000 : #stype, #tfield, \
1001 : (unsigned int)s1->stype.out.tfield); \
1002 : } \
1003 : s1 = fname_find(is_ipc, sname); \
1004 : if (s1 && s1->stype.out.tfield != 0) { \
1005 : printf("(%d) path %s/%s unknown != 0 (0x%x)\n", __LINE__, \
1006 : #stype, #tfield, \
1007 : (unsigned int)s1->stype.out.tfield); \
1008 : }} while (0)
1009 : #endif
1010 : /* now get a bit fancier .... */
1011 :
1012 : /* when we set the delete disposition then the link count should drop
1013 : to 0 and delete_pending should be 1 */
1014 :
1015 2 : return ret;
1016 : }
1017 :
1018 : /* basic testing of all RAW_FILEINFO_* calls
1019 : for each call we test that it succeeds, and where possible test
1020 : for consistency between the calls.
1021 : */
1022 1 : bool torture_raw_qfileinfo(struct torture_context *torture,
1023 : struct smbcli_state *cli)
1024 : {
1025 0 : int fnum;
1026 0 : bool ret;
1027 1 : const char *fname = "\\torture_qfileinfo.txt";
1028 :
1029 1 : fnum = create_complex_file(cli, torture, fname);
1030 1 : if (fnum == -1) {
1031 0 : printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1032 0 : return false;
1033 : }
1034 :
1035 1 : ret = torture_raw_qfileinfo_internals(torture, torture, cli->tree, fnum, fname, false /* is_ipc */);
1036 :
1037 1 : smbcli_close(cli->tree, fnum);
1038 1 : smbcli_unlink(cli->tree, fname);
1039 :
1040 1 : return ret;
1041 : }
1042 :
1043 1 : bool torture_raw_qfileinfo_pipe(struct torture_context *torture,
1044 : struct smbcli_state *cli)
1045 : {
1046 1 : bool ret = true;
1047 0 : int fnum;
1048 1 : const char *fname = "\\lsass";
1049 0 : union smb_open op;
1050 0 : NTSTATUS status;
1051 :
1052 1 : op.ntcreatex.level = RAW_OPEN_NTCREATEX;
1053 1 : op.ntcreatex.in.flags = 0;
1054 1 : op.ntcreatex.in.root_fid.fnum = 0;
1055 1 : op.ntcreatex.in.access_mask =
1056 : SEC_STD_READ_CONTROL |
1057 : SEC_FILE_WRITE_ATTRIBUTE |
1058 : SEC_FILE_WRITE_EA |
1059 : SEC_FILE_READ_DATA |
1060 : SEC_FILE_WRITE_DATA;
1061 1 : op.ntcreatex.in.file_attr = 0;
1062 1 : op.ntcreatex.in.alloc_size = 0;
1063 1 : op.ntcreatex.in.share_access =
1064 : NTCREATEX_SHARE_ACCESS_READ |
1065 : NTCREATEX_SHARE_ACCESS_WRITE;
1066 1 : op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1067 1 : op.ntcreatex.in.create_options = 0;
1068 1 : op.ntcreatex.in.impersonation =
1069 : NTCREATEX_IMPERSONATION_IMPERSONATION;
1070 1 : op.ntcreatex.in.security_flags = 0;
1071 1 : op.ntcreatex.in.fname = fname;
1072 :
1073 1 : status = smb_raw_open(cli->tree, torture, &op);
1074 1 : torture_assert_ntstatus_ok(torture, status, "smb_raw_open failed");
1075 :
1076 1 : fnum = op.ntcreatex.out.file.fnum;
1077 :
1078 1 : ret = torture_raw_qfileinfo_internals(torture, torture, cli->tree,
1079 : fnum, fname,
1080 : true /* is_ipc */);
1081 :
1082 1 : smbcli_close(cli->tree, fnum);
1083 1 : return ret;
1084 : }
|