2 Unix SMB/CIFS implementation.
3 Test some misc Samba3 code paths
4 Copyright (C) Volker Lendecke 2006
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 "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/raw/raw_proto.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
28 #include "lib/events/events.h"
29 #include "param/param.h"
31 #define CHECK_STATUS(status, correct) do { \
32 if (!NT_STATUS_EQUAL(status, correct)) { \
33 printf("(%s) Incorrect status %s - should be %s\n", \
34 __location__, nt_errstr(status), nt_errstr(correct)); \
39 bool torture_samba3_checkfsp(struct torture_context
*torture
)
41 struct smbcli_state
*cli
;
42 const char *fname
= "test.txt";
43 const char *dirname
= "testdir";
50 struct smbcli_tree
*tree2
;
52 if ((mem_ctx
= talloc_init("torture_samba3_checkfsp")) == NULL
) {
53 d_printf("talloc_init failed\n");
57 if (!torture_open_connection_share(
58 torture
, &cli
, torture
, torture_setting_string(torture
, "host", NULL
),
59 torture_setting_string(torture
, "share", NULL
), torture
->ev
)) {
60 d_printf("torture_open_connection_share failed\n");
65 smbcli_deltree(cli
->tree
, dirname
);
67 status
= torture_second_tcon(torture
, cli
->session
,
68 torture_setting_string(torture
, "share", NULL
),
70 CHECK_STATUS(status
, NT_STATUS_OK
);
71 if (!NT_STATUS_IS_OK(status
))
74 /* Try a read on an invalid FID */
76 nread
= smbcli_read(cli
->tree
, 4711, buf
, 0, sizeof(buf
));
77 CHECK_STATUS(smbcli_nt_error(cli
->tree
), NT_STATUS_INVALID_HANDLE
);
79 /* Try a read on a directory handle */
81 status
= smbcli_mkdir(cli
->tree
, dirname
);
82 if (!NT_STATUS_IS_OK(status
)) {
83 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status
));
88 /* Open the directory */
91 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
92 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
93 io
.ntcreatex
.in
.root_fid
= 0;
94 io
.ntcreatex
.in
.security_flags
= 0;
95 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
96 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
97 io
.ntcreatex
.in
.alloc_size
= 0;
98 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
99 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
100 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
101 io
.ntcreatex
.in
.create_options
= 0;
102 io
.ntcreatex
.in
.fname
= dirname
;
103 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
104 if (!NT_STATUS_IS_OK(status
)) {
105 d_printf("smb_open on the directory failed: %s\n",
110 fnum
= io
.ntcreatex
.out
.file
.fnum
;
113 /* Try a read on the directory */
115 nread
= smbcli_read(cli
->tree
, fnum
, buf
, 0, sizeof(buf
));
117 d_printf("smbcli_read on a directory succeeded, expected "
122 CHECK_STATUS(smbcli_nt_error(cli
->tree
),
123 NT_STATUS_INVALID_DEVICE_REQUEST
);
125 /* Same test on the second tcon */
127 nread
= smbcli_read(tree2
, fnum
, buf
, 0, sizeof(buf
));
129 d_printf("smbcli_read on a directory succeeded, expected "
134 CHECK_STATUS(smbcli_nt_error(tree2
), NT_STATUS_INVALID_HANDLE
);
136 smbcli_close(cli
->tree
, fnum
);
138 /* Try a normal file read on a second tcon */
140 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
142 d_printf("Failed to create %s - %s\n", fname
,
143 smbcli_errstr(cli
->tree
));
148 nread
= smbcli_read(tree2
, fnum
, buf
, 0, sizeof(buf
));
149 CHECK_STATUS(smbcli_nt_error(tree2
), NT_STATUS_INVALID_HANDLE
);
151 smbcli_close(cli
->tree
, fnum
);
154 smbcli_deltree(cli
->tree
, dirname
);
155 torture_close_connection(cli
);
156 talloc_free(mem_ctx
);
161 static NTSTATUS
raw_smbcli_open(struct smbcli_tree
*tree
, const char *fname
, int flags
, int share_mode
, int *fnum
)
163 union smb_open open_parms
;
169 mem_ctx
= talloc_init("raw_open");
170 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
172 if (flags
& O_CREAT
) {
173 openfn
|= OPENX_OPEN_FUNC_CREATE
;
175 if (!(flags
& O_EXCL
)) {
176 if (flags
& O_TRUNC
) {
177 openfn
|= OPENX_OPEN_FUNC_TRUNC
;
179 openfn
|= OPENX_OPEN_FUNC_OPEN
;
183 accessmode
= (share_mode
<<OPENX_MODE_DENY_SHIFT
);
185 if ((flags
& O_ACCMODE
) == O_RDWR
) {
186 accessmode
|= OPENX_MODE_ACCESS_RDWR
;
187 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
188 accessmode
|= OPENX_MODE_ACCESS_WRITE
;
189 } else if ((flags
& O_ACCMODE
) == O_RDONLY
) {
190 accessmode
|= OPENX_MODE_ACCESS_READ
;
194 if ((flags
& O_SYNC
) == O_SYNC
) {
195 accessmode
|= OPENX_MODE_WRITE_THRU
;
199 if (share_mode
== DENY_FCB
) {
200 accessmode
= OPENX_MODE_ACCESS_FCB
| OPENX_MODE_DENY_FCB
;
203 open_parms
.openx
.level
= RAW_OPEN_OPENX
;
204 open_parms
.openx
.in
.flags
= 0;
205 open_parms
.openx
.in
.open_mode
= accessmode
;
206 open_parms
.openx
.in
.search_attrs
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
207 open_parms
.openx
.in
.file_attrs
= 0;
208 open_parms
.openx
.in
.write_time
= 0;
209 open_parms
.openx
.in
.open_func
= openfn
;
210 open_parms
.openx
.in
.size
= 0;
211 open_parms
.openx
.in
.timeout
= 0;
212 open_parms
.openx
.in
.fname
= fname
;
214 status
= smb_raw_open(tree
, mem_ctx
, &open_parms
);
215 talloc_free(mem_ctx
);
217 if (fnum
&& NT_STATUS_IS_OK(status
)) {
218 *fnum
= open_parms
.openx
.out
.file
.fnum
;
224 static NTSTATUS
raw_smbcli_t2open(struct smbcli_tree
*tree
, const char *fname
, int flags
, int share_mode
, int *fnum
)
232 mem_ctx
= talloc_init("raw_t2open");
233 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
235 if (flags
& O_CREAT
) {
236 openfn
|= OPENX_OPEN_FUNC_CREATE
;
238 if (!(flags
& O_EXCL
)) {
239 if (flags
& O_TRUNC
) {
240 openfn
|= OPENX_OPEN_FUNC_TRUNC
;
242 openfn
|= OPENX_OPEN_FUNC_OPEN
;
246 accessmode
= (share_mode
<<OPENX_MODE_DENY_SHIFT
);
248 if ((flags
& O_ACCMODE
) == O_RDWR
) {
249 accessmode
|= OPENX_MODE_ACCESS_RDWR
;
250 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
251 accessmode
|= OPENX_MODE_ACCESS_WRITE
;
252 } else if ((flags
& O_ACCMODE
) == O_RDONLY
) {
253 accessmode
|= OPENX_MODE_ACCESS_READ
;
257 if ((flags
& O_SYNC
) == O_SYNC
) {
258 accessmode
|= OPENX_MODE_WRITE_THRU
;
262 if (share_mode
== DENY_FCB
) {
263 accessmode
= OPENX_MODE_ACCESS_FCB
| OPENX_MODE_DENY_FCB
;
266 memset(&io
, '\0', sizeof(io
));
267 io
.t2open
.level
= RAW_OPEN_T2OPEN
;
268 io
.t2open
.in
.flags
= 0;
269 io
.t2open
.in
.open_mode
= accessmode
;
270 io
.t2open
.in
.search_attrs
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
271 io
.t2open
.in
.file_attrs
= 0;
272 io
.t2open
.in
.write_time
= 0;
273 io
.t2open
.in
.open_func
= openfn
;
274 io
.t2open
.in
.size
= 0;
275 io
.t2open
.in
.timeout
= 0;
276 io
.t2open
.in
.fname
= fname
;
278 io
.t2open
.in
.num_eas
= 1;
279 io
.t2open
.in
.eas
= talloc_array(mem_ctx
, struct ea_struct
, io
.t2open
.in
.num_eas
);
280 io
.t2open
.in
.eas
[0].flags
= 0;
281 io
.t2open
.in
.eas
[0].name
.s
= ".CLASSINFO";
282 io
.t2open
.in
.eas
[0].value
= data_blob_talloc(mem_ctx
, "first value", 11);
284 status
= smb_raw_open(tree
, mem_ctx
, &io
);
285 talloc_free(mem_ctx
);
287 if (fnum
&& NT_STATUS_IS_OK(status
)) {
288 *fnum
= io
.openx
.out
.file
.fnum
;
294 static NTSTATUS
raw_smbcli_ntcreate(struct smbcli_tree
*tree
, const char *fname
, int *fnum
)
300 mem_ctx
= talloc_init("raw_t2open");
301 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
303 memset(&io
, '\0', sizeof(io
));
304 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
305 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
306 io
.ntcreatex
.in
.root_fid
= 0;
307 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
308 io
.ntcreatex
.in
.alloc_size
= 0;
309 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
310 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
311 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
312 io
.ntcreatex
.in
.create_options
= 0;
313 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
314 io
.ntcreatex
.in
.security_flags
= 0;
315 io
.ntcreatex
.in
.fname
= fname
;
317 status
= smb_raw_open(tree
, mem_ctx
, &io
);
318 talloc_free(mem_ctx
);
320 if (fnum
&& NT_STATUS_IS_OK(status
)) {
321 *fnum
= io
.openx
.out
.file
.fnum
;
328 bool torture_samba3_badpath(struct torture_context
*torture
)
330 struct smbcli_state
*cli_nt
;
331 struct smbcli_state
*cli_dos
;
332 const char *fname
= "test.txt";
333 const char *fname1
= "test1.txt";
334 const char *dirname
= "testdir";
341 bool nt_status_support
;
343 if (!(mem_ctx
= talloc_init("torture_samba3_badpath"))) {
344 d_printf("talloc_init failed\n");
348 nt_status_support
= lp_nt_status_support(torture
->lp_ctx
);
350 if (!lp_set_cmdline(torture
->lp_ctx
, "nt status support", "yes")) {
351 printf("Could not set 'nt status support = yes'\n");
355 if (!torture_open_connection(&cli_nt
, torture
, 0)) {
359 if (!lp_set_cmdline(torture
->lp_ctx
, "nt status support", "no")) {
360 printf("Could not set 'nt status support = yes'\n");
364 if (!torture_open_connection(&cli_dos
, torture
, 1)) {
368 if (!lp_set_cmdline(torture
->lp_ctx
, "nt status support",
369 nt_status_support
? "yes":"no")) {
370 printf("Could not reset 'nt status support = yes'");
374 smbcli_deltree(cli_nt
->tree
, dirname
);
376 status
= smbcli_mkdir(cli_nt
->tree
, dirname
);
377 if (!NT_STATUS_IS_OK(status
)) {
378 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status
));
383 status
= smbcli_chkpath(cli_nt
->tree
, dirname
);
384 CHECK_STATUS(status
, NT_STATUS_OK
);
386 status
= smbcli_chkpath(cli_nt
->tree
,
387 talloc_asprintf(mem_ctx
, "%s\\bla", dirname
));
388 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
390 status
= smbcli_chkpath(cli_dos
->tree
,
391 talloc_asprintf(mem_ctx
, "%s\\bla", dirname
));
392 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
394 status
= smbcli_chkpath(cli_nt
->tree
,
395 talloc_asprintf(mem_ctx
, "%s\\bla\\blub",
397 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
398 status
= smbcli_chkpath(cli_dos
->tree
,
399 talloc_asprintf(mem_ctx
, "%s\\bla\\blub",
401 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
403 if (!(fpath
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname
))) {
406 fnum
= smbcli_open(cli_nt
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
408 d_printf("Could not create file %s: %s\n", fpath
,
409 smbcli_errstr(cli_nt
->tree
));
412 smbcli_close(cli_nt
->tree
, fnum
);
414 if (!(fpath1
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname1
))) {
417 fnum
= smbcli_open(cli_nt
->tree
, fpath1
, O_RDWR
| O_CREAT
, DENY_NONE
);
419 d_printf("Could not create file %s: %s\n", fpath1
,
420 smbcli_errstr(cli_nt
->tree
));
423 smbcli_close(cli_nt
->tree
, fnum
);
426 * Do a whole bunch of error code checks on chkpath
429 status
= smbcli_chkpath(cli_nt
->tree
, fpath
);
430 CHECK_STATUS(status
, NT_STATUS_NOT_A_DIRECTORY
);
431 status
= smbcli_chkpath(cli_dos
->tree
, fpath
);
432 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
434 status
= smbcli_chkpath(cli_nt
->tree
, "..");
435 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
436 status
= smbcli_chkpath(cli_dos
->tree
, "..");
437 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
439 status
= smbcli_chkpath(cli_nt
->tree
, ".");
440 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
441 status
= smbcli_chkpath(cli_dos
->tree
, ".");
442 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
444 status
= smbcli_chkpath(cli_nt
->tree
, "\t");
445 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
446 status
= smbcli_chkpath(cli_dos
->tree
, "\t");
447 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
449 status
= smbcli_chkpath(cli_nt
->tree
, "\t\\bla");
450 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
451 status
= smbcli_chkpath(cli_dos
->tree
, "\t\\bla");
452 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
454 status
= smbcli_chkpath(cli_nt
->tree
, "<");
455 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
456 status
= smbcli_chkpath(cli_dos
->tree
, "<");
457 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
459 status
= smbcli_chkpath(cli_nt
->tree
, "<\\bla");
460 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
461 status
= smbcli_chkpath(cli_dos
->tree
, "<\\bla");
462 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
465 * .... And the same gang against getatr. Note that the DOS error codes
469 status
= smbcli_getatr(cli_nt
->tree
, fpath
, NULL
, NULL
, NULL
);
470 CHECK_STATUS(status
, NT_STATUS_OK
);
471 status
= smbcli_getatr(cli_dos
->tree
, fpath
, NULL
, NULL
, NULL
);
472 CHECK_STATUS(status
, NT_STATUS_OK
);
474 status
= smbcli_getatr(cli_nt
->tree
, "..", NULL
, NULL
, NULL
);
475 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
476 status
= smbcli_getatr(cli_dos
->tree
, "..", NULL
, NULL
, NULL
);
477 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
479 status
= smbcli_getatr(cli_nt
->tree
, ".", NULL
, NULL
, NULL
);
480 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
481 status
= smbcli_getatr(cli_dos
->tree
, ".", NULL
, NULL
, NULL
);
482 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
484 status
= smbcli_getatr(cli_nt
->tree
, "\t", NULL
, NULL
, NULL
);
485 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
486 status
= smbcli_getatr(cli_dos
->tree
, "\t", NULL
, NULL
, NULL
);
487 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
489 status
= smbcli_getatr(cli_nt
->tree
, "\t\\bla", NULL
, NULL
, NULL
);
490 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
491 status
= smbcli_getatr(cli_dos
->tree
, "\t\\bla", NULL
, NULL
, NULL
);
492 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
494 status
= smbcli_getatr(cli_nt
->tree
, "<", NULL
, NULL
, NULL
);
495 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
496 status
= smbcli_getatr(cli_dos
->tree
, "<", NULL
, NULL
, NULL
);
497 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
499 status
= smbcli_getatr(cli_nt
->tree
, "<\\bla", NULL
, NULL
, NULL
);
500 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
501 status
= smbcli_getatr(cli_dos
->tree
, "<\\bla", NULL
, NULL
, NULL
);
502 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
504 /* Try the same set with openX. */
506 status
= raw_smbcli_open(cli_nt
->tree
, "..", O_RDONLY
, DENY_NONE
, NULL
);
507 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
508 status
= raw_smbcli_open(cli_dos
->tree
, "..", O_RDONLY
, DENY_NONE
, NULL
);
509 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
511 status
= raw_smbcli_open(cli_nt
->tree
, ".", O_RDONLY
, DENY_NONE
, NULL
);
512 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
513 status
= raw_smbcli_open(cli_dos
->tree
, ".", O_RDONLY
, DENY_NONE
, NULL
);
514 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
516 status
= raw_smbcli_open(cli_nt
->tree
, "\t", O_RDONLY
, DENY_NONE
, NULL
);
517 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
518 status
= raw_smbcli_open(cli_dos
->tree
, "\t", O_RDONLY
, DENY_NONE
, NULL
);
519 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
521 status
= raw_smbcli_open(cli_nt
->tree
, "\t\\bla", O_RDONLY
, DENY_NONE
, NULL
);
522 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
523 status
= raw_smbcli_open(cli_dos
->tree
, "\t\\bla", O_RDONLY
, DENY_NONE
, NULL
);
524 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
526 status
= raw_smbcli_open(cli_nt
->tree
, "<", O_RDONLY
, DENY_NONE
, NULL
);
527 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
528 status
= raw_smbcli_open(cli_dos
->tree
, "<", O_RDONLY
, DENY_NONE
, NULL
);
529 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
531 status
= raw_smbcli_open(cli_nt
->tree
, "<\\bla", O_RDONLY
, DENY_NONE
, NULL
);
532 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
533 status
= raw_smbcli_open(cli_dos
->tree
, "<\\bla", O_RDONLY
, DENY_NONE
, NULL
);
534 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
536 /* Let's test EEXIST error code mapping. */
537 status
= raw_smbcli_open(cli_nt
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
538 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
539 status
= raw_smbcli_open(cli_dos
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
540 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
542 status
= raw_smbcli_t2open(cli_nt
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
543 if (!NT_STATUS_EQUAL(status
, NT_STATUS_EAS_NOT_SUPPORTED
)
544 || !torture_setting_bool(torture
, "samba3", false)) {
545 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
546 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
548 status
= raw_smbcli_t2open(cli_dos
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
549 if (!NT_STATUS_EQUAL(status
, NT_STATUS_DOS(ERRDOS
,ERReasnotsupported
))
550 || !torture_setting_bool(torture
, "samba3", false)) {
551 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
552 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
555 status
= raw_smbcli_ntcreate(cli_nt
->tree
, fpath
, NULL
);
556 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
557 status
= raw_smbcli_ntcreate(cli_dos
->tree
, fpath
, NULL
);
558 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
560 /* Try the rename test. */
563 memset(&io
, '\0', sizeof(io
));
564 io
.rename
.in
.pattern1
= fpath1
;
565 io
.rename
.in
.pattern2
= fpath
;
567 /* Try with SMBmv rename. */
568 status
= smb_raw_rename(cli_nt
->tree
, &io
);
569 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
570 status
= smb_raw_rename(cli_dos
->tree
, &io
);
571 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRrename
));
573 /* Try with NT rename. */
574 io
.generic
.level
= RAW_RENAME_NTRENAME
;
575 io
.ntrename
.in
.old_name
= fpath1
;
576 io
.ntrename
.in
.new_name
= fpath
;
577 io
.ntrename
.in
.attrib
= 0;
578 io
.ntrename
.in
.cluster_size
= 0;
579 io
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
581 status
= smb_raw_rename(cli_nt
->tree
, &io
);
582 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
583 status
= smb_raw_rename(cli_dos
->tree
, &io
);
584 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRrename
));
593 if (cli_nt
!= NULL
) {
594 smbcli_deltree(cli_nt
->tree
, dirname
);
595 torture_close_connection(cli_nt
);
597 if (cli_dos
!= NULL
) {
598 torture_close_connection(cli_dos
);
600 talloc_free(mem_ctx
);
605 static void count_fn(struct clilist_file_info
*info
, const char *name
,
608 int *counter
= (int *)private_data
;
612 bool torture_samba3_caseinsensitive(struct torture_context
*torture
)
614 struct smbcli_state
*cli
;
617 const char *dirname
= "insensitive";
618 const char *ucase_dirname
= "InSeNsItIvE";
619 const char *fname
= "foo";
625 if (!(mem_ctx
= talloc_init("torture_samba3_caseinsensitive"))) {
626 d_printf("talloc_init failed\n");
630 if (!torture_open_connection(&cli
, torture
, 0)) {
634 smbcli_deltree(cli
->tree
, dirname
);
636 status
= smbcli_mkdir(cli
->tree
, dirname
);
637 if (!NT_STATUS_IS_OK(status
)) {
638 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status
));
642 if (!(fpath
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname
))) {
645 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
647 d_printf("Could not create file %s: %s\n", fpath
,
648 smbcli_errstr(cli
->tree
));
651 smbcli_close(cli
->tree
, fnum
);
653 smbcli_list(cli
->tree
, talloc_asprintf(
654 mem_ctx
, "%s\\*", ucase_dirname
),
655 FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_HIDDEN
656 |FILE_ATTRIBUTE_SYSTEM
,
657 count_fn
, (void *)&counter
);
663 d_fprintf(stderr
, "expected 3 entries, got %d\n", counter
);
668 talloc_free(mem_ctx
);
673 * Check that Samba3 correctly deals with conflicting posix byte range locks
674 * on an underlying file
677 bool torture_samba3_posixtimedlock(struct torture_context
*tctx
)
679 struct smbcli_state
*cli
;
682 const char *dirname
= "posixlock";
683 const char *fname
= "locked";
685 const char *localdir
;
686 const char *localname
;
690 struct flock posix_lock
;
693 struct smb_lock_entry lock_entry
;
694 struct smbcli_request
*req
;
696 if (!torture_open_connection(&cli
, tctx
, 0)) {
701 smbcli_deltree(cli
->tree
, dirname
);
703 status
= smbcli_mkdir(cli
->tree
, dirname
);
704 if (!NT_STATUS_IS_OK(status
)) {
705 torture_warning(tctx
, "smbcli_mkdir failed: %s\n",
711 if (!(fpath
= talloc_asprintf(tctx
, "%s\\%s", dirname
, fname
))) {
712 torture_warning(tctx
, "talloc failed\n");
716 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
718 torture_warning(tctx
, "Could not create file %s: %s\n", fpath
,
719 smbcli_errstr(cli
->tree
));
724 if (!(localdir
= torture_setting_string(tctx
, "localdir", NULL
))) {
725 torture_warning(tctx
, "Need 'localdir' setting\n");
730 if (!(localname
= talloc_asprintf(tctx
, "%s/%s/%s", localdir
, dirname
,
732 torture_warning(tctx
, "talloc failed\n");
738 * Lock a byte range from posix
741 fd
= open(localname
, O_RDWR
);
743 torture_warning(tctx
, "open(%s) failed: %s\n",
744 localname
, strerror(errno
));
748 posix_lock
.l_type
= F_WRLCK
;
749 posix_lock
.l_whence
= SEEK_SET
;
750 posix_lock
.l_start
= 0;
751 posix_lock
.l_len
= 1;
753 if (fcntl(fd
, F_SETLK
, &posix_lock
) == -1) {
754 torture_warning(tctx
, "fcntl failed: %s\n", strerror(errno
));
760 * Try a cifs brlock without timeout to see if posix locking = yes
763 io
.lockx
.in
.ulock_cnt
= 0;
764 io
.lockx
.in
.lock_cnt
= 1;
766 lock_entry
.count
= 1;
767 lock_entry
.offset
= 0;
768 lock_entry
.pid
= cli
->tree
->session
->pid
;
770 io
.lockx
.level
= RAW_LOCK_LOCKX
;
771 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
772 io
.lockx
.in
.timeout
= 0;
773 io
.lockx
.in
.locks
= &lock_entry
;
774 io
.lockx
.in
.file
.fnum
= fnum
;
776 status
= smb_raw_lock(cli
->tree
, &io
);
779 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
786 * Now fire off a timed brlock, unlock the posix lock and see if the
787 * timed lock gets through.
790 io
.lockx
.in
.timeout
= 5000;
792 req
= smb_raw_lock_send(cli
->tree
, &io
);
794 torture_warning(tctx
, "smb_raw_lock_send failed\n");
800 * Ship the async timed request to the server
802 event_loop_once(req
->transport
->socket
->event
.ctx
);
807 status
= smbcli_request_simple_recv(req
);
809 CHECK_STATUS(status
, NT_STATUS_OK
);
813 smbcli_close(cli
->tree
, fnum
);
818 smbcli_deltree(cli
->tree
, dirname
);
822 bool torture_samba3_rootdirfid(struct torture_context
*tctx
)
824 struct smbcli_state
*cli
;
828 const char *fname
= "testfile";
831 if (!torture_open_connection(&cli
, tctx
, 0)) {
836 smbcli_unlink(cli
->tree
, fname
);
839 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
840 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
841 io
.ntcreatex
.in
.root_fid
= 0;
842 io
.ntcreatex
.in
.security_flags
= 0;
843 io
.ntcreatex
.in
.access_mask
=
844 SEC_STD_SYNCHRONIZE
| SEC_FILE_EXECUTE
;
845 io
.ntcreatex
.in
.alloc_size
= 0;
846 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
847 io
.ntcreatex
.in
.share_access
=
848 NTCREATEX_SHARE_ACCESS_READ
849 | NTCREATEX_SHARE_ACCESS_READ
;
850 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
851 io
.ntcreatex
.in
.create_options
= 0;
852 io
.ntcreatex
.in
.fname
= "\\";
853 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
854 if (!NT_STATUS_IS_OK(status
)) {
855 d_printf("smb_open on the directory failed: %s\n",
860 dnum
= io
.ntcreatex
.out
.file
.fnum
;
862 io
.ntcreatex
.in
.flags
=
863 NTCREATEX_FLAGS_REQUEST_OPLOCK
864 | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
865 io
.ntcreatex
.in
.root_fid
= dnum
;
866 io
.ntcreatex
.in
.security_flags
= 0;
867 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
868 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
869 io
.ntcreatex
.in
.alloc_size
= 0;
870 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
871 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
872 io
.ntcreatex
.in
.create_options
= 0;
873 io
.ntcreatex
.in
.fname
= fname
;
875 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
876 if (!NT_STATUS_IS_OK(status
)) {
877 d_printf("smb_open on the file %s failed: %s\n",
878 fname
, nt_errstr(status
));
883 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
884 smbcli_close(cli
->tree
, dnum
);
885 smbcli_unlink(cli
->tree
, fname
);