2 Unix SMB/CIFS implementation.
3 RAW_OPEN_* individual test suite
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libcli/raw/libcliraw.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "lib/events/events.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
28 /* enum for whether reads/writes are possible on a file */
29 enum rdwr_mode
{RDWR_NONE
, RDWR_RDONLY
, RDWR_WRONLY
, RDWR_RDWR
};
31 #define BASEDIR "\\rawopen"
34 check if a open file can be read/written
36 static enum rdwr_mode
check_rdwr(struct smbcli_tree
*tree
, int fnum
)
39 bool can_read
= (smbcli_read(tree
, fnum
, &c
, 0, 1) == 1);
40 bool can_write
= (smbcli_write(tree
, fnum
, 0, &c
, 0, 1) == 1);
41 if ( can_read
&& can_write
) return RDWR_RDWR
;
42 if ( can_read
&& !can_write
) return RDWR_RDONLY
;
43 if (!can_read
&& can_write
) return RDWR_WRONLY
;
48 describe a RDWR mode as a string
50 static const char *rdwr_string(enum rdwr_mode m
)
53 case RDWR_NONE
: return "NONE";
54 case RDWR_RDONLY
: return "RDONLY";
55 case RDWR_WRONLY
: return "WRONLY";
56 case RDWR_RDWR
: return "RDWR";
61 #define CHECK_STATUS(status, correct) do { \
62 if (!NT_STATUS_EQUAL(status, correct)) { \
63 torture_result(tctx, TORTURE_FAIL, \
64 "(%s) Incorrect status %s - should be %s\n", \
65 __location__, nt_errstr(status), nt_errstr(correct)); \
70 #define CREATE_FILE do { \
71 fnum = create_complex_file(cli, tctx, fname); \
73 torture_result(tctx, TORTURE_FAIL, \
74 "(%s) Failed to create %s - %s\n", \
75 __location__, fname, smbcli_errstr(cli->tree)); \
80 #define CHECK_RDWR(fnum, correct) do { \
81 enum rdwr_mode m = check_rdwr(cli->tree, fnum); \
83 torture_result(tctx, TORTURE_FAIL, \
84 "(%s) Incorrect readwrite mode %s - expected %s\n", \
85 __location__, rdwr_string(m), rdwr_string(correct)); \
89 #define CHECK_TIME(t, field) do { \
91 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
92 finfo.all_info.in.file.path = fname; \
93 status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
94 CHECK_STATUS(status, NT_STATUS_OK); \
96 t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
97 if (abs(t1-t2) > 2) { \
98 torture_result(tctx, TORTURE_FAIL, \
99 "(%s) wrong time for field %s %s - %s\n", \
100 __location__, #field, \
101 timestring(tctx, t1), \
102 timestring(tctx, t2)); \
103 dump_all_info(tctx, &finfo); \
107 #define CHECK_NTTIME(t, field) do { \
109 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
110 finfo.all_info.in.file.path = fname; \
111 status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
112 CHECK_STATUS(status, NT_STATUS_OK); \
113 t2 = finfo.all_info.out.field; \
115 torture_result(tctx, TORTURE_FAIL, \
116 "(%s) wrong time for field %s %s - %s\n", \
117 __location__, #field, \
118 nt_time_string(tctx, t), \
119 nt_time_string(tctx, t2)); \
120 dump_all_info(tctx, &finfo); \
124 #define CHECK_ALL_INFO(v, field) do { \
125 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
126 finfo.all_info.in.file.path = fname; \
127 status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
128 CHECK_STATUS(status, NT_STATUS_OK); \
129 if ((v) != (finfo.all_info.out.field)) { \
130 torture_result(tctx, TORTURE_FAIL, \
131 "(%s) wrong value for field %s 0x%x - 0x%x\n", \
132 __location__, #field, (int)v, (int)(finfo.all_info.out.field)); \
133 dump_all_info(tctx, &finfo); \
137 #define CHECK_VAL(v, correct) do { \
138 if ((v) != (correct)) { \
139 torture_result(tctx, TORTURE_FAIL, \
140 "(%s) wrong value for %s 0x%x - should be 0x%x\n", \
141 __location__, #v, (int)(v), (int)correct); \
145 #define SET_ATTRIB(sattrib) do { \
146 union smb_setfileinfo sfinfo; \
147 ZERO_STRUCT(sfinfo.basic_info.in); \
148 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
149 sfinfo.basic_info.in.file.path = fname; \
150 sfinfo.basic_info.in.attrib = sattrib; \
151 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
152 if (!NT_STATUS_IS_OK(status)) { \
153 torture_warning(tctx, "(%s) Failed to set attrib 0x%x on %s\n", \
154 __location__, sattrib, fname); \
160 static bool test_open(struct torture_context
*tctx
, struct smbcli_state
*cli
)
163 union smb_fileinfo finfo
;
164 const char *fname
= BASEDIR
"\\torture_open.txt";
166 int fnum
= -1, fnum2
;
169 if (!torture_setup_dir(cli
, BASEDIR
)) {
173 io
.openold
.level
= RAW_OPEN_OPEN
;
174 io
.openold
.in
.fname
= fname
;
175 io
.openold
.in
.open_mode
= OPEN_FLAGS_FCB
;
176 io
.openold
.in
.search_attrs
= 0;
177 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
178 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
179 fnum
= io
.openold
.out
.file
.fnum
;
181 smbcli_unlink(cli
->tree
, fname
);
183 smbcli_close(cli
->tree
, fnum
);
185 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
186 CHECK_STATUS(status
, NT_STATUS_OK
);
187 fnum
= io
.openold
.out
.file
.fnum
;
188 CHECK_RDWR(fnum
, RDWR_RDWR
);
190 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
191 CHECK_STATUS(status
, NT_STATUS_OK
);
192 fnum2
= io
.openold
.out
.file
.fnum
;
193 CHECK_RDWR(fnum2
, RDWR_RDWR
);
194 smbcli_close(cli
->tree
, fnum2
);
195 smbcli_close(cli
->tree
, fnum
);
197 /* check the read/write modes */
198 io
.openold
.level
= RAW_OPEN_OPEN
;
199 io
.openold
.in
.fname
= fname
;
200 io
.openold
.in
.search_attrs
= 0;
202 io
.openold
.in
.open_mode
= OPEN_FLAGS_OPEN_READ
;
203 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
204 CHECK_STATUS(status
, NT_STATUS_OK
);
205 fnum
= io
.openold
.out
.file
.fnum
;
206 CHECK_RDWR(fnum
, RDWR_RDONLY
);
207 smbcli_close(cli
->tree
, fnum
);
209 io
.openold
.in
.open_mode
= OPEN_FLAGS_OPEN_WRITE
;
210 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
211 CHECK_STATUS(status
, NT_STATUS_OK
);
212 fnum
= io
.openold
.out
.file
.fnum
;
213 CHECK_RDWR(fnum
, RDWR_WRONLY
);
214 smbcli_close(cli
->tree
, fnum
);
216 io
.openold
.in
.open_mode
= OPEN_FLAGS_OPEN_RDWR
;
217 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
218 CHECK_STATUS(status
, NT_STATUS_OK
);
219 fnum
= io
.openold
.out
.file
.fnum
;
220 CHECK_RDWR(fnum
, RDWR_RDWR
);
221 smbcli_close(cli
->tree
, fnum
);
223 /* check the share modes roughly - not a complete matrix */
224 io
.openold
.in
.open_mode
= OPEN_FLAGS_OPEN_RDWR
| OPEN_FLAGS_DENY_WRITE
;
225 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
226 CHECK_STATUS(status
, NT_STATUS_OK
);
227 fnum
= io
.openold
.out
.file
.fnum
;
228 CHECK_RDWR(fnum
, RDWR_RDWR
);
230 if (io
.openold
.in
.open_mode
!= io
.openold
.out
.rmode
) {
231 torture_warning(tctx
, "(%s) rmode should equal open_mode - 0x%x 0x%x\n",
232 __location__
, io
.openold
.out
.rmode
, io
.openold
.in
.open_mode
);
235 io
.openold
.in
.open_mode
= OPEN_FLAGS_OPEN_RDWR
| OPEN_FLAGS_DENY_NONE
;
236 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
237 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
239 io
.openold
.in
.open_mode
= OPEN_FLAGS_OPEN_READ
| OPEN_FLAGS_DENY_NONE
;
240 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
241 CHECK_STATUS(status
, NT_STATUS_OK
);
242 fnum2
= io
.openold
.out
.file
.fnum
;
243 CHECK_RDWR(fnum2
, RDWR_RDONLY
);
244 smbcli_close(cli
->tree
, fnum
);
245 smbcli_close(cli
->tree
, fnum2
);
248 /* check the returned write time */
249 io
.openold
.level
= RAW_OPEN_OPEN
;
250 io
.openold
.in
.fname
= fname
;
251 io
.openold
.in
.search_attrs
= 0;
252 io
.openold
.in
.open_mode
= OPEN_FLAGS_OPEN_READ
;
253 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
254 CHECK_STATUS(status
, NT_STATUS_OK
);
255 fnum
= io
.openold
.out
.file
.fnum
;
257 /* check other reply fields */
258 CHECK_TIME(io
.openold
.out
.write_time
, write_time
);
259 CHECK_ALL_INFO(io
.openold
.out
.size
, size
);
260 CHECK_ALL_INFO(io
.openold
.out
.attrib
, attrib
& ~FILE_ATTRIBUTE_NONINDEXED
);
263 smbcli_close(cli
->tree
, fnum
);
264 smbcli_deltree(cli
->tree
, BASEDIR
);
273 static bool test_openx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
276 union smb_fileinfo finfo
;
277 const char *fname
= BASEDIR
"\\torture_openx.txt";
278 const char *fname_exe
= BASEDIR
"\\torture_openx.exe";
280 int fnum
= -1, fnum2
;
287 NTSTATUS correct_status
;
289 { OPENX_OPEN_FUNC_OPEN
, true, NT_STATUS_OK
},
290 { OPENX_OPEN_FUNC_OPEN
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
291 { OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
, true, NT_STATUS_OK
},
292 { OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
, false, NT_STATUS_OK
},
293 { OPENX_OPEN_FUNC_FAIL
, true, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
) },
294 { OPENX_OPEN_FUNC_FAIL
, false, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
) },
295 { OPENX_OPEN_FUNC_FAIL
| OPENX_OPEN_FUNC_CREATE
, true, NT_STATUS_OBJECT_NAME_COLLISION
},
296 { OPENX_OPEN_FUNC_FAIL
| OPENX_OPEN_FUNC_CREATE
, false, NT_STATUS_OK
},
297 { OPENX_OPEN_FUNC_TRUNC
, true, NT_STATUS_OK
},
298 { OPENX_OPEN_FUNC_TRUNC
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
299 { OPENX_OPEN_FUNC_TRUNC
| OPENX_OPEN_FUNC_CREATE
, true, NT_STATUS_OK
},
300 { OPENX_OPEN_FUNC_TRUNC
| OPENX_OPEN_FUNC_CREATE
, false, NT_STATUS_OK
},
303 if (!torture_setup_dir(cli
, BASEDIR
)) {
307 io
.openx
.level
= RAW_OPEN_OPENX
;
308 io
.openx
.in
.fname
= fname
;
309 io
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
310 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
;
311 io
.openx
.in
.search_attrs
= 0;
312 io
.openx
.in
.file_attrs
= 0;
313 io
.openx
.in
.write_time
= 0;
314 io
.openx
.in
.size
= 1024*1024;
315 io
.openx
.in
.timeout
= 0;
317 /* check all combinations of open_func */
318 for (i
=0; i
<ARRAY_SIZE(open_funcs
); i
++) {
319 if (open_funcs
[i
].with_file
) {
320 fnum
= create_complex_file(cli
, tctx
, fname
);
322 torture_result(tctx
, TORTURE_FAIL
,
323 "Failed to create file %s - %s\n",
324 fname
, smbcli_errstr(cli
->tree
));
328 smbcli_close(cli
->tree
, fnum
);
330 io
.openx
.in
.open_func
= open_funcs
[i
].open_func
;
331 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
332 if (!NT_STATUS_EQUAL(status
, open_funcs
[i
].correct_status
)) {
333 torture_result(tctx
, TORTURE_FAIL
,
334 "(%s) incorrect status %s should be %s "
335 "(i=%d with_file=%d open_func=0x%x)\n",
336 __location__
, nt_errstr(status
),
337 nt_errstr(open_funcs
[i
].correct_status
),
338 i
, (int)open_funcs
[i
].with_file
,
339 (int)open_funcs
[i
].open_func
);
342 if (NT_STATUS_IS_OK(status
)) {
343 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
345 if (open_funcs
[i
].with_file
) {
346 smbcli_unlink(cli
->tree
, fname
);
350 smbcli_unlink(cli
->tree
, fname
);
352 /* check the basic return fields */
353 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
354 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
355 CHECK_STATUS(status
, NT_STATUS_OK
);
356 fnum
= io
.openx
.out
.file
.fnum
;
358 CHECK_ALL_INFO(io
.openx
.out
.size
, size
);
359 CHECK_TIME(io
.openx
.out
.write_time
, write_time
);
360 CHECK_ALL_INFO(io
.openx
.out
.attrib
, attrib
& ~FILE_ATTRIBUTE_NONINDEXED
);
361 CHECK_VAL(io
.openx
.out
.access
, OPENX_MODE_ACCESS_RDWR
);
362 CHECK_VAL(io
.openx
.out
.ftype
, 0);
363 CHECK_VAL(io
.openx
.out
.devstate
, 0);
364 CHECK_VAL(io
.openx
.out
.action
, OPENX_ACTION_CREATED
);
365 CHECK_VAL(io
.openx
.out
.size
, 1024*1024);
366 CHECK_ALL_INFO(io
.openx
.in
.size
, size
);
367 smbcli_close(cli
->tree
, fnum
);
368 smbcli_unlink(cli
->tree
, fname
);
370 /* check the fields when the file already existed */
371 fnum2
= create_complex_file(cli
, tctx
, fname
);
376 smbcli_close(cli
->tree
, fnum2
);
378 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
;
379 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
380 CHECK_STATUS(status
, NT_STATUS_OK
);
381 fnum
= io
.openx
.out
.file
.fnum
;
383 CHECK_ALL_INFO(io
.openx
.out
.size
, size
);
384 CHECK_TIME(io
.openx
.out
.write_time
, write_time
);
385 CHECK_VAL(io
.openx
.out
.action
, OPENX_ACTION_EXISTED
);
386 CHECK_VAL(io
.openx
.out
.unknown
, 0);
387 CHECK_ALL_INFO(io
.openx
.out
.attrib
, attrib
& ~FILE_ATTRIBUTE_NONINDEXED
);
388 smbcli_close(cli
->tree
, fnum
);
390 /* now check the search attrib for hidden files - win2003 ignores this? */
391 SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN
);
392 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN
, attrib
);
394 io
.openx
.in
.search_attrs
= FILE_ATTRIBUTE_HIDDEN
;
395 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
396 CHECK_STATUS(status
, NT_STATUS_OK
);
397 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
399 io
.openx
.in
.search_attrs
= 0;
400 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
401 CHECK_STATUS(status
, NT_STATUS_OK
);
402 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
404 SET_ATTRIB(FILE_ATTRIBUTE_NORMAL
);
405 smbcli_unlink(cli
->tree
, fname
);
407 /* and check attrib on create */
408 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_FAIL
| OPENX_OPEN_FUNC_CREATE
;
409 io
.openx
.in
.search_attrs
= 0;
410 io
.openx
.in
.file_attrs
= FILE_ATTRIBUTE_SYSTEM
;
411 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
412 CHECK_STATUS(status
, NT_STATUS_OK
);
413 if (torture_setting_bool(tctx
, "samba3", false)) {
414 CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_ARCHIVE
,
415 attrib
& ~(FILE_ATTRIBUTE_NONINDEXED
|
416 FILE_ATTRIBUTE_SPARSE
));
419 CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_ARCHIVE
,
420 attrib
& ~(FILE_ATTRIBUTE_NONINDEXED
));
422 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
423 smbcli_unlink(cli
->tree
, fname
);
425 /* check timeout on create - win2003 ignores the timeout! */
426 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
427 io
.openx
.in
.file_attrs
= 0;
428 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| OPENX_MODE_DENY_ALL
;
429 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
430 CHECK_STATUS(status
, NT_STATUS_OK
);
431 fnum
= io
.openx
.out
.file
.fnum
;
433 io
.openx
.in
.timeout
= 20000;
434 tv
= timeval_current();
435 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| OPENX_MODE_DENY_NONE
;
436 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
437 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
438 if (timeval_elapsed(&tv
) > 3.0) {
439 torture_result(tctx
, TORTURE_FAIL
,
440 "(%s) Incorrect timing in openx with timeout "
441 "- waited %.2f seconds\n",
442 __location__
, timeval_elapsed(&tv
));
445 smbcli_close(cli
->tree
, fnum
);
446 smbcli_unlink(cli
->tree
, fname
);
448 /* now this is a really weird one - open for execute implies create?! */
449 io
.openx
.in
.fname
= fname
;
450 io
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
451 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_EXEC
| OPENX_MODE_DENY_NONE
;
452 io
.openx
.in
.search_attrs
= 0;
453 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_FAIL
;
454 io
.openx
.in
.file_attrs
= 0;
455 io
.openx
.in
.write_time
= 0;
456 io
.openx
.in
.size
= 0;
457 io
.openx
.in
.timeout
= 0;
458 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
459 CHECK_STATUS(status
, NT_STATUS_OK
);
460 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
462 /* check the extended return flag */
463 io
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
| OPENX_FLAGS_EXTENDED_RETURN
;
464 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
;
465 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
466 CHECK_STATUS(status
, NT_STATUS_OK
);
467 CHECK_VAL(io
.openx
.out
.access_mask
, SEC_STD_ALL
);
468 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
470 io
.openx
.in
.fname
= "\\A.+,;=[].B";
471 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
472 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
474 /* Check the mapping for open exec. */
476 /* First create an .exe file. */
477 smbcli_unlink(cli
->tree
, fname_exe
);
478 fnum
= create_complex_file(cli
, tctx
, fname_exe
);
479 smbcli_close(cli
->tree
, fnum
);
481 io
.openx
.level
= RAW_OPEN_OPENX
;
482 io
.openx
.in
.fname
= fname_exe
;
483 io
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
484 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_EXEC
| OPENX_MODE_DENY_NONE
;
485 io
.openx
.in
.search_attrs
= 0;
486 io
.openx
.in
.file_attrs
= 0;
487 io
.openx
.in
.write_time
= 0;
488 io
.openx
.in
.size
= 0;
489 io
.openx
.in
.timeout
= 0;
490 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
491 CHECK_STATUS(status
, NT_STATUS_OK
);
493 /* Can we read and write ? */
494 CHECK_RDWR(io
.openx
.out
.file
.fnum
, RDWR_RDONLY
);
495 smbcli_close(cli
->tree
, io
.openx
.out
.file
.fnum
);
496 smbcli_unlink(cli
->tree
, fname
);
499 smbcli_close(cli
->tree
, fnum
);
500 smbcli_deltree(cli
->tree
, BASEDIR
);
509 many thanks to kukks for a sniff showing how this works with os2->w2k
511 static bool test_t2open(struct torture_context
*tctx
, struct smbcli_state
*cli
)
514 union smb_fileinfo finfo
;
515 const char *fname1
= BASEDIR
"\\torture_t2open_yes.txt";
516 const char *fname2
= BASEDIR
"\\torture_t2open_no.txt";
517 const char *fname
= BASEDIR
"\\torture_t2open_3.txt";
525 NTSTATUS correct_status
;
527 { OPENX_OPEN_FUNC_OPEN
, true, NT_STATUS_OK
},
528 { OPENX_OPEN_FUNC_OPEN
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
529 { OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
, true, NT_STATUS_OK
},
530 { OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
, false, NT_STATUS_OK
},
531 { OPENX_OPEN_FUNC_FAIL
, true, NT_STATUS_OBJECT_NAME_COLLISION
},
532 { OPENX_OPEN_FUNC_FAIL
, false, NT_STATUS_OBJECT_NAME_COLLISION
},
533 { OPENX_OPEN_FUNC_FAIL
| OPENX_OPEN_FUNC_CREATE
, true, NT_STATUS_OBJECT_NAME_COLLISION
},
534 { OPENX_OPEN_FUNC_FAIL
| OPENX_OPEN_FUNC_CREATE
, false, NT_STATUS_OBJECT_NAME_COLLISION
},
535 { OPENX_OPEN_FUNC_TRUNC
, true, NT_STATUS_OK
},
536 { OPENX_OPEN_FUNC_TRUNC
, false, NT_STATUS_OK
},
537 { OPENX_OPEN_FUNC_TRUNC
| OPENX_OPEN_FUNC_CREATE
, true, NT_STATUS_OK
},
538 { OPENX_OPEN_FUNC_TRUNC
| OPENX_OPEN_FUNC_CREATE
, false, NT_STATUS_OK
},
541 if (!torture_setup_dir(cli
, BASEDIR
)) {
545 fnum
= create_complex_file(cli
, tctx
, fname1
);
547 torture_result(tctx
, TORTURE_FAIL
,
548 "(%s): Failed to create file %s - %s\n",
549 __location__
, fname1
, smbcli_errstr(cli
->tree
));
553 smbcli_close(cli
->tree
, fnum
);
555 io
.t2open
.level
= RAW_OPEN_T2OPEN
;
556 io
.t2open
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
557 io
.t2open
.in
.open_mode
= OPENX_MODE_DENY_NONE
| OPENX_MODE_ACCESS_RDWR
;
558 io
.t2open
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
559 io
.t2open
.in
.search_attrs
= 0;
560 io
.t2open
.in
.file_attrs
= 0;
561 io
.t2open
.in
.write_time
= 0;
562 io
.t2open
.in
.size
= 0;
563 io
.t2open
.in
.timeout
= 0;
565 io
.t2open
.in
.num_eas
= 3;
566 io
.t2open
.in
.eas
= talloc_array(tctx
, struct ea_struct
, io
.t2open
.in
.num_eas
);
567 io
.t2open
.in
.eas
[0].flags
= 0;
568 io
.t2open
.in
.eas
[0].name
.s
= ".CLASSINFO";
569 io
.t2open
.in
.eas
[0].value
= data_blob_talloc(tctx
, "first value", 11);
570 io
.t2open
.in
.eas
[1].flags
= 0;
571 io
.t2open
.in
.eas
[1].name
.s
= "EA TWO";
572 io
.t2open
.in
.eas
[1].value
= data_blob_talloc(tctx
, "foo", 3);
573 io
.t2open
.in
.eas
[2].flags
= 0;
574 io
.t2open
.in
.eas
[2].name
.s
= "X THIRD";
575 io
.t2open
.in
.eas
[2].value
= data_blob_talloc(tctx
, "xy", 2);
577 /* check all combinations of open_func */
578 for (i
=0; i
<ARRAY_SIZE(open_funcs
); i
++) {
580 if (open_funcs
[i
].with_file
) {
581 io
.t2open
.in
.fname
= fname1
;
583 io
.t2open
.in
.fname
= fname2
;
585 io
.t2open
.in
.open_func
= open_funcs
[i
].open_func
;
586 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
587 if ((io
.t2open
.in
.num_eas
!= 0)
588 && NT_STATUS_EQUAL(status
, NT_STATUS_EAS_NOT_SUPPORTED
)
589 && torture_setting_bool(tctx
, "samba3", false)) {
590 torture_warning(tctx
, "(%s) EAs not supported, not "
591 "treating as fatal in Samba3 test\n",
593 io
.t2open
.in
.num_eas
= 0;
597 if (!NT_STATUS_EQUAL(status
, open_funcs
[i
].correct_status
)) {
598 torture_result(tctx
, TORTURE_FAIL
,
599 "(%s) incorrect status %s should be %s "
600 "(i=%d with_file=%d open_func=0x%x)\n",
601 __location__
, nt_errstr(status
),
602 nt_errstr(open_funcs
[i
].correct_status
),
603 i
, (int)open_funcs
[i
].with_file
,
604 (int)open_funcs
[i
].open_func
);
607 if (NT_STATUS_IS_OK(status
)) {
608 smbcli_close(cli
->tree
, io
.t2open
.out
.file
.fnum
);
612 smbcli_unlink(cli
->tree
, fname1
);
613 smbcli_unlink(cli
->tree
, fname2
);
615 /* check the basic return fields */
616 io
.t2open
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
617 io
.t2open
.in
.write_time
= 0;
618 io
.t2open
.in
.fname
= fname
;
619 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
620 CHECK_STATUS(status
, NT_STATUS_OK
);
621 fnum
= io
.t2open
.out
.file
.fnum
;
623 CHECK_ALL_INFO(io
.t2open
.out
.size
, size
);
625 /* windows appears to leak uninitialised memory here */
626 CHECK_VAL(io
.t2open
.out
.write_time
, 0);
628 CHECK_ALL_INFO(io
.t2open
.out
.attrib
, attrib
& ~FILE_ATTRIBUTE_NONINDEXED
);
629 CHECK_VAL(io
.t2open
.out
.access
, OPENX_MODE_DENY_NONE
| OPENX_MODE_ACCESS_RDWR
);
630 CHECK_VAL(io
.t2open
.out
.ftype
, 0);
631 CHECK_VAL(io
.t2open
.out
.devstate
, 0);
632 CHECK_VAL(io
.t2open
.out
.action
, OPENX_ACTION_CREATED
);
633 smbcli_close(cli
->tree
, fnum
);
635 status
= torture_check_ea(cli
, fname
, ".CLASSINFO", "first value");
636 CHECK_STATUS(status
, io
.t2open
.in
.num_eas
637 ? NT_STATUS_OK
: NT_STATUS_EAS_NOT_SUPPORTED
);
638 status
= torture_check_ea(cli
, fname
, "EA TWO", "foo");
639 CHECK_STATUS(status
, io
.t2open
.in
.num_eas
640 ? NT_STATUS_OK
: NT_STATUS_EAS_NOT_SUPPORTED
);
641 status
= torture_check_ea(cli
, fname
, "X THIRD", "xy");
642 CHECK_STATUS(status
, io
.t2open
.in
.num_eas
643 ? NT_STATUS_OK
: NT_STATUS_EAS_NOT_SUPPORTED
);
645 /* now check the search attrib for hidden files - win2003 ignores this? */
646 SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN
);
647 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN
, attrib
);
649 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
650 CHECK_STATUS(status
, NT_STATUS_OK
);
651 smbcli_close(cli
->tree
, io
.t2open
.out
.file
.fnum
);
653 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
654 CHECK_STATUS(status
, NT_STATUS_OK
);
655 smbcli_close(cli
->tree
, io
.t2open
.out
.file
.fnum
);
657 SET_ATTRIB(FILE_ATTRIBUTE_NORMAL
);
658 smbcli_unlink(cli
->tree
, fname
);
660 /* and check attrib on create */
661 io
.t2open
.in
.open_func
= OPENX_OPEN_FUNC_FAIL
| OPENX_OPEN_FUNC_CREATE
;
662 io
.t2open
.in
.file_attrs
= FILE_ATTRIBUTE_SYSTEM
;
663 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
664 CHECK_STATUS(status
, NT_STATUS_OK
);
666 /* check timeout on create - win2003 ignores the timeout! */
667 io
.t2open
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
668 io
.t2open
.in
.file_attrs
= 0;
669 io
.t2open
.in
.timeout
= 20000;
670 io
.t2open
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| OPENX_MODE_DENY_ALL
;
671 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
672 CHECK_STATUS(status
, NT_STATUS_SHARING_VIOLATION
);
675 smbcli_close(cli
->tree
, fnum
);
676 smbcli_deltree(cli
->tree
, BASEDIR
);
683 test RAW_OPEN_NTCREATEX
685 static bool test_ntcreatex(struct torture_context
*tctx
, struct smbcli_state
*cli
)
688 union smb_fileinfo finfo
;
689 const char *fname
= BASEDIR
"\\torture_ntcreatex.txt";
690 const char *dname
= BASEDIR
"\\torture_ntcreatex.dir";
698 NTSTATUS correct_status
;
700 { NTCREATEX_DISP_SUPERSEDE
, true, NT_STATUS_OK
},
701 { NTCREATEX_DISP_SUPERSEDE
, false, NT_STATUS_OK
},
702 { NTCREATEX_DISP_OPEN
, true, NT_STATUS_OK
},
703 { NTCREATEX_DISP_OPEN
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
704 { NTCREATEX_DISP_CREATE
, true, NT_STATUS_OBJECT_NAME_COLLISION
},
705 { NTCREATEX_DISP_CREATE
, false, NT_STATUS_OK
},
706 { NTCREATEX_DISP_OPEN_IF
, true, NT_STATUS_OK
},
707 { NTCREATEX_DISP_OPEN_IF
, false, NT_STATUS_OK
},
708 { NTCREATEX_DISP_OVERWRITE
, true, NT_STATUS_OK
},
709 { NTCREATEX_DISP_OVERWRITE
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
710 { NTCREATEX_DISP_OVERWRITE_IF
, true, NT_STATUS_OK
},
711 { NTCREATEX_DISP_OVERWRITE_IF
, false, NT_STATUS_OK
},
712 { 6, true, NT_STATUS_INVALID_PARAMETER
},
713 { 6, false, NT_STATUS_INVALID_PARAMETER
},
716 if (!torture_setup_dir(cli
, BASEDIR
)) {
720 /* reasonable default parameters */
721 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
722 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
723 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
724 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
725 io
.ntcreatex
.in
.alloc_size
= 1024*1024;
726 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
727 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
728 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
729 io
.ntcreatex
.in
.create_options
= 0;
730 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
731 io
.ntcreatex
.in
.security_flags
= 0;
732 io
.ntcreatex
.in
.fname
= fname
;
734 /* test the open disposition */
735 for (i
=0; i
<ARRAY_SIZE(open_funcs
); i
++) {
736 if (open_funcs
[i
].with_file
) {
737 fnum
= smbcli_open(cli
->tree
, fname
, O_CREAT
|O_RDWR
|O_TRUNC
, DENY_NONE
);
739 torture_result(tctx
, TORTURE_FAIL
,
740 "Failed to create file %s - %s\n",
741 fname
, smbcli_errstr(cli
->tree
));
745 smbcli_close(cli
->tree
, fnum
);
747 io
.ntcreatex
.in
.open_disposition
= open_funcs
[i
].open_disp
;
748 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
749 if (!NT_STATUS_EQUAL(status
, open_funcs
[i
].correct_status
)) {
750 torture_result(tctx
, TORTURE_FAIL
,
751 "(%s) incorrect status %s should be %s "
752 "(i=%d with_file=%d open_disp=%d)\n",
753 __location__
, nt_errstr(status
),
754 nt_errstr(open_funcs
[i
].correct_status
),
755 i
, (int)open_funcs
[i
].with_file
,
756 (int)open_funcs
[i
].open_disp
);
759 if (NT_STATUS_IS_OK(status
) || open_funcs
[i
].with_file
) {
760 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
761 smbcli_unlink(cli
->tree
, fname
);
765 /* basic field testing */
766 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
768 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
769 CHECK_STATUS(status
, NT_STATUS_OK
);
770 fnum
= io
.ntcreatex
.out
.file
.fnum
;
772 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
773 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_CREATED
);
774 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
775 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
776 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
777 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
778 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
779 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
780 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
781 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
782 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
784 /* check fields when the file already existed */
785 smbcli_close(cli
->tree
, fnum
);
786 smbcli_unlink(cli
->tree
, fname
);
787 fnum
= create_complex_file(cli
, tctx
, fname
);
792 smbcli_close(cli
->tree
, fnum
);
794 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
795 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
796 CHECK_STATUS(status
, NT_STATUS_OK
);
797 fnum
= io
.ntcreatex
.out
.file
.fnum
;
799 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
800 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_EXISTED
);
801 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
802 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
803 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
804 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
805 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
806 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
807 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
808 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
809 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
810 smbcli_close(cli
->tree
, fnum
);
811 smbcli_unlink(cli
->tree
, fname
);
814 /* create a directory */
815 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
816 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
817 io
.ntcreatex
.in
.alloc_size
= 0;
818 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
819 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
820 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
821 io
.ntcreatex
.in
.create_options
= 0;
822 io
.ntcreatex
.in
.fname
= dname
;
825 smbcli_rmdir(cli
->tree
, fname
);
826 smbcli_unlink(cli
->tree
, fname
);
828 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
829 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
830 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
831 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
832 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
833 CHECK_STATUS(status
, NT_STATUS_OK
);
834 fnum
= io
.ntcreatex
.out
.file
.fnum
;
836 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
837 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_CREATED
);
838 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
839 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
840 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
841 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
842 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
843 CHECK_VAL(io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
844 FILE_ATTRIBUTE_DIRECTORY
);
845 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
846 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
847 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
848 CHECK_VAL(io
.ntcreatex
.out
.is_directory
, 1);
849 CHECK_VAL(io
.ntcreatex
.out
.size
, 0);
850 CHECK_VAL(io
.ntcreatex
.out
.alloc_size
, 0);
851 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
852 smbcli_unlink(cli
->tree
, fname
);
856 smbcli_close(cli
->tree
, fnum
);
857 smbcli_deltree(cli
->tree
, BASEDIR
);
864 test RAW_OPEN_NTTRANS_CREATE
866 static bool test_nttrans_create(struct torture_context
*tctx
, struct smbcli_state
*cli
)
869 union smb_fileinfo finfo
;
870 const char *fname
= BASEDIR
"\\torture_ntcreatex.txt";
871 const char *dname
= BASEDIR
"\\torture_ntcreatex.dir";
876 uint32_t ok_mask
, not_supported_mask
, invalid_parameter_mask
;
877 uint32_t not_a_directory_mask
, unexpected_mask
;
881 NTSTATUS correct_status
;
883 { NTCREATEX_DISP_SUPERSEDE
, true, NT_STATUS_OK
},
884 { NTCREATEX_DISP_SUPERSEDE
, false, NT_STATUS_OK
},
885 { NTCREATEX_DISP_OPEN
, true, NT_STATUS_OK
},
886 { NTCREATEX_DISP_OPEN
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
887 { NTCREATEX_DISP_CREATE
, true, NT_STATUS_OBJECT_NAME_COLLISION
},
888 { NTCREATEX_DISP_CREATE
, false, NT_STATUS_OK
},
889 { NTCREATEX_DISP_OPEN_IF
, true, NT_STATUS_OK
},
890 { NTCREATEX_DISP_OPEN_IF
, false, NT_STATUS_OK
},
891 { NTCREATEX_DISP_OVERWRITE
, true, NT_STATUS_OK
},
892 { NTCREATEX_DISP_OVERWRITE
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
893 { NTCREATEX_DISP_OVERWRITE_IF
, true, NT_STATUS_OK
},
894 { NTCREATEX_DISP_OVERWRITE_IF
, false, NT_STATUS_OK
},
895 { 6, true, NT_STATUS_INVALID_PARAMETER
},
896 { 6, false, NT_STATUS_INVALID_PARAMETER
},
899 if (!torture_setup_dir(cli
, BASEDIR
)) {
903 /* reasonable default parameters */
904 io
.generic
.level
= RAW_OPEN_NTTRANS_CREATE
;
905 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
906 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
907 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
908 io
.ntcreatex
.in
.alloc_size
= 1024*1024;
909 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
910 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
911 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
912 io
.ntcreatex
.in
.create_options
= 0;
913 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
914 io
.ntcreatex
.in
.security_flags
= 0;
915 io
.ntcreatex
.in
.fname
= fname
;
916 io
.ntcreatex
.in
.sec_desc
= NULL
;
917 io
.ntcreatex
.in
.ea_list
= NULL
;
919 /* test the open disposition */
920 for (i
=0; i
<ARRAY_SIZE(open_funcs
); i
++) {
921 if (open_funcs
[i
].with_file
) {
922 fnum
= smbcli_open(cli
->tree
, fname
, O_CREAT
|O_RDWR
|O_TRUNC
, DENY_NONE
);
924 torture_result(tctx
, TORTURE_FAIL
,
925 "Failed to create file %s - %s\n",
926 fname
, smbcli_errstr(cli
->tree
));
930 smbcli_close(cli
->tree
, fnum
);
932 io
.ntcreatex
.in
.open_disposition
= open_funcs
[i
].open_disp
;
933 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
934 if (!NT_STATUS_EQUAL(status
, open_funcs
[i
].correct_status
)) {
935 torture_result(tctx
, TORTURE_FAIL
,
936 "(%s) incorrect status %s should be %s "
937 "(i=%d with_file=%d open_disp=%d)\n",
938 __location__
, nt_errstr(status
),
939 nt_errstr(open_funcs
[i
].correct_status
),
940 i
, (int)open_funcs
[i
].with_file
,
941 (int)open_funcs
[i
].open_disp
);
944 if (NT_STATUS_IS_OK(status
) || open_funcs
[i
].with_file
) {
945 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
946 smbcli_unlink(cli
->tree
, fname
);
950 /* basic field testing */
951 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
953 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
954 CHECK_STATUS(status
, NT_STATUS_OK
);
955 fnum
= io
.ntcreatex
.out
.file
.fnum
;
957 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
958 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_CREATED
);
959 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
960 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
961 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
962 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
963 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
964 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
965 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
966 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
967 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
969 /* check fields when the file already existed */
970 smbcli_close(cli
->tree
, fnum
);
971 smbcli_unlink(cli
->tree
, fname
);
972 fnum
= create_complex_file(cli
, tctx
, fname
);
977 smbcli_close(cli
->tree
, fnum
);
979 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
980 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
981 CHECK_STATUS(status
, NT_STATUS_OK
);
982 fnum
= io
.ntcreatex
.out
.file
.fnum
;
984 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
985 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_EXISTED
);
986 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
987 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
988 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
989 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
990 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
991 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
992 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
993 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
994 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
995 smbcli_close(cli
->tree
, fnum
);
997 /* check no-recall - don't pull a file from tape on a HSM */
998 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_NO_RECALL
;
999 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1000 CHECK_STATUS(status
, NT_STATUS_OK
);
1001 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1003 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1004 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_EXISTED
);
1005 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
1006 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
1007 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
1008 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
1009 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
1010 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
1011 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
1012 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
1013 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
1014 smbcli_close(cli
->tree
, fnum
);
1016 /* Check some create options (these all should be ignored) */
1017 for (i
=0; i
< 32; i
++) {
1018 uint32_t create_option
= (1 << i
) & NTCREATEX_OPTIONS_MUST_IGNORE_MASK
;
1019 if (create_option
== 0) {
1022 io
.ntcreatex
.in
.create_options
= create_option
;
1023 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1024 if (!NT_STATUS_IS_OK(status
)) {
1025 torture_warning(tctx
, "ntcreatex create option 0x%08x "
1026 "gave %s - should give NT_STATUS_OK\n",
1027 create_option
, nt_errstr(status
));
1029 CHECK_STATUS(status
, NT_STATUS_OK
);
1030 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1032 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1033 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_EXISTED
);
1034 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
1035 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
1036 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
1037 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
1038 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
1039 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
1040 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
1041 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
1042 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
1043 smbcli_close(cli
->tree
, fnum
);
1046 io
.ntcreatex
.in
.file_attr
= 0;
1047 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1048 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1050 /* Check for options that should return NOT_SUPPORTED, OK or INVALID_PARAMETER */
1052 not_supported_mask
= 0;
1053 invalid_parameter_mask
= 0;
1054 not_a_directory_mask
= 0;
1055 unexpected_mask
= 0;
1056 for (i
=0; i
< 32; i
++) {
1057 uint32_t create_option
= 1<<i
;
1058 if (create_option
& NTCREATEX_OPTIONS_DELETE_ON_CLOSE
) {
1061 io
.ntcreatex
.in
.create_options
= create_option
;
1062 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1063 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
)) {
1064 not_supported_mask
|= create_option
;
1065 } else if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1066 ok_mask
|= create_option
;
1067 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1068 } else if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
1069 invalid_parameter_mask
|= create_option
;
1070 } else if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_A_DIRECTORY
)) {
1071 not_a_directory_mask
|= 1<<i
;
1073 unexpected_mask
|= 1<<i
;
1074 torture_comment(tctx
, "create option 0x%08x returned %s\n",
1075 create_option
, nt_errstr(status
));
1079 CHECK_VAL(ok_mask
, 0x00efcfce);
1080 CHECK_VAL(not_a_directory_mask
, 0x00000001);
1081 CHECK_VAL(not_supported_mask
, 0x00002000);
1082 CHECK_VAL(invalid_parameter_mask
, 0xff100030);
1083 CHECK_VAL(unexpected_mask
, 0x00000000);
1085 smbcli_unlink(cli
->tree
, fname
);
1088 /* create a directory */
1089 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1090 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1091 io
.ntcreatex
.in
.alloc_size
= 0;
1092 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1093 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1094 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1095 io
.ntcreatex
.in
.create_options
= 0;
1096 io
.ntcreatex
.in
.fname
= dname
;
1099 smbcli_rmdir(cli
->tree
, fname
);
1100 smbcli_unlink(cli
->tree
, fname
);
1102 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1103 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1104 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1105 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1106 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1107 CHECK_STATUS(status
, NT_STATUS_OK
);
1108 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1110 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1111 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_CREATED
);
1112 CHECK_NTTIME(io
.ntcreatex
.out
.create_time
, create_time
);
1113 CHECK_NTTIME(io
.ntcreatex
.out
.access_time
, access_time
);
1114 CHECK_NTTIME(io
.ntcreatex
.out
.write_time
, write_time
);
1115 CHECK_NTTIME(io
.ntcreatex
.out
.change_time
, change_time
);
1116 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
1117 CHECK_VAL(io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1118 FILE_ATTRIBUTE_DIRECTORY
);
1119 CHECK_ALL_INFO(io
.ntcreatex
.out
.alloc_size
, alloc_size
);
1120 CHECK_ALL_INFO(io
.ntcreatex
.out
.size
, size
);
1121 CHECK_ALL_INFO(io
.ntcreatex
.out
.is_directory
, directory
);
1122 CHECK_VAL(io
.ntcreatex
.out
.is_directory
, 1);
1123 CHECK_VAL(io
.ntcreatex
.out
.size
, 0);
1124 CHECK_VAL(io
.ntcreatex
.out
.alloc_size
, 0);
1125 CHECK_VAL(io
.ntcreatex
.out
.file_type
, FILE_TYPE_DISK
);
1126 smbcli_unlink(cli
->tree
, fname
);
1130 smbcli_close(cli
->tree
, fnum
);
1131 smbcli_deltree(cli
->tree
, BASEDIR
);
1137 test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
1139 I've got an application that does a similar sequence of ntcreate&x,
1140 locking&x and another ntcreate&x with
1141 open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
1144 static bool test_ntcreatex_brlocked(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1146 union smb_open io
, io1
;
1148 struct smb_lock_entry lock
[1];
1149 const char *fname
= BASEDIR
"\\torture_ntcreatex.txt";
1153 if (!torture_setup_dir(cli
, BASEDIR
)) {
1157 torture_comment(tctx
, "Testing ntcreatex with a byte range locked file\n");
1159 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1160 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1161 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1162 io
.ntcreatex
.in
.access_mask
= 0x2019f;
1163 io
.ntcreatex
.in
.alloc_size
= 0;
1164 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1165 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1166 NTCREATEX_SHARE_ACCESS_WRITE
;
1167 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1168 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
1169 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1170 io
.ntcreatex
.in
.security_flags
= NTCREATEX_SECURITY_DYNAMIC
|
1171 NTCREATEX_SECURITY_ALL
;
1172 io
.ntcreatex
.in
.fname
= fname
;
1174 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1175 CHECK_STATUS(status
, NT_STATUS_OK
);
1177 io2
.lockx
.level
= RAW_LOCK_LOCKX
;
1178 io2
.lockx
.in
.file
.fnum
= io
.ntcreatex
.out
.file
.fnum
;
1179 io2
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1180 io2
.lockx
.in
.timeout
= 0;
1181 io2
.lockx
.in
.ulock_cnt
= 0;
1182 io2
.lockx
.in
.lock_cnt
= 1;
1183 lock
[0].pid
= cli
->session
->pid
;
1185 lock
[0].count
= 0x1;
1186 io2
.lockx
.in
.locks
= &lock
[0];
1187 status
= smb_raw_lock(cli
->tree
, &io2
);
1188 CHECK_STATUS(status
, NT_STATUS_OK
);
1190 io1
.generic
.level
= RAW_OPEN_NTCREATEX
;
1191 io1
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1192 io1
.ntcreatex
.in
.root_fid
.fnum
= 0;
1193 io1
.ntcreatex
.in
.access_mask
= 0x20196;
1194 io1
.ntcreatex
.in
.alloc_size
= 0;
1195 io1
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1196 io1
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1197 NTCREATEX_SHARE_ACCESS_WRITE
;
1198 io1
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
1199 io1
.ntcreatex
.in
.create_options
= 0;
1200 io1
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1201 io1
.ntcreatex
.in
.security_flags
= NTCREATEX_SECURITY_DYNAMIC
|
1202 NTCREATEX_SECURITY_ALL
;
1203 io1
.ntcreatex
.in
.fname
= fname
;
1205 status
= smb_raw_open(cli
->tree
, tctx
, &io1
);
1206 CHECK_STATUS(status
, NT_STATUS_OK
);
1209 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1210 smbcli_close(cli
->tree
, io1
.ntcreatex
.out
.file
.fnum
);
1211 smbcli_deltree(cli
->tree
, BASEDIR
);
1218 static bool test_mknew(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1221 const char *fname
= BASEDIR
"\\torture_mknew.txt";
1225 time_t basetime
= (time(NULL
) + 3600*24*3) & ~1;
1226 union smb_fileinfo finfo
;
1228 if (!torture_setup_dir(cli
, BASEDIR
)) {
1232 io
.mknew
.level
= RAW_OPEN_MKNEW
;
1233 io
.mknew
.in
.attrib
= 0;
1234 io
.mknew
.in
.write_time
= 0;
1235 io
.mknew
.in
.fname
= fname
;
1236 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1237 CHECK_STATUS(status
, NT_STATUS_OK
);
1238 fnum
= io
.mknew
.out
.file
.fnum
;
1240 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1241 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
1243 smbcli_close(cli
->tree
, fnum
);
1244 smbcli_unlink(cli
->tree
, fname
);
1246 /* make sure write_time works */
1247 io
.mknew
.in
.write_time
= basetime
;
1248 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1249 CHECK_STATUS(status
, NT_STATUS_OK
);
1250 fnum
= io
.mknew
.out
.file
.fnum
;
1251 CHECK_TIME(basetime
, write_time
);
1253 smbcli_close(cli
->tree
, fnum
);
1254 smbcli_unlink(cli
->tree
, fname
);
1256 /* make sure file_attrs works */
1257 io
.mknew
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
1258 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1259 CHECK_STATUS(status
, NT_STATUS_OK
);
1260 fnum
= io
.mknew
.out
.file
.fnum
;
1261 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_ARCHIVE
,
1262 attrib
& ~FILE_ATTRIBUTE_NONINDEXED
);
1265 smbcli_close(cli
->tree
, fnum
);
1266 smbcli_deltree(cli
->tree
, BASEDIR
);
1273 test RAW_OPEN_CREATE
1275 static bool test_create(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1278 const char *fname
= BASEDIR
"\\torture_create.txt";
1282 time_t basetime
= (time(NULL
) + 3600*24*3) & ~1;
1283 union smb_fileinfo finfo
;
1285 if (!torture_setup_dir(cli
, BASEDIR
)) {
1289 io
.create
.level
= RAW_OPEN_CREATE
;
1290 io
.create
.in
.attrib
= 0;
1291 io
.create
.in
.write_time
= 0;
1292 io
.create
.in
.fname
= fname
;
1293 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1294 CHECK_STATUS(status
, NT_STATUS_OK
);
1295 fnum
= io
.create
.out
.file
.fnum
;
1297 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1298 CHECK_STATUS(status
, NT_STATUS_OK
);
1300 smbcli_close(cli
->tree
, io
.create
.out
.file
.fnum
);
1301 smbcli_close(cli
->tree
, fnum
);
1302 smbcli_unlink(cli
->tree
, fname
);
1304 /* make sure write_time works */
1305 io
.create
.in
.write_time
= basetime
;
1306 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1307 CHECK_STATUS(status
, NT_STATUS_OK
);
1308 fnum
= io
.create
.out
.file
.fnum
;
1309 CHECK_TIME(basetime
, write_time
);
1311 smbcli_close(cli
->tree
, fnum
);
1312 smbcli_unlink(cli
->tree
, fname
);
1314 /* make sure file_attrs works */
1315 io
.create
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
1316 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1317 CHECK_STATUS(status
, NT_STATUS_OK
);
1318 fnum
= io
.create
.out
.file
.fnum
;
1319 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_ARCHIVE
,
1320 attrib
& ~FILE_ATTRIBUTE_NONINDEXED
);
1323 smbcli_close(cli
->tree
, fnum
);
1324 smbcli_deltree(cli
->tree
, BASEDIR
);
1333 static bool test_ctemp(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1339 time_t basetime
= (time(NULL
) + 3600*24*3) & ~1;
1340 union smb_fileinfo finfo
;
1341 const char *name
, *fname
= NULL
;
1343 if (!torture_setup_dir(cli
, BASEDIR
)) {
1347 io
.ctemp
.level
= RAW_OPEN_CTEMP
;
1348 io
.ctemp
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
1349 io
.ctemp
.in
.write_time
= basetime
;
1350 io
.ctemp
.in
.directory
= BASEDIR
;
1351 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1352 CHECK_STATUS(status
, NT_STATUS_OK
);
1353 fnum
= io
.ctemp
.out
.file
.fnum
;
1355 name
= io
.ctemp
.out
.name
;
1357 finfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
1358 finfo
.generic
.in
.file
.fnum
= fnum
;
1359 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1360 CHECK_STATUS(status
, NT_STATUS_OK
);
1362 fname
= finfo
.name_info
.out
.fname
.s
;
1363 torture_comment(tctx
, "ctemp name=%s real name=%s\n", name
, fname
);
1366 smbcli_close(cli
->tree
, fnum
);
1367 smbcli_deltree(cli
->tree
, BASEDIR
);
1374 test chained RAW_OPEN_OPENX_READX
1376 static bool test_chained(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1379 const char *fname
= BASEDIR
"\\torture_chained.txt";
1383 const char *buf
= "test";
1386 if (!torture_setup_dir(cli
, BASEDIR
)) {
1390 fnum
= create_complex_file(cli
, tctx
, fname
);
1392 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, sizeof(buf
));
1394 smbcli_close(cli
->tree
, fnum
);
1396 io
.openxreadx
.level
= RAW_OPEN_OPENX_READX
;
1397 io
.openxreadx
.in
.fname
= fname
;
1398 io
.openxreadx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1399 io
.openxreadx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
;
1400 io
.openxreadx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
;
1401 io
.openxreadx
.in
.search_attrs
= 0;
1402 io
.openxreadx
.in
.file_attrs
= 0;
1403 io
.openxreadx
.in
.write_time
= 0;
1404 io
.openxreadx
.in
.size
= 1024*1024;
1405 io
.openxreadx
.in
.timeout
= 0;
1407 io
.openxreadx
.in
.offset
= 0;
1408 io
.openxreadx
.in
.mincnt
= sizeof(buf
);
1409 io
.openxreadx
.in
.maxcnt
= sizeof(buf
);
1410 io
.openxreadx
.in
.remaining
= 0;
1411 io
.openxreadx
.out
.data
= (uint8_t *)buf2
;
1413 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1414 CHECK_STATUS(status
, NT_STATUS_OK
);
1415 fnum
= io
.openxreadx
.out
.file
.fnum
;
1417 if (memcmp(buf
, buf2
, sizeof(buf
)) != 0) {
1418 torture_result(tctx
, TORTURE_FAIL
,
1419 "wrong data in reply buffer\n");
1424 smbcli_close(cli
->tree
, fnum
);
1425 smbcli_deltree(cli
->tree
, BASEDIR
);
1431 test RAW_OPEN_OPENX without a leading slash on the path.
1432 NetApp filers are known to fail on this.
1435 static bool test_no_leading_slash(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1438 const char *fname
= BASEDIR
"\\torture_no_leading_slash.txt";
1442 const char *buf
= "test";
1444 if (!torture_setup_dir(cli
, BASEDIR
)) {
1448 smbcli_unlink(cli
->tree
, fname
);
1450 /* Create the file */
1451 fnum
= create_complex_file(cli
, tctx
, fname
);
1452 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, sizeof(buf
));
1453 smbcli_close(cli
->tree
, fnum
);
1455 /* Prepare to open the file using path without leading slash */
1456 io
.openx
.level
= RAW_OPEN_OPENX
;
1457 io
.openx
.in
.fname
= fname
+ 1;
1458 io
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1459 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
;
1460 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
;
1461 io
.openx
.in
.search_attrs
= 0;
1462 io
.openx
.in
.file_attrs
= 0;
1463 io
.openx
.in
.write_time
= 0;
1464 io
.openx
.in
.size
= 1024*1024;
1465 io
.openx
.in
.timeout
= 0;
1467 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1468 CHECK_STATUS(status
, NT_STATUS_OK
);
1469 fnum
= io
.openx
.out
.file
.fnum
;
1472 smbcli_close(cli
->tree
, fnum
);
1473 smbcli_deltree(cli
->tree
, BASEDIR
);
1479 test RAW_OPEN_OPENX against an existing directory to
1480 ensure it returns NT_STATUS_FILE_IS_A_DIRECTORY.
1481 Samba 3.2.0 - 3.2.6 are known to fail this.
1484 static bool test_openx_over_dir(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1487 const char *fname
= BASEDIR
"\\openx_over_dir";
1493 if (!torture_setup_dir(cli
, BASEDIR
)) {
1497 /* Create the Directory */
1498 status
= create_directory_handle(cli
->tree
, fname
, &d_fnum
);
1499 smbcli_close(cli
->tree
, d_fnum
);
1501 /* Prepare to open the file over the directory. */
1502 io
.openx
.level
= RAW_OPEN_OPENX
;
1503 io
.openx
.in
.fname
= fname
;
1504 io
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1505 io
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
;
1506 io
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
;
1507 io
.openx
.in
.search_attrs
= 0;
1508 io
.openx
.in
.file_attrs
= 0;
1509 io
.openx
.in
.write_time
= 0;
1510 io
.openx
.in
.size
= 1024*1024;
1511 io
.openx
.in
.timeout
= 0;
1513 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1514 CHECK_STATUS(status
, NT_STATUS_FILE_IS_A_DIRECTORY
);
1515 fnum
= io
.openx
.out
.file
.fnum
;
1518 smbcli_close(cli
->tree
, fnum
);
1519 smbcli_deltree(cli
->tree
, BASEDIR
);
1525 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1527 static bool test_raw_open_multi(struct torture_context
*tctx
, struct smbcli_state
*cli_ignored
)
1529 struct smbcli_state
*cli
;
1530 TALLOC_CTX
*mem_ctx
= talloc_init("torture_test_oplock_multi");
1531 const char *fname
= "\\test_oplock.dat";
1535 struct smbcli_state
**clients
;
1536 struct smbcli_request
**requests
;
1537 union smb_open
*ios
;
1538 const char *host
= torture_setting_string(tctx
, "host", NULL
);
1539 const char *share
= torture_setting_string(tctx
, "share", NULL
);
1540 int i
, num_files
= 3;
1542 int num_collision
= 0;
1544 clients
= talloc_array(mem_ctx
, struct smbcli_state
*, num_files
);
1545 requests
= talloc_array(mem_ctx
, struct smbcli_request
*, num_files
);
1546 ios
= talloc_array(mem_ctx
, union smb_open
, num_files
);
1547 if ((tctx
->ev
== NULL
) || (clients
== NULL
) || (requests
== NULL
) ||
1549 torture_result(tctx
, TORTURE_FAIL
, "(%s): talloc failed\n",
1554 if (!torture_open_connection_share(mem_ctx
, &cli
, tctx
, host
, share
, tctx
->ev
)) {
1558 cli
->tree
->session
->transport
->options
.request_timeout
= 60;
1560 for (i
=0; i
<num_files
; i
++) {
1561 if (!torture_open_connection_share(mem_ctx
, &(clients
[i
]),
1562 tctx
, host
, share
, tctx
->ev
)) {
1563 torture_result(tctx
, TORTURE_FAIL
,
1564 "(%s): Could not open %d'th connection\n",
1568 clients
[i
]->tree
->session
->transport
->options
.request_timeout
= 60;
1572 smbcli_unlink(cli
->tree
, fname
);
1575 base ntcreatex parms
1577 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1578 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1579 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1580 io
.ntcreatex
.in
.alloc_size
= 0;
1581 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1582 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1583 NTCREATEX_SHARE_ACCESS_WRITE
|
1584 NTCREATEX_SHARE_ACCESS_DELETE
;
1585 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1586 io
.ntcreatex
.in
.create_options
= 0;
1587 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1588 io
.ntcreatex
.in
.security_flags
= 0;
1589 io
.ntcreatex
.in
.fname
= fname
;
1590 io
.ntcreatex
.in
.flags
= 0;
1592 for (i
=0; i
<num_files
; i
++) {
1594 requests
[i
] = smb_raw_open_send(clients
[i
]->tree
, &ios
[i
]);
1595 if (requests
[i
] == NULL
) {
1596 torture_result(tctx
, TORTURE_FAIL
,
1597 "(%s): could not send %d'th request\n",
1603 torture_comment(tctx
, "waiting for replies\n");
1605 bool unreplied
= false;
1606 for (i
=0; i
<num_files
; i
++) {
1607 if (requests
[i
] == NULL
) {
1610 if (requests
[i
]->state
< SMBCLI_REQUEST_DONE
) {
1614 status
= smb_raw_open_recv(requests
[i
], mem_ctx
,
1617 torture_comment(tctx
, "File %d returned status %s\n", i
,
1620 if (NT_STATUS_IS_OK(status
)) {
1624 if (NT_STATUS_EQUAL(status
,
1625 NT_STATUS_OBJECT_NAME_COLLISION
)) {
1635 if (event_loop_once(tctx
->ev
) != 0) {
1636 torture_result(tctx
, TORTURE_FAIL
,
1637 "(%s): event_loop_once failed\n", __location__
);
1642 if ((num_ok
!= 1) || (num_ok
+ num_collision
!= num_files
)) {
1646 for (i
=0; i
<num_files
; i
++) {
1647 torture_close_connection(clients
[i
]);
1649 talloc_free(mem_ctx
);
1654 test opening for delete on a read-only attribute file.
1656 static bool test_open_for_delete(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1659 union smb_fileinfo finfo
;
1660 const char *fname
= BASEDIR
"\\torture_open_for_delete.txt";
1665 if (!torture_setup_dir(cli
, BASEDIR
)) {
1669 /* reasonable default parameters */
1670 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1671 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1672 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1673 io
.ntcreatex
.in
.alloc_size
= 0;
1674 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1675 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_READONLY
;
1676 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1677 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1678 io
.ntcreatex
.in
.create_options
= 0;
1679 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1680 io
.ntcreatex
.in
.security_flags
= 0;
1681 io
.ntcreatex
.in
.fname
= fname
;
1683 /* Create the readonly file. */
1685 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1686 CHECK_STATUS(status
, NT_STATUS_OK
);
1687 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1689 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1690 io
.ntcreatex
.in
.create_options
= 0;
1691 CHECK_VAL(io
.ntcreatex
.out
.create_action
, NTCREATEX_ACTION_CREATED
);
1692 CHECK_ALL_INFO(io
.ntcreatex
.out
.attrib
, attrib
);
1693 smbcli_close(cli
->tree
, fnum
);
1695 /* Now try and open for delete only - should succeed. */
1696 io
.ntcreatex
.in
.access_mask
= SEC_STD_DELETE
;
1697 io
.ntcreatex
.in
.file_attr
= 0;
1698 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
1699 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1700 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1701 CHECK_STATUS(status
, NT_STATUS_OK
);
1703 smbcli_unlink(cli
->tree
, fname
);
1706 smbcli_close(cli
->tree
, fnum
);
1707 smbcli_deltree(cli
->tree
, BASEDIR
);
1713 test chained RAW_OPEN_NTCREATEX_READX
1714 Send chained NTCREATEX_READX on a file that doesn't exist, then create
1715 the file and try again.
1717 static bool test_chained_ntcreatex_readx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1719 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
1721 const char *fname
= BASEDIR
"\\torture_chained.txt";
1725 const char *buf
= "test";
1728 if (!torture_setup_dir(cli
, BASEDIR
)) {
1732 torture_comment(tctx
, "Checking RAW_NTCREATEX_READX chained on "
1733 "non-existant file \n");
1735 /* ntcreatex parameters */
1736 io
.generic
.level
= RAW_OPEN_NTCREATEX_READX
;
1737 io
.ntcreatexreadx
.in
.flags
= 0;
1738 io
.ntcreatexreadx
.in
.root_fid
.fnum
= 0;
1739 io
.ntcreatexreadx
.in
.access_mask
= SEC_FILE_READ_DATA
;
1740 io
.ntcreatexreadx
.in
.alloc_size
= 0;
1741 io
.ntcreatexreadx
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1742 io
.ntcreatexreadx
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1743 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
1744 io
.ntcreatexreadx
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1745 io
.ntcreatexreadx
.in
.create_options
= 0;
1746 io
.ntcreatexreadx
.in
.impersonation
= NTCREATEX_IMPERSONATION_IMPERSONATION
;
1747 io
.ntcreatexreadx
.in
.security_flags
= 0;
1748 io
.ntcreatexreadx
.in
.fname
= fname
;
1750 /* readx parameters */
1751 io
.ntcreatexreadx
.in
.offset
= 0;
1752 io
.ntcreatexreadx
.in
.mincnt
= sizeof(buf
);
1753 io
.ntcreatexreadx
.in
.maxcnt
= sizeof(buf
);
1754 io
.ntcreatexreadx
.in
.remaining
= 0;
1755 io
.ntcreatexreadx
.out
.data
= (uint8_t *)buf2
;
1757 /* try to open the non-existant file */
1758 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1759 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
1760 fnum
= io
.ntcreatexreadx
.out
.file
.fnum
;
1762 smbcli_close(cli
->tree
, fnum
);
1763 smbcli_unlink(cli
->tree
, fname
);
1765 torture_comment(tctx
, "Checking RAW_NTCREATEX_READX chained on "
1766 "existing file \n");
1768 fnum
= create_complex_file(cli
, mem_ctx
, fname
);
1769 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, sizeof(buf
));
1770 smbcli_close(cli
->tree
, fnum
);
1772 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
1773 CHECK_STATUS(status
, NT_STATUS_OK
);
1774 fnum
= io
.ntcreatexreadx
.out
.file
.fnum
;
1776 if (memcmp(buf
, buf2
, sizeof(buf
)) != 0) {
1777 torture_result(tctx
, TORTURE_FAIL
,
1778 "(%s): wrong data in reply buffer\n", __location__
);
1783 smbcli_close(cli
->tree
, fnum
);
1784 smbcli_deltree(cli
->tree
, BASEDIR
);
1785 talloc_free(mem_ctx
);
1790 static bool test_ntcreatex_opendisp_dir(struct torture_context
*tctx
,
1791 struct smbcli_state
*cli
)
1793 const char *dname
= BASEDIR
"\\torture_ntcreatex_opendisp_dir";
1800 NTSTATUS correct_status
;
1801 } open_funcs_dir
[] = {
1802 { NTCREATEX_DISP_SUPERSEDE
, true, NT_STATUS_INVALID_PARAMETER
},
1803 { NTCREATEX_DISP_SUPERSEDE
, false, NT_STATUS_INVALID_PARAMETER
},
1804 { NTCREATEX_DISP_OPEN
, true, NT_STATUS_OK
},
1805 { NTCREATEX_DISP_OPEN
, false, NT_STATUS_OBJECT_NAME_NOT_FOUND
},
1806 { NTCREATEX_DISP_CREATE
, true, NT_STATUS_OBJECT_NAME_COLLISION
},
1807 { NTCREATEX_DISP_CREATE
, false, NT_STATUS_OK
},
1808 { NTCREATEX_DISP_OPEN_IF
, true, NT_STATUS_OK
},
1809 { NTCREATEX_DISP_OPEN_IF
, false, NT_STATUS_OK
},
1810 { NTCREATEX_DISP_OVERWRITE
, true, NT_STATUS_INVALID_PARAMETER
},
1811 { NTCREATEX_DISP_OVERWRITE
, false, NT_STATUS_INVALID_PARAMETER
},
1812 { NTCREATEX_DISP_OVERWRITE_IF
, true, NT_STATUS_INVALID_PARAMETER
},
1813 { NTCREATEX_DISP_OVERWRITE_IF
, false, NT_STATUS_INVALID_PARAMETER
},
1814 { 6, true, NT_STATUS_INVALID_PARAMETER
},
1815 { 6, false, NT_STATUS_INVALID_PARAMETER
},
1820 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1821 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1822 io
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
1823 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1824 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1825 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1826 io
.ntcreatex
.in
.fname
= dname
;
1828 if (!torture_setup_dir(cli
, BASEDIR
)) {
1832 smbcli_rmdir(cli
->tree
, dname
);
1833 smbcli_unlink(cli
->tree
, dname
);
1835 /* test the open disposition for directories */
1836 torture_comment(tctx
, "Testing open dispositions for directories...\n");
1838 for (i
=0; i
<ARRAY_SIZE(open_funcs_dir
); i
++) {
1839 if (open_funcs_dir
[i
].dir_exists
) {
1840 status
= smbcli_mkdir(cli
->tree
, dname
);
1841 if (!NT_STATUS_IS_OK(status
)) {
1842 torture_result(tctx
, TORTURE_FAIL
,
1843 "(%s): Failed to make directory "
1844 "%s - %s\n", __location__
, dname
,
1845 smbcli_errstr(cli
->tree
));
1851 io
.ntcreatex
.in
.open_disposition
= open_funcs_dir
[i
].open_disp
;
1852 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1853 if (!NT_STATUS_EQUAL(status
, open_funcs_dir
[i
].correct_status
)) {
1854 torture_result(tctx
, TORTURE_FAIL
,
1855 "(%s) incorrect status %s should be %s "
1856 "(i=%d dir_exists=%d open_disp=%d)\n",
1857 __location__
, nt_errstr(status
),
1858 nt_errstr(open_funcs_dir
[i
].correct_status
),
1859 i
, (int)open_funcs_dir
[i
].dir_exists
,
1860 (int)open_funcs_dir
[i
].open_disp
);
1863 if (NT_STATUS_IS_OK(status
) || open_funcs_dir
[i
].dir_exists
) {
1864 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
1865 smbcli_rmdir(cli
->tree
, dname
);
1870 smbcli_deltree(cli
->tree
, BASEDIR
);
1876 * Test what happens when trying to open a file with directory parameters and
1877 * vice-versa. Also test that NTCREATEX_OPTIONS_DIRECTORY is treated as
1878 * mandatory and FILE_ATTRIBUTE_DIRECTORY is advisory for directory
1881 static bool test_ntcreatexdir(struct torture_context
*tctx
,
1882 struct smbcli_state
*cli
)
1885 const char *fname
= BASEDIR
"\\torture_ntcreatex.txt";
1886 const char *dname
= BASEDIR
"\\torture_ntcreatex_dir";
1893 uint32_t create_options
;
1894 NTSTATUS correct_status
;
1896 { NTCREATEX_DISP_SUPERSEDE
, 0, NTCREATEX_OPTIONS_DIRECTORY
,
1897 NT_STATUS_INVALID_PARAMETER
},
1898 { NTCREATEX_DISP_OPEN
, 0, NTCREATEX_OPTIONS_DIRECTORY
,
1899 NT_STATUS_OBJECT_NAME_NOT_FOUND
},
1900 { NTCREATEX_DISP_CREATE
, 0, NTCREATEX_OPTIONS_DIRECTORY
,
1902 { NTCREATEX_DISP_OPEN_IF
, 0, NTCREATEX_OPTIONS_DIRECTORY
,
1904 { NTCREATEX_DISP_OVERWRITE
, 0, NTCREATEX_OPTIONS_DIRECTORY
,
1905 NT_STATUS_INVALID_PARAMETER
},
1906 { NTCREATEX_DISP_OVERWRITE_IF
, 0, NTCREATEX_OPTIONS_DIRECTORY
,
1907 NT_STATUS_INVALID_PARAMETER
},
1908 { NTCREATEX_DISP_SUPERSEDE
, FILE_ATTRIBUTE_DIRECTORY
, 0,
1910 { NTCREATEX_DISP_OPEN
, FILE_ATTRIBUTE_DIRECTORY
, 0,
1911 NT_STATUS_OBJECT_NAME_NOT_FOUND
},
1912 { NTCREATEX_DISP_CREATE
, FILE_ATTRIBUTE_DIRECTORY
, 0,
1914 { NTCREATEX_DISP_OPEN_IF
, FILE_ATTRIBUTE_DIRECTORY
, 0,
1916 { NTCREATEX_DISP_OVERWRITE
, FILE_ATTRIBUTE_DIRECTORY
, 0,
1917 NT_STATUS_OBJECT_NAME_NOT_FOUND
},
1918 { NTCREATEX_DISP_OVERWRITE_IF
, FILE_ATTRIBUTE_DIRECTORY
, 0,
1923 if (!torture_setup_dir(cli
, BASEDIR
)) {
1927 /* setup some base params. */
1928 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1929 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1930 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1931 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1932 io
.ntcreatex
.in
.alloc_size
= 0;
1933 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1934 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1935 io
.ntcreatex
.in
.security_flags
= 0;
1936 io
.ntcreatex
.in
.fname
= fname
;
1939 * Test the validity checking for create dispositions, which is done
1940 * against the requested parameters rather than what's actually on
1943 for (i
=0; i
<ARRAY_SIZE(open_funcs
); i
++) {
1944 io
.ntcreatex
.in
.open_disposition
= open_funcs
[i
].open_disp
;
1945 io
.ntcreatex
.in
.file_attr
= open_funcs
[i
].file_attr
;
1946 io
.ntcreatex
.in
.create_options
= open_funcs
[i
].create_options
;
1947 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1948 if (!NT_STATUS_EQUAL(status
, open_funcs
[i
].correct_status
)) {
1949 torture_result(tctx
, TORTURE_FAIL
,
1950 "(%s) incorrect status %s should be %s "
1951 "(i=%d open_disp=%d)\n",
1952 __location__
, nt_errstr(status
),
1953 nt_errstr(open_funcs
[i
].correct_status
),
1954 i
, (int)open_funcs
[i
].open_disp
);
1957 /* Close and delete the file. */
1958 if (NT_STATUS_IS_OK(status
)) {
1959 if (open_funcs
[i
].create_options
!= 0) {
1960 /* out attrib should be a directory. */
1961 torture_assert_int_equal(tctx
,
1962 io
.ntcreatex
.out
.attrib
,
1963 FILE_ATTRIBUTE_DIRECTORY
, "should have "
1964 "created a directory");
1966 smbcli_close(cli
->tree
,
1967 io
.ntcreatex
.out
.file
.fnum
);
1969 /* Make sure unlink fails. */
1970 status
= smbcli_unlink(cli
->tree
, fname
);
1971 torture_assert_ntstatus_equal(tctx
, status
,
1972 NT_STATUS_FILE_IS_A_DIRECTORY
,
1973 "unlink should fail for a directory");
1975 status
= smbcli_rmdir(cli
->tree
, fname
);
1976 torture_assert_ntstatus_ok(tctx
, status
,
1979 torture_assert_int_equal(tctx
,
1980 io
.ntcreatex
.out
.attrib
,
1981 FILE_ATTRIBUTE_ARCHIVE
, "should not have "
1982 "created a directory");
1984 smbcli_close(cli
->tree
,
1985 io
.ntcreatex
.out
.file
.fnum
);
1987 /* Make sure rmdir fails. */
1988 status
= smbcli_rmdir(cli
->tree
, fname
);
1989 torture_assert_ntstatus_equal(tctx
, status
,
1990 NT_STATUS_NOT_A_DIRECTORY
,
1991 "rmdir should fail for a file");
1993 status
= smbcli_unlink(cli
->tree
, fname
);
1994 torture_assert_ntstatus_ok(tctx
, status
,
2000 /* Create a file. */
2001 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2002 io
.ntcreatex
.in
.create_options
= 0;
2003 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2004 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2005 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create file.");
2006 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
2008 /* Try and open the file with file_attr_dir and check the error. */
2009 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
2010 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
2012 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2013 torture_assert_ntstatus_ok(tctx
, status
, "FILE_ATTRIBUTE_DIRECTORY "
2014 "doesn't produce a hard failure.");
2015 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
2017 /* Try and open file with createx_option_dir and check the error. */
2018 io
.ntcreatex
.in
.file_attr
= 0;
2019 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
2021 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2022 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NOT_A_DIRECTORY
,
2023 "NTCREATEX_OPTIONS_DIRECTORY will a file from being opened.");
2024 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
2026 /* Delete the file and move onto directory testing. */
2027 smbcli_unlink(cli
->tree
, fname
);
2029 /* Now try some tests on a directory. */
2030 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2031 io
.ntcreatex
.in
.file_attr
= 0;
2032 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
2033 io
.ntcreatex
.in
.fname
= dname
;
2035 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2036 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create dir.");
2038 /* out attrib should be a directory. */
2039 torture_assert_int_equal(tctx
, io
.ntcreatex
.out
.attrib
,
2040 FILE_ATTRIBUTE_DIRECTORY
, "should have created a directory");
2042 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
2044 /* Try and open it with normal attr and check the error. */
2045 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2046 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
2048 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2049 torture_assert_ntstatus_ok(tctx
, status
, "FILE_ATTRIBUTE_NORMAL "
2050 "doesn't produce a hard failure.");
2051 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
2053 /* Try and open it with file create_options and check the error. */
2054 io
.ntcreatex
.in
.file_attr
= 0;
2055 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
2057 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
2058 torture_assert_ntstatus_equal(tctx
, status
,
2059 NT_STATUS_FILE_IS_A_DIRECTORY
,
2060 "NTCREATEX_OPTIONS_NON_DIRECTORY_FILE should be returned ");
2061 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
2063 smbcli_deltree(cli
->tree
, BASEDIR
);
2068 /* basic testing of all RAW_OPEN_* calls
2070 struct torture_suite
*torture_raw_open(TALLOC_CTX
*mem_ctx
)
2072 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "open");
2074 torture_suite_add_1smb_test(suite
, "brlocked", test_ntcreatex_brlocked
);
2075 torture_suite_add_1smb_test(suite
, "open", test_open
);
2076 torture_suite_add_1smb_test(suite
, "open-multi", test_raw_open_multi
);
2077 torture_suite_add_1smb_test(suite
, "openx", test_openx
);
2078 torture_suite_add_1smb_test(suite
, "ntcreatex", test_ntcreatex
);
2079 torture_suite_add_1smb_test(suite
, "nttrans-create", test_nttrans_create
);
2080 torture_suite_add_1smb_test(suite
, "t2open", test_t2open
);
2081 torture_suite_add_1smb_test(suite
, "mknew", test_mknew
);
2082 torture_suite_add_1smb_test(suite
, "create", test_create
);
2083 torture_suite_add_1smb_test(suite
, "ctemp", test_ctemp
);
2084 torture_suite_add_1smb_test(suite
, "chained-openx", test_chained
);
2085 torture_suite_add_1smb_test(suite
, "chained-ntcreatex", test_chained_ntcreatex_readx
);
2086 torture_suite_add_1smb_test(suite
, "no-leading-slash", test_no_leading_slash
);
2087 torture_suite_add_1smb_test(suite
, "openx-over-dir", test_openx_over_dir
);
2088 torture_suite_add_1smb_test(suite
, "open-for-delete", test_open_for_delete
);
2089 torture_suite_add_1smb_test(suite
, "opendisp-dir", test_ntcreatex_opendisp_dir
);
2090 torture_suite_add_1smb_test(suite
, "ntcreatedir", test_ntcreatexdir
);