2 Unix SMB/CIFS implementation.
4 test alternate data streams
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/locale.h"
24 #include "torture/torture.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "system/filesys.h"
27 #include "libcli/libcli.h"
28 #include "torture/util.h"
30 #define BASEDIR "\\teststreams"
32 #define CHECK_STATUS(status, correct) do { \
33 if (!NT_STATUS_EQUAL(status, correct)) { \
34 printf("(%s) Incorrect status %s - should be %s\n", \
35 __location__, nt_errstr(status), nt_errstr(correct)); \
40 #define CHECK_VALUE(v, correct) do { \
41 if ((v) != (correct)) { \
42 printf("(%s) Incorrect value %s=%d - should be %d\n", \
43 __location__, #v, (int)v, (int)correct); \
47 #define CHECK_NTTIME(v, correct) do { \
48 if ((v) != (correct)) { \
49 printf("(%s) Incorrect value %s=%llu - should be %llu\n", \
50 __location__, #v, (unsigned long long)v, \
51 (unsigned long long)correct); \
55 #define CHECK_STR(v, correct) do { \
57 if ((v) && !(correct)) { \
59 } else if (!(v) && (correct)) { \
61 } else if (!(v) && !(correct)) { \
63 } else if (strcmp((v), (correct)) == 0) { \
69 printf("(%s) Incorrect value %s='%s' - should be '%s'\n", \
70 __location__, #v, (v)?(v):"NULL", \
71 (correct)?(correct):"NULL"); \
76 check that a stream has the right contents
78 static bool check_stream(struct smbcli_state
*cli
, const char *location
,
80 const char *fname
, const char *sname
,
84 const char *full_name
;
88 full_name
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, sname
);
90 fnum
= smbcli_open(cli
->tree
, full_name
, O_RDONLY
, DENY_NONE
);
94 printf("(%s) should have failed stream open of %s\n",
102 printf("(%s) Failed to open stream '%s' - %s\n",
103 location
, full_name
, smbcli_errstr(cli
->tree
));
107 buf
= talloc_array(mem_ctx
, uint8_t, strlen(value
)+11);
109 ret
= smbcli_read(cli
->tree
, fnum
, buf
, 0, strlen(value
)+11);
110 if (ret
!= strlen(value
)) {
111 printf("(%s) Failed to read %lu bytes from stream '%s' - got %d\n",
112 location
, (long)strlen(value
), full_name
, (int)ret
);
116 if (memcmp(buf
, value
, strlen(value
)) != 0) {
117 printf("(%s) Bad data in stream\n", location
);
121 smbcli_close(cli
->tree
, fnum
);
125 static int qsort_string(const void *v1
, const void *v2
)
127 char * const *s1
= v1
;
128 char * const *s2
= v2
;
129 return strcmp(*s1
, *s2
);
132 static int qsort_stream(const void *v1
, const void *v2
)
134 const struct stream_struct
* s1
= v1
;
135 const struct stream_struct
* s2
= v2
;
136 return strcmp(s1
->stream_name
.s
, s2
->stream_name
.s
);
139 static bool check_stream_list(struct smbcli_state
*cli
, const char *fname
,
140 int num_exp
, const char **exp
)
142 union smb_fileinfo finfo
;
145 TALLOC_CTX
*tmp_ctx
= talloc_new(cli
);
147 struct stream_struct
*stream_sort
;
150 finfo
.generic
.level
= RAW_FILEINFO_STREAM_INFO
;
151 finfo
.generic
.in
.file
.path
= fname
;
153 status
= smb_raw_pathinfo(cli
->tree
, tmp_ctx
, &finfo
);
154 if (!NT_STATUS_IS_OK(status
)) {
155 d_fprintf(stderr
, "(%s) smb_raw_pathinfo failed: %s\n",
156 __location__
, nt_errstr(status
));
160 if (finfo
.stream_info
.out
.num_streams
!= num_exp
) {
161 d_fprintf(stderr
, "(%s) expected %d streams, got %d\n",
162 __location__
, num_exp
,
163 finfo
.stream_info
.out
.num_streams
);
172 exp_sort
= talloc_memdup(tmp_ctx
, exp
, num_exp
* sizeof(*exp
));
174 if (exp_sort
== NULL
) {
178 qsort(exp_sort
, num_exp
, sizeof(*exp_sort
), qsort_string
);
180 stream_sort
= talloc_memdup(tmp_ctx
, finfo
.stream_info
.out
.streams
,
181 finfo
.stream_info
.out
.num_streams
*
182 sizeof(*stream_sort
));
184 if (stream_sort
== NULL
) {
188 qsort(stream_sort
, finfo
.stream_info
.out
.num_streams
,
189 sizeof(*stream_sort
), qsort_stream
);
191 for (i
=0; i
<num_exp
; i
++) {
192 if (strcmp(exp_sort
[i
], stream_sort
[i
].stream_name
.s
) != 0) {
193 d_fprintf(stderr
, "(%s) expected stream name %s, got "
194 "%s\n", __location__
, exp_sort
[i
],
195 stream_sort
[i
].stream_name
.s
);
202 talloc_free(tmp_ctx
);
207 test bahavior of streams on directories
209 static bool test_stream_dir(struct torture_context
*tctx
,
210 struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
214 const char *fname
= BASEDIR
"\\stream.txt";
217 const char *basedir_data
;
219 basedir_data
= talloc_asprintf(mem_ctx
, "%s::$DATA", BASEDIR
);
220 sname1
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, "Stream One");
222 printf("(%s) opening non-existant directory stream\n", __location__
);
223 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
224 io
.ntcreatex
.in
.root_fid
= 0;
225 io
.ntcreatex
.in
.flags
= 0;
226 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
227 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
228 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
229 io
.ntcreatex
.in
.share_access
= 0;
230 io
.ntcreatex
.in
.alloc_size
= 0;
231 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
232 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
233 io
.ntcreatex
.in
.security_flags
= 0;
234 io
.ntcreatex
.in
.fname
= sname1
;
235 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
236 CHECK_STATUS(status
, NT_STATUS_NOT_A_DIRECTORY
);
238 printf("(%s) opening basedir stream\n", __location__
);
239 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
240 io
.ntcreatex
.in
.root_fid
= 0;
241 io
.ntcreatex
.in
.flags
= 0;
242 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
243 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
244 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
245 io
.ntcreatex
.in
.share_access
= 0;
246 io
.ntcreatex
.in
.alloc_size
= 0;
247 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
248 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
249 io
.ntcreatex
.in
.security_flags
= 0;
250 io
.ntcreatex
.in
.fname
= basedir_data
;
251 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
252 CHECK_STATUS(status
, NT_STATUS_NOT_A_DIRECTORY
);
254 printf("(%s) opening basedir ::$DATA stream\n", __location__
);
255 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
256 io
.ntcreatex
.in
.root_fid
= 0;
257 io
.ntcreatex
.in
.flags
= 0x10;
258 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
259 io
.ntcreatex
.in
.create_options
= 0;
260 io
.ntcreatex
.in
.file_attr
= 0;
261 io
.ntcreatex
.in
.share_access
= 0;
262 io
.ntcreatex
.in
.alloc_size
= 0;
263 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
264 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
265 io
.ntcreatex
.in
.security_flags
= 0;
266 io
.ntcreatex
.in
.fname
= basedir_data
;
267 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
268 CHECK_STATUS(status
, NT_STATUS_FILE_IS_A_DIRECTORY
);
270 printf("(%s) list the streams on the basedir\n", __location__
);
271 ret
&= check_stream_list(cli
, BASEDIR
, 0, NULL
);
277 test basic behavior of streams on directories
279 static bool test_stream_io(struct torture_context
*tctx
,
280 struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
284 const char *fname
= BASEDIR
"\\stream.txt";
285 const char *sname1
, *sname2
;
290 const char *one
[] = { "::$DATA" };
291 const char *two
[] = { "::$DATA", ":Second Stream:$DATA" };
292 const char *three
[] = { "::$DATA", ":Stream One:$DATA",
293 ":Second Stream:$DATA" };
295 sname1
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, "Stream One");
296 sname2
= talloc_asprintf(mem_ctx
, "%s:%s:$DaTa", fname
, "Second Stream");
298 printf("(%s) creating a stream on a non-existant file\n", __location__
);
299 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
300 io
.ntcreatex
.in
.root_fid
= 0;
301 io
.ntcreatex
.in
.flags
= 0;
302 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
303 io
.ntcreatex
.in
.create_options
= 0;
304 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
305 io
.ntcreatex
.in
.share_access
= 0;
306 io
.ntcreatex
.in
.alloc_size
= 0;
307 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
308 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
309 io
.ntcreatex
.in
.security_flags
= 0;
310 io
.ntcreatex
.in
.fname
= sname1
;
311 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
312 CHECK_STATUS(status
, NT_STATUS_OK
);
313 fnum
= io
.ntcreatex
.out
.file
.fnum
;
315 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Stream One", NULL
);
317 printf("(%s) check that open of base file is allowed\n", __location__
);
318 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
319 io
.ntcreatex
.in
.fname
= fname
;
320 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
321 CHECK_STATUS(status
, NT_STATUS_OK
);
322 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
324 printf("(%s) writing to stream\n", __location__
);
325 retsize
= smbcli_write(cli
->tree
, fnum
, 0, "test data", 0, 9);
326 CHECK_VALUE(retsize
, 9);
328 smbcli_close(cli
->tree
, fnum
);
330 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Stream One", "test data");
332 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
333 io
.ntcreatex
.in
.fname
= sname1
;
334 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
335 CHECK_STATUS(status
, NT_STATUS_OK
);
336 fnum
= io
.ntcreatex
.out
.file
.fnum
;
338 printf("(%s) modifying stream\n", __location__
);
339 retsize
= smbcli_write(cli
->tree
, fnum
, 0, "MORE DATA ", 5, 10);
340 CHECK_VALUE(retsize
, 10);
342 smbcli_close(cli
->tree
, fnum
);
344 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Stream One:$FOO", NULL
);
346 printf("(%s) creating a stream2 on a existing file\n", __location__
);
347 io
.ntcreatex
.in
.fname
= sname2
;
348 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
349 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
350 CHECK_STATUS(status
, NT_STATUS_OK
);
351 fnum
= io
.ntcreatex
.out
.file
.fnum
;
353 printf("(%s) modifying stream\n", __location__
);
354 retsize
= smbcli_write(cli
->tree
, fnum
, 0, "SECOND STREAM", 0, 13);
355 CHECK_VALUE(retsize
, 13);
357 smbcli_close(cli
->tree
, fnum
);
359 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Stream One", "test MORE DATA ");
360 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Stream One:$DATA", "test MORE DATA ");
361 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Stream One:", NULL
);
362 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Second Stream", "SECOND STREAM");
363 if (!torture_setting_bool(tctx
, "samba4", false)) {
364 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
,
365 "SECOND STREAM:$DATA", "SECOND STREAM");
367 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Second Stream:$DATA", "SECOND STREAM");
368 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Second Stream:", NULL
);
369 ret
&= check_stream(cli
, __location__
, mem_ctx
, fname
, "Second Stream:$FOO", NULL
);
371 check_stream_list(cli
, fname
, 3, three
);
373 printf("(%s) deleting stream\n", __location__
);
374 status
= smbcli_unlink(cli
->tree
, sname1
);
375 CHECK_STATUS(status
, NT_STATUS_OK
);
377 check_stream_list(cli
, fname
, 2, two
);
379 printf("(%s) delete a stream via delete-on-close\n", __location__
);
380 io
.ntcreatex
.in
.fname
= sname2
;
381 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
382 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
;
383 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
384 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
386 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
387 CHECK_STATUS(status
, NT_STATUS_OK
);
388 fnum
= io
.ntcreatex
.out
.file
.fnum
;
390 smbcli_close(cli
->tree
, fnum
);
391 status
= smbcli_unlink(cli
->tree
, sname2
);
392 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
394 check_stream_list(cli
, fname
, 1, one
);
396 if (!torture_setting_bool(tctx
, "samba4", false)) {
397 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
398 io
.ntcreatex
.in
.fname
= sname1
;
399 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
400 CHECK_STATUS(status
, NT_STATUS_OK
);
401 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
402 io
.ntcreatex
.in
.fname
= sname2
;
403 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
404 CHECK_STATUS(status
, NT_STATUS_OK
);
405 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
408 printf("(%s) deleting file\n", __location__
);
409 status
= smbcli_unlink(cli
->tree
, fname
);
410 CHECK_STATUS(status
, NT_STATUS_OK
);
413 smbcli_close(cli
->tree
, fnum
);
418 test stream sharemodes
420 static bool test_stream_sharemodes(struct torture_context
*tctx
,
421 struct smbcli_state
*cli
,
426 const char *fname
= BASEDIR
"\\stream.txt";
427 const char *sname1
, *sname2
;
432 sname1
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, "Stream One");
433 sname2
= talloc_asprintf(mem_ctx
, "%s:%s:$DaTa", fname
, "Second Stream");
435 printf("(%s) testing stream share mode conflicts\n", __location__
);
436 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
437 io
.ntcreatex
.in
.root_fid
= 0;
438 io
.ntcreatex
.in
.flags
= 0;
439 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
440 io
.ntcreatex
.in
.create_options
= 0;
441 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
442 io
.ntcreatex
.in
.share_access
= 0;
443 io
.ntcreatex
.in
.alloc_size
= 0;
444 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
445 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
446 io
.ntcreatex
.in
.security_flags
= 0;
447 io
.ntcreatex
.in
.fname
= sname1
;
449 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
450 CHECK_STATUS(status
, NT_STATUS_OK
);
451 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
454 * A different stream does not give a sharing violation
457 io
.ntcreatex
.in
.fname
= sname2
;
458 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
459 CHECK_STATUS(status
, NT_STATUS_OK
);
460 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
463 * ... whereas the same stream does with unchanged access/share_access
467 io
.ntcreatex
.in
.fname
= sname1
;
468 io
.ntcreatex
.in
.open_disposition
= 0;
469 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
470 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
472 io
.ntcreatex
.in
.fname
= sname2
;
473 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
474 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
477 if (fnum1
!= -1) smbcli_close(cli
->tree
, fnum1
);
478 if (fnum2
!= -1) smbcli_close(cli
->tree
, fnum2
);
479 status
= smbcli_unlink(cli
->tree
, fname
);
484 * Test FILE_SHARE_DELETE on streams
486 * A stream opened with !FILE_SHARE_DELETE prevents the main file to be opened
487 * with SEC_STD_DELETE.
489 * The main file opened with !FILE_SHARE_DELETE does *not* prevent a stream to
490 * be opened with SEC_STD_DELETE.
492 * A stream held open with FILE_SHARE_DELETE allows the file to be
493 * deleted. After the main file is deleted, access to the open file descriptor
494 * still works, but all name-based access to both the main file as well as the
495 * stream is denied with DELETE ending.
497 * This means, an open of the main file with SEC_STD_DELETE should walk all
498 * streams and also open them with SEC_STD_DELETE. If any of these opens gives
499 * SHARING_VIOLATION, the main open fails.
501 * Closing the main file after delete_on_close has been set does not really
502 * unlink it but leaves the corresponding share mode entry with
503 * delete_on_close being set around until all streams are closed.
505 * Opening a stream must also look at the main file's share mode entry, look
506 * at the delete_on_close bit and potentially return DELETE_PENDING.
509 static bool test_stream_delete(struct torture_context
*tctx
,
510 struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
514 const char *fname
= BASEDIR
"\\stream.txt";
520 union smb_fileinfo finfo
;
522 sname1
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, "Stream One");
524 printf("(%s) opening non-existant file stream\n", __location__
);
525 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
526 io
.ntcreatex
.in
.root_fid
= 0;
527 io
.ntcreatex
.in
.flags
= 0;
528 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
;
529 io
.ntcreatex
.in
.create_options
= 0;
530 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
531 io
.ntcreatex
.in
.share_access
= 0;
532 io
.ntcreatex
.in
.alloc_size
= 0;
533 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
534 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
535 io
.ntcreatex
.in
.security_flags
= 0;
536 io
.ntcreatex
.in
.fname
= sname1
;
538 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
539 CHECK_STATUS(status
, NT_STATUS_OK
);
540 fnum
= io
.ntcreatex
.out
.file
.fnum
;
542 retsize
= smbcli_write(cli
->tree
, fnum
, 0, "test data", 0, 9);
543 CHECK_VALUE(retsize
, 9);
546 * One stream opened without FILE_SHARE_DELETE prevents the main file
547 * to be deleted or even opened with DELETE access
550 status
= smbcli_unlink(cli
->tree
, fname
);
551 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
553 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
554 io
.ntcreatex
.in
.fname
= fname
;
555 io
.ntcreatex
.in
.access_mask
= SEC_STD_DELETE
;
556 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
557 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
559 smbcli_close(cli
->tree
, fnum
);
562 * ... but unlink works if a stream is opened with FILE_SHARE_DELETE
565 io
.ntcreatex
.in
.fname
= sname1
;
566 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
;
567 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_DELETE
;
568 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
569 CHECK_STATUS(status
, NT_STATUS_OK
);
570 fnum
= io
.ntcreatex
.out
.file
.fnum
;
572 status
= smbcli_unlink(cli
->tree
, fname
);
573 CHECK_STATUS(status
, NT_STATUS_OK
);
576 * file access still works on the stream while the main file is closed
579 retsize
= smbcli_read(cli
->tree
, fnum
, buf
, 0, 9);
580 CHECK_VALUE(retsize
, 9);
582 finfo
.generic
.level
= RAW_FILEINFO_STANDARD
;
583 finfo
.generic
.in
.file
.path
= fname
;
586 * name-based access to both the main file and the stream does not
587 * work anymore but gives DELETE_PENDING
590 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
591 CHECK_STATUS(status
, NT_STATUS_DELETE_PENDING
);
594 * older S3 doesn't do this
596 finfo
.generic
.in
.file
.path
= sname1
;
597 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
598 CHECK_STATUS(status
, NT_STATUS_DELETE_PENDING
);
601 * fd-based qfileinfo on the stream still works, the stream does not
602 * have the delete-on-close bit set. This could mean that open on the
603 * stream first opens the main file
606 finfo
.all_info
.level
= RAW_FILEINFO_ALL_INFO
;
607 finfo
.all_info
.in
.file
.fnum
= fnum
;
609 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &finfo
);
610 CHECK_STATUS(status
, NT_STATUS_OK
);
611 /* w2k and w2k3 return 0 and w2k8 returns 1
612 CHECK_VALUE(finfo.all_info.out.delete_pending, 0);
615 smbcli_close(cli
->tree
, fnum
);
618 * After closing the stream the file is really gone.
621 finfo
.generic
.in
.file
.path
= fname
;
622 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
623 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
625 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
627 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
628 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
629 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
630 CHECK_STATUS(status
, NT_STATUS_OK
);
631 fnum
= io
.ntcreatex
.out
.file
.fnum
;
633 finfo
.generic
.in
.file
.path
= fname
;
634 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
635 CHECK_STATUS(status
, NT_STATUS_OK
);
637 smbcli_close(cli
->tree
, fnum
);
639 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
640 CHECK_STATUS(status
, NT_STATUS_OK
);
642 smbcli_close(cli
->tree
, fnum
);
643 smbcli_unlink(cli
->tree
, fname
);
650 static bool test_stream_names(struct torture_context
*tctx
,
651 struct smbcli_state
*cli
,
656 union smb_fileinfo finfo
;
657 union smb_fileinfo stinfo
;
658 union smb_setfileinfo sinfo
;
659 const char *fname
= BASEDIR
"\\stream_names.txt";
660 const char *sname1
, *sname1b
, *sname1c
, *sname1d
;
661 const char *sname2
, *snamew
, *snamew2
;
662 const char *snamer1
, *snamer2
;
668 const char *four
[4] = {
670 ":\x05Stream\n One:$DATA",
671 ":MStream Two:$DATA",
674 const char *five1
[5] = {
676 ":\x05Stream\n One:$DATA",
677 ":BeforeRename:$DATA",
678 ":MStream Two:$DATA",
681 const char *five2
[5] = {
683 ":\x05Stream\n One:$DATA",
684 ":AfterRename:$DATA",
685 ":MStream Two:$DATA",
689 sname1
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, "\x05Stream\n One");
690 sname1b
= talloc_asprintf(mem_ctx
, "%s:", sname1
);
691 sname1c
= talloc_asprintf(mem_ctx
, "%s:$FOO", sname1
);
692 sname1d
= talloc_asprintf(mem_ctx
, "%s:?D*a", sname1
);
693 sname2
= talloc_asprintf(mem_ctx
, "%s:%s:$DaTa", fname
, "MStream Two");
694 snamew
= talloc_asprintf(mem_ctx
, "%s:%s:$DATA", fname
, "?Stream*");
695 snamew2
= talloc_asprintf(mem_ctx
, "%s\\stream*:%s:$DATA", BASEDIR
, "?Stream*");
696 snamer1
= talloc_asprintf(mem_ctx
, "%s:%s:$DATA", fname
, "BeforeRename");
697 snamer2
= talloc_asprintf(mem_ctx
, "%s:%s:$DATA", fname
, "AfterRename");
699 printf("(%s) testing stream names\n", __location__
);
700 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
701 io
.ntcreatex
.in
.root_fid
= 0;
702 io
.ntcreatex
.in
.flags
= 0;
703 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
704 io
.ntcreatex
.in
.create_options
= 0;
705 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
706 io
.ntcreatex
.in
.share_access
= 0;
707 io
.ntcreatex
.in
.alloc_size
= 0;
708 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
709 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
710 io
.ntcreatex
.in
.security_flags
= 0;
711 io
.ntcreatex
.in
.fname
= sname1
;
713 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
714 CHECK_STATUS(status
, NT_STATUS_OK
);
715 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
718 * A different stream does not give a sharing violation
721 io
.ntcreatex
.in
.fname
= sname2
;
722 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
723 CHECK_STATUS(status
, NT_STATUS_OK
);
724 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
727 * ... whereas the same stream does with unchanged access/share_access
731 io
.ntcreatex
.in
.fname
= sname1
;
732 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_SUPERSEDE
;
733 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
734 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
736 io
.ntcreatex
.in
.fname
= sname1b
;
737 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
738 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
740 io
.ntcreatex
.in
.fname
= sname1c
;
741 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
742 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
743 /* w2k returns INVALID_PARAMETER */
744 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
746 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
749 io
.ntcreatex
.in
.fname
= sname1d
;
750 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
751 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
752 /* w2k returns INVALID_PARAMETER */
753 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
755 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
758 io
.ntcreatex
.in
.fname
= sname2
;
759 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
760 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
762 io
.ntcreatex
.in
.fname
= snamew
;
763 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
764 CHECK_STATUS(status
, NT_STATUS_OK
);
765 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
767 io
.ntcreatex
.in
.fname
= snamew2
;
768 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
769 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
771 ret
&= check_stream_list(cli
, fname
, 4, four
);
773 smbcli_close(cli
->tree
, fnum1
);
774 smbcli_close(cli
->tree
, fnum2
);
775 smbcli_close(cli
->tree
, fnum3
);
777 if (torture_setting_bool(tctx
, "samba4", true)) {
781 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
782 finfo
.generic
.in
.file
.path
= fname
;
783 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
784 CHECK_STATUS(status
, NT_STATUS_OK
);
786 ret
&= check_stream_list(cli
, fname
, 4, four
);
788 for (i
=0; i
< 4; i
++) {
790 uint64_t stream_size
;
791 char *path
= talloc_asprintf(tctx
, "%s%s",
794 char *rpath
= talloc_strdup(path
, path
);
795 char *p
= strrchr(rpath
, ':');
803 printf("(%s): i[%u][%s]\n", __location__
, i
, path
);
804 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
805 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|
806 SEC_FILE_WRITE_ATTRIBUTE
|
808 io
.ntcreatex
.in
.fname
= path
;
809 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
810 CHECK_STATUS(status
, NT_STATUS_OK
);
811 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
813 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
814 finfo
.generic
.in
.file
.path
= fname
;
815 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
816 CHECK_STATUS(status
, NT_STATUS_OK
);
818 stinfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
819 stinfo
.generic
.in
.file
.fnum
= fnum1
;
820 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &stinfo
);
821 CHECK_STATUS(status
, NT_STATUS_OK
);
822 if (!torture_setting_bool(tctx
, "samba3", false)) {
823 CHECK_NTTIME(stinfo
.all_info
.out
.create_time
,
824 finfo
.all_info
.out
.create_time
);
825 CHECK_NTTIME(stinfo
.all_info
.out
.access_time
,
826 finfo
.all_info
.out
.access_time
);
827 CHECK_NTTIME(stinfo
.all_info
.out
.write_time
,
828 finfo
.all_info
.out
.write_time
);
829 CHECK_NTTIME(stinfo
.all_info
.out
.change_time
,
830 finfo
.all_info
.out
.change_time
);
832 CHECK_VALUE(stinfo
.all_info
.out
.attrib
,
833 finfo
.all_info
.out
.attrib
);
834 CHECK_VALUE(stinfo
.all_info
.out
.size
,
835 finfo
.all_info
.out
.size
);
836 CHECK_VALUE(stinfo
.all_info
.out
.delete_pending
,
837 finfo
.all_info
.out
.delete_pending
);
838 CHECK_VALUE(stinfo
.all_info
.out
.directory
,
839 finfo
.all_info
.out
.directory
);
840 CHECK_VALUE(stinfo
.all_info
.out
.ea_size
,
841 finfo
.all_info
.out
.ea_size
);
843 stinfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
844 stinfo
.generic
.in
.file
.fnum
= fnum1
;
845 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &stinfo
);
846 CHECK_STATUS(status
, NT_STATUS_OK
);
847 if (!torture_setting_bool(tctx
, "samba3", false)) {
848 CHECK_STR(rpath
, stinfo
.name_info
.out
.fname
.s
);
851 write_time
= finfo
.all_info
.out
.write_time
;
852 write_time
+= i
*1000000;
853 write_time
/= 1000000;
854 write_time
*= 1000000;
857 sinfo
.basic_info
.level
= RAW_SFILEINFO_BASIC_INFO
;
858 sinfo
.basic_info
.in
.file
.fnum
= fnum1
;
859 sinfo
.basic_info
.in
.write_time
= write_time
;
860 sinfo
.basic_info
.in
.attrib
= stinfo
.all_info
.out
.attrib
;
861 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
862 CHECK_STATUS(status
, NT_STATUS_OK
);
864 stream_size
= i
*8192;
867 sinfo
.end_of_file_info
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
868 sinfo
.end_of_file_info
.in
.file
.fnum
= fnum1
;
869 sinfo
.end_of_file_info
.in
.size
= stream_size
;
870 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
871 CHECK_STATUS(status
, NT_STATUS_OK
);
873 stinfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
874 stinfo
.generic
.in
.file
.fnum
= fnum1
;
875 status
= smb_raw_fileinfo(cli
->tree
, mem_ctx
, &stinfo
);
876 CHECK_STATUS(status
, NT_STATUS_OK
);
877 if (!torture_setting_bool(tctx
, "samba3", false)) {
878 CHECK_NTTIME(stinfo
.all_info
.out
.write_time
,
880 CHECK_VALUE(stinfo
.all_info
.out
.attrib
,
881 finfo
.all_info
.out
.attrib
);
883 CHECK_VALUE(stinfo
.all_info
.out
.size
,
885 CHECK_VALUE(stinfo
.all_info
.out
.delete_pending
,
886 finfo
.all_info
.out
.delete_pending
);
887 CHECK_VALUE(stinfo
.all_info
.out
.directory
,
888 finfo
.all_info
.out
.directory
);
889 CHECK_VALUE(stinfo
.all_info
.out
.ea_size
,
890 finfo
.all_info
.out
.ea_size
);
892 ret
&= check_stream_list(cli
, fname
, 4, four
);
894 smbcli_close(cli
->tree
, fnum1
);
898 printf("(%s): testing stream renames\n", __location__
);
899 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
900 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|
901 SEC_FILE_WRITE_ATTRIBUTE
|
903 io
.ntcreatex
.in
.fname
= snamer1
;
904 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
905 CHECK_STATUS(status
, NT_STATUS_OK
);
906 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
908 ret
&= check_stream_list(cli
, fname
, 5, five1
);
911 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
912 sinfo
.rename_information
.in
.file
.fnum
= fnum1
;
913 sinfo
.rename_information
.in
.overwrite
= true;
914 sinfo
.rename_information
.in
.root_fid
= 0;
915 sinfo
.rename_information
.in
.new_name
= ":AfterRename:$DATA";
916 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
917 CHECK_STATUS(status
, NT_STATUS_OK
);
919 ret
&= check_stream_list(cli
, fname
, 5, five2
);
922 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
923 sinfo
.rename_information
.in
.file
.fnum
= fnum1
;
924 sinfo
.rename_information
.in
.overwrite
= false;
925 sinfo
.rename_information
.in
.root_fid
= 0;
926 sinfo
.rename_information
.in
.new_name
= ":MStream Two:$DATA";
927 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
928 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
930 ret
&= check_stream_list(cli
, fname
, 5, five2
);
933 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
934 sinfo
.rename_information
.in
.file
.fnum
= fnum1
;
935 sinfo
.rename_information
.in
.overwrite
= true;
936 sinfo
.rename_information
.in
.root_fid
= 0;
937 sinfo
.rename_information
.in
.new_name
= ":MStream Two:$DATA";
938 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
939 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
941 ret
&= check_stream_list(cli
, fname
, 5, five2
);
943 /* TODO: we need to test more rename combinations */
946 if (fnum1
!= -1) smbcli_close(cli
->tree
, fnum1
);
947 if (fnum2
!= -1) smbcli_close(cli
->tree
, fnum2
);
948 if (fnum3
!= -1) smbcli_close(cli
->tree
, fnum3
);
949 status
= smbcli_unlink(cli
->tree
, fname
);
956 static bool test_stream_names2(struct torture_context
*tctx
,
957 struct smbcli_state
*cli
,
962 const char *fname
= BASEDIR
"\\stream_names2.txt";
967 printf("(%s) testing stream names\n", __location__
);
968 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
969 io
.ntcreatex
.in
.root_fid
= 0;
970 io
.ntcreatex
.in
.flags
= 0;
971 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
972 io
.ntcreatex
.in
.create_options
= 0;
973 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
974 io
.ntcreatex
.in
.share_access
= 0;
975 io
.ntcreatex
.in
.alloc_size
= 0;
976 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
977 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
978 io
.ntcreatex
.in
.security_flags
= 0;
979 io
.ntcreatex
.in
.fname
= fname
;
980 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
981 CHECK_STATUS(status
, NT_STATUS_OK
);
982 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
984 for (i
=0x01; i
< 0x7F; i
++) {
985 char *path
= talloc_asprintf(tctx
, "%s:Stream%c0x%02X:$DATA",
993 expected
= NT_STATUS_OBJECT_NAME_INVALID
;
996 expected
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1001 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1002 io
.ntcreatex
.in
.fname
= path
;
1003 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1004 if (!NT_STATUS_EQUAL(status
, expected
)) {
1005 printf("(%s) %s:Stream%c0x%02X:$DATA%s => expected[%s]\n",
1006 __location__
, fname
, isprint(i
)?(char)i
:' ', i
,
1007 isprint(i
)?"":" (not printable)",
1008 nt_errstr(expected
));
1010 CHECK_STATUS(status
, expected
);
1016 if (fnum1
!= -1) smbcli_close(cli
->tree
, fnum1
);
1017 status
= smbcli_unlink(cli
->tree
, fname
);
1021 #define CHECK_CALL_FNUM(call, rightstatus) do { \
1022 check_fnum = true; \
1023 call_name = #call; \
1024 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
1025 sfinfo.generic.in.file.fnum = fnum; \
1026 status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
1027 if (!NT_STATUS_EQUAL(status, rightstatus)) { \
1028 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
1029 nt_errstr(status), nt_errstr(rightstatus)); \
1032 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
1033 finfo1.generic.in.file.fnum = fnum; \
1034 status2 = smb_raw_fileinfo(cli->tree, tctx, &finfo1); \
1035 if (!NT_STATUS_IS_OK(status2)) { \
1036 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
1043 static bool test_stream_rename(struct torture_context
*tctx
,
1044 struct smbcli_state
*cli
,
1045 TALLOC_CTX
*mem_ctx
)
1047 NTSTATUS status
, status2
;
1049 const char *fname
= BASEDIR
"\\stream_rename.txt";
1050 const char *sname1
, *sname2
;
1051 union smb_fileinfo finfo1
;
1052 union smb_setfileinfo sfinfo
;
1056 const char *call_name
;
1058 sname1
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, "Stream One");
1059 sname2
= talloc_asprintf(mem_ctx
, "%s:%s:$DaTa", fname
, "Second Stream");
1061 printf("(%s) testing stream renames\n", __location__
);
1062 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1063 io
.ntcreatex
.in
.root_fid
= 0;
1064 io
.ntcreatex
.in
.flags
= 0;
1065 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|
1066 SEC_FILE_WRITE_ATTRIBUTE
|
1067 SEC_RIGHTS_FILE_ALL
;
1068 io
.ntcreatex
.in
.create_options
= 0;
1069 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1070 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
1071 io
.ntcreatex
.in
.alloc_size
= 0;
1072 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1073 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1074 io
.ntcreatex
.in
.security_flags
= 0;
1075 io
.ntcreatex
.in
.fname
= sname1
;
1077 /* Create two streams. */
1078 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1079 CHECK_STATUS(status
, NT_STATUS_OK
);
1080 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1081 if (fnum
!= -1) smbcli_close(cli
->tree
, fnum
);
1083 io
.ntcreatex
.in
.fname
= sname2
;
1084 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1085 CHECK_STATUS(status
, NT_STATUS_OK
);
1086 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1088 if (fnum
!= -1) smbcli_close(cli
->tree
, fnum
);
1091 * Open the second stream.
1094 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1095 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1096 CHECK_STATUS(status
, NT_STATUS_OK
);
1097 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1100 * Now rename the second stream onto the first.
1103 ZERO_STRUCT(sfinfo
);
1105 sfinfo
.rename_information
.in
.overwrite
= 1;
1106 sfinfo
.rename_information
.in
.root_fid
= 0;
1107 sfinfo
.rename_information
.in
.new_name
= ":Stream One";
1108 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
1111 if (fnum
!= -1) smbcli_close(cli
->tree
, fnum
);
1112 status
= smbcli_unlink(cli
->tree
, fname
);
1116 static bool test_stream_rename2(struct torture_context
*tctx
,
1117 struct smbcli_state
*cli
, TALLOC_CTX
*mem_ctx
)
1121 const char *fname1
= BASEDIR
"\\stream.txt";
1122 const char *fname2
= BASEDIR
"\\stream2.txt";
1123 const char *stream_name1
= ":Stream One:$DATA";
1124 const char *stream_name2
= ":Stream Two:$DATA";
1125 const char *stream_name_default
= "::$DATA";
1130 union smb_setfileinfo sinfo
;
1131 union smb_rename rio
;
1133 sname1
= talloc_asprintf(mem_ctx
, "%s:%s", fname1
, "Stream One");
1134 sname2
= talloc_asprintf(mem_ctx
, "%s:%s", fname1
, "Stream Two");
1136 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1137 io
.ntcreatex
.in
.root_fid
= 0;
1138 io
.ntcreatex
.in
.flags
= 0;
1139 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
1140 SEC_STD_DELETE
|SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
1141 io
.ntcreatex
.in
.create_options
= 0;
1142 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1143 io
.ntcreatex
.in
.share_access
= (NTCREATEX_SHARE_ACCESS_READ
|
1144 NTCREATEX_SHARE_ACCESS_WRITE
|
1145 NTCREATEX_SHARE_ACCESS_DELETE
);
1146 io
.ntcreatex
.in
.alloc_size
= 0;
1147 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1148 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1149 io
.ntcreatex
.in
.security_flags
= 0;
1150 io
.ntcreatex
.in
.fname
= sname1
;
1152 /* Open/create new stream. */
1153 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1154 CHECK_STATUS(status
, NT_STATUS_OK
);
1156 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1159 * Check raw rename with <base>:<stream>.
1161 printf("(%s) Checking NTRENAME of a stream using <base>:<stream>\n",
1163 rio
.generic
.level
= RAW_RENAME_NTRENAME
;
1164 rio
.ntrename
.in
.old_name
= sname1
;
1165 rio
.ntrename
.in
.new_name
= sname2
;
1166 rio
.ntrename
.in
.attrib
= 0;
1167 rio
.ntrename
.in
.cluster_size
= 0;
1168 rio
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
1169 status
= smb_raw_rename(cli
->tree
, &rio
);
1170 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1173 * Check raw rename to the default stream using :<stream>.
1175 printf("(%s) Checking NTRENAME to default stream using :<stream>\n",
1177 rio
.ntrename
.in
.new_name
= stream_name_default
;
1178 status
= smb_raw_rename(cli
->tree
, &rio
);
1179 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
1182 * Check raw rename using :<stream>.
1184 printf("(%s) Checking NTRENAME of a stream using :<stream>\n",
1186 rio
.ntrename
.in
.new_name
= stream_name2
;
1187 status
= smb_raw_rename(cli
->tree
, &rio
);
1188 CHECK_STATUS(status
, NT_STATUS_OK
);
1191 * Check raw rename of a stream to a file.
1193 printf("(%s) Checking NTRENAME of a stream to a file\n",
1195 rio
.ntrename
.in
.old_name
= sname2
;
1196 rio
.ntrename
.in
.new_name
= fname2
;
1197 status
= smb_raw_rename(cli
->tree
, &rio
);
1198 CHECK_STATUS(status
, NT_STATUS_INVALID_PARAMETER
);
1201 * Check raw rename of a file to a stream.
1203 printf("(%s) Checking NTRENAME of a file to a stream\n",
1206 /* Create the file. */
1207 io
.ntcreatex
.in
.fname
= fname2
;
1208 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1209 CHECK_STATUS(status
, NT_STATUS_OK
);
1210 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1212 /* Try the rename. */
1213 rio
.ntrename
.in
.old_name
= fname2
;
1214 rio
.ntrename
.in
.new_name
= sname1
;
1215 status
= smb_raw_rename(cli
->tree
, &rio
);
1216 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
1219 * Reopen the stream for trans2 renames.
1221 io
.ntcreatex
.in
.fname
= sname2
;
1222 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1223 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1224 CHECK_STATUS(status
, NT_STATUS_OK
);
1225 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1228 * Check trans2 rename of a stream using :<stream>.
1230 printf("(%s) Checking trans2 rename of a stream using :<stream>\n",
1233 sinfo
.rename_information
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
1234 sinfo
.rename_information
.in
.file
.fnum
= fnum
;
1235 sinfo
.rename_information
.in
.overwrite
= 1;
1236 sinfo
.rename_information
.in
.root_fid
= 0;
1237 sinfo
.rename_information
.in
.new_name
= stream_name1
;
1238 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
1239 CHECK_STATUS(status
, NT_STATUS_OK
);
1242 * Check trans2 rename of an overwriting stream using :<stream>.
1244 printf("(%s) Checking trans2 rename of an overwriting stream using "
1245 ":<stream>\n", __location__
);
1247 /* Create second stream. */
1248 io
.ntcreatex
.in
.fname
= sname2
;
1249 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1250 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1251 CHECK_STATUS(status
, NT_STATUS_OK
);
1252 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1254 /* Rename the first stream onto the second. */
1255 sinfo
.rename_information
.in
.file
.fnum
= fnum
;
1256 sinfo
.rename_information
.in
.new_name
= stream_name2
;
1257 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
1258 CHECK_STATUS(status
, NT_STATUS_OK
);
1260 smbcli_close(cli
->tree
, fnum
);
1263 * Reopen the stream with the new name.
1265 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1266 io
.ntcreatex
.in
.fname
= sname2
;
1267 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1268 CHECK_STATUS(status
, NT_STATUS_OK
);
1269 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1272 * Check trans2 rename of a stream using <base>:<stream>.
1274 printf("(%s) Checking trans2 rename of a stream using "
1275 "<base>:<stream>\n", __location__
);
1276 sinfo
.rename_information
.in
.file
.fnum
= fnum
;
1277 sinfo
.rename_information
.in
.new_name
= sname1
;
1278 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
1279 CHECK_STATUS(status
, NT_STATUS_NOT_SUPPORTED
);
1282 * Samba3 doesn't currently support renaming a stream to the default
1283 * stream. This test does pass on windows.
1285 if (torture_setting_bool(tctx
, "samba3", false) ||
1286 torture_setting_bool(tctx
, "samba4", false)) {
1291 * Check trans2 rename to the default stream using :<stream>.
1293 printf("(%s) Checking trans2 rename to defaualt stream using "
1294 ":<stream>\n", __location__
);
1295 sinfo
.rename_information
.in
.file
.fnum
= fnum
;
1296 sinfo
.rename_information
.in
.new_name
= stream_name_default
;
1297 status
= smb_raw_setfileinfo(cli
->tree
, &sinfo
);
1298 CHECK_STATUS(status
, NT_STATUS_OK
);
1300 smbcli_close(cli
->tree
, fnum
);
1303 smbcli_close(cli
->tree
, fnum
);
1304 status
= smbcli_unlink(cli
->tree
, fname1
);
1305 status
= smbcli_unlink(cli
->tree
, fname2
);
1309 static bool create_file_with_stream(struct torture_context
*tctx
,
1310 struct smbcli_state
*cli
,
1311 TALLOC_CTX
*mem_ctx
,
1318 /* Create a file with a stream */
1319 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1320 io
.ntcreatex
.in
.root_fid
= 0;
1321 io
.ntcreatex
.in
.flags
= 0;
1322 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
1323 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
1324 io
.ntcreatex
.in
.create_options
= 0;
1325 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1326 io
.ntcreatex
.in
.share_access
= 0;
1327 io
.ntcreatex
.in
.alloc_size
= 0;
1328 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1329 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1330 io
.ntcreatex
.in
.security_flags
= 0;
1331 io
.ntcreatex
.in
.fname
= stream
;
1333 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1334 CHECK_STATUS(status
, NT_STATUS_OK
);
1337 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1341 /* Test how streams interact with create dispositions */
1342 static bool test_stream_create_disposition(struct torture_context
*tctx
,
1343 struct smbcli_state
*cli
,
1344 TALLOC_CTX
*mem_ctx
)
1348 const char *fname
= BASEDIR
"\\stream.txt";
1349 const char *stream
= "Stream One:$DATA";
1350 const char *fname_stream
;
1351 const char *default_stream_name
= "::$DATA";
1352 const char *stream_list
[2];
1356 fname_stream
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, stream
);
1358 stream_list
[0] = talloc_asprintf(mem_ctx
, ":%s", stream
);
1359 stream_list
[1] = default_stream_name
;
1361 if (!create_file_with_stream(tctx
, cli
, mem_ctx
, fname_stream
)) {
1365 /* Open the base file with OPEN */
1366 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1367 io
.ntcreatex
.in
.root_fid
= 0;
1368 io
.ntcreatex
.in
.flags
= 0;
1369 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
1370 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
1371 io
.ntcreatex
.in
.create_options
= 0;
1372 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1373 io
.ntcreatex
.in
.share_access
= 0;
1374 io
.ntcreatex
.in
.alloc_size
= 0;
1375 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1376 io
.ntcreatex
.in
.security_flags
= 0;
1377 io
.ntcreatex
.in
.fname
= fname
;
1380 * check ntcreatex open: sanity check
1382 printf("(%s) Checking ntcreatex disp: open\n", __location__
);
1383 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1384 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1385 CHECK_STATUS(status
, NT_STATUS_OK
);
1386 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1387 if (!check_stream_list(cli
, fname
, 2, stream_list
)) {
1392 * check ntcreatex overwrite
1394 printf("(%s) Checking ntcreatex disp: overwrite\n", __location__
);
1395 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1396 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1397 CHECK_STATUS(status
, NT_STATUS_OK
);
1398 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1399 if (!check_stream_list(cli
, fname
, 1, &default_stream_name
)) {
1404 * check ntcreatex overwrite_if
1406 printf("(%s) Checking ntcreatex disp: overwrite_if\n", __location__
);
1407 smbcli_unlink(cli
->tree
, fname
);
1408 if (!create_file_with_stream(tctx
, cli
, mem_ctx
, fname_stream
)) {
1412 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1413 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1414 CHECK_STATUS(status
, NT_STATUS_OK
);
1415 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1416 if (!check_stream_list(cli
, fname
, 1, &default_stream_name
)) {
1421 * check ntcreatex supersede
1423 printf("(%s) Checking ntcreatex disp: supersede\n", __location__
);
1424 smbcli_unlink(cli
->tree
, fname
);
1425 if (!create_file_with_stream(tctx
, cli
, mem_ctx
, fname_stream
)) {
1429 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_SUPERSEDE
;
1430 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1431 CHECK_STATUS(status
, NT_STATUS_OK
);
1432 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1433 if (!check_stream_list(cli
, fname
, 1, &default_stream_name
)) {
1438 * check ntcreatex overwrite_if on a stream.
1440 printf("(%s) Checking ntcreatex disp: overwrite_if on stream\n",
1442 smbcli_unlink(cli
->tree
, fname
);
1443 if (!create_file_with_stream(tctx
, cli
, mem_ctx
, fname_stream
)) {
1447 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1448 io
.ntcreatex
.in
.fname
= fname_stream
;
1449 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1450 CHECK_STATUS(status
, NT_STATUS_OK
);
1451 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1452 if (!check_stream_list(cli
, fname
, 1, &default_stream_name
)) {
1457 * check openx overwrite_if
1459 printf("(%s) Checking openx disp: overwrite_if\n", __location__
);
1460 smbcli_unlink(cli
->tree
, fname
);
1461 if (!create_file_with_stream(tctx
, cli
, mem_ctx
, fname_stream
)) {
1465 io
.openx
.level
= RAW_OPEN_OPENX
;
1466 io
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1467 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
;
1468 io
.openx
.in
.search_attrs
= 0;
1469 io
.openx
.in
.file_attrs
= 0;
1470 io
.openx
.in
.write_time
= 0;
1471 io
.openx
.in
.size
= 1024*1024;
1472 io
.openx
.in
.timeout
= 0;
1473 io
.openx
.in
.fname
= fname
;
1475 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_TRUNC
| OPENX_OPEN_FUNC_CREATE
;
1476 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1477 CHECK_STATUS(status
, NT_STATUS_OK
);
1478 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
1479 if (!check_stream_list(cli
, fname
, 1, &default_stream_name
)) {
1484 smbcli_close(cli
->tree
, fnum
);
1485 smbcli_unlink(cli
->tree
, fname
);
1489 /* Test streaminfo with enough streams on a file to fill up the buffer. */
1490 static bool test_stream_large_streaminfo(struct torture_context
*tctx
,
1491 struct smbcli_state
*cli
,
1492 TALLOC_CTX
*mem_ctx
)
1494 #define LONG_STREAM_SIZE 2
1496 const char *fname
= BASEDIR
"\\stream.txt";
1497 const char *fname_stream
;
1501 union smb_fileinfo finfo
;
1503 lstream_name
= talloc_array(mem_ctx
, char, LONG_STREAM_SIZE
);
1505 for (i
= 0; i
< LONG_STREAM_SIZE
- 1; i
++) {
1506 lstream_name
[i
] = (char)('a' + i
%26);
1508 lstream_name
[LONG_STREAM_SIZE
- 1] = '\0';
1510 printf("(%s) Creating a file with a lot of streams\n", __location__
);
1511 for (i
= 0; i
< 10000; i
++) {
1512 fname_stream
= talloc_asprintf(mem_ctx
, "%s:%s%d", fname
,
1514 ret
= create_file_with_stream(tctx
, cli
, mem_ctx
,
1521 finfo
.generic
.level
= RAW_FILEINFO_STREAM_INFO
;
1522 finfo
.generic
.in
.file
.path
= fname
;
1524 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
1525 CHECK_STATUS(status
, STATUS_BUFFER_OVERFLOW
);
1528 smbcli_unlink(cli
->tree
, fname
);
1532 /* Test the effect of setting attributes on a stream. */
1533 static bool test_stream_attributes(struct torture_context
*tctx
,
1534 struct smbcli_state
*cli
,
1535 TALLOC_CTX
*mem_ctx
)
1540 const char *fname
= BASEDIR
"\\stream_attr.txt";
1541 const char *stream
= "Stream One:$DATA";
1542 const char *fname_stream
;
1544 union smb_fileinfo finfo
;
1545 union smb_setfileinfo sfinfo
;
1546 time_t basetime
= (time(NULL
) - 86400) & ~1;
1548 printf ("(%s) testing attribute setting on stream\n", __location__
);
1550 fname_stream
= talloc_asprintf(mem_ctx
, "%s:%s", fname
, stream
);
1552 /* Create a file with a stream with attribute FILE_ATTRIBUTE_ARCHIVE. */
1553 ret
= create_file_with_stream(tctx
, cli
, mem_ctx
, fname_stream
);
1559 finfo
.generic
.level
= RAW_FILEINFO_BASIC_INFO
;
1560 finfo
.generic
.in
.file
.path
= fname
;
1561 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
1562 CHECK_STATUS(status
, NT_STATUS_OK
);
1564 if (finfo
.basic_info
.out
.attrib
!= FILE_ATTRIBUTE_ARCHIVE
) {
1565 printf("(%s) Incorrect attrib %x - should be %x\n", \
1566 __location__
, (unsigned int)finfo
.basic_info
.out
.attrib
,
1567 (unsigned int)FILE_ATTRIBUTE_ARCHIVE
);
1572 /* Now open the stream name. */
1574 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1575 io
.ntcreatex
.in
.root_fid
= 0;
1576 io
.ntcreatex
.in
.flags
= 0;
1577 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
1578 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
|SEC_FILE_WRITE_ATTRIBUTE
);
1579 io
.ntcreatex
.in
.create_options
= 0;
1580 io
.ntcreatex
.in
.file_attr
= 0;
1581 io
.ntcreatex
.in
.share_access
= 0;
1582 io
.ntcreatex
.in
.alloc_size
= 0;
1583 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1584 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1585 io
.ntcreatex
.in
.security_flags
= 0;
1586 io
.ntcreatex
.in
.fname
= fname_stream
;
1588 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1589 CHECK_STATUS(status
, NT_STATUS_OK
);
1591 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1593 /* Change the attributes + time on the stream fnum. */
1594 ZERO_STRUCT(sfinfo
);
1595 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
1596 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
);
1598 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
1599 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1600 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1601 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1602 printf("(%s) %s - %s (should be %s)\n", __location__
, "SETATTR",
1603 nt_errstr(status
), nt_errstr(NT_STATUS_OK
));
1608 smbcli_close(cli
->tree
, fnum
);
1612 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1613 finfo
.generic
.in
.file
.path
= fname
;
1614 status
= smb_raw_pathinfo(cli
->tree
, mem_ctx
, &finfo
);
1615 if (!NT_STATUS_IS_OK(status
)) {
1616 printf("(%s) %s pathinfo - %s\n", __location__
, "SETATTRE", nt_errstr(status
));
1621 if (finfo
.all_info
.out
.attrib
!= FILE_ATTRIBUTE_READONLY
) {
1622 printf("(%s) attrib incorrect. Was 0x%x, should be 0x%x\n",
1624 (unsigned int)finfo
.all_info
.out
.attrib
,
1625 (unsigned int)FILE_ATTRIBUTE_READONLY
);
1630 if (nt_time_to_unix(finfo
.all_info
.out
.write_time
) != basetime
) {
1631 printf("(%s) time incorrect.\n",
1640 smbcli_close(cli
->tree
, fnum
);
1642 smbcli_unlink(cli
->tree
, fname
);
1647 basic testing of streams calls
1649 bool torture_raw_streams(struct torture_context
*torture
,
1650 struct smbcli_state
*cli
)
1654 if (!torture_setup_dir(cli
, BASEDIR
)) {
1658 ret
&= test_stream_dir(torture
, cli
, torture
);
1659 smb_raw_exit(cli
->session
);
1660 ret
&= test_stream_io(torture
, cli
, torture
);
1661 smb_raw_exit(cli
->session
);
1662 ret
&= test_stream_sharemodes(torture
, cli
, torture
);
1663 smb_raw_exit(cli
->session
);
1664 if (!torture_setting_bool(torture
, "samba4", false)) {
1665 ret
&= test_stream_delete(torture
, cli
, torture
);
1667 ret
&= test_stream_names(torture
, cli
, torture
);
1668 smb_raw_exit(cli
->session
);
1669 ret
&= test_stream_names2(torture
, cli
, torture
);
1670 smb_raw_exit(cli
->session
);
1671 ret
&= test_stream_rename(torture
, cli
, torture
);
1672 smb_raw_exit(cli
->session
);
1673 ret
&= test_stream_rename2(torture
, cli
, torture
);
1674 smb_raw_exit(cli
->session
);
1675 ret
&= test_stream_create_disposition(torture
, cli
, torture
);
1676 smb_raw_exit(cli
->session
);
1678 ret
&= test_stream_attributes(torture
, cli
, torture
);
1679 smb_raw_exit(cli
->session
);
1681 /* ret &= test_stream_large_streaminfo(torture, cli, torture); */
1682 /* smb_raw_exit(cli->session); */
1684 smbcli_deltree(cli
->tree
, BASEDIR
);