Fixed very subtle bug returning correct error on an open, when we have
[Samba.git] / source / utils / torture.c
blobcd348f67fd040f0905f00e7944ca190abb5e8146
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB torture tester
5 Copyright (C) Andrew Tridgell 1997-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define NO_SYSLOG
24 #include "includes.h"
25 #include <sys/ipc.h>
26 #include <sys/shm.h>
28 static fstring host, workgroup, share, password, username, myname;
29 static int max_protocol = PROTOCOL_NT1;
30 static char *sockops="TCP_NODELAY";
31 static int nprocs=1, numops=100;
32 static int procnum; /* records process count number when forking */
33 static struct cli_state current_cli;
34 static fstring randomfname;
35 static BOOL use_oplocks;
36 static BOOL use_level_II_oplocks;
38 static double create_procs(void (*fn)(int));
41 static struct timeval tp1,tp2;
43 static void start_timer(void)
45 gettimeofday(&tp1,NULL);
48 static double end_timer(void)
50 gettimeofday(&tp2,NULL);
51 return((tp2.tv_sec - tp1.tv_sec) +
52 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
56 /* return a pointer to a anonymous shared memory segment of size "size"
57 which will persist across fork() but will disappear when all processes
58 exit
60 The memory is not zeroed
62 This function uses system5 shared memory. It takes advantage of a property
63 that the memory is not destroyed if it is attached when the id is removed
65 static void *shm_setup(int size)
67 int shmid;
68 void *ret;
70 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
71 if (shmid == -1) {
72 printf("can't get shared memory\n");
73 exit(1);
75 ret = (void *)shmat(shmid, 0, 0);
76 if (!ret || ret == (void *)-1) {
77 printf("can't attach to shared memory\n");
78 return NULL;
80 /* the following releases the ipc, but note that this process
81 and all its children will still have access to the memory, its
82 just that the shmid is no longer valid for other shm calls. This
83 means we don't leave behind lots of shm segments after we exit
85 See Stevens "advanced programming in unix env" for details
87 shmctl(shmid, IPC_RMID, 0);
89 return ret;
93 static BOOL open_nbt_connection(struct cli_state *c)
95 struct nmb_name called, calling;
96 struct in_addr ip;
97 extern struct in_addr ipzero;
99 ZERO_STRUCTP(c);
101 make_nmb_name(&calling, myname, 0x0);
102 make_nmb_name(&called , host, 0x20);
104 ip = ipzero;
106 if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
107 printf("Failed to connect with %s\n", host);
108 return False;
111 c->timeout = 120000; /* set a really long timeout (2 minutes) */
112 if (use_oplocks) c->use_oplocks = True;
113 if (use_level_II_oplocks) c->use_level_II_oplocks = True;
115 if (!cli_session_request(c, &calling, &called)) {
116 printf("%s rejected the session\n",host);
117 cli_shutdown(c);
118 return False;
121 return True;
124 static BOOL open_connection(struct cli_state *c)
126 ZERO_STRUCTP(c);
128 if (!open_nbt_connection(c)) {
129 return False;
132 if (!cli_negprot(c)) {
133 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
134 cli_shutdown(c);
135 return False;
138 if (!cli_session_setup(c, username,
139 password, strlen(password),
140 password, strlen(password),
141 workgroup)) {
142 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
143 cli_shutdown(c);
144 return False;
147 if (!cli_send_tconX(c, share, "?????",
148 password, strlen(password)+1)) {
149 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
150 cli_shutdown(c);
151 return False;
154 return True;
158 static void close_connection(struct cli_state *c)
160 if (!cli_tdis(c)) {
161 printf("tdis failed (%s)\n", cli_errstr(c));
164 cli_shutdown(c);
168 /* check if the server produced the expected error code */
169 static BOOL check_error(struct cli_state *c,
170 uint8 eclass, uint32 ecode, uint32 nterr)
172 uint8 class;
173 uint32 num;
174 (void)cli_error(c, &class, &num, NULL);
175 if ((eclass != class || ecode != num) &&
176 num != (nterr&0xFFFFFF)) {
177 printf("unexpected error code class=%d code=%d\n",
178 (int)class, (int)num);
179 printf(" expected %d/%d %d\n",
180 (int)eclass, (int)ecode, (int)nterr);
181 return False;
183 return True;
187 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
189 while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
190 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
192 return True;
196 static BOOL rw_torture(struct cli_state *c)
198 char *lockfname = "\\torture.lck";
199 fstring fname;
200 int fnum;
201 int fnum2;
202 pid_t pid2, pid = getpid();
203 int i, j;
204 char buf[1024];
206 fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
207 DENY_NONE);
208 if (fnum2 == -1)
209 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
210 if (fnum2 == -1) {
211 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
212 return False;
216 for (i=0;i<numops;i++) {
217 unsigned n = (unsigned)sys_random()%10;
218 if (i % 10 == 0) {
219 printf("%d\r", i); fflush(stdout);
221 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
223 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
224 return False;
227 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
228 if (fnum == -1) {
229 printf("open failed (%s)\n", cli_errstr(c));
230 break;
233 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
234 printf("write failed (%s)\n", cli_errstr(c));
237 for (j=0;j<50;j++) {
238 if (cli_write(c, fnum, 0, (char *)buf,
239 sizeof(pid)+(j*sizeof(buf)),
240 sizeof(buf)) != sizeof(buf)) {
241 printf("write failed (%s)\n", cli_errstr(c));
245 pid2 = 0;
247 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
248 printf("read failed (%s)\n", cli_errstr(c));
251 if (pid2 != pid) {
252 printf("data corruption!\n");
255 if (!cli_close(c, fnum)) {
256 printf("close failed (%s)\n", cli_errstr(c));
259 if (!cli_unlink(c, fname)) {
260 printf("unlink failed (%s)\n", cli_errstr(c));
263 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
264 printf("unlock failed (%s)\n", cli_errstr(c));
268 cli_close(c, fnum2);
269 cli_unlink(c, lockfname);
271 printf("%d\n", i);
273 return True;
276 static void run_torture(int dummy)
278 struct cli_state cli;
280 cli = current_cli;
282 cli_sockopt(&cli, sockops);
284 rw_torture(&cli);
286 close_connection(&cli);
289 static BOOL rw_torture3(struct cli_state *c, char *lockfname)
291 int fnum = -1;
292 int i = 0;
293 char buf[131072];
294 char buf_rd[131072];
295 unsigned count;
296 unsigned countprev = 0;
297 unsigned sent = 0;
299 srandom(1);
300 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
302 SIVAL(buf, i, sys_random());
305 if (procnum == 0)
307 fnum = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
308 DENY_NONE);
309 if (fnum == -1) {
310 printf("first open read/write of %s failed (%s)\n",
311 lockfname, cli_errstr(c));
312 return False;
315 else
317 for (i = 0; i < 500 && fnum == -1; i++)
319 fnum = cli_open(c, lockfname, O_RDONLY,
320 DENY_NONE);
321 msleep(10);
323 if (fnum == -1) {
324 printf("second open read-only of %s failed (%s)\n",
325 lockfname, cli_errstr(c));
326 return False;
330 i = 0;
331 for (count = 0; count < sizeof(buf); count += sent)
333 if (count >= countprev) {
334 printf("%d %8d\r", i, count);
335 fflush(stdout);
336 i++;
337 countprev += (sizeof(buf) / 20);
340 if (procnum == 0)
342 sent = ((unsigned)sys_random()%(20))+ 1;
343 if (sent > sizeof(buf) - count)
345 sent = sizeof(buf) - count;
348 if (cli_write(c, fnum, 0, buf+count, count, sent) != sent) {
349 printf("write failed (%s)\n", cli_errstr(c));
352 else
354 sent = cli_read(c, fnum, buf_rd+count, count,
355 sizeof(buf)-count);
356 if (sent < 0)
358 printf("read failed offset:%d size:%d (%s)\n",
359 count, sizeof(buf)-count,
360 cli_errstr(c));
361 sent = 0;
363 if (sent > 0)
365 if (memcmp(buf_rd+count, buf+count, sent) != 0)
367 printf("read/write compare failed\n");
368 printf("offset: %d req %d recvd %d\n",
369 count, sizeof(buf)-count, sent);
370 break;
377 if (!cli_close(c, fnum)) {
378 printf("close failed (%s)\n", cli_errstr(c));
381 return True;
384 static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
386 char *lockfname = "\\torture.lck";
387 int fnum1;
388 int fnum2;
389 int i;
390 char buf[131072];
391 char buf_rd[131072];
393 if (!cli_unlink(c1, lockfname)) {
394 printf("unlink failed (%s)\n", cli_errstr(c1));
397 fnum1 = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
398 DENY_NONE);
399 if (fnum1 == -1) {
400 printf("first open read/write of %s failed (%s)\n",
401 lockfname, cli_errstr(c1));
402 return False;
404 fnum2 = cli_open(c2, lockfname, O_RDONLY,
405 DENY_NONE);
406 if (fnum2 == -1) {
407 printf("second open read-only of %s failed (%s)\n",
408 lockfname, cli_errstr(c2));
409 cli_close(c1, fnum1);
410 return False;
413 for (i=0;i<numops;i++)
415 unsigned buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
416 if (i % 10 == 0) {
417 printf("%d\r", i); fflush(stdout);
420 generate_random_buffer(buf, buf_size, False);
422 if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
423 printf("write failed (%s)\n", cli_errstr(c1));
426 if (cli_read(c2, fnum2, buf_rd, 0, buf_size) != buf_size) {
427 printf("read failed (%s)\n", cli_errstr(c2));
430 if (memcmp(buf_rd, buf, buf_size) != 0)
432 printf("read/write compare failed\n");
436 if (!cli_close(c2, fnum2)) {
437 printf("close failed (%s)\n", cli_errstr(c2));
439 if (!cli_close(c1, fnum1)) {
440 printf("close failed (%s)\n", cli_errstr(c1));
443 if (!cli_unlink(c1, lockfname)) {
444 printf("unlink failed (%s)\n", cli_errstr(c1));
447 return True;
450 static void run_readwritetest(int dummy)
452 static struct cli_state cli1, cli2;
453 BOOL test;
455 if (!open_connection(&cli1) || !open_connection(&cli2)) {
456 return;
458 cli_sockopt(&cli1, sockops);
459 cli_sockopt(&cli2, sockops);
461 printf("starting readwritetest\n");
463 test = rw_torture2(&cli1, &cli2);
464 printf("Passed readwritetest v1: %s\n", BOOLSTR(test));
466 test = rw_torture2(&cli1, &cli1);
467 printf("Passed readwritetest v2: %s\n", BOOLSTR(test));
469 close_connection(&cli1);
470 close_connection(&cli2);
473 static void run_readwritemulti(int dummy)
475 static struct cli_state cli;
476 BOOL test;
478 cli = current_cli;
480 cli_sockopt(&cli, sockops);
482 printf("run_readwritemulti: fname %s\n", randomfname);
483 test = rw_torture3(&cli, randomfname);
485 close_connection(&cli);
488 int line_count = 0;
490 /* run a test that simulates an approximate netbench client load */
491 static void run_netbench(int client)
493 struct cli_state cli;
494 int i;
495 fstring fname;
496 pstring line;
497 char cname[20];
498 FILE *f;
499 char *params[20];
501 cli = current_cli;
503 cli_sockopt(&cli, sockops);
505 nb_setup(&cli);
507 slprintf(cname,sizeof(fname), "CLIENT%d", client);
509 f = fopen("client.txt", "r");
511 if (!f) {
512 perror("client.txt");
513 return;
516 while (fgets(line, sizeof(line)-1, f)) {
517 line_count++;
519 line[strlen(line)-1] = 0;
521 /* printf("[%d] %s\n", line_count, line); */
523 all_string_sub(line,"CLIENT1", cname, sizeof(line));
525 for (i=0;i<20;i++) params[i] = "";
527 /* parse the command parameters */
528 params[0] = strtok(line," ");
529 i = 0;
530 while (params[i]) params[++i] = strtok(NULL," ");
532 params[i] = "";
534 if (i < 2) continue;
536 if (strcmp(params[1],"REQUEST") == 0) {
537 if (!strcmp(params[0],"SMBopenX")) {
538 fstrcpy(fname, params[5]);
539 } else if (!strcmp(params[0],"SMBclose")) {
540 nb_close(atoi(params[3]));
541 } else if (!strcmp(params[0],"SMBmkdir")) {
542 nb_mkdir(params[3]);
543 } else if (!strcmp(params[0],"CREATE")) {
544 nb_create(params[3], atoi(params[5]));
545 } else if (!strcmp(params[0],"SMBrmdir")) {
546 nb_rmdir(params[3]);
547 } else if (!strcmp(params[0],"SMBunlink")) {
548 fstrcpy(fname, params[3]);
549 } else if (!strcmp(params[0],"SMBmv")) {
550 nb_rename(params[3], params[5]);
551 } else if (!strcmp(params[0],"SMBgetatr")) {
552 fstrcpy(fname, params[3]);
553 } else if (!strcmp(params[0],"SMBwrite")) {
554 nb_write(atoi(params[3]),
555 atoi(params[5]), atoi(params[7]));
556 } else if (!strcmp(params[0],"SMBwritebraw")) {
557 nb_write(atoi(params[3]),
558 atoi(params[7]), atoi(params[5]));
559 } else if (!strcmp(params[0],"SMBreadbraw")) {
560 nb_read(atoi(params[3]),
561 atoi(params[7]), atoi(params[5]));
562 } else if (!strcmp(params[0],"SMBread")) {
563 nb_read(atoi(params[3]),
564 atoi(params[5]), atoi(params[7]));
566 } else {
567 if (!strcmp(params[0],"SMBopenX")) {
568 if (!strncmp(params[2], "ERR", 3)) continue;
569 nb_open(fname, atoi(params[3]), atoi(params[5]));
570 } else if (!strcmp(params[0],"SMBgetatr")) {
571 if (!strncmp(params[2], "ERR", 3)) continue;
572 nb_stat(fname, atoi(params[3]));
573 } else if (!strcmp(params[0],"SMBunlink")) {
574 if (!strncmp(params[2], "ERR", 3)) continue;
575 nb_unlink(fname);
579 fclose(f);
581 slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
582 rmdir(fname);
583 rmdir("CLIENTS");
585 printf("+");
587 close_connection(&cli);
591 /* run a test that simulates an approximate netbench w9X client load */
592 static void run_nbw95(int dummy)
594 double t;
595 t = create_procs(run_netbench);
596 /* to produce a netbench result we scale accoding to the
597 netbench measured throughput for the run that produced the
598 sniff that was used to produce client.txt. That run used 2
599 clients and ran for 660 seconds to produce a result of
600 4MBit/sec. */
601 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
602 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
605 /* run a test that simulates an approximate netbench wNT client load */
606 static void run_nbwnt(int dummy)
608 double t;
609 t = create_procs(run_netbench);
610 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
611 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
617 This test checks for two things:
619 1) correct support for retaining locks over a close (ie. the server
620 must not use posix semantics)
621 2) support for lock timeouts
623 static void run_locktest1(int dummy)
625 static struct cli_state cli1, cli2;
626 char *fname = "\\lockt1.lck";
627 int fnum1, fnum2, fnum3;
628 time_t t1, t2;
630 if (!open_connection(&cli1) || !open_connection(&cli2)) {
631 return;
633 cli_sockopt(&cli1, sockops);
634 cli_sockopt(&cli2, sockops);
636 printf("starting locktest1\n");
638 cli_unlink(&cli1, fname);
640 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
641 if (fnum1 == -1) {
642 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
643 return;
645 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
646 if (fnum2 == -1) {
647 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
648 return;
650 fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
651 if (fnum3 == -1) {
652 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
653 return;
656 if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
657 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
658 return;
662 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
663 printf("lock2 succeeded! This is a locking bug\n");
664 return;
665 } else {
666 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
670 printf("Testing lock timeouts\n");
671 t1 = time(NULL);
672 if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
673 printf("lock3 succeeded! This is a locking bug\n");
674 return;
675 } else {
676 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
678 t2 = time(NULL);
680 if (t2 - t1 < 5) {
681 printf("error: This server appears not to support timed lock requests\n");
684 if (!cli_close(&cli1, fnum2)) {
685 printf("close1 failed (%s)\n", cli_errstr(&cli1));
686 return;
689 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
690 printf("lock4 succeeded! This is a locking bug\n");
691 return;
692 } else {
693 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
696 if (!cli_close(&cli1, fnum1)) {
697 printf("close2 failed (%s)\n", cli_errstr(&cli1));
698 return;
701 if (!cli_close(&cli2, fnum3)) {
702 printf("close3 failed (%s)\n", cli_errstr(&cli2));
703 return;
706 if (!cli_unlink(&cli1, fname)) {
707 printf("unlink failed (%s)\n", cli_errstr(&cli1));
708 return;
712 close_connection(&cli1);
713 close_connection(&cli2);
715 printf("Passed locktest1\n");
719 checks for correct tconX support
721 static void run_tcon_test(int dummy)
723 static struct cli_state cli1;
724 char *fname = "\\tcontest.tmp";
725 int fnum1;
726 uint16 cnum;
727 char buf[4];
729 if (!open_connection(&cli1)) {
730 return;
732 cli_sockopt(&cli1, sockops);
734 printf("starting tcontest\n");
736 cli_unlink(&cli1, fname);
738 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
739 if (fnum1 == -1)
741 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
742 return;
745 cnum = cli1.cnum;
747 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) != 4)
749 printf("write failed (%s)", cli_errstr(&cli1));
750 return;
753 if (!cli_send_tconX(&cli1, share, "?????",
754 password, strlen(password)+1)) {
755 printf("%s refused 2nd tree connect (%s)\n", host,
756 cli_errstr(&cli1));
757 cli_shutdown(&cli1);
758 return ;
761 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) == 4)
763 printf("write succeeded (%s)", cli_errstr(&cli1));
764 return;
767 if (cli_close(&cli1, fnum1)) {
768 printf("close2 succeeded (%s)\n", cli_errstr(&cli1));
769 return;
772 if (!cli_tdis(&cli1)) {
773 printf("tdis failed (%s)\n", cli_errstr(&cli1));
774 return;
777 cli1.cnum = cnum;
779 if (!cli_close(&cli1, fnum1)) {
780 printf("close2 failed (%s)\n", cli_errstr(&cli1));
781 return;
784 close_connection(&cli1);
786 printf("Passed tcontest\n");
791 This test checks that
793 1) the server supports multiple locking contexts on the one SMB
794 connection, distinguished by PID.
796 2) the server correctly fails overlapping locks made by the same PID (this
797 goes against POSIX behaviour, which is why it is tricky to implement)
799 3) the server denies unlock requests by an incorrect client PID
801 static void run_locktest2(int dummy)
803 static struct cli_state cli;
804 char *fname = "\\lockt2.lck";
805 int fnum1, fnum2, fnum3;
807 if (!open_connection(&cli)) {
808 return;
811 cli_sockopt(&cli, sockops);
813 printf("starting locktest2\n");
815 cli_unlink(&cli, fname);
817 cli_setpid(&cli, 1);
819 fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
820 if (fnum1 == -1) {
821 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
822 return;
825 fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
826 if (fnum2 == -1) {
827 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
828 return;
831 cli_setpid(&cli, 2);
833 fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
834 if (fnum3 == -1) {
835 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
836 return;
839 cli_setpid(&cli, 1);
841 if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
842 printf("lock1 failed (%s)\n", cli_errstr(&cli));
843 return;
846 if (cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
847 printf("WRITE lock1 succeeded! This is a locking bug\n");
848 } else {
849 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
852 if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
853 printf("WRITE lock2 succeeded! This is a locking bug\n");
854 } else {
855 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
858 if (cli_lock(&cli, fnum2, 0, 4, 0, READ_LOCK)) {
859 printf("READ lock2 succeeded! This is a locking bug\n");
860 } else {
861 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
864 cli_setpid(&cli, 2);
866 if (cli_unlock(&cli, fnum1, 0, 8)) {
867 printf("unlock1 succeeded! This is a locking bug\n");
870 if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
871 printf("lock3 succeeded! This is a locking bug\n");
872 } else {
873 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
876 cli_setpid(&cli, 1);
878 if (!cli_close(&cli, fnum1)) {
879 printf("close1 failed (%s)\n", cli_errstr(&cli));
880 return;
883 if (!cli_close(&cli, fnum2)) {
884 printf("close2 failed (%s)\n", cli_errstr(&cli));
885 return;
888 if (!cli_close(&cli, fnum3)) {
889 printf("close3 failed (%s)\n", cli_errstr(&cli));
890 return;
893 close_connection(&cli);
895 printf("locktest2 finished\n");
900 This test checks that
902 1) the server supports the full offset range in lock requests
904 static void run_locktest3(int dummy)
906 static struct cli_state cli1, cli2;
907 char *fname = "\\lockt3.lck";
908 int fnum1, fnum2, i;
909 uint32 offset;
911 #define NEXT_OFFSET offset += (~(uint32)0) / numops
913 if (!open_connection(&cli1) || !open_connection(&cli2)) {
914 return;
916 cli_sockopt(&cli1, sockops);
917 cli_sockopt(&cli2, sockops);
919 printf("starting locktest3\n");
921 cli_unlink(&cli1, fname);
923 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
924 if (fnum1 == -1) {
925 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
926 return;
928 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
929 if (fnum2 == -1) {
930 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
931 return;
934 for (offset=i=0;i<numops;i++) {
935 NEXT_OFFSET;
936 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
937 printf("lock1 %d failed (%s)\n",
939 cli_errstr(&cli1));
940 return;
943 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
944 printf("lock2 %d failed (%s)\n",
946 cli_errstr(&cli1));
947 return;
951 for (offset=i=0;i<numops;i++) {
952 NEXT_OFFSET;
954 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
955 printf("error: lock1 %d succeeded!\n", i);
956 return;
959 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
960 printf("error: lock2 %d succeeded!\n", i);
961 return;
964 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
965 printf("error: lock3 %d succeeded!\n", i);
966 return;
969 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
970 printf("error: lock4 %d succeeded!\n", i);
971 return;
975 for (offset=i=0;i<numops;i++) {
976 NEXT_OFFSET;
978 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
979 printf("unlock1 %d failed (%s)\n",
981 cli_errstr(&cli1));
982 return;
985 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
986 printf("unlock2 %d failed (%s)\n",
988 cli_errstr(&cli1));
989 return;
993 if (!cli_close(&cli1, fnum1)) {
994 printf("close1 failed (%s)\n", cli_errstr(&cli1));
997 if (!cli_close(&cli2, fnum2)) {
998 printf("close2 failed (%s)\n", cli_errstr(&cli2));
1001 if (!cli_unlink(&cli1, fname)) {
1002 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1003 return;
1006 close_connection(&cli1);
1007 close_connection(&cli2);
1009 printf("finished locktest3\n");
1012 #define EXPECTED(ret, v) if ((ret) != (v)) printf("** ")
1015 looks at overlapping locks
1017 static void run_locktest4(int dummy)
1019 static struct cli_state cli1, cli2;
1020 char *fname = "\\lockt4.lck";
1021 int fnum1, fnum2, f;
1022 BOOL ret;
1023 char buf[1000];
1025 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1026 return;
1029 cli_sockopt(&cli1, sockops);
1030 cli_sockopt(&cli2, sockops);
1032 printf("starting locktest4\n");
1034 cli_unlink(&cli1, fname);
1036 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1037 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1039 memset(buf, 0, sizeof(buf));
1041 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1042 printf("Failed to create file\n");
1043 goto fail;
1046 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1047 cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1048 EXPECTED(ret, False);
1049 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1051 ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1052 cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
1053 EXPECTED(ret, True);
1054 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1056 ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1057 cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1058 EXPECTED(ret, False);
1059 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1061 ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1062 cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
1063 EXPECTED(ret, True);
1064 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1066 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1067 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1068 EXPECTED(ret, False);
1069 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1071 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1072 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
1073 EXPECTED(ret, True);
1074 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1076 ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1077 cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
1078 EXPECTED(ret, True);
1079 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1081 ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1082 cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1083 EXPECTED(ret, False);
1084 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1086 ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1087 cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1088 EXPECTED(ret, False);
1089 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1091 ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1092 cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
1093 EXPECTED(ret, True);
1094 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1096 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1097 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
1098 EXPECTED(ret, False);
1099 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1101 ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1102 cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1103 cli_unlock(&cli1, fnum1, 110, 6);
1104 EXPECTED(ret, False);
1105 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1108 ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1109 (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
1110 EXPECTED(ret, False);
1111 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1113 ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
1114 (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
1115 EXPECTED(ret, False);
1116 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1119 ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1120 cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1121 cli_unlock(&cli1, fnum1, 140, 4) &&
1122 cli_unlock(&cli1, fnum1, 140, 4);
1123 EXPECTED(ret, True);
1124 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1127 ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1128 cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1129 cli_unlock(&cli1, fnum1, 150, 4) &&
1130 (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
1131 !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
1132 cli_unlock(&cli1, fnum1, 150, 4);
1133 EXPECTED(ret, True);
1134 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1136 ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1137 cli_unlock(&cli1, fnum1, 160, 4) &&
1138 (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&
1139 (cli_read(&cli2, fnum2, buf, 160, 4) == 4);
1140 EXPECTED(ret, True);
1141 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1143 ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
1144 cli_unlock(&cli1, fnum1, 170, 4) &&
1145 (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&
1146 (cli_read(&cli2, fnum2, buf, 170, 4) == 4);
1147 EXPECTED(ret, True);
1148 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1150 ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
1151 cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
1152 cli_unlock(&cli1, fnum1, 190, 4) &&
1153 !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&
1154 (cli_read(&cli2, fnum2, buf, 190, 4) == 4);
1155 EXPECTED(ret, True);
1156 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1158 cli_close(&cli1, fnum1);
1159 cli_close(&cli2, fnum2);
1160 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1161 f = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1162 ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1163 cli_lock(&cli1, f, 0, 1, 0, READ_LOCK) &&
1164 cli_close(&cli1, fnum1) &&
1165 ((fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE)) != -1) &&
1166 cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1167 cli_close(&cli1, f);
1168 EXPECTED(ret, True);
1169 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1173 fail:
1174 cli_close(&cli1, fnum1);
1175 cli_close(&cli2, fnum2);
1176 cli_unlink(&cli1, fname);
1177 close_connection(&cli1);
1178 close_connection(&cli2);
1180 printf("finished locktest4\n");
1184 looks at lock upgrade/downgrade.
1186 static void run_locktest5(int dummy)
1188 static struct cli_state cli1, cli2;
1189 char *fname = "\\lockt5.lck";
1190 int fnum1, fnum2, fnum3;
1191 BOOL ret;
1192 char buf[1000];
1194 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1195 return;
1198 cli_sockopt(&cli1, sockops);
1199 cli_sockopt(&cli2, sockops);
1201 printf("starting locktest5\n");
1203 cli_unlink(&cli1, fname);
1205 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1206 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1207 fnum3 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1209 memset(buf, 0, sizeof(buf));
1211 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1212 printf("Failed to create file\n");
1213 goto fail;
1216 /* Check for NT bug... */
1217 ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1218 cli_lock(&cli1, fnum3, 0, 1, 0, READ_LOCK);
1219 cli_close(&cli1, fnum1);
1220 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1221 ret = cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1222 EXPECTED(ret, True);
1223 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1224 cli_close(&cli1, fnum1);
1225 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1226 cli_unlock(&cli1, fnum3, 0, 1);
1228 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1229 cli_lock(&cli1, fnum1, 1, 1, 0, READ_LOCK);
1230 EXPECTED(ret, True);
1231 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1233 ret = cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1234 EXPECTED(ret, False);
1236 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1238 /* Unlock the process 2 lock. */
1239 cli_unlock(&cli2, fnum2, 0, 4);
1241 ret = cli_lock(&cli1, fnum3, 0, 4, 0, READ_LOCK);
1242 EXPECTED(ret, False);
1244 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1246 /* Unlock the process 1 fnum3 lock. */
1247 cli_unlock(&cli1, fnum3, 0, 4);
1249 /* Stack 2 more locks here. */
1250 ret = cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1251 cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK);
1253 EXPECTED(ret, True);
1254 printf("the same process %s stack read locks\n", ret?"can":"cannot");
1256 /* Unlock the first process lock, then check this was the WRITE lock that was
1257 removed. */
1259 ret = cli_unlock(&cli1, fnum1, 0, 4) &&
1260 cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1262 EXPECTED(ret, True);
1263 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1265 /* Unlock the process 2 lock. */
1266 cli_unlock(&cli2, fnum2, 0, 4);
1268 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1270 ret = cli_unlock(&cli1, fnum1, 1, 1) &&
1271 cli_unlock(&cli1, fnum1, 0, 4) &&
1272 cli_unlock(&cli1, fnum1, 0, 4);
1274 EXPECTED(ret, True);
1275 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
1277 /* Ensure the next unlock fails. */
1278 ret = cli_unlock(&cli1, fnum1, 0, 4);
1279 EXPECTED(ret, False);
1280 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
1282 /* Ensure connection 2 can get a write lock. */
1283 ret = cli_lock(&cli2, fnum2, 0, 4, 0, WRITE_LOCK);
1284 EXPECTED(ret, True);
1286 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1288 fail:
1289 cli_close(&cli1, fnum1);
1290 cli_close(&cli2, fnum2);
1291 cli_unlink(&cli1, fname);
1292 close_connection(&cli1);
1293 close_connection(&cli2);
1295 printf("finished locktest5\n");
1300 this produces a matrix of deny mode behaviour
1302 static void run_denytest1(int dummy)
1304 static struct cli_state cli1, cli2;
1305 int fnum1, fnum2;
1306 int f, d1, d2, o1, o2, x=0;
1307 char *fnames[] = {"\\denytest1.exe", "\\denytest1.dat", NULL};
1308 struct {
1309 int v;
1310 char *name;
1311 } deny_modes[] = {
1312 {DENY_DOS, "DENY_DOS"},
1313 {DENY_ALL, "DENY_ALL"},
1314 {DENY_WRITE, "DENY_WRITE"},
1315 {DENY_READ, "DENY_READ"},
1316 {DENY_NONE, "DENY_NONE"},
1317 {DENY_FCB, "DENY_FCB"},
1318 {-1, NULL}};
1319 struct {
1320 int v;
1321 char *name;
1322 } open_modes[] = {
1323 {O_RDWR, "O_RDWR"},
1324 {O_RDONLY, "O_RDONLY"},
1325 {O_WRONLY, "O_WRONLY"},
1326 {-1, NULL}};
1328 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1329 return;
1331 cli_sockopt(&cli1, sockops);
1332 cli_sockopt(&cli2, sockops);
1334 printf("starting denytest1\n");
1336 for (f=0;fnames[f];f++) {
1337 cli_unlink(&cli1, fnames[f]);
1339 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1340 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1341 cli_close(&cli1, fnum1);
1343 for (d1=0;deny_modes[d1].name;d1++)
1344 for (o1=0;open_modes[o1].name;o1++)
1345 for (d2=0;deny_modes[d2].name;d2++)
1346 for (o2=0;open_modes[o2].name;o2++) {
1347 fnum1 = cli_open(&cli1, fnames[f],
1348 open_modes[o1].v,
1349 deny_modes[d1].v);
1350 fnum2 = cli_open(&cli2, fnames[f],
1351 open_modes[o2].v,
1352 deny_modes[d2].v);
1354 printf("%s %8s %10s %8s %10s ",
1355 fnames[f],
1356 open_modes[o1].name,
1357 deny_modes[d1].name,
1358 open_modes[o2].name,
1359 deny_modes[d2].name);
1361 if (fnum1 == -1) {
1362 printf("X");
1363 } else if (fnum2 == -1) {
1364 printf("-");
1365 } else {
1366 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
1367 printf("R");
1369 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
1370 printf("W");
1374 printf("\n");
1375 cli_close(&cli1, fnum1);
1376 cli_close(&cli2, fnum2);
1379 cli_unlink(&cli1, fnames[f]);
1382 close_connection(&cli1);
1383 close_connection(&cli2);
1385 printf("finshed denytest1\n");
1390 this produces a matrix of deny mode behaviour for two opens on the
1391 same connection
1393 static void run_denytest2(int dummy)
1395 static struct cli_state cli1;
1396 int fnum1, fnum2;
1397 int f, d1, d2, o1, o2, x=0;
1398 char *fnames[] = {"\\denytest2.exe", "\\denytest2.dat", NULL};
1399 struct {
1400 int v;
1401 char *name;
1402 } deny_modes[] = {
1403 {DENY_DOS, "DENY_DOS"},
1404 {DENY_ALL, "DENY_ALL"},
1405 {DENY_WRITE, "DENY_WRITE"},
1406 {DENY_READ, "DENY_READ"},
1407 {DENY_NONE, "DENY_NONE"},
1408 {DENY_FCB, "DENY_FCB"},
1409 {-1, NULL}};
1410 struct {
1411 int v;
1412 char *name;
1413 } open_modes[] = {
1414 {O_RDWR, "O_RDWR"},
1415 {O_RDONLY, "O_RDONLY"},
1416 {O_WRONLY, "O_WRONLY"},
1417 {-1, NULL}};
1419 if (!open_connection(&cli1)) {
1420 return;
1422 cli_sockopt(&cli1, sockops);
1424 printf("starting denytest2\n");
1426 for (f=0;fnames[f];f++) {
1427 cli_unlink(&cli1, fnames[f]);
1429 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1430 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1431 cli_close(&cli1, fnum1);
1433 for (d1=0;deny_modes[d1].name;d1++)
1434 for (o1=0;open_modes[o1].name;o1++)
1435 for (d2=0;deny_modes[d2].name;d2++)
1436 for (o2=0;open_modes[o2].name;o2++) {
1437 fnum1 = cli_open(&cli1, fnames[f],
1438 open_modes[o1].v,
1439 deny_modes[d1].v);
1440 fnum2 = cli_open(&cli1, fnames[f],
1441 open_modes[o2].v,
1442 deny_modes[d2].v);
1444 printf("%s %8s %10s %8s %10s ",
1445 fnames[f],
1446 open_modes[o1].name,
1447 deny_modes[d1].name,
1448 open_modes[o2].name,
1449 deny_modes[d2].name);
1451 if (fnum1 == -1) {
1452 printf("X");
1453 } else if (fnum2 == -1) {
1454 printf("-");
1455 } else {
1456 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1457 printf("R");
1459 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1460 printf("W");
1464 printf("\n");
1465 cli_close(&cli1, fnum1);
1466 cli_close(&cli1, fnum2);
1469 cli_unlink(&cli1, fnames[f]);
1472 close_connection(&cli1);
1474 printf("finshed denytest2\n");
1478 test whether fnums and tids open on one VC are available on another (a major
1479 security hole)
1481 static void run_fdpasstest(int dummy)
1483 static struct cli_state cli1, cli2, cli3;
1484 char *fname = "\\fdpass.tst";
1485 int fnum1;
1486 pstring buf;
1488 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1489 return;
1491 cli_sockopt(&cli1, sockops);
1492 cli_sockopt(&cli2, sockops);
1494 printf("starting fdpasstest\n");
1496 cli_unlink(&cli1, fname);
1498 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1499 if (fnum1 == -1) {
1500 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1501 return;
1504 if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1505 printf("write failed (%s)\n", cli_errstr(&cli1));
1506 return;
1509 cli3 = cli2;
1510 cli3.vuid = cli1.vuid;
1511 cli3.cnum = cli1.cnum;
1512 cli3.pid = cli1.pid;
1514 if (cli_read(&cli3, fnum1, buf, 0, 13) == 13) {
1515 printf("read succeeded! nasty security hole [%s]\n",
1516 buf);
1517 return;
1520 cli_close(&cli1, fnum1);
1521 cli_unlink(&cli1, fname);
1523 close_connection(&cli1);
1524 close_connection(&cli2);
1526 printf("finished fdpasstest\n");
1531 This test checks that
1533 1) the server does not allow an unlink on a file that is open
1535 static void run_unlinktest(int dummy)
1537 static struct cli_state cli;
1538 char *fname = "\\unlink.tst";
1539 int fnum;
1541 if (!open_connection(&cli)) {
1542 return;
1545 cli_sockopt(&cli, sockops);
1547 printf("starting unlink test\n");
1549 cli_unlink(&cli, fname);
1551 cli_setpid(&cli, 1);
1553 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1554 if (fnum == -1) {
1555 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1556 return;
1559 if (cli_unlink(&cli, fname)) {
1560 printf("error: server allowed unlink on an open file\n");
1563 cli_close(&cli, fnum);
1564 cli_unlink(&cli, fname);
1566 close_connection(&cli);
1568 printf("unlink test finished\n");
1573 test how many open files this server supports on the one socket
1575 static void run_maxfidtest(int dummy)
1577 static struct cli_state cli;
1578 char *template = "\\maxfid.%d.%d";
1579 fstring fname;
1580 int fnum;
1581 int retries=4;
1583 cli = current_cli;
1585 if (retries <= 0) {
1586 printf("failed to connect\n");
1587 return;
1590 cli_sockopt(&cli, sockops);
1592 fnum = 0;
1593 while (1) {
1594 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1595 if (cli_open(&cli, fname,
1596 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
1597 -1) {
1598 printf("open of %s failed (%s)\n",
1599 fname, cli_errstr(&cli));
1600 printf("maximum fnum is %d\n", fnum);
1601 break;
1603 fnum++;
1604 if (fnum % 100 == 0) printf("%d\r", fnum);
1606 printf("%d\n", fnum);
1608 printf("cleaning up\n");
1609 while (fnum > 0) {
1610 fnum--;
1611 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1612 cli_close(&cli, fnum);
1613 if (!cli_unlink(&cli, fname)) {
1614 printf("unlink of %s failed (%s)\n",
1615 fname, cli_errstr(&cli));
1619 printf("maxfid test finished\n");
1620 close_connection(&cli);
1623 /* generate a random buffer */
1624 static void rand_buf(char *buf, int len)
1626 while (len--) {
1627 *buf = (char)sys_random();
1628 buf++;
1632 /* send smb negprot commands, not reading the response */
1633 static void run_negprot_nowait(int dummy)
1635 int i;
1636 static struct cli_state cli;
1638 printf("starting negprot nowait test\n");
1640 if (!open_nbt_connection(&cli)) {
1641 return;
1644 for (i=0;i<50000;i++) {
1645 cli_negprot_send(&cli);
1648 close_connection(&cli);
1650 printf("finished negprot nowait test\n");
1654 /* send random IPC commands */
1655 static void run_randomipc(int dummy)
1657 char *rparam = NULL;
1658 char *rdata = NULL;
1659 int rdrcnt,rprcnt;
1660 pstring param;
1661 int api, param_len, i;
1662 static struct cli_state cli;
1664 printf("starting random ipc test\n");
1666 if (!open_connection(&cli)) {
1667 return;
1670 for (i=0;i<50000;i++) {
1671 api = sys_random() % 500;
1672 param_len = (sys_random() % 64);
1674 rand_buf(param, param_len);
1676 SSVAL(param,0,api);
1678 cli_api(&cli,
1679 param, param_len, 8,
1680 NULL, 0, BUFFER_SIZE,
1681 &rparam, &rprcnt,
1682 &rdata, &rdrcnt);
1685 close_connection(&cli);
1687 printf("finished random ipc test\n");
1692 static void browse_callback(const char *sname, uint32 stype,
1693 const char *comment)
1695 printf("\t%20.20s %08x %s\n", sname, stype, comment);
1701 This test checks the browse list code
1704 static void run_browsetest(int dummy)
1706 static struct cli_state cli;
1708 printf("starting browse test\n");
1710 if (!open_connection(&cli)) {
1711 return;
1714 printf("domain list:\n");
1715 cli_NetServerEnum(&cli, cli.server_domain,
1716 SV_TYPE_DOMAIN_ENUM,
1717 browse_callback);
1719 printf("machine list:\n");
1720 cli_NetServerEnum(&cli, cli.server_domain,
1721 SV_TYPE_ALL,
1722 browse_callback);
1724 close_connection(&cli);
1726 printf("browse test finished\n");
1731 This checks how the getatr calls works
1733 static void run_attrtest(int dummy)
1735 static struct cli_state cli;
1736 int fnum;
1737 time_t t, t2;
1738 char *fname = "\\attrib.tst";
1740 printf("starting attrib test\n");
1742 if (!open_connection(&cli)) {
1743 return;
1746 cli_unlink(&cli, fname);
1747 fnum = cli_open(&cli, fname,
1748 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1749 cli_close(&cli, fnum);
1750 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1751 printf("getatr failed (%s)\n", cli_errstr(&cli));
1754 if (abs(t - time(NULL)) > 2) {
1755 printf("ERROR: SMBgetatr bug. time is %s",
1756 ctime(&t));
1757 t = time(NULL);
1760 t2 = t-60*60*24; /* 1 day ago */
1762 if (!cli_setatr(&cli, fname, 0, t2)) {
1763 printf("setatr failed (%s)\n", cli_errstr(&cli));
1766 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1767 printf("getatr failed (%s)\n", cli_errstr(&cli));
1770 if (t != t2) {
1771 printf("ERROR: getatr/setatr bug. times are\n%s",
1772 ctime(&t));
1773 printf("%s", ctime(&t2));
1776 cli_unlink(&cli, fname);
1778 close_connection(&cli);
1780 printf("attrib test finished\n");
1785 This checks a couple of trans2 calls
1787 static void run_trans2test(int dummy)
1789 static struct cli_state cli;
1790 int fnum;
1791 size_t size;
1792 time_t c_time, a_time, m_time, w_time, m_time2;
1793 char *fname = "\\trans2.tst";
1794 char *dname = "\\trans2";
1795 char *fname2 = "\\trans2\\trans2.tst";
1797 printf("starting trans2 test\n");
1799 if (!open_connection(&cli)) {
1800 return;
1803 cli_unlink(&cli, fname);
1804 fnum = cli_open(&cli, fname,
1805 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1806 if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1807 NULL, NULL)) {
1808 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1810 cli_close(&cli, fnum);
1812 sleep(2);
1814 cli_unlink(&cli, fname);
1815 fnum = cli_open(&cli, fname,
1816 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1817 cli_close(&cli, fnum);
1819 if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1820 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1821 } else {
1822 if (c_time != m_time) {
1823 printf("create time=%s", ctime(&c_time));
1824 printf("modify time=%s", ctime(&m_time));
1825 printf("This system appears to have sticky create times\n");
1827 if (a_time % (60*60) == 0) {
1828 printf("access time=%s", ctime(&a_time));
1829 printf("This system appears to set a midnight access time\n");
1832 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1833 printf("ERROR: totally incorrect times - maybe word reversed?\n");
1838 cli_unlink(&cli, fname);
1839 fnum = cli_open(&cli, fname,
1840 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1841 cli_close(&cli, fnum);
1842 if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
1843 &w_time, &size, NULL, NULL)) {
1844 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1845 } else {
1846 if (w_time < 60*60*24*2) {
1847 printf("write time=%s", ctime(&w_time));
1848 printf("This system appears to set a initial 0 write time\n");
1852 cli_unlink(&cli, fname);
1855 /* check if the server updates the directory modification time
1856 when creating a new file */
1857 if (!cli_mkdir(&cli, dname)) {
1858 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1860 sleep(3);
1861 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
1862 &w_time, &size, NULL, NULL)) {
1863 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1866 fnum = cli_open(&cli, fname2,
1867 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1868 cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
1869 cli_close(&cli, fnum);
1870 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
1871 &w_time, &size, NULL, NULL)) {
1872 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1873 } else {
1874 if (m_time2 == m_time)
1875 printf("This system does not update directory modification times\n");
1877 cli_unlink(&cli, fname2);
1878 cli_rmdir(&cli, dname);
1881 close_connection(&cli);
1883 printf("trans2 test finished\n");
1888 this is a harness for some oplock tests
1890 static void run_oplock1(int dummy)
1892 static struct cli_state cli1;
1893 char *fname = "\\lockt1.lck";
1894 int fnum1;
1896 printf("starting oplock test 1\n");
1898 if (!open_connection(&cli1)) {
1899 return;
1902 cli_unlink(&cli1, fname);
1904 cli_sockopt(&cli1, sockops);
1906 cli1.use_oplocks = True;
1908 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1909 if (fnum1 == -1) {
1910 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1911 return;
1914 cli1.use_oplocks = False;
1916 cli_unlink(&cli1, fname);
1917 cli_unlink(&cli1, fname);
1919 if (!cli_close(&cli1, fnum1)) {
1920 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1921 return;
1924 if (!cli_unlink(&cli1, fname)) {
1925 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1926 return;
1930 close_connection(&cli1);
1932 printf("finished oplock test 1\n");
1935 static void run_oplock2(int dummy)
1937 static struct cli_state cli1, cli2;
1938 char *fname = "\\lockt2.lck";
1939 int fnum1, fnum2;
1940 int saved_use_oplocks = use_oplocks;
1941 char buf[4];
1943 use_level_II_oplocks = True;
1944 use_oplocks = True;
1946 printf("starting oplock test 2\n");
1948 if (!open_connection(&cli1)) {
1949 use_level_II_oplocks = False;
1950 use_oplocks = saved_use_oplocks;
1951 return;
1954 cli1.use_oplocks = True;
1955 cli1.use_level_II_oplocks = True;
1957 if (!open_connection(&cli2)) {
1958 use_level_II_oplocks = False;
1959 use_oplocks = saved_use_oplocks;
1960 return;
1963 cli2.use_oplocks = True;
1964 cli2.use_level_II_oplocks = True;
1966 cli_unlink(&cli1, fname);
1968 cli_sockopt(&cli1, sockops);
1969 cli_sockopt(&cli2, sockops);
1971 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1972 if (fnum1 == -1) {
1973 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1974 return;
1977 /* Don't need the globals any more. */
1978 use_level_II_oplocks = False;
1979 use_oplocks = saved_use_oplocks;
1981 if (fork() == 0) {
1982 /* Child code */
1983 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1984 if (fnum2 == -1) {
1985 printf("second open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1986 exit(0);
1989 sleep(2);
1991 if (!cli_close(&cli2, fnum2)) {
1992 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1995 exit(0);
1998 sleep(2);
2000 /* Ensure cli1 processes the break. */
2002 if (cli_read(&cli1, fnum1, buf, 0, 4) != 4) {
2003 printf("read on fnum1 failed (%s)\n", cli_errstr(&cli1));
2006 /* Should now be at level II. */
2007 /* Test if sending a write locks causes a break to none. */
2009 if (!cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK)) {
2010 printf("lock failed (%s)\n", cli_errstr(&cli1));
2013 cli_unlock(&cli1, fnum1, 0, 4);
2015 sleep(2);
2017 if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
2018 printf("lock failed (%s)\n", cli_errstr(&cli1));
2021 cli_unlock(&cli1, fnum1, 0, 4);
2023 sleep(2);
2025 cli_read(&cli1, fnum1, buf, 0, 4);
2027 #if 0
2028 if (cli_write(&cli1, fnum1, 0, buf, 0, 4) != 4) {
2029 printf("write on fnum1 failed (%s)\n", cli_errstr(&cli1));
2031 #endif
2033 if (!cli_close(&cli1, fnum1)) {
2034 printf("close1 failed (%s)\n", cli_errstr(&cli1));
2037 sleep(4);
2039 if (!cli_unlink(&cli1, fname)) {
2040 printf("unlink failed (%s)\n", cli_errstr(&cli1));
2043 close_connection(&cli1);
2045 printf("finished oplock test 2\n");
2049 Test open mode returns on read-only files.
2051 static void run_opentest(int dummy)
2053 static struct cli_state cli1;
2054 char *fname = "\\readonly.file";
2055 int fnum1, fnum2;
2056 uint8 eclass;
2057 uint32 errnum;
2059 printf("starting open test\n");
2061 if (!open_connection(&cli1)) {
2062 return;
2065 cli_setatr(&cli1, fname, 0, 0);
2066 cli_unlink(&cli1, fname);
2068 cli_sockopt(&cli1, sockops);
2070 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2071 if (fnum1 == -1) {
2072 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2073 return;
2076 if (!cli_close(&cli1, fnum1)) {
2077 printf("close2 failed (%s)\n", cli_errstr(&cli1));
2078 return;
2081 if (!cli_setatr(&cli1, fname, aRONLY, 0)) {
2082 printf("cli_setatr failed (%s)\n", cli_errstr(&cli1));
2083 return;
2086 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
2087 if (fnum1 == -1) {
2088 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2089 return;
2092 /* This will fail - but the error should be ERRnoaccess, not ERRshare. */
2093 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
2095 cli_error( &cli1, &eclass, &errnum, NULL);
2097 if (eclass != ERRDOS || errnum != ERRnoaccess) {
2098 printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
2099 (unsigned int)errnum, cli_errstr(&cli1) );
2100 } else {
2101 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2105 cli_close(&cli1, fnum1);
2107 cli_setatr(&cli1, fname, 0, 0);
2108 cli_unlink(&cli1, fname);
2110 close_connection(&cli1);
2112 printf("finished open test 1\n");
2115 static void list_fn(file_info *finfo, const char *name)
2121 test directory listing speed
2123 static void run_dirtest(int dummy)
2125 int i;
2126 static struct cli_state cli;
2127 int fnum;
2128 double t1;
2130 printf("starting directory test\n");
2132 if (!open_connection(&cli)) {
2133 return;
2136 cli_sockopt(&cli, sockops);
2138 srandom(0);
2139 for (i=0;i<numops;i++) {
2140 fstring fname;
2141 slprintf(fname, sizeof(fname), "%x", (int)random());
2142 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
2143 if (fnum == -1) {
2144 fprintf(stderr,"Failed to open %s\n", fname);
2145 return;
2147 cli_close(&cli, fnum);
2150 t1 = end_timer();
2152 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
2153 printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
2154 printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
2156 printf("dirtest core %g seconds\n", end_timer() - t1);
2158 srandom(0);
2159 for (i=0;i<numops;i++) {
2160 fstring fname;
2161 slprintf(fname, sizeof(fname), "%x", (int)random());
2162 cli_unlink(&cli, fname);
2165 close_connection(&cli);
2167 printf("finished dirtest\n");
2172 static double create_procs(void (*fn)(int))
2174 int i, status;
2175 volatile int *child_status;
2176 int synccount;
2177 int tries = 8;
2179 start_timer();
2181 synccount = 0;
2183 child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
2184 if (!child_status) {
2185 printf("Failed to setup shared memory\n");
2186 return end_timer();
2189 memset((char *)child_status, 0, sizeof(int)*nprocs);
2191 for (i=0;i<nprocs;i++) {
2192 procnum = i;
2193 if (fork() == 0) {
2194 pid_t mypid = getpid();
2195 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
2197 slprintf(myname,sizeof(myname),"CLIENT%d", i);
2199 while (1) {
2200 memset(&current_cli, 0, sizeof(current_cli));
2201 if (open_connection(&current_cli)) break;
2202 if (tries-- == 0) {
2203 printf("pid %d failed to start\n", (int)getpid());
2204 _exit(1);
2206 msleep(10);
2209 child_status[i] = getpid();
2211 while (child_status[i]) msleep(2);
2213 fn(i);
2214 _exit(0);
2218 do {
2219 synccount = 0;
2220 for (i=0;i<nprocs;i++) {
2221 if (child_status[i]) synccount++;
2223 if (synccount == nprocs) break;
2224 msleep(10);
2225 } while (end_timer() < 30);
2227 if (synccount != nprocs) {
2228 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
2229 return end_timer();
2232 /* start the client load */
2233 start_timer();
2235 for (i=0;i<nprocs;i++) {
2236 child_status[i] = 0;
2239 printf("%d clients started\n", nprocs);
2241 for (i=0;i<nprocs;i++) {
2242 waitpid(0, &status, 0);
2243 printf("*");
2245 printf("\n");
2246 return end_timer();
2250 #define FLAG_MULTIPROC 1
2252 static struct {
2253 char *name;
2254 void (*fn)(int);
2255 unsigned flags;
2256 } torture_ops[] = {
2257 {"FDPASS", run_fdpasstest, 0},
2258 {"LOCK1", run_locktest1, 0},
2259 {"LOCK2", run_locktest2, 0},
2260 {"LOCK3", run_locktest3, 0},
2261 {"LOCK4", run_locktest4, 0},
2262 {"LOCK5", run_locktest5, 0},
2263 {"UNLINK", run_unlinktest, 0},
2264 {"BROWSE", run_browsetest, 0},
2265 {"ATTR", run_attrtest, 0},
2266 {"TRANS2", run_trans2test, 0},
2267 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
2268 {"TORTURE",run_torture, FLAG_MULTIPROC},
2269 {"RANDOMIPC", run_randomipc, 0},
2270 {"NEGNOWAIT", run_negprot_nowait, 0},
2271 {"NBW95", run_nbw95, 0},
2272 {"NBWNT", run_nbwnt, 0},
2273 {"OPLOCK1", run_oplock1, 0},
2274 {"OPLOCK2", run_oplock2, 0},
2275 {"DIR", run_dirtest, 0},
2276 {"DENY1", run_denytest1, 0},
2277 {"DENY2", run_denytest2, 0},
2278 {"TCON", run_tcon_test, 0},
2279 {"RW1", run_readwritetest, 0},
2280 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
2281 {"OPEN", run_opentest, 0},
2282 {NULL, NULL, 0}};
2286 /****************************************************************************
2287 run a specified test or "ALL"
2288 ****************************************************************************/
2289 static void run_test(char *name)
2291 int i;
2292 if (strequal(name,"ALL")) {
2293 for (i=0;torture_ops[i].name;i++) {
2294 run_test(torture_ops[i].name);
2298 for (i=0;torture_ops[i].name;i++) {
2299 fstrcpy(randomfname, "\\XXXXXXX");
2300 mktemp(randomfname);
2302 if (strequal(name, torture_ops[i].name)) {
2303 start_timer();
2304 printf("Running %s\n", name);
2305 if (torture_ops[i].flags & FLAG_MULTIPROC) {
2306 create_procs(torture_ops[i].fn);
2307 } else {
2308 torture_ops[i].fn(0);
2310 printf("%s took %g secs\n\n", name, end_timer());
2316 static void usage(void)
2318 int i;
2320 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
2322 printf("\t-d debuglevel\n");
2323 printf("\t-U user%%pass\n");
2324 printf("\t-N numprocs\n");
2325 printf("\t-n my_netbios_name\n");
2326 printf("\t-W workgroup\n");
2327 printf("\t-o num_operations\n");
2328 printf("\t-O socket_options\n");
2329 printf("\t-m maximum protocol\n");
2330 printf("\t-L use oplocks\n");
2331 printf("\n\n");
2333 printf("tests are:");
2334 for (i=0;torture_ops[i].name;i++) {
2335 printf(" %s", torture_ops[i].name);
2337 printf("\n");
2339 printf("default test is ALL\n");
2341 exit(1);
2348 /****************************************************************************
2349 main program
2350 ****************************************************************************/
2351 int main(int argc,char *argv[])
2353 int opt, i;
2354 char *p;
2355 int gotpass = 0;
2356 extern char *optarg;
2357 extern int optind;
2358 extern FILE *dbf;
2359 static pstring servicesf = CONFIGFILE;
2361 dbf = stdout;
2363 setbuffer(stdout, NULL, 0);
2365 charset_initialise();
2367 lp_load(servicesf,True,False,False);
2368 load_interfaces();
2370 if (argc < 2) {
2371 usage();
2374 for(p = argv[1]; *p; p++)
2375 if(*p == '\\')
2376 *p = '/';
2378 if (strncmp(argv[1], "//", 2)) {
2379 usage();
2382 fstrcpy(host, &argv[1][2]);
2383 p = strchr(&host[2],'/');
2384 if (!p) {
2385 usage();
2387 *p = 0;
2388 fstrcpy(share, p+1);
2390 get_myname(myname);
2392 if (*username == 0 && getenv("LOGNAME")) {
2393 pstrcpy(username,getenv("LOGNAME"));
2396 argc--;
2397 argv++;
2400 fstrcpy(workgroup, lp_workgroup());
2402 while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:Ld:")) != EOF) {
2403 switch (opt) {
2404 case 'W':
2405 fstrcpy(workgroup,optarg);
2406 break;
2407 case 'm':
2408 max_protocol = interpret_protocol(optarg, max_protocol);
2409 break;
2410 case 'N':
2411 nprocs = atoi(optarg);
2412 break;
2413 case 'o':
2414 numops = atoi(optarg);
2415 break;
2416 case 'd':
2417 DEBUGLEVEL = atoi(optarg);
2418 break;
2419 case 'O':
2420 sockops = optarg;
2421 break;
2422 case 'L':
2423 use_oplocks = True;
2424 break;
2425 case 'n':
2426 fstrcpy(myname, optarg);
2427 break;
2428 case 'U':
2429 pstrcpy(username,optarg);
2430 p = strchr(username,'%');
2431 if (p) {
2432 *p = 0;
2433 pstrcpy(password, p+1);
2434 gotpass = 1;
2436 break;
2437 default:
2438 printf("Unknown option %c (%d)\n", (char)opt, opt);
2439 usage();
2444 while (!gotpass) {
2445 p = getpass("Password:");
2446 if (p) {
2447 pstrcpy(password, p);
2448 gotpass = 1;
2452 printf("host=%s share=%s user=%s myname=%s\n",
2453 host, share, username, myname);
2455 if (argc == 1) {
2456 run_test("ALL");
2457 } else {
2458 for (i=1;i<argc;i++) {
2459 run_test(argv[i]);
2463 return(0);