r13121: Tag 4.0.0TP1
[Samba.git] / source / torture / torture.c
blob50034f430b8672986bcb6d5c1329bae6210d0fef
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-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.
21 #include "includes.h"
22 #include "lib/cmdline/popt_common.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/wait.h"
26 #include "system/filesys.h"
27 #include "ioctl.h"
28 #include "libcli/libcli.h"
29 #include "librpc/rpc/dcerpc_table.h"
31 int torture_nprocs=4;
32 int torture_numops=10;
33 int torture_entries=1000;
34 int torture_failures=1;
35 int torture_seed=0;
36 static int procnum; /* records process count number when forking */
37 static struct smbcli_state *current_cli;
38 static BOOL use_oplocks;
39 static BOOL use_level_II_oplocks;
41 BOOL torture_showall = False;
43 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
45 static struct smbcli_state *open_nbt_connection(void)
47 struct nbt_name called, calling;
48 struct smbcli_state *cli;
49 const char *host = lp_parm_string(-1, "torture", "host");
51 make_nbt_name_client(&calling, lp_netbios_name());
53 nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
55 cli = smbcli_state_init(NULL);
56 if (!cli) {
57 printf("Failed initialize smbcli_struct to connect with %s\n", host);
58 goto failed;
61 if (!smbcli_socket_connect(cli, host)) {
62 printf("Failed to connect with %s\n", host);
63 goto failed;
66 if (!smbcli_transport_establish(cli, &calling, &called)) {
67 printf("%s rejected the session\n",host);
68 goto failed;
71 return cli;
73 failed:
74 talloc_free(cli);
75 return NULL;
78 BOOL torture_open_connection_share(TALLOC_CTX *mem_ctx,
79 struct smbcli_state **c,
80 const char *hostname,
81 const char *sharename,
82 struct event_context *ev)
84 NTSTATUS status;
86 status = smbcli_full_connection(mem_ctx, c, hostname,
87 sharename, NULL,
88 cmdline_credentials, ev);
89 if (!NT_STATUS_IS_OK(status)) {
90 printf("Failed to open connection - %s\n", nt_errstr(status));
91 return False;
94 (*c)->transport->options.use_oplocks = use_oplocks;
95 (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
97 return True;
100 BOOL torture_open_connection(struct smbcli_state **c)
102 const char *host = lp_parm_string(-1, "torture", "host");
103 const char *share = lp_parm_string(-1, "torture", "share");
105 return torture_open_connection_share(NULL, c, host, share, NULL);
110 BOOL torture_close_connection(struct smbcli_state *c)
112 BOOL ret = True;
113 if (!c) return True;
114 if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
115 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
116 ret = False;
118 talloc_free(c);
119 return ret;
122 /* open a rpc connection to the chosen binding string */
123 NTSTATUS torture_rpc_connection(TALLOC_CTX *parent_ctx,
124 struct dcerpc_pipe **p,
125 const struct dcerpc_interface_table *table)
127 NTSTATUS status;
128 const char *binding = lp_parm_string(-1, "torture", "binding");
130 if (!binding) {
131 printf("You must specify a ncacn binding string\n");
132 return NT_STATUS_INVALID_PARAMETER;
135 status = dcerpc_pipe_connect(parent_ctx,
136 p, binding, table,
137 cmdline_credentials, NULL);
139 return status;
142 /* open a rpc connection to a specific transport */
143 NTSTATUS torture_rpc_connection_transport(TALLOC_CTX *parent_ctx,
144 struct dcerpc_pipe **p,
145 const struct dcerpc_interface_table *table,
146 enum dcerpc_transport_t transport)
148 NTSTATUS status;
149 const char *binding = lp_parm_string(-1, "torture", "binding");
150 struct dcerpc_binding *b;
151 TALLOC_CTX *mem_ctx = talloc_named(parent_ctx, 0, "torture_rpc_connection_smb");
153 if (!binding) {
154 printf("You must specify a ncacn binding string\n");
155 talloc_free(mem_ctx);
156 return NT_STATUS_INVALID_PARAMETER;
159 status = dcerpc_parse_binding(mem_ctx, binding, &b);
160 if (!NT_STATUS_IS_OK(status)) {
161 DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding));
162 talloc_free(mem_ctx);
163 return status;
166 b->transport = transport;
168 status = dcerpc_pipe_connect_b(mem_ctx, p, b, table,
169 cmdline_credentials, NULL);
171 if (NT_STATUS_IS_OK(status)) {
172 *p = talloc_reference(parent_ctx, *p);
173 } else {
174 *p = NULL;
176 talloc_free(mem_ctx);
177 return status;
180 /* check if the server produced the expected error code */
181 BOOL check_error(const char *location, struct smbcli_state *c,
182 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
184 NTSTATUS status;
186 status = smbcli_nt_error(c->tree);
187 if (NT_STATUS_IS_DOS(status)) {
188 int class, num;
189 class = NT_STATUS_DOS_CLASS(status);
190 num = NT_STATUS_DOS_CODE(status);
191 if (eclass != class || ecode != num) {
192 printf("unexpected error code %s\n", nt_errstr(status));
193 printf(" expected %s or %s (at %s)\n",
194 nt_errstr(NT_STATUS_DOS(eclass, ecode)),
195 nt_errstr(nterr), location);
196 return False;
198 } else {
199 if (!NT_STATUS_EQUAL(nterr, status)) {
200 printf("unexpected error code %s\n", nt_errstr(status));
201 printf(" expected %s (at %s)\n", nt_errstr(nterr), location);
202 return False;
206 return True;
210 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
212 while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
213 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
215 return True;
219 static BOOL rw_torture(struct smbcli_state *c)
221 const char *lockfname = "\\torture.lck";
222 char *fname;
223 int fnum;
224 int fnum2;
225 pid_t pid2, pid = getpid();
226 int i, j;
227 uint8_t buf[1024];
228 BOOL correct = True;
230 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
231 DENY_NONE);
232 if (fnum2 == -1)
233 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
234 if (fnum2 == -1) {
235 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
236 return False;
240 for (i=0;i<torture_numops;i++) {
241 uint_t n = (uint_t)random()%10;
242 if (i % 10 == 0) {
243 printf("%d\r", i); fflush(stdout);
245 asprintf(&fname, "\\torture.%u", n);
247 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
248 return False;
251 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
252 if (fnum == -1) {
253 printf("open failed (%s)\n", smbcli_errstr(c->tree));
254 correct = False;
255 break;
258 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
259 printf("write failed (%s)\n", smbcli_errstr(c->tree));
260 correct = False;
263 for (j=0;j<50;j++) {
264 if (smbcli_write(c->tree, fnum, 0, buf,
265 sizeof(pid)+(j*sizeof(buf)),
266 sizeof(buf)) != sizeof(buf)) {
267 printf("write failed (%s)\n", smbcli_errstr(c->tree));
268 correct = False;
272 pid2 = 0;
274 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
275 printf("read failed (%s)\n", smbcli_errstr(c->tree));
276 correct = False;
279 if (pid2 != pid) {
280 printf("data corruption!\n");
281 correct = False;
284 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
285 printf("close failed (%s)\n", smbcli_errstr(c->tree));
286 correct = False;
289 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
290 printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
291 correct = False;
294 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
295 printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
296 correct = False;
298 free(fname);
301 smbcli_close(c->tree, fnum2);
302 smbcli_unlink(c->tree, lockfname);
304 printf("%d\n", i);
306 return correct;
309 static BOOL run_torture(struct smbcli_state *cli, int dummy)
311 BOOL ret;
313 ret = rw_torture(cli);
315 if (!torture_close_connection(cli)) {
316 ret = False;
319 return ret;
323 static BOOL rw_torture2(struct smbcli_state *c1, struct smbcli_state *c2)
325 const char *lockfname = "\\torture2.lck";
326 int fnum1;
327 int fnum2;
328 int i;
329 uint8_t buf[131072];
330 uint8_t buf_rd[131072];
331 BOOL correct = True;
332 ssize_t bytes_read, bytes_written;
334 if (smbcli_deltree(c1->tree, lockfname) == -1) {
335 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
338 fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
339 DENY_NONE);
340 if (fnum1 == -1) {
341 printf("first open read/write of %s failed (%s)\n",
342 lockfname, smbcli_errstr(c1->tree));
343 return False;
345 fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY,
346 DENY_NONE);
347 if (fnum2 == -1) {
348 printf("second open read-only of %s failed (%s)\n",
349 lockfname, smbcli_errstr(c2->tree));
350 smbcli_close(c1->tree, fnum1);
351 return False;
354 printf("Checking data integrity over %d ops\n", torture_numops);
356 for (i=0;i<torture_numops;i++)
358 size_t buf_size = ((uint_t)random()%(sizeof(buf)-1))+ 1;
359 if (i % 10 == 0) {
360 printf("%d\r", i); fflush(stdout);
363 generate_random_buffer(buf, buf_size);
365 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
366 printf("write failed (%s)\n", smbcli_errstr(c1->tree));
367 printf("wrote %d, expected %d\n", (int)bytes_written, (int)buf_size);
368 correct = False;
369 break;
372 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
373 printf("read failed (%s)\n", smbcli_errstr(c2->tree));
374 printf("read %d, expected %d\n", (int)bytes_read, (int)buf_size);
375 correct = False;
376 break;
379 if (memcmp(buf_rd, buf, buf_size) != 0)
381 printf("read/write compare failed\n");
382 correct = False;
383 break;
387 if (NT_STATUS_IS_ERR(smbcli_close(c2->tree, fnum2))) {
388 printf("close failed (%s)\n", smbcli_errstr(c2->tree));
389 correct = False;
391 if (NT_STATUS_IS_ERR(smbcli_close(c1->tree, fnum1))) {
392 printf("close failed (%s)\n", smbcli_errstr(c1->tree));
393 correct = False;
396 if (NT_STATUS_IS_ERR(smbcli_unlink(c1->tree, lockfname))) {
397 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
398 correct = False;
401 return correct;
404 #define BOOLSTR(b) ((b) ? "Yes" : "No")
406 static BOOL run_readwritetest(void)
408 struct smbcli_state *cli1, *cli2;
409 BOOL test1, test2 = True;
411 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
412 return False;
415 printf("starting readwritetest\n");
417 test1 = rw_torture2(cli1, cli2);
418 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
420 if (test1) {
421 test2 = rw_torture2(cli1, cli1);
422 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
425 if (!torture_close_connection(cli1)) {
426 test1 = False;
429 if (!torture_close_connection(cli2)) {
430 test2 = False;
433 return (test1 && test2);
437 this checks to see if a secondary tconx can use open files from an
438 earlier tconx
440 static BOOL run_tcon_test(void)
442 struct smbcli_state *cli;
443 const char *fname = "\\tcontest.tmp";
444 int fnum1;
445 uint16_t cnum1, cnum2, cnum3;
446 uint16_t vuid1, vuid2;
447 uint8_t buf[4];
448 BOOL ret = True;
449 struct smbcli_tree *tree1;
450 const char *host = lp_parm_string(-1, "torture", "host");
451 const char *share = lp_parm_string(-1, "torture", "share");
452 const char *password = lp_parm_string(-1, "torture", "password");
454 if (!torture_open_connection(&cli)) {
455 return False;
458 printf("starting tcontest\n");
460 if (smbcli_deltree(cli->tree, fname) == -1) {
461 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
464 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
465 if (fnum1 == -1) {
466 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
467 return False;
470 cnum1 = cli->tree->tid;
471 vuid1 = cli->session->vuid;
473 memset(&buf, 0, 4); /* init buf so valgrind won't complain */
474 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
475 printf("initial write failed (%s)\n", smbcli_errstr(cli->tree));
476 return False;
479 tree1 = cli->tree; /* save old tree connection */
480 if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
481 printf("%s refused 2nd tree connect (%s)\n", host,
482 smbcli_errstr(cli->tree));
483 talloc_free(cli);
484 return False;
487 cnum2 = cli->tree->tid;
488 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
489 vuid2 = cli->session->vuid + 1;
491 /* try a write with the wrong tid */
492 cli->tree->tid = cnum2;
494 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
495 printf("* server allows write with wrong TID\n");
496 ret = False;
497 } else {
498 printf("server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
502 /* try a write with an invalid tid */
503 cli->tree->tid = cnum3;
505 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
506 printf("* server allows write with invalid TID\n");
507 ret = False;
508 } else {
509 printf("server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
512 /* try a write with an invalid vuid */
513 cli->session->vuid = vuid2;
514 cli->tree->tid = cnum1;
516 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
517 printf("* server allows write with invalid VUID\n");
518 ret = False;
519 } else {
520 printf("server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
523 cli->session->vuid = vuid1;
524 cli->tree->tid = cnum1;
526 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
527 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
528 return False;
531 cli->tree->tid = cnum2;
533 if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
534 printf("secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
535 return False;
538 cli->tree = tree1; /* restore initial tree */
539 cli->tree->tid = cnum1;
541 smbcli_unlink(tree1, fname);
543 if (!torture_close_connection(cli)) {
544 return False;
547 return ret;
552 static BOOL tcon_devtest(struct smbcli_state *cli,
553 const char *myshare, const char *devtype,
554 NTSTATUS expected_error)
556 BOOL status;
557 BOOL ret;
558 const char *password = lp_parm_string(-1, "torture", "password");
560 status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype,
561 password));
563 printf("Trying share %s with devtype %s\n", myshare, devtype);
565 if (NT_STATUS_IS_OK(expected_error)) {
566 if (status) {
567 ret = True;
568 } else {
569 printf("tconX to share %s with type %s "
570 "should have succeeded but failed\n",
571 myshare, devtype);
572 ret = False;
574 smbcli_tdis(cli);
575 } else {
576 if (status) {
577 printf("tconx to share %s with type %s "
578 "should have failed but succeeded\n",
579 myshare, devtype);
580 ret = False;
581 } else {
582 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
583 expected_error)) {
584 ret = True;
585 } else {
586 printf("Returned unexpected error\n");
587 ret = False;
591 return ret;
595 checks for correct tconX support
597 static BOOL run_tcon_devtype_test(void)
599 struct smbcli_state *cli1 = NULL;
600 NTSTATUS status;
601 BOOL ret = True;
602 const char *host = lp_parm_string(-1, "torture", "host");
603 const char *share = lp_parm_string(-1, "torture", "share");
605 status = smbcli_full_connection(NULL,
606 &cli1, host,
607 share, NULL,
608 cmdline_credentials, NULL);
610 if (!NT_STATUS_IS_OK(status)) {
611 printf("could not open connection\n");
612 return False;
615 if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
616 ret = False;
618 if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
619 ret = False;
621 if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
622 ret = False;
624 if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
625 ret = False;
627 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
628 ret = False;
630 if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
631 ret = False;
633 if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
634 ret = False;
636 if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
637 ret = False;
639 if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
640 ret = False;
642 if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
643 ret = False;
645 talloc_free(cli1);
647 if (ret)
648 printf("Passed tcondevtest\n");
650 return ret;
655 test whether fnums and tids open on one VC are available on another (a major
656 security hole)
658 static BOOL run_fdpasstest(void)
660 struct smbcli_state *cli1, *cli2;
661 const char *fname = "\\fdpass.tst";
662 int fnum1, oldtid;
663 uint8_t buf[1024];
665 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
666 return False;
669 printf("starting fdpasstest\n");
671 smbcli_unlink(cli1->tree, fname);
673 printf("Opening a file on connection 1\n");
675 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
676 if (fnum1 == -1) {
677 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
678 return False;
681 printf("writing to file on connection 1\n");
683 if (smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
684 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
685 return False;
688 oldtid = cli2->tree->tid;
689 cli2->session->vuid = cli1->session->vuid;
690 cli2->tree->tid = cli1->tree->tid;
691 cli2->session->pid = cli1->session->pid;
693 printf("reading from file on connection 2\n");
695 if (smbcli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
696 printf("read succeeded! nasty security hole [%s]\n",
697 buf);
698 return False;
701 smbcli_close(cli1->tree, fnum1);
702 smbcli_unlink(cli1->tree, fname);
704 cli2->tree->tid = oldtid;
706 torture_close_connection(cli1);
707 torture_close_connection(cli2);
709 printf("finished fdpasstest\n");
710 return True;
715 test the timing of deferred open requests
717 static BOOL run_deferopen(struct smbcli_state *cli, int dummy)
719 const char *fname = "\\defer_open_test.dat";
720 int retries=4;
721 int i = 0;
722 BOOL correct = True;
724 if (retries <= 0) {
725 printf("failed to connect\n");
726 return False;
729 printf("Testing deferred open requests.\n");
731 while (i < 4) {
732 int fnum = -1;
734 do {
735 struct timeval tv;
736 tv = timeval_current();
737 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
738 SEC_RIGHTS_FILE_ALL,
739 FILE_ATTRIBUTE_NORMAL,
740 NTCREATEX_SHARE_ACCESS_NONE,
741 NTCREATEX_DISP_OPEN_IF, 0, 0);
742 if (fnum != -1) {
743 break;
745 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
746 double e = timeval_elapsed(&tv);
747 if (e < 0.5 || e > 1.5) {
748 fprintf(stderr,"Timing incorrect %.2f violation\n",
752 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
754 if (fnum == -1) {
755 fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
756 return False;
759 printf("pid %u open %d\n", getpid(), i);
761 sleep(10);
762 i++;
763 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
764 fprintf(stderr,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
765 return False;
767 sleep(2);
770 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
771 /* All until the last unlink will fail with sharing violation. */
772 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
773 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
774 correct = False;
778 printf("deferred test finished\n");
779 if (!torture_close_connection(cli)) {
780 correct = False;
782 return correct;
786 test how many open files this server supports on the one socket
788 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
790 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
791 char *fname;
792 int fnums[0x11000], i;
793 int retries=4, maxfid;
794 BOOL correct = True;
796 if (retries <= 0) {
797 printf("failed to connect\n");
798 return False;
801 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
802 printf("Failed to deltree \\maxfid - %s\n",
803 smbcli_errstr(cli->tree));
804 return False;
806 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
807 printf("Failed to mkdir \\maxfid, error=%s\n",
808 smbcli_errstr(cli->tree));
809 return False;
812 printf("Testing maximum number of open files\n");
814 for (i=0; i<0x11000; i++) {
815 if (i % 1000 == 0) {
816 asprintf(&fname, "\\maxfid\\fid%d", i/1000);
817 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
818 printf("Failed to mkdir %s, error=%s\n",
819 fname, smbcli_errstr(cli->tree));
820 return False;
822 free(fname);
824 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
825 if ((fnums[i] = smbcli_open(cli->tree, fname,
826 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
827 -1) {
828 printf("open of %s failed (%s)\n",
829 fname, smbcli_errstr(cli->tree));
830 printf("maximum fnum is %d\n", i);
831 break;
833 free(fname);
834 printf("%6d\r", i);
836 printf("%6d\n", i);
837 i--;
839 maxfid = i;
841 printf("cleaning up\n");
842 for (i=0;i<maxfid/2;i++) {
843 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
844 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
845 printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
847 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
848 printf("unlink of %s failed (%s)\n",
849 fname, smbcli_errstr(cli->tree));
850 correct = False;
852 free(fname);
854 asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
855 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
856 printf("Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
858 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
859 printf("unlink of %s failed (%s)\n",
860 fname, smbcli_errstr(cli->tree));
861 correct = False;
863 free(fname);
865 printf("%6d %6d\r", i, maxfid-i);
867 printf("%6d\n", 0);
869 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
870 printf("Failed to deltree \\maxfid - %s\n",
871 smbcli_errstr(cli->tree));
872 return False;
875 printf("maxfid test finished\n");
876 if (!torture_close_connection(cli)) {
877 correct = False;
879 return correct;
880 #undef MAXFID_TEMPLATE
883 /* send smb negprot commands, not reading the response */
884 static BOOL run_negprot_nowait(void)
886 int i;
887 struct smbcli_state *cli, *cli2;
888 BOOL correct = True;
890 printf("starting negprot nowait test\n");
892 cli = open_nbt_connection();
893 if (!cli) {
894 return False;
897 printf("Filling send buffer\n");
899 for (i=0;i<1000;i++) {
900 struct smbcli_request *req;
901 req = smb_raw_negotiate_send(cli->transport, PROTOCOL_NT1);
902 smbcli_transport_process(cli->transport);
903 if (req->state == SMBCLI_REQUEST_ERROR) {
904 printf("Failed to fill pipe - %s\n", nt_errstr(req->status));
905 torture_close_connection(cli);
906 return correct;
910 printf("Opening secondary connection\n");
911 if (!torture_open_connection(&cli2)) {
912 return False;
915 if (!torture_close_connection(cli)) {
916 correct = False;
919 if (!torture_close_connection(cli2)) {
920 correct = False;
923 printf("finished negprot nowait test\n");
925 return correct;
930 This checks how the getatr calls works
932 static BOOL run_attrtest(void)
934 struct smbcli_state *cli;
935 int fnum;
936 time_t t, t2;
937 const char *fname = "\\attrib123456789.tst";
938 BOOL correct = True;
940 printf("starting attrib test\n");
942 if (!torture_open_connection(&cli)) {
943 return False;
946 smbcli_unlink(cli->tree, fname);
947 fnum = smbcli_open(cli->tree, fname,
948 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
949 smbcli_close(cli->tree, fnum);
951 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
952 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
953 correct = False;
956 printf("New file time is %s", ctime(&t));
958 if (abs(t - time(NULL)) > 60*60*24*10) {
959 printf("ERROR: SMBgetatr bug. time is %s",
960 ctime(&t));
961 t = time(NULL);
962 correct = False;
965 t2 = t-60*60*24; /* 1 day ago */
967 printf("Setting file time to %s", ctime(&t2));
969 if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
970 printf("setatr failed (%s)\n", smbcli_errstr(cli->tree));
971 correct = True;
974 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
975 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
976 correct = True;
979 printf("Retrieved file time as %s", ctime(&t));
981 if (t != t2) {
982 printf("ERROR: getatr/setatr bug. times are\n%s",
983 ctime(&t));
984 printf("%s", ctime(&t2));
985 correct = True;
988 smbcli_unlink(cli->tree, fname);
990 if (!torture_close_connection(cli)) {
991 correct = False;
994 printf("attrib test finished\n");
996 return correct;
1001 This checks a couple of trans2 calls
1003 static BOOL run_trans2test(void)
1005 struct smbcli_state *cli;
1006 int fnum;
1007 size_t size;
1008 time_t c_time, a_time, m_time, w_time, m_time2;
1009 const char *fname = "\\trans2.tst";
1010 const char *dname = "\\trans2";
1011 const char *fname2 = "\\trans2\\trans2.tst";
1012 const char *pname;
1013 BOOL correct = True;
1015 printf("starting trans2 test\n");
1017 if (!torture_open_connection(&cli)) {
1018 return False;
1021 smbcli_unlink(cli->tree, fname);
1023 printf("Testing qfileinfo\n");
1025 fnum = smbcli_open(cli->tree, fname,
1026 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1027 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
1028 NULL, NULL))) {
1029 printf("ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
1030 correct = False;
1033 printf("Testing NAME_INFO\n");
1035 if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
1036 printf("ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
1037 correct = False;
1040 if (!pname || strcmp(pname, fname)) {
1041 printf("qfilename gave different name? [%s] [%s]\n",
1042 fname, pname);
1043 correct = False;
1046 smbcli_close(cli->tree, fnum);
1047 smbcli_unlink(cli->tree, fname);
1049 fnum = smbcli_open(cli->tree, fname,
1050 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1051 if (fnum == -1) {
1052 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1053 return False;
1055 smbcli_close(cli->tree, fnum);
1057 printf("Checking for sticky create times\n");
1059 if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
1060 printf("ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
1061 correct = False;
1062 } else {
1063 if (c_time != m_time) {
1064 printf("create time=%s", ctime(&c_time));
1065 printf("modify time=%s", ctime(&m_time));
1066 printf("This system appears to have sticky create times\n");
1068 if (a_time % (60*60) == 0) {
1069 printf("access time=%s", ctime(&a_time));
1070 printf("This system appears to set a midnight access time\n");
1071 correct = False;
1074 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1075 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
1076 correct = False;
1081 smbcli_unlink(cli->tree, fname);
1082 fnum = smbcli_open(cli->tree, fname,
1083 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1084 smbcli_close(cli->tree, fnum);
1085 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1086 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1087 correct = False;
1088 } else {
1089 if (w_time < 60*60*24*2) {
1090 printf("write time=%s", ctime(&w_time));
1091 printf("This system appears to set a initial 0 write time\n");
1092 correct = False;
1096 smbcli_unlink(cli->tree, fname);
1099 /* check if the server updates the directory modification time
1100 when creating a new file */
1101 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1102 printf("ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
1103 correct = False;
1105 sleep(3);
1106 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1107 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1108 correct = False;
1111 fnum = smbcli_open(cli->tree, fname2,
1112 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1113 smbcli_write(cli->tree, fnum, 0, &fnum, 0, sizeof(fnum));
1114 smbcli_close(cli->tree, fnum);
1115 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
1116 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1117 correct = False;
1118 } else {
1119 if (m_time2 == m_time) {
1120 printf("This system does not update directory modification times\n");
1121 correct = False;
1124 smbcli_unlink(cli->tree, fname2);
1125 smbcli_rmdir(cli->tree, dname);
1127 if (!torture_close_connection(cli)) {
1128 correct = False;
1131 printf("trans2 test finished\n");
1133 return correct;
1138 /* FIRST_DESIRED_ACCESS 0xf019f */
1139 #define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1140 SEC_FILE_READ_EA| /* 0xf */ \
1141 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1142 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1143 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1144 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1145 /* SECOND_DESIRED_ACCESS 0xe0080 */
1146 #define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1147 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1148 SEC_STD_WRITE_OWNER /* 0xe0000 */
1150 #if 0
1151 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1152 READ_CONTROL|WRITE_DAC|\
1153 SEC_FILE_READ_DATA|\
1154 WRITE_OWNER /* */
1155 #endif
1158 Test ntcreate calls made by xcopy
1160 static BOOL run_xcopy(void)
1162 struct smbcli_state *cli1;
1163 const char *fname = "\\test.txt";
1164 BOOL correct = True;
1165 int fnum1, fnum2;
1167 printf("starting xcopy test\n");
1169 if (!torture_open_connection(&cli1)) {
1170 return False;
1173 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1174 FIRST_DESIRED_ACCESS,
1175 FILE_ATTRIBUTE_ARCHIVE,
1176 NTCREATEX_SHARE_ACCESS_NONE,
1177 NTCREATEX_DISP_OVERWRITE_IF,
1178 0x4044, 0);
1180 if (fnum1 == -1) {
1181 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
1182 return False;
1185 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1186 SECOND_DESIRED_ACCESS, 0,
1187 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1188 0x200000, 0);
1189 if (fnum2 == -1) {
1190 printf("second open failed - %s\n", smbcli_errstr(cli1->tree));
1191 return False;
1194 if (!torture_close_connection(cli1)) {
1195 correct = False;
1198 return correct;
1203 see how many RPC pipes we can open at once
1205 static BOOL run_pipe_number(void)
1207 struct smbcli_state *cli1;
1208 const char *pipe_name = "\\WKSSVC";
1209 int fnum;
1210 int num_pipes = 0;
1212 printf("starting pipenumber test\n");
1213 if (!torture_open_connection(&cli1)) {
1214 return False;
1217 while(1) {
1218 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1219 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1221 if (fnum == -1) {
1222 printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
1223 break;
1225 num_pipes++;
1226 printf("%d\r", num_pipes);
1227 fflush(stdout);
1230 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
1231 torture_close_connection(cli1);
1232 return True;
1239 open N connections to the server and just hold them open
1240 used for testing performance when there are N idle users
1241 already connected
1243 static BOOL torture_holdcon(void)
1245 int i;
1246 struct smbcli_state **cli;
1247 int num_dead = 0;
1249 printf("Opening %d connections\n", torture_numops);
1251 cli = malloc_array_p(struct smbcli_state *, torture_numops);
1253 for (i=0;i<torture_numops;i++) {
1254 if (!torture_open_connection(&cli[i])) {
1255 return False;
1257 printf("opened %d connections\r", i);
1258 fflush(stdout);
1261 printf("\nStarting pings\n");
1263 while (1) {
1264 for (i=0;i<torture_numops;i++) {
1265 NTSTATUS status;
1266 if (cli[i]) {
1267 status = smbcli_chkpath(cli[i]->tree, "\\");
1268 if (!NT_STATUS_IS_OK(status)) {
1269 printf("Connection %d is dead\n", i);
1270 cli[i] = NULL;
1271 num_dead++;
1273 usleep(100);
1277 if (num_dead == torture_numops) {
1278 printf("All connections dead - finishing\n");
1279 break;
1282 printf(".");
1283 fflush(stdout);
1286 return True;
1290 Try with a wrong vuid and check error message.
1293 static BOOL run_vuidtest(void)
1295 struct smbcli_state *cli;
1296 const char *fname = "\\vuid.tst";
1297 int fnum;
1298 size_t size;
1299 time_t c_time, a_time, m_time;
1300 BOOL correct = True;
1302 uint16_t orig_vuid;
1303 NTSTATUS result;
1305 printf("starting vuid test\n");
1307 if (!torture_open_connection(&cli)) {
1308 return False;
1311 smbcli_unlink(cli->tree, fname);
1313 fnum = smbcli_open(cli->tree, fname,
1314 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1316 orig_vuid = cli->session->vuid;
1318 cli->session->vuid += 1234;
1320 printf("Testing qfileinfo with wrong vuid\n");
1322 if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
1323 &size, &c_time, &a_time,
1324 &m_time, NULL, NULL))) {
1325 printf("ERROR: qfileinfo passed with wrong vuid\n");
1326 correct = False;
1329 if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
1330 NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
1331 !NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
1332 NT_STATUS_INVALID_HANDLE)) {
1333 printf("ERROR: qfileinfo should have returned DOS error "
1334 "ERRSRV:ERRbaduid\n but returned %s\n",
1335 smbcli_errstr(cli->tree));
1336 correct = False;
1339 cli->session->vuid -= 1234;
1341 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
1342 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
1343 correct = False;
1346 smbcli_unlink(cli->tree, fname);
1348 if (!torture_close_connection(cli)) {
1349 correct = False;
1352 printf("vuid test finished\n");
1354 return correct;
1358 Test open mode returns on read-only files.
1360 static BOOL run_opentest(void)
1362 static struct smbcli_state *cli1;
1363 static struct smbcli_state *cli2;
1364 const char *fname = "\\readonly.file";
1365 char *control_char_fname;
1366 int fnum1, fnum2;
1367 uint8_t buf[20];
1368 size_t fsize;
1369 BOOL correct = True;
1370 char *tmp_path;
1371 int failures = 0;
1372 int i;
1374 printf("starting open test\n");
1376 if (!torture_open_connection(&cli1)) {
1377 return False;
1380 asprintf(&control_char_fname, "\\readonly.afile");
1381 for (i = 1; i <= 0x1f; i++) {
1382 control_char_fname[10] = i;
1383 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
1384 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1386 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
1387 NT_STATUS_OBJECT_NAME_INVALID)) {
1388 printf("Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
1389 smbcli_errstr(cli1->tree), i);
1390 failures++;
1393 if (fnum1 != -1) {
1394 smbcli_close(cli1->tree, fnum1);
1396 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
1397 smbcli_unlink(cli1->tree, control_char_fname);
1399 free(control_char_fname);
1401 if (!failures)
1402 printf("Create file with control char names passed.\n");
1404 smbcli_setatr(cli1->tree, fname, 0, 0);
1405 smbcli_unlink(cli1->tree, fname);
1407 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1408 if (fnum1 == -1) {
1409 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1410 return False;
1413 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1414 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1415 return False;
1418 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
1419 printf("smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
1420 CHECK_MAX_FAILURES(error_test1);
1421 return False;
1424 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1425 if (fnum1 == -1) {
1426 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1427 CHECK_MAX_FAILURES(error_test1);
1428 return False;
1431 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
1432 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1434 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
1435 NT_STATUS_ACCESS_DENIED)) {
1436 printf("correct error code ERRDOS/ERRnoaccess returned\n");
1439 printf("finished open test 1\n");
1440 error_test1:
1441 smbcli_close(cli1->tree, fnum1);
1443 /* Now try not readonly and ensure ERRbadshare is returned. */
1445 smbcli_setatr(cli1->tree, fname, 0, 0);
1447 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1448 if (fnum1 == -1) {
1449 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1450 return False;
1453 /* This will fail - but the error should be ERRshare. */
1454 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1456 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
1457 NT_STATUS_SHARING_VIOLATION)) {
1458 printf("correct error code ERRDOS/ERRbadshare returned\n");
1461 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1462 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1463 return False;
1466 smbcli_unlink(cli1->tree, fname);
1468 printf("finished open test 2\n");
1470 /* Test truncate open disposition on file opened for read. */
1472 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1473 if (fnum1 == -1) {
1474 printf("(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1475 return False;
1478 /* write 20 bytes. */
1480 memset(buf, '\0', 20);
1482 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1483 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
1484 correct = False;
1487 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1488 printf("(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1489 return False;
1492 /* Ensure size == 20. */
1493 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1494 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1495 CHECK_MAX_FAILURES(error_test3);
1496 return False;
1499 if (fsize != 20) {
1500 printf("(3) file size != 20\n");
1501 CHECK_MAX_FAILURES(error_test3);
1502 return False;
1505 /* Now test if we can truncate a file opened for readonly. */
1507 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
1508 if (fnum1 == -1) {
1509 printf("(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1510 CHECK_MAX_FAILURES(error_test3);
1511 return False;
1514 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1515 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1516 return False;
1519 /* Ensure size == 0. */
1520 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1521 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1522 CHECK_MAX_FAILURES(error_test3);
1523 return False;
1526 if (fsize != 0) {
1527 printf("(3) file size != 0\n");
1528 CHECK_MAX_FAILURES(error_test3);
1529 return False;
1531 printf("finished open test 3\n");
1532 error_test3:
1533 smbcli_unlink(cli1->tree, fname);
1536 printf("testing ctemp\n");
1537 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
1538 if (fnum1 == -1) {
1539 printf("ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
1540 CHECK_MAX_FAILURES(error_test4);
1541 return False;
1543 printf("ctemp gave path %s\n", tmp_path);
1544 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1545 printf("close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1547 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
1548 printf("unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1550 error_test4:
1551 /* Test the non-io opens... */
1553 if (!torture_open_connection(&cli2)) {
1554 return False;
1557 smbcli_setatr(cli2->tree, fname, 0, 0);
1558 smbcli_unlink(cli2->tree, fname);
1560 printf("TEST #1 testing 2 non-io opens (no delete)\n");
1562 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1563 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1565 if (fnum1 == -1) {
1566 printf("test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1567 CHECK_MAX_FAILURES(error_test10);
1568 return False;
1571 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1572 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1573 if (fnum2 == -1) {
1574 printf("test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1575 CHECK_MAX_FAILURES(error_test10);
1576 return False;
1579 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1580 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1581 return False;
1583 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1584 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1585 return False;
1588 printf("non-io open test #1 passed.\n");
1589 error_test10:
1590 smbcli_unlink(cli1->tree, fname);
1592 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
1594 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1595 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1597 if (fnum1 == -1) {
1598 printf("test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1599 CHECK_MAX_FAILURES(error_test20);
1600 return False;
1603 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1604 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1606 if (fnum2 == -1) {
1607 printf("test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1608 CHECK_MAX_FAILURES(error_test20);
1609 return False;
1612 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1613 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1614 return False;
1616 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1617 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1618 return False;
1621 printf("non-io open test #2 passed.\n");
1622 error_test20:
1623 smbcli_unlink(cli1->tree, fname);
1625 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
1627 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1628 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1630 if (fnum1 == -1) {
1631 printf("test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1632 CHECK_MAX_FAILURES(error_test30);
1633 return False;
1636 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1637 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1639 if (fnum2 == -1) {
1640 printf("test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1641 CHECK_MAX_FAILURES(error_test30);
1642 return False;
1645 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1646 printf("test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1647 return False;
1649 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1650 printf("test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1651 return False;
1654 printf("non-io open test #3 passed.\n");
1655 error_test30:
1656 smbcli_unlink(cli1->tree, fname);
1658 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
1660 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1661 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1663 if (fnum1 == -1) {
1664 printf("test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1665 CHECK_MAX_FAILURES(error_test40);
1666 return False;
1669 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1670 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1672 if (fnum2 != -1) {
1673 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1674 CHECK_MAX_FAILURES(error_test40);
1675 return False;
1678 printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1680 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1681 printf("test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1682 return False;
1685 printf("non-io open test #4 passed.\n");
1686 error_test40:
1687 smbcli_unlink(cli1->tree, fname);
1689 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1691 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1692 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1694 if (fnum1 == -1) {
1695 printf("test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1696 CHECK_MAX_FAILURES(error_test50);
1697 return False;
1700 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1701 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1703 if (fnum2 == -1) {
1704 printf("test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1705 CHECK_MAX_FAILURES(error_test50);
1706 return False;
1709 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1710 printf("test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1711 return False;
1714 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1715 printf("test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1716 return False;
1719 printf("non-io open test #5 passed.\n");
1720 error_test50:
1721 printf("TEST #6 testing 1 non-io open, one io open\n");
1723 smbcli_unlink(cli1->tree, fname);
1725 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1726 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1728 if (fnum1 == -1) {
1729 printf("test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1730 CHECK_MAX_FAILURES(error_test60);
1731 return False;
1734 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1735 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1737 if (fnum2 == -1) {
1738 printf("test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1739 CHECK_MAX_FAILURES(error_test60);
1740 return False;
1743 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1744 printf("test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1745 return False;
1748 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1749 printf("test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1750 return False;
1753 printf("non-io open test #6 passed.\n");
1754 error_test60:
1755 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
1757 smbcli_unlink(cli1->tree, fname);
1759 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1760 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1762 if (fnum1 == -1) {
1763 printf("test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1764 CHECK_MAX_FAILURES(error_test70);
1765 return False;
1768 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1769 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1771 if (fnum2 != -1) {
1772 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1773 CHECK_MAX_FAILURES(error_test70);
1774 return False;
1777 printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1779 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1780 printf("test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1781 return False;
1784 printf("non-io open test #7 passed.\n");
1786 error_test70:
1788 printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
1790 smbcli_unlink(cli1->tree, fname);
1792 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1793 if (fnum1 == -1) {
1794 printf("(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1795 return False;
1798 /* write 20 bytes. */
1800 memset(buf, '\0', 20);
1802 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1803 printf("(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1804 correct = False;
1807 /* Ensure size == 20. */
1808 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1809 printf("(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1810 CHECK_MAX_FAILURES(error_test80);
1811 return False;
1814 if (fsize != 20) {
1815 printf("(8) file size != 20\n");
1816 CHECK_MAX_FAILURES(error_test80);
1817 return False;
1820 /* Get an exclusive lock on the open file. */
1821 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1822 printf("(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1823 CHECK_MAX_FAILURES(error_test80);
1824 return False;
1827 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1828 if (fnum1 == -1) {
1829 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1830 return False;
1833 /* Ensure size == 0. */
1834 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1835 printf("(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1836 CHECK_MAX_FAILURES(error_test80);
1837 return False;
1840 if (fsize != 0) {
1841 printf("(8) file size != 0\n");
1842 CHECK_MAX_FAILURES(error_test80);
1843 return False;
1846 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1847 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1848 return False;
1851 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1852 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1853 return False;
1856 error_test80:
1858 printf("open test #8 passed.\n");
1860 smbcli_unlink(cli1->tree, fname);
1862 if (!torture_close_connection(cli1)) {
1863 correct = False;
1865 if (!torture_close_connection(cli2)) {
1866 correct = False;
1869 return correct;
1874 sees what IOCTLs are supported
1876 BOOL torture_ioctl_test(void)
1878 struct smbcli_state *cli;
1879 uint16_t device, function;
1880 int fnum;
1881 const char *fname = "\\ioctl.dat";
1882 NTSTATUS status;
1883 union smb_ioctl parms;
1884 TALLOC_CTX *mem_ctx;
1886 if (!torture_open_connection(&cli)) {
1887 return False;
1890 mem_ctx = talloc_init("ioctl_test");
1892 printf("starting ioctl test\n");
1894 smbcli_unlink(cli->tree, fname);
1896 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1897 if (fnum == -1) {
1898 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1899 return False;
1902 parms.ioctl.level = RAW_IOCTL_IOCTL;
1903 parms.ioctl.in.fnum = fnum;
1904 parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
1905 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1906 printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
1908 for (device=0;device<0x100;device++) {
1909 printf("testing device=0x%x\n", device);
1910 for (function=0;function<0x100;function++) {
1911 parms.ioctl.in.request = (device << 16) | function;
1912 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1914 if (NT_STATUS_IS_OK(status)) {
1915 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n",
1916 device, function, (int)parms.ioctl.out.blob.length);
1921 if (!torture_close_connection(cli)) {
1922 return False;
1925 return True;
1930 tries variants of chkpath
1932 BOOL torture_chkpath_test(void)
1934 struct smbcli_state *cli;
1935 int fnum;
1936 BOOL ret;
1938 if (!torture_open_connection(&cli)) {
1939 return False;
1942 printf("starting chkpath test\n");
1944 printf("Testing valid and invalid paths\n");
1946 /* cleanup from an old run */
1947 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1948 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1949 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1951 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1952 printf("mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1953 return False;
1956 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1957 printf("mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1958 return False;
1961 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1962 if (fnum == -1) {
1963 printf("open1 failed (%s)\n", smbcli_errstr(cli->tree));
1964 return False;
1966 smbcli_close(cli->tree, fnum);
1968 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1969 printf("chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1970 ret = False;
1973 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1974 printf("chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1975 ret = False;
1978 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1979 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1980 NT_STATUS_NOT_A_DIRECTORY);
1981 } else {
1982 printf("* chkpath on a file should fail\n");
1983 ret = False;
1986 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1987 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1988 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1989 } else {
1990 printf("* chkpath on a non existent file should fail\n");
1991 ret = False;
1994 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1995 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1996 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1997 } else {
1998 printf("* chkpath on a non existent component should fail\n");
1999 ret = False;
2002 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
2003 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
2004 smbcli_rmdir(cli->tree, "\\chkpath.dir");
2006 if (!torture_close_connection(cli)) {
2007 return False;
2010 return ret;
2014 static void sigcont(int sig)
2018 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
2020 int i, status;
2021 volatile pid_t *child_status;
2022 volatile BOOL *child_status_out;
2023 int synccount;
2024 int tries = 8;
2025 double start_time_limit = 10 + (torture_nprocs * 1.5);
2026 char **unc_list = NULL;
2027 const char *p;
2028 int num_unc_names = 0;
2029 struct timeval tv;
2031 *result = True;
2033 synccount = 0;
2035 signal(SIGCONT, sigcont);
2037 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
2038 if (!child_status) {
2039 printf("Failed to setup shared memory\n");
2040 return -1;
2043 child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
2044 if (!child_status_out) {
2045 printf("Failed to setup result status shared memory\n");
2046 return -1;
2049 p = lp_parm_string(-1, "torture", "unclist");
2050 if (p) {
2051 unc_list = file_lines_load(p, &num_unc_names, NULL);
2052 if (!unc_list || num_unc_names <= 0) {
2053 printf("Failed to load unc names list from '%s'\n", p);
2054 exit(1);
2058 for (i = 0; i < torture_nprocs; i++) {
2059 child_status[i] = 0;
2060 child_status_out[i] = True;
2063 tv = timeval_current();
2065 for (i=0;i<torture_nprocs;i++) {
2066 procnum = i;
2067 if (fork() == 0) {
2068 char *myname;
2069 const char *hostname=NULL, *sharename;
2071 pid_t mypid = getpid();
2072 srandom(((int)mypid) ^ ((int)time(NULL)));
2074 asprintf(&myname, "CLIENT%d", i);
2075 lp_set_cmdline("netbios name", myname);
2076 free(myname);
2079 if (unc_list) {
2080 if (!smbcli_parse_unc(unc_list[i % num_unc_names],
2081 NULL, &hostname, &sharename)) {
2082 printf("Failed to parse UNC name %s\n",
2083 unc_list[i % num_unc_names]);
2084 exit(1);
2088 while (1) {
2089 if (hostname) {
2090 if (torture_open_connection_share(NULL,
2091 &current_cli,
2092 hostname,
2093 sharename,
2094 NULL)) {
2095 break;
2097 } else if (torture_open_connection(&current_cli)) {
2098 break;
2100 if (tries-- == 0) {
2101 printf("pid %d failed to start\n", (int)getpid());
2102 _exit(1);
2104 msleep(100);
2107 child_status[i] = getpid();
2109 pause();
2111 if (child_status[i]) {
2112 printf("Child %d failed to start!\n", i);
2113 child_status_out[i] = 1;
2114 _exit(1);
2117 child_status_out[i] = fn(current_cli, i);
2118 _exit(0);
2122 do {
2123 synccount = 0;
2124 for (i=0;i<torture_nprocs;i++) {
2125 if (child_status[i]) synccount++;
2127 if (synccount == torture_nprocs) break;
2128 msleep(100);
2129 } while (timeval_elapsed(&tv) < start_time_limit);
2131 if (synccount != torture_nprocs) {
2132 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
2133 *result = False;
2134 return timeval_elapsed(&tv);
2137 printf("Starting %d clients\n", torture_nprocs);
2139 /* start the client load */
2140 tv = timeval_current();
2141 for (i=0;i<torture_nprocs;i++) {
2142 child_status[i] = 0;
2145 printf("%d clients started\n", torture_nprocs);
2147 kill(0, SIGCONT);
2149 for (i=0;i<torture_nprocs;i++) {
2150 int ret;
2151 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
2152 if (ret == -1 || WEXITSTATUS(status) != 0) {
2153 *result = False;
2157 printf("\n");
2159 for (i=0;i<torture_nprocs;i++) {
2160 if (!child_status_out[i]) {
2161 *result = False;
2164 return timeval_elapsed(&tv);
2167 #define FLAG_MULTIPROC 1
2169 static struct {
2170 const char *name;
2171 BOOL (*fn)(void);
2172 BOOL (*multi_fn)(struct smbcli_state *, int );
2173 } torture_ops[] = {
2174 /* base tests */
2175 {"BASE-FDPASS", run_fdpasstest, 0},
2176 {"BASE-LOCK1", torture_locktest1, 0},
2177 {"BASE-LOCK2", torture_locktest2, 0},
2178 {"BASE-LOCK3", torture_locktest3, 0},
2179 {"BASE-LOCK4", torture_locktest4, 0},
2180 {"BASE-LOCK5", torture_locktest5, 0},
2181 {"BASE-LOCK6", torture_locktest6, 0},
2182 {"BASE-LOCK7", torture_locktest7, 0},
2183 {"BASE-UNLINK", torture_unlinktest, 0},
2184 {"BASE-ATTR", run_attrtest, 0},
2185 {"BASE-TRANS2", run_trans2test, 0},
2186 {"BASE-NEGNOWAIT", run_negprot_nowait, 0},
2187 {"BASE-DIR1", torture_dirtest1, 0},
2188 {"BASE-DIR2", torture_dirtest2, 0},
2189 {"BASE-DENY1", torture_denytest1, 0},
2190 {"BASE-DENY2", torture_denytest2, 0},
2191 {"BASE-DENY3", torture_denytest3, 0},
2192 {"BASE-DENYDOS", torture_denydos_sharing, 0},
2193 {"BASE-NTDENY1", NULL, torture_ntdenytest1},
2194 {"BASE-NTDENY2", torture_ntdenytest2, 0},
2195 {"BASE-TCON", run_tcon_test, 0},
2196 {"BASE-TCONDEV", run_tcon_devtype_test, 0},
2197 {"BASE-VUID", run_vuidtest, 0},
2198 {"BASE-RW1", run_readwritetest, 0},
2199 {"BASE-OPEN", run_opentest, 0},
2200 {"BASE-DEFER_OPEN", NULL, run_deferopen},
2201 {"BASE-XCOPY", run_xcopy, 0},
2202 {"BASE-RENAME", torture_test_rename, 0},
2203 {"BASE-DELETE", torture_test_delete, 0},
2204 {"BASE-PROPERTIES", torture_test_properties, 0},
2205 {"BASE-MANGLE", torture_mangle, 0},
2206 {"BASE-OPENATTR", torture_openattrtest, 0},
2207 {"BASE-CHARSET", torture_charset, 0},
2208 {"BASE-CHKPATH", torture_chkpath_test, 0},
2209 {"BASE-SECLEAK", torture_sec_leak, 0},
2210 {"BASE-DISCONNECT", torture_disconnect, 0},
2211 {"BASE-DELAYWRITE", torture_delay_write, 0},
2213 /* benchmarking tests */
2214 {"BENCH-HOLDCON", torture_holdcon, 0},
2215 {"BENCH-NBENCH", torture_nbench, 0},
2216 {"BENCH-TORTURE", NULL, run_torture},
2217 {"BENCH-NBT", torture_bench_nbt, 0},
2218 {"BENCH-WINS", torture_bench_wins, 0},
2219 {"BENCH-RPC", torture_bench_rpc, 0},
2220 {"BENCH-CLDAP", torture_bench_cldap, 0},
2222 /* RAW smb tests */
2223 {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
2224 {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
2225 {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
2226 {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
2227 {"RAW-SEARCH", torture_raw_search, 0},
2228 {"RAW-CLOSE", torture_raw_close, 0},
2229 {"RAW-OPEN", torture_raw_open, 0},
2230 {"RAW-MKDIR", torture_raw_mkdir, 0},
2231 {"RAW-OPLOCK", torture_raw_oplock, 0},
2232 {"RAW-NOTIFY", torture_raw_notify, 0},
2233 {"RAW-MUX", torture_raw_mux, 0},
2234 {"RAW-IOCTL", torture_raw_ioctl, 0},
2235 {"RAW-CHKPATH", torture_raw_chkpath, 0},
2236 {"RAW-UNLINK", torture_raw_unlink, 0},
2237 {"RAW-READ", torture_raw_read, 0},
2238 {"RAW-WRITE", torture_raw_write, 0},
2239 {"RAW-LOCK", torture_raw_lock, 0},
2240 {"RAW-CONTEXT", torture_raw_context, 0},
2241 {"RAW-RENAME", torture_raw_rename, 0},
2242 {"RAW-SEEK", torture_raw_seek, 0},
2243 {"RAW-EAS", torture_raw_eas, 0},
2244 {"RAW-EAMAX", torture_max_eas, 0},
2245 {"RAW-STREAMS", torture_raw_streams, 0},
2246 {"RAW-ACLS", torture_raw_acls, 0},
2247 {"RAW-RAP", torture_raw_rap, 0},
2248 {"RAW-COMPOSITE", torture_raw_composite, 0},
2250 /* SMB2 tests */
2251 {"SMB2-CONNECT", torture_smb2_connect, 0},
2252 {"SMB2-SCAN", torture_smb2_scan, 0},
2253 {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0},
2254 {"SMB2-SCANSETINFO", torture_smb2_setinfo_scan, 0},
2255 {"SMB2-SCANFIND", torture_smb2_find_scan, 0},
2256 {"SMB2-GETINFO", torture_smb2_getinfo, 0},
2257 {"SMB2-SETINFO", torture_smb2_setinfo, 0},
2258 {"SMB2-FIND", torture_smb2_find, 0},
2260 /* protocol scanners */
2261 {"SCAN-TRANS2", torture_trans2_scan, 0},
2262 {"SCAN-NTTRANS", torture_nttrans_scan, 0},
2263 {"SCAN-ALIASES", torture_trans2_aliases, 0},
2264 {"SCAN-SMB", torture_smb_scan, 0},
2265 {"SCAN-MAXFID", NULL, run_maxfidtest},
2266 {"SCAN-UTABLE", torture_utable, 0},
2267 {"SCAN-CASETABLE", torture_casetable, 0},
2268 {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
2269 {"SCAN-IOCTL", torture_ioctl_test, 0},
2270 {"SCAN-RAP", torture_rap_scan, 0},
2272 /* rpc testers */
2273 {"RPC-LSA", torture_rpc_lsa, 0},
2274 {"RPC-LSALOOKUP", torture_rpc_lsa_lookup, 0},
2275 {"RPC-SECRETS", torture_rpc_lsa_secrets, 0},
2276 {"RPC-ECHO", torture_rpc_echo, 0},
2277 {"RPC-DFS", torture_rpc_dfs, 0},
2278 {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
2279 {"RPC-SAMR", torture_rpc_samr, 0},
2280 {"RPC-UNIXINFO", torture_rpc_unixinfo, 0},
2281 {"RPC-NETLOGON", torture_rpc_netlogon, 0},
2282 {"RPC-SAMLOGON", torture_rpc_samlogon, 0},
2283 {"RPC-SAMSYNC", torture_rpc_samsync, 0},
2284 {"RPC-SCHANNEL", torture_rpc_schannel, 0},
2285 {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
2286 {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
2287 {"RPC-SVCCTL", torture_rpc_svcctl, 0},
2288 {"RPC-ATSVC", torture_rpc_atsvc, 0},
2289 {"RPC-EVENTLOG", torture_rpc_eventlog, 0},
2290 {"RPC-EPMAPPER", torture_rpc_epmapper, 0},
2291 {"RPC-WINREG", torture_rpc_winreg, 0},
2292 {"RPC-INITSHUTDOWN", torture_rpc_initshutdown, 0},
2293 {"RPC-OXIDRESOLVE", torture_rpc_oxidresolve, 0},
2294 {"RPC-REMACT", torture_rpc_remact, 0},
2295 {"RPC-MGMT", torture_rpc_mgmt, 0},
2296 {"RPC-SCANNER", torture_rpc_scanner, 0},
2297 {"RPC-AUTOIDL", torture_rpc_autoidl, 0},
2298 {"RPC-COUNTCALLS", torture_rpc_countcalls, 0},
2299 {"RPC-MULTIBIND", torture_multi_bind, 0},
2300 {"RPC-DRSUAPI", torture_rpc_drsuapi, 0},
2301 {"RPC-CRACKNAMES", torture_rpc_drsuapi_cracknames, 0},
2302 {"RPC-ROT", torture_rpc_rot, 0},
2303 {"RPC-DSSETUP", torture_rpc_dssetup, 0},
2304 {"RPC-ALTERCONTEXT", torture_rpc_alter_context, 0},
2305 {"RPC-JOIN", torture_rpc_join, 0},
2306 {"RPC-DSSYNC", torture_rpc_dssync, 0},
2308 /* local (no server) testers */
2309 {"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},
2310 {"LOCAL-ICONV", torture_local_iconv, 0},
2311 {"LOCAL-TALLOC", torture_local_talloc, 0},
2312 {"LOCAL-MESSAGING", torture_local_messaging, 0},
2313 {"LOCAL-IRPC", torture_local_irpc, 0},
2314 {"LOCAL-BINDING", torture_local_binding_string, 0},
2315 {"LOCAL-STRLIST", torture_local_util_strlist, 0},
2316 {"LOCAL-FILE", torture_local_util_file, 0},
2317 {"LOCAL-IDTREE", torture_local_idtree, 0},
2318 {"LOCAL-SOCKET", torture_local_socket, 0},
2319 {"LOCAL-PAC", torture_pac, 0},
2320 {"LOCAL-REGISTRY", torture_registry, 0},
2321 {"LOCAL-RESOLVE", torture_local_resolve, 0},
2322 {"LOCAL-SDDL", torture_local_sddl, 0},
2323 {"LOCAL-NDR", torture_local_ndr, 0},
2325 /* COM (Component Object Model) testers */
2326 {"COM-SIMPLE", torture_com_simple, 0 },
2328 /* ldap testers */
2329 {"LDAP-BASIC", torture_ldap_basic, 0},
2330 {"LDAP-CLDAP", torture_cldap, 0},
2332 /* nbt tests */
2333 {"NBT-REGISTER", torture_nbt_register, 0},
2334 {"NBT-WINS", torture_nbt_wins, 0},
2335 {"NBT-DGRAM", torture_nbt_dgram, 0},
2336 {"NBT-WINSREPLICATION", torture_nbt_winsreplication, 0},
2338 /* libnet tests */
2339 {"NET-USERINFO", torture_userinfo, 0},
2340 {"NET-USERADD", torture_useradd, 0},
2341 {"NET-USERDEL", torture_userdel, 0},
2342 {"NET-USERMOD", torture_usermod, 0},
2343 {"NET-DOMOPEN", torture_domainopen, 0},
2344 {"NET-API-LOOKUP", torture_lookup, 0},
2345 {"NET-API-LOOKUPHOST", torture_lookup_host, 0},
2346 {"NET-API-LOOKUPPDC", torture_lookup_pdc, 0},
2347 {"NET-API-CREATEUSER", torture_createuser, 0},
2348 {"NET-API-RPCCONNECT", torture_rpc_connect, 0},
2349 {"NET-API-LISTSHARES", torture_listshares, 0},
2350 {"NET-API-DELSHARE", torture_delshare, 0},
2352 {NULL, NULL, 0}};
2356 /****************************************************************************
2357 run a specified test or "ALL"
2358 ****************************************************************************/
2359 static BOOL run_test(const char *name)
2361 BOOL ret = True;
2362 int i;
2363 BOOL matched = False;
2365 if (strequal(name,"ALL")) {
2366 for (i=0;torture_ops[i].name;i++) {
2367 if (!run_test(torture_ops[i].name)) {
2368 ret = False;
2371 return ret;
2374 for (i=0;torture_ops[i].name;i++) {
2375 if (gen_fnmatch(name, torture_ops[i].name) == 0) {
2376 double t;
2377 matched = True;
2378 init_iconv();
2379 printf("Running %s\n", torture_ops[i].name);
2380 if (torture_ops[i].multi_fn) {
2381 BOOL result = False;
2382 t = torture_create_procs(torture_ops[i].multi_fn,
2383 &result);
2384 if (!result) {
2385 ret = False;
2386 printf("TEST %s FAILED!\n", torture_ops[i].name);
2389 } else {
2390 struct timeval tv = timeval_current();
2391 if (!torture_ops[i].fn()) {
2392 ret = False;
2393 printf("TEST %s FAILED!\n", torture_ops[i].name);
2395 t = timeval_elapsed(&tv);
2397 printf("%s took %g secs\n\n", torture_ops[i].name, t);
2401 if (!matched) {
2402 printf("Unknown torture operation '%s'\n", name);
2405 return ret;
2409 static void parse_dns(const char *dns)
2411 char *userdn, *basedn, *secret;
2412 char *p, *d;
2414 /* retrievieng the userdn */
2415 p = strchr_m(dns, '#');
2416 if (!p) {
2417 lp_set_cmdline("torture:ldap_userdn", "");
2418 lp_set_cmdline("torture:ldap_basedn", "");
2419 lp_set_cmdline("torture:ldap_secret", "");
2420 return;
2422 userdn = strndup(dns, p - dns);
2423 lp_set_cmdline("torture:ldap_userdn", userdn);
2425 /* retrieve the basedn */
2426 d = p + 1;
2427 p = strchr_m(d, '#');
2428 if (!p) {
2429 lp_set_cmdline("torture:ldap_basedn", "");
2430 lp_set_cmdline("torture:ldap_secret", "");
2431 return;
2433 basedn = strndup(d, p - d);
2434 lp_set_cmdline("torture:ldap_basedn", basedn);
2436 /* retrieve the secret */
2437 p = p + 1;
2438 if (!p) {
2439 lp_set_cmdline("torture:ldap_secret", "");
2440 return;
2442 secret = strdup(p);
2443 lp_set_cmdline("torture:ldap_secret", secret);
2445 printf ("%s - %s - %s\n", userdn, basedn, secret);
2449 static void usage(poptContext pc)
2451 int i;
2452 int perline = 5;
2454 poptPrintUsage(pc, stdout, 0);
2455 printf("\n");
2457 printf("The binding format is:\n\n");
2459 printf(" TRANSPORT:host[flags]\n\n");
2461 printf(" where TRANSPORT is either ncacn_np for SMB or ncacn_ip_tcp for RPC/TCP\n\n");
2463 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
2464 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
2465 printf(" string.\n\n");
2467 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
2468 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
2469 printf(" will be auto-determined.\n\n");
2471 printf(" other recognised flags are:\n\n");
2473 printf(" sign : enable ntlmssp signing\n");
2474 printf(" seal : enable ntlmssp sealing\n");
2475 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
2476 printf(" validate: enable the NDR validator\n");
2477 printf(" print: enable debugging of the packets\n");
2478 printf(" bigendian: use bigendian RPC\n");
2479 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
2481 printf(" For example, these all connect to the samr pipe:\n\n");
2483 printf(" ncacn_np:myserver\n");
2484 printf(" ncacn_np:myserver[samr]\n");
2485 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
2486 printf(" ncacn_np:myserver[/pipe/samr]\n");
2487 printf(" ncacn_np:myserver[samr,sign,print]\n");
2488 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
2489 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
2490 printf(" ncacn_np:\n");
2491 printf(" ncacn_np:[/pipe/samr]\n\n");
2493 printf(" ncacn_ip_tcp:myserver\n");
2494 printf(" ncacn_ip_tcp:myserver[1024]\n");
2495 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
2497 printf("The unc format is:\n\n");
2499 printf(" //server/share\n\n");
2501 printf("tests are:");
2502 for (i=0;torture_ops[i].name;i++) {
2503 if ((i%perline)==0) {
2504 printf("\n");
2506 printf("%s ", torture_ops[i].name);
2508 printf("\n\n");
2510 printf("default test is ALL\n");
2512 exit(1);
2515 static BOOL is_binding_string(const char *binding_string)
2517 TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
2518 struct dcerpc_binding *binding_struct;
2519 NTSTATUS status;
2521 status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
2523 talloc_free(mem_ctx);
2524 return NT_STATUS_IS_OK(status);
2527 static void max_runtime_handler(int sig)
2529 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
2530 exit(1);
2533 /****************************************************************************
2534 main program
2535 ****************************************************************************/
2536 int main(int argc,char *argv[])
2538 int opt, i;
2539 char *p;
2540 BOOL correct = True;
2541 int max_runtime=0;
2542 int argc_new;
2543 char **argv_new;
2544 poptContext pc;
2545 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,OPT_DANGEROUS};
2546 struct poptOption long_options[] = {
2547 POPT_AUTOHELP
2548 {"smb-ports", 'p', POPT_ARG_STRING, NULL, 0, "SMB ports", NULL},
2549 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
2550 {"num-progs", 0, POPT_ARG_INT, &torture_nprocs, 0, "num progs", NULL},
2551 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
2552 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
2553 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks, 0, "use oplocks", NULL},
2554 {"show-all", 0, POPT_ARG_NONE, &torture_showall, 0, "show all", NULL},
2555 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
2556 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
2557 {"timelimit", 't', POPT_ARG_STRING, NULL, OPT_TIMELIMIT, "timelimit", NULL},
2558 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
2559 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
2560 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS, "dangerous", NULL},
2561 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
2562 "set maximum time for smbtorture to live", "seconds"},
2563 POPT_COMMON_SAMBA
2564 POPT_COMMON_CONNECTION
2565 POPT_COMMON_CREDENTIALS
2566 POPT_COMMON_VERSION
2567 POPT_TABLEEND
2570 #ifdef HAVE_SETBUFFER
2571 setbuffer(stdout, NULL, 0);
2572 #endif
2574 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
2575 POPT_CONTEXT_KEEP_FIRST);
2577 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
2579 while((opt = poptGetNextOpt(pc)) != -1) {
2580 switch (opt) {
2581 case OPT_LOADFILE:
2582 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
2583 break;
2584 case OPT_UNCLIST:
2585 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
2586 break;
2587 case OPT_TIMELIMIT:
2588 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
2589 break;
2590 case OPT_DNS:
2591 parse_dns(poptGetOptArg(pc));
2592 break;
2593 case OPT_DANGEROUS:
2594 lp_set_cmdline("torture:dangerous", "Yes");
2595 break;
2596 default:
2597 d_printf("Invalid option %s: %s\n",
2598 poptBadOption(pc, 0), poptStrerror(opt));
2599 usage(pc);
2600 exit(1);
2604 if (max_runtime) {
2605 /* this will only work if nobody else uses alarm(),
2606 which means it won't work for some tests, but we
2607 can't use the event context method we use for smbd
2608 as so many tests create their own event
2609 context. This will at least catch most cases. */
2610 signal(SIGALRM, max_runtime_handler);
2611 alarm(max_runtime);
2614 dcerpc_init();
2616 dcerpc_table_init();
2618 if (torture_seed == 0) {
2619 torture_seed = time(NULL);
2621 printf("Using seed %d\n", torture_seed);
2622 srandom(torture_seed);
2624 argv_new = discard_const_p(char *, poptGetArgs(pc));
2626 argc_new = argc;
2627 for (i=0; i<argc; i++) {
2628 if (argv_new[i] == NULL) {
2629 argc_new = i;
2630 break;
2634 if (argc_new < 3) {
2635 usage(pc);
2636 exit(1);
2639 for(p = argv_new[1]; *p; p++) {
2640 if(*p == '\\')
2641 *p = '/';
2644 /* see if its a RPC transport specifier */
2645 if (is_binding_string(argv_new[1])) {
2646 lp_set_cmdline("torture:binding", argv_new[1]);
2647 } else {
2648 char *binding = NULL;
2649 const char *host = NULL, *share = NULL;
2651 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
2652 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
2653 usage(pc);
2656 lp_set_cmdline("torture:host", host);
2657 lp_set_cmdline("torture:share", share);
2658 asprintf(&binding, "ncacn_np:%s", host);
2659 lp_set_cmdline("torture:binding", binding);
2662 if (argc_new == 0) {
2663 printf("You must specify a test to run, or 'ALL'\n");
2664 } else {
2665 for (i=2;i<argc_new;i++) {
2666 if (!run_test(argv_new[i])) {
2667 correct = False;
2672 if (correct) {
2673 return(0);
2674 } else {
2675 return(1);