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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* enum for whether reads/writes are possible on a file */
24 enum rdwr_mode {RDWR_NONE, RDWR_RDONLY, RDWR_WRONLY, RDWR_RDWR};
26 #define BASEDIR "\\rawopen"
29 check if a open file can be read/written
31 static enum rdwr_mode check_rdwr(struct smbcli_tree *tree, int fnum)
34 BOOL can_read = (smbcli_read(tree, fnum, &c, 0, 1) == 1);
35 BOOL can_write = (smbcli_write(tree, fnum, 0, &c, 0, 1) == 1);
36 if ( can_read && can_write) return RDWR_RDWR;
37 if ( can_read && !can_write) return RDWR_RDONLY;
38 if (!can_read && can_write) return RDWR_WRONLY;
43 describe a RDWR mode as a string
45 static const char *rdwr_string(enum rdwr_mode m)
48 case RDWR_NONE: return "NONE";
49 case RDWR_RDONLY: return "RDONLY";
50 case RDWR_WRONLY: return "WRONLY";
51 case RDWR_RDWR: return "RDWR";
56 #define CHECK_STATUS(status, correct) do { \
57 if (!NT_STATUS_EQUAL(status, correct)) { \
58 printf("(%d) Incorrect status %s - should be %s\n", \
59 __LINE__, nt_errstr(status), nt_errstr(correct)); \
64 #define CREATE_FILE do { \
65 fnum = create_complex_file(cli, mem_ctx, fname); \
67 printf("(%d) Failed to create %s - %s\n", __LINE__, fname, smbcli_errstr(cli->tree)); \
72 #define CHECK_RDWR(fnum, correct) do { \
73 enum rdwr_mode m = check_rdwr(cli->tree, fnum); \
75 printf("(%d) Incorrect readwrite mode %s - expected %s\n", \
76 __LINE__, rdwr_string(m), rdwr_string(correct)); \
80 #define CHECK_TIME(t, field) do { \
82 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
83 finfo.all_info.in.fname = fname; \
84 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
85 CHECK_STATUS(status, NT_STATUS_OK); \
87 t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
88 if (ABS(t1-t2) > 2) { \
89 printf("(%d) wrong time for field %s %s - %s\n", \
91 timestring(mem_ctx, t1), \
92 timestring(mem_ctx, t2)); \
93 dump_all_info(mem_ctx, &finfo); \
97 #define CHECK_NTTIME(t, field) do { \
99 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
100 finfo.all_info.in.fname = fname; \
101 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
102 CHECK_STATUS(status, NT_STATUS_OK); \
103 t2 = finfo.all_info.out.field; \
105 printf("(%d) wrong time for field %s %s - %s\n", \
107 nt_time_string(mem_ctx, t), \
108 nt_time_string(mem_ctx, t2)); \
109 dump_all_info(mem_ctx, &finfo); \
113 #define CHECK_ALL_INFO(v, field) do { \
114 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
115 finfo.all_info.in.fname = fname; \
116 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
117 CHECK_STATUS(status, NT_STATUS_OK); \
118 if ((v) != finfo.all_info.out.field) { \
119 printf("(%d) wrong value for field %s 0x%x - 0x%x\n", \
120 __LINE__, #field, (int)v, (int)finfo.all_info.out.field); \
121 dump_all_info(mem_ctx, &finfo); \
125 #define CHECK_VAL(v, correct) do { \
126 if ((v) != (correct)) { \
127 printf("(%d) wrong value for %s 0x%x - 0x%x\n", \
128 __LINE__, #v, (int)v, (int)correct); \
132 #define SET_ATTRIB(sattrib) do { \
133 union smb_setfileinfo sfinfo; \
134 sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION; \
135 sfinfo.generic.file.fname = fname; \
136 ZERO_STRUCT(sfinfo.basic_info.in); \
137 sfinfo.basic_info.in.attrib = sattrib; \
138 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
139 if (!NT_STATUS_IS_OK(status)) { \
140 printf("(%d) Failed to set attrib 0x%x on %s\n", \
141 __LINE__, sattrib, fname); \
147 static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
150 union smb_fileinfo finfo;
151 const char *fname = BASEDIR "\\torture_open.txt";
156 printf("Checking RAW_OPEN_OPEN\n");
158 io.open.level = RAW_OPEN_OPEN;
159 io.open.in.fname = fname;
160 io.open.in.flags = OPEN_FLAGS_FCB;
161 io.open.in.search_attrs = 0;
162 status = smb_raw_open(cli->tree, mem_ctx, &io);
163 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
164 fnum = io.open.out.fnum;
166 smbcli_unlink(cli->tree, fname);
168 smbcli_close(cli->tree, fnum);
170 status = smb_raw_open(cli->tree, mem_ctx, &io);
171 CHECK_STATUS(status, NT_STATUS_OK);
172 fnum = io.open.out.fnum;
173 CHECK_RDWR(fnum, RDWR_RDWR);
175 status = smb_raw_open(cli->tree, mem_ctx, &io);
176 CHECK_STATUS(status, NT_STATUS_OK);
177 fnum2 = io.open.out.fnum;
178 CHECK_RDWR(fnum2, RDWR_RDWR);
179 smbcli_close(cli->tree, fnum2);
180 smbcli_close(cli->tree, fnum);
182 /* check the read/write modes */
183 io.open.level = RAW_OPEN_OPEN;
184 io.open.in.fname = fname;
185 io.open.in.search_attrs = 0;
187 io.open.in.flags = OPEN_FLAGS_OPEN_READ;
188 status = smb_raw_open(cli->tree, mem_ctx, &io);
189 CHECK_STATUS(status, NT_STATUS_OK);
190 fnum = io.open.out.fnum;
191 CHECK_RDWR(fnum, RDWR_RDONLY);
192 smbcli_close(cli->tree, fnum);
194 io.open.in.flags = OPEN_FLAGS_OPEN_WRITE;
195 status = smb_raw_open(cli->tree, mem_ctx, &io);
196 CHECK_STATUS(status, NT_STATUS_OK);
197 fnum = io.open.out.fnum;
198 CHECK_RDWR(fnum, RDWR_WRONLY);
199 smbcli_close(cli->tree, fnum);
201 io.open.in.flags = OPEN_FLAGS_OPEN_RDWR;
202 status = smb_raw_open(cli->tree, mem_ctx, &io);
203 CHECK_STATUS(status, NT_STATUS_OK);
204 fnum = io.open.out.fnum;
205 CHECK_RDWR(fnum, RDWR_RDWR);
206 smbcli_close(cli->tree, fnum);
208 /* check the share modes roughly - not a complete matrix */
209 io.open.in.flags = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
210 status = smb_raw_open(cli->tree, mem_ctx, &io);
211 CHECK_STATUS(status, NT_STATUS_OK);
212 fnum = io.open.out.fnum;
213 CHECK_RDWR(fnum, RDWR_RDWR);
215 if (io.open.in.flags != io.open.out.rmode) {
216 printf("(%d) rmode should equal flags - 0x%x 0x%x\n",
217 __LINE__, io.open.out.rmode, io.open.in.flags);
220 io.open.in.flags = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
221 status = smb_raw_open(cli->tree, mem_ctx, &io);
222 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
224 io.open.in.flags = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
225 status = smb_raw_open(cli->tree, mem_ctx, &io);
226 CHECK_STATUS(status, NT_STATUS_OK);
227 fnum2 = io.open.out.fnum;
228 CHECK_RDWR(fnum2, RDWR_RDONLY);
229 smbcli_close(cli->tree, fnum);
230 smbcli_close(cli->tree, fnum2);
233 /* check the returned write time */
234 io.open.level = RAW_OPEN_OPEN;
235 io.open.in.fname = fname;
236 io.open.in.search_attrs = 0;
237 io.open.in.flags = OPEN_FLAGS_OPEN_READ;
238 status = smb_raw_open(cli->tree, mem_ctx, &io);
239 CHECK_STATUS(status, NT_STATUS_OK);
240 fnum = io.open.out.fnum;
242 /* check other reply fields */
243 CHECK_TIME(io.open.out.write_time, write_time);
244 CHECK_ALL_INFO(io.open.out.size, size);
245 CHECK_ALL_INFO(io.open.out.attrib, attrib);
248 smbcli_close(cli->tree, fnum);
249 smbcli_unlink(cli->tree, fname);
258 static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
261 union smb_fileinfo finfo;
262 const char *fname = BASEDIR "\\torture_openx.txt";
270 NTSTATUS correct_status;
272 { OPENX_OPEN_FUNC_OPEN, True, NT_STATUS_OK },
273 { OPENX_OPEN_FUNC_OPEN, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
274 { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OK },
275 { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
276 { OPENX_OPEN_FUNC_FAIL, True, NT_STATUS_INVALID_LOCK_SEQUENCE },
277 { OPENX_OPEN_FUNC_FAIL, False, NT_STATUS_INVALID_LOCK_SEQUENCE },
278 { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OBJECT_NAME_COLLISION },
279 { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
280 { OPENX_OPEN_FUNC_TRUNC, True, NT_STATUS_OK },
281 { OPENX_OPEN_FUNC_TRUNC, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
282 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OK },
283 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
286 printf("Checking RAW_OPEN_OPENX\n");
287 smbcli_unlink(cli->tree, fname);
289 io.openx.level = RAW_OPEN_OPENX;
290 io.openx.in.fname = fname;
291 io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
292 io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
293 io.openx.in.search_attrs = 0;
294 io.openx.in.file_attrs = 0;
295 io.openx.in.write_time = 0;
296 io.openx.in.size = 1024*1024;
297 io.openx.in.timeout = 0;
299 /* check all combinations of open_func */
300 for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
301 if (open_funcs[i].with_file) {
302 fnum = create_complex_file(cli, mem_ctx, fname);
304 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
308 smbcli_close(cli->tree, fnum);
310 io.openx.in.open_func = open_funcs[i].open_func;
311 status = smb_raw_open(cli->tree, mem_ctx, &io);
312 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
313 printf("(%d) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n",
314 __LINE__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
315 i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
318 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
319 smbcli_close(cli->tree, io.openx.out.fnum);
320 smbcli_unlink(cli->tree, fname);
324 /* check the basic return fields */
325 io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
326 status = smb_raw_open(cli->tree, mem_ctx, &io);
327 CHECK_STATUS(status, NT_STATUS_OK);
328 fnum = io.openx.out.fnum;
330 CHECK_ALL_INFO(io.openx.out.size, size);
331 CHECK_VAL(io.openx.out.size, 1024*1024);
332 CHECK_ALL_INFO(io.openx.in.size, size);
333 CHECK_TIME(io.openx.out.write_time, write_time);
334 CHECK_ALL_INFO(io.openx.out.attrib, attrib);
335 CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR);
336 CHECK_VAL(io.openx.out.ftype, 0);
337 CHECK_VAL(io.openx.out.devstate, 0);
338 CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED);
339 smbcli_close(cli->tree, fnum);
340 smbcli_unlink(cli->tree, fname);
342 /* check the fields when the file already existed */
343 fnum2 = create_complex_file(cli, mem_ctx, fname);
348 smbcli_close(cli->tree, fnum2);
350 io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
351 status = smb_raw_open(cli->tree, mem_ctx, &io);
352 CHECK_STATUS(status, NT_STATUS_OK);
353 fnum = io.openx.out.fnum;
355 CHECK_ALL_INFO(io.openx.out.size, size);
356 CHECK_TIME(io.openx.out.write_time, write_time);
357 CHECK_VAL(io.openx.out.action, OPENX_ACTION_EXISTED);
358 CHECK_VAL(io.openx.out.unknown, 0);
359 CHECK_ALL_INFO(io.openx.out.attrib, attrib);
360 smbcli_close(cli->tree, fnum);
362 /* now check the search attrib for hidden files - win2003 ignores this? */
363 SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
364 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
366 io.openx.in.search_attrs = FILE_ATTRIBUTE_HIDDEN;
367 status = smb_raw_open(cli->tree, mem_ctx, &io);
368 CHECK_STATUS(status, NT_STATUS_OK);
369 smbcli_close(cli->tree, io.openx.out.fnum);
371 io.openx.in.search_attrs = 0;
372 status = smb_raw_open(cli->tree, mem_ctx, &io);
373 CHECK_STATUS(status, NT_STATUS_OK);
374 smbcli_close(cli->tree, io.openx.out.fnum);
376 SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
377 smbcli_unlink(cli->tree, fname);
379 /* and check attrib on create */
380 io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
381 io.openx.in.search_attrs = 0;
382 io.openx.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
383 status = smb_raw_open(cli->tree, mem_ctx, &io);
384 CHECK_STATUS(status, NT_STATUS_OK);
385 CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE, attrib);
386 smbcli_close(cli->tree, io.openx.out.fnum);
387 smbcli_unlink(cli->tree, fname);
389 /* check timeout on create - win2003 ignores the timeout! */
390 io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
391 io.openx.in.file_attrs = 0;
392 io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
393 status = smb_raw_open(cli->tree, mem_ctx, &io);
394 CHECK_STATUS(status, NT_STATUS_OK);
395 fnum = io.openx.out.fnum;
397 io.openx.in.timeout = 20000;
399 io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_NONE;
400 status = smb_raw_open(cli->tree, mem_ctx, &io);
401 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
402 if (end_timer() > 3) {
403 printf("(%d) Incorrect timing in openx with timeout - waited %d seconds\n",
404 __LINE__, (int)end_timer());
407 smbcli_close(cli->tree, fnum);
408 smbcli_unlink(cli->tree, fname);
410 /* now this is a really weird one - open for execute implies create?! */
411 io.openx.in.fname = fname;
412 io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
413 io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
414 io.openx.in.search_attrs = 0;
415 io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL;
416 io.openx.in.file_attrs = 0;
417 io.openx.in.write_time = 0;
418 io.openx.in.size = 0;
419 io.openx.in.timeout = 0;
420 status = smb_raw_open(cli->tree, mem_ctx, &io);
421 CHECK_STATUS(status, NT_STATUS_OK);
422 smbcli_close(cli->tree, io.openx.out.fnum);
424 /* check the extended return flag */
425 io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | OPENX_FLAGS_EXTENDED_RETURN;
426 io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
427 status = smb_raw_open(cli->tree, mem_ctx, &io);
428 CHECK_STATUS(status, NT_STATUS_OK);
429 CHECK_VAL(io.openx.out.access_mask, STD_RIGHT_ALL_ACCESS);
430 smbcli_close(cli->tree, io.openx.out.fnum);
433 smbcli_close(cli->tree, fnum);
434 smbcli_unlink(cli->tree, fname);
443 I can't work out how to get win2003 to accept a create file via TRANS2_OPEN, which
444 is why you see all the ACCESS_DENIED results below. When we finally work this out then this
445 test will make more sense
447 static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
450 union smb_fileinfo finfo;
451 const char *fname = BASEDIR "\\torture_t2open.txt";
459 NTSTATUS correct_status;
461 { OPENX_OPEN_FUNC_OPEN, True, NT_STATUS_OK },
462 { OPENX_OPEN_FUNC_OPEN, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
463 { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OK },
464 { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
465 { OPENX_OPEN_FUNC_FAIL, True, NT_STATUS_OBJECT_NAME_COLLISION },
466 { OPENX_OPEN_FUNC_FAIL, False, NT_STATUS_ACCESS_DENIED },
467 { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_OBJECT_NAME_COLLISION },
468 { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
469 { OPENX_OPEN_FUNC_TRUNC, True, NT_STATUS_ACCESS_DENIED },
470 { OPENX_OPEN_FUNC_TRUNC, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
471 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True, NT_STATUS_ACCESS_DENIED },
472 { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_ACCESS_DENIED },
475 printf("Checking RAW_OPEN_T2OPEN\n");
477 io.t2open.level = RAW_OPEN_T2OPEN;
478 io.t2open.in.fname = fname;
479 io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO |
480 OPENX_FLAGS_EA_LEN | OPENX_FLAGS_EXTENDED_RETURN;
481 io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
482 io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
483 io.t2open.in.file_attrs = 0;
484 io.t2open.in.write_time = 0;
485 io.t2open.in.size = 0;
486 io.t2open.in.timeout = 0;
488 io.t2open.in.eas = talloc(mem_ctx, sizeof(io.t2open.in.eas[0]));
489 io.t2open.in.num_eas = 1;
490 io.t2open.in.eas[0].flags = 0;
491 io.t2open.in.eas[0].name.s = "EAONE";
492 io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "1", 1);
494 /* check all combinations of open_func */
495 for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
496 if (open_funcs[i].with_file) {
497 fnum = create_complex_file(cli, mem_ctx, fname);
499 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
503 smbcli_close(cli->tree, fnum);
505 io.t2open.in.open_func = open_funcs[i].open_func;
506 status = smb_raw_open(cli->tree, mem_ctx, &io);
507 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
508 printf("(%d) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n",
509 __LINE__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
510 i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
513 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
514 smbcli_close(cli->tree, io.t2open.out.fnum);
515 smbcli_unlink(cli->tree, fname);
519 /* check the basic return fields */
520 fnum = create_complex_file(cli, mem_ctx, fname);
521 smbcli_close(cli->tree, fnum);
522 io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
523 status = smb_raw_open(cli->tree, mem_ctx, &io);
524 CHECK_STATUS(status, NT_STATUS_OK);
525 fnum = io.t2open.out.fnum;
527 CHECK_ALL_INFO(io.t2open.out.size, size);
528 CHECK_VAL(io.t2open.out.write_time, 0);
529 CHECK_ALL_INFO(io.t2open.out.attrib, attrib);
530 CHECK_VAL(io.t2open.out.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
531 CHECK_VAL(io.t2open.out.ftype, 0);
532 CHECK_VAL(io.t2open.out.devstate, 0);
533 CHECK_VAL(io.t2open.out.action, OPENX_ACTION_EXISTED);
534 smbcli_close(cli->tree, fnum);
536 /* now check the search attrib for hidden files - win2003 ignores this? */
537 SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
538 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
540 status = smb_raw_open(cli->tree, mem_ctx, &io);
541 CHECK_STATUS(status, NT_STATUS_OK);
542 smbcli_close(cli->tree, io.t2open.out.fnum);
544 status = smb_raw_open(cli->tree, mem_ctx, &io);
545 CHECK_STATUS(status, NT_STATUS_OK);
546 smbcli_close(cli->tree, io.t2open.out.fnum);
548 SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
549 smbcli_unlink(cli->tree, fname);
551 /* and check attrib on create */
552 io.t2open.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
553 io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
554 status = smb_raw_open(cli->tree, mem_ctx, &io);
555 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
557 /* check timeout on create - win2003 ignores the timeout! */
558 io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
559 io.t2open.in.file_attrs = 0;
560 io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
561 status = smb_raw_open(cli->tree, mem_ctx, &io);
562 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
565 smbcli_close(cli->tree, fnum);
566 smbcli_unlink(cli->tree, fname);
573 test RAW_OPEN_NTCREATEX
575 static BOOL test_ntcreatex(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
578 union smb_fileinfo finfo;
579 const char *fname = BASEDIR "\\torture_ntcreatex.txt";
580 const char *dname = BASEDIR "\\torture_ntcreatex.dir";
588 NTSTATUS correct_status;
590 { NTCREATEX_DISP_SUPERSEDE, True, NT_STATUS_OK },
591 { NTCREATEX_DISP_SUPERSEDE, False, NT_STATUS_OK },
592 { NTCREATEX_DISP_OPEN, True, NT_STATUS_OK },
593 { NTCREATEX_DISP_OPEN, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
594 { NTCREATEX_DISP_CREATE, True, NT_STATUS_OBJECT_NAME_COLLISION },
595 { NTCREATEX_DISP_CREATE, False, NT_STATUS_OK },
596 { NTCREATEX_DISP_OPEN_IF, True, NT_STATUS_OK },
597 { NTCREATEX_DISP_OPEN_IF, False, NT_STATUS_OK },
598 { NTCREATEX_DISP_OVERWRITE, True, NT_STATUS_OK },
599 { NTCREATEX_DISP_OVERWRITE, False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
600 { NTCREATEX_DISP_OVERWRITE_IF, True, NT_STATUS_OK },
601 { NTCREATEX_DISP_OVERWRITE_IF, False, NT_STATUS_OK },
602 { 6, True, NT_STATUS_INVALID_PARAMETER },
603 { 6, False, NT_STATUS_INVALID_PARAMETER },
606 printf("Checking RAW_OPEN_NTCREATEX\n");
608 /* reasonable default parameters */
609 io.generic.level = RAW_OPEN_NTCREATEX;
610 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
611 io.ntcreatex.in.root_fid = 0;
612 io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
613 io.ntcreatex.in.alloc_size = 1024*1024;
614 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
615 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
616 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
617 io.ntcreatex.in.create_options = 0;
618 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
619 io.ntcreatex.in.security_flags = 0;
620 io.ntcreatex.in.fname = fname;
622 /* test the open disposition */
623 for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
624 if (open_funcs[i].with_file) {
625 fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
627 d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
631 smbcli_close(cli->tree, fnum);
633 io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
634 status = smb_raw_open(cli->tree, mem_ctx, &io);
635 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
636 printf("(%d) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n",
637 __LINE__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
638 i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
641 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
642 smbcli_close(cli->tree, io.ntcreatex.out.fnum);
643 smbcli_unlink(cli->tree, fname);
647 /* basic field testing */
648 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
650 status = smb_raw_open(cli->tree, mem_ctx, &io);
651 CHECK_STATUS(status, NT_STATUS_OK);
652 fnum = io.ntcreatex.out.fnum;
654 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
655 CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
656 CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
657 CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
658 CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
659 CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
660 CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
661 CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
662 CHECK_ALL_INFO(io.ntcreatex.out.size, size);
663 CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
664 CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
666 /* check fields when the file already existed */
667 smbcli_close(cli->tree, fnum);
668 smbcli_unlink(cli->tree, fname);
669 fnum = create_complex_file(cli, mem_ctx, fname);
674 smbcli_close(cli->tree, fnum);
676 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
677 status = smb_raw_open(cli->tree, mem_ctx, &io);
678 CHECK_STATUS(status, NT_STATUS_OK);
679 fnum = io.ntcreatex.out.fnum;
681 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
682 CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
683 CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
684 CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
685 CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
686 CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
687 CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
688 CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
689 CHECK_ALL_INFO(io.ntcreatex.out.size, size);
690 CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
691 CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
692 smbcli_close(cli->tree, fnum);
693 smbcli_unlink(cli->tree, fname);
696 /* create a directory */
697 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
698 io.ntcreatex.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
699 io.ntcreatex.in.alloc_size = 0;
700 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
701 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
702 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
703 io.ntcreatex.in.create_options = 0;
704 io.ntcreatex.in.fname = dname;
707 smbcli_rmdir(cli->tree, fname);
708 smbcli_unlink(cli->tree, fname);
710 io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
711 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
712 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
713 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
714 status = smb_raw_open(cli->tree, mem_ctx, &io);
715 CHECK_STATUS(status, NT_STATUS_OK);
716 fnum = io.ntcreatex.out.fnum;
718 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
719 CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
720 CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
721 CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
722 CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
723 CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
724 CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
725 CHECK_VAL(io.ntcreatex.out.attrib, FILE_ATTRIBUTE_DIRECTORY);
726 CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
727 CHECK_ALL_INFO(io.ntcreatex.out.size, size);
728 CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
729 CHECK_VAL(io.ntcreatex.out.is_directory, 1);
730 CHECK_VAL(io.ntcreatex.out.size, 0);
731 CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
732 CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
733 smbcli_unlink(cli->tree, fname);
737 smbcli_close(cli->tree, fnum);
738 smbcli_unlink(cli->tree, fname);
744 test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
746 I've got an application that does a similar sequence of ntcreate&x,
747 locking&x and another ntcreate&x with
748 open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
751 static BOOL test_ntcreatex_brlocked(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
753 union smb_open io, io1;
755 struct smb_lock_entry lock[1];
756 const char *fname = BASEDIR "\\torture_ntcreatex.txt";
760 /* reasonable default parameters */
761 io.generic.level = RAW_OPEN_NTCREATEX;
762 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
763 io.ntcreatex.in.root_fid = 0;
764 io.ntcreatex.in.access_mask = 0x2019f;
765 io.ntcreatex.in.alloc_size = 0;
766 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
767 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
768 NTCREATEX_SHARE_ACCESS_WRITE;
769 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
770 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
771 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
772 io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
773 NTCREATEX_SECURITY_ALL;
774 io.ntcreatex.in.fname = fname;
776 status = smb_raw_open(cli->tree, mem_ctx, &io);
777 CHECK_STATUS(status, NT_STATUS_OK);
779 io2.lockx.level = RAW_LOCK_LOCKX;
780 io2.lockx.in.fnum = io.ntcreatex.out.fnum;
781 io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
782 io2.lockx.in.timeout = 0;
783 io2.lockx.in.ulock_cnt = 0;
784 io2.lockx.in.lock_cnt = 1;
785 lock[0].pid = cli->session->pid;
788 io2.lockx.in.locks = &lock[0];
789 status = smb_raw_lock(cli->tree, &io2);
790 CHECK_STATUS(status, NT_STATUS_OK);
792 io1.generic.level = RAW_OPEN_NTCREATEX;
793 io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
794 io1.ntcreatex.in.root_fid = 0;
795 io1.ntcreatex.in.access_mask = 0x20196;
796 io1.ntcreatex.in.alloc_size = 0;
797 io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
798 io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
799 NTCREATEX_SHARE_ACCESS_WRITE;
800 io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
801 io1.ntcreatex.in.create_options = 0;
802 io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
803 io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
804 NTCREATEX_SECURITY_ALL;
805 io1.ntcreatex.in.fname = fname;
807 status = smb_raw_open(cli->tree, mem_ctx, &io1);
808 CHECK_STATUS(status, NT_STATUS_OK);
811 smbcli_close(cli->tree, io.ntcreatex.out.fnum);
812 smbcli_close(cli->tree, io1.ntcreatex.out.fnum);
813 smbcli_unlink(cli->tree, fname);
820 static BOOL test_mknew(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
823 const char *fname = BASEDIR "\\torture_mknew.txt";
827 time_t basetime = (time(NULL) + 3600*24*3) & ~1;
828 union smb_fileinfo finfo;
830 printf("Checking RAW_OPEN_MKNEW\n");
832 io.mknew.level = RAW_OPEN_MKNEW;
833 io.mknew.in.attrib = 0;
834 io.mknew.in.write_time = 0;
835 io.mknew.in.fname = fname;
836 status = smb_raw_open(cli->tree, mem_ctx, &io);
837 CHECK_STATUS(status, NT_STATUS_OK);
838 fnum = io.mknew.out.fnum;
840 status = smb_raw_open(cli->tree, mem_ctx, &io);
841 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
843 smbcli_close(cli->tree, fnum);
844 smbcli_unlink(cli->tree, fname);
846 /* make sure write_time works */
847 io.mknew.in.write_time = basetime;
848 status = smb_raw_open(cli->tree, mem_ctx, &io);
849 CHECK_STATUS(status, NT_STATUS_OK);
850 fnum = io.mknew.out.fnum;
851 CHECK_TIME(basetime, write_time);
853 smbcli_close(cli->tree, fnum);
854 smbcli_unlink(cli->tree, fname);
856 /* make sure file_attrs works */
857 io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
858 status = smb_raw_open(cli->tree, mem_ctx, &io);
859 CHECK_STATUS(status, NT_STATUS_OK);
860 fnum = io.mknew.out.fnum;
861 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, attrib);
864 smbcli_close(cli->tree, fnum);
865 smbcli_unlink(cli->tree, fname);
874 static BOOL test_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
877 const char *fname = BASEDIR "\\torture_create.txt";
881 time_t basetime = (time(NULL) + 3600*24*3) & ~1;
882 union smb_fileinfo finfo;
884 printf("Checking RAW_OPEN_CREATE\n");
886 io.create.level = RAW_OPEN_CREATE;
887 io.create.in.attrib = 0;
888 io.create.in.write_time = 0;
889 io.create.in.fname = fname;
890 status = smb_raw_open(cli->tree, mem_ctx, &io);
891 CHECK_STATUS(status, NT_STATUS_OK);
892 fnum = io.create.out.fnum;
894 status = smb_raw_open(cli->tree, mem_ctx, &io);
895 CHECK_STATUS(status, NT_STATUS_OK);
897 smbcli_close(cli->tree, io.create.out.fnum);
898 smbcli_close(cli->tree, fnum);
899 smbcli_unlink(cli->tree, fname);
901 /* make sure write_time works */
902 io.create.in.write_time = basetime;
903 status = smb_raw_open(cli->tree, mem_ctx, &io);
904 CHECK_STATUS(status, NT_STATUS_OK);
905 fnum = io.create.out.fnum;
906 CHECK_TIME(basetime, write_time);
908 smbcli_close(cli->tree, fnum);
909 smbcli_unlink(cli->tree, fname);
911 /* make sure file_attrs works */
912 io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
913 status = smb_raw_open(cli->tree, mem_ctx, &io);
914 CHECK_STATUS(status, NT_STATUS_OK);
915 fnum = io.create.out.fnum;
916 CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE, attrib);
919 smbcli_close(cli->tree, fnum);
920 smbcli_unlink(cli->tree, fname);
929 static BOOL test_ctemp(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
935 time_t basetime = (time(NULL) + 3600*24*3) & ~1;
936 union smb_fileinfo finfo;
937 const char *name, *fname = NULL;
939 printf("Checking RAW_OPEN_CTEMP\n");
941 io.ctemp.level = RAW_OPEN_CTEMP;
942 io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
943 io.ctemp.in.write_time = basetime;
944 io.ctemp.in.directory = BASEDIR;
945 status = smb_raw_open(cli->tree, mem_ctx, &io);
946 CHECK_STATUS(status, NT_STATUS_OK);
947 fnum = io.ctemp.out.fnum;
949 name = io.ctemp.out.name;
951 finfo.generic.level = RAW_FILEINFO_NAME_INFO;
952 finfo.generic.in.fnum = fnum;
953 status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
954 CHECK_STATUS(status, NT_STATUS_OK);
956 fname = finfo.name_info.out.fname.s;
957 d_printf("ctemp name=%s real name=%s\n", name, fname);
959 CHECK_TIME(basetime, write_time);
962 smbcli_close(cli->tree, fnum);
964 smbcli_unlink(cli->tree, fname);
970 /* basic testing of all RAW_OPEN_* calls
972 BOOL torture_raw_open(int dummy)
974 struct smbcli_state *cli;
978 if (!torture_open_connection(&cli)) {
982 mem_ctx = talloc_init("torture_raw_open");
984 if (smbcli_deltree(cli->tree, BASEDIR) == -1) {
985 printf("Failed to clean " BASEDIR "\n");
988 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
989 printf("Failed to create " BASEDIR " - %s\n", smbcli_errstr(cli->tree));
993 if (!test_ntcreatex_brlocked(cli, mem_ctx)) {
997 if (!test_open(cli, mem_ctx)) {
1001 if (!test_openx(cli, mem_ctx)) {
1005 if (!test_ntcreatex(cli, mem_ctx)) {
1009 if (!test_t2open(cli, mem_ctx)) {
1013 if (!test_mknew(cli, mem_ctx)) {
1017 if (!test_create(cli, mem_ctx)) {
1021 if (!test_ctemp(cli, mem_ctx)) {
1025 smb_raw_exit(cli->session);
1026 smbcli_deltree(cli->tree, BASEDIR);
1028 torture_close_connection(cli);
1029 talloc_destroy(mem_ctx);