2 Unix SMB/Netbios implementation.
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.
26 static fstring host, workgroup, share, password, username, myname;
27 static int max_protocol = PROTOCOL_NT1;
28 static char *sockops="TCP_NODELAY";
29 static int nprocs=1, numops=100;
30 static struct cli_state current_cli;
32 static double create_procs(void (*fn)(int));
35 static struct timeval tp1,tp2;
37 static void start_timer(void)
39 gettimeofday(&tp1,NULL);
42 static double end_timer(void)
44 gettimeofday(&tp2,NULL);
45 return((tp2.tv_sec - tp1.tv_sec) +
46 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
50 /* return a pointer to a anonymous shared memory segment of size "size"
51 which will persist across fork() but will disappear when all processes
54 The memory is not zeroed
56 This function uses system5 shared memory. It takes advantage of a property
57 that the memory is not destroyed if it is attached when the id is removed
59 static void *shm_setup(int size)
64 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
66 printf("can't get shared memory\n");
69 ret = (void *)shmat(shmid, 0, 0);
70 if (!ret || ret == (void *)-1) {
71 printf("can't attach to shared memory\n");
74 /* the following releases the ipc, but note that this process
75 and all its children will still have access to the memory, its
76 just that the shmid is no longer valid for other shm calls. This
77 means we don't leave behind lots of shm segments after we exit
79 See Stevens "advanced programming in unix env" for details
81 shmctl(shmid, IPC_RMID, 0);
87 static BOOL open_connection(struct cli_state *c)
89 struct nmb_name called, calling;
91 extern struct in_addr ipzero;
95 make_nmb_name(&calling, myname, 0x0, "");
96 make_nmb_name(&called , host, 0x20, "");
100 if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
101 printf("Failed to connect with %s\n", host);
105 c->timeout = 120000; /* set a really long timeout (2 minutes) */
107 if (!cli_session_request(c, &calling, &called)) {
108 printf("%s rejected the session\n",host);
113 if (!cli_negprot(c)) {
114 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
119 if (!cli_session_setup(c, username,
120 password, strlen(password),
121 password, strlen(password),
123 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
128 if (!cli_send_tconX(c, share, "?????",
129 password, strlen(password)+1)) {
130 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
140 static void close_connection(struct cli_state *c)
143 printf("tdis failed (%s)\n", cli_errstr(c));
150 /* check if the server produced the expected error code */
151 static BOOL check_error(struct cli_state *c,
152 uint8 eclass, uint32 ecode, uint32 nterr)
156 (void)cli_error(c, &class, &num, NULL);
157 if ((eclass != class || ecode != num) &&
158 num != (nterr&0xFFFFFF)) {
159 printf("unexpected error code class=%d code=%d\n",
160 (int)class, (int)num);
161 printf(" expected %d/%d %d\n",
162 (int)eclass, (int)ecode, (int)nterr);
169 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
171 while (!cli_lock(c, fnum, offset, len, -1)) {
172 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
178 static BOOL rw_torture(struct cli_state *c)
180 char *lockfname = "\\torture.lck";
184 pid_t pid2, pid = getpid();
188 fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
191 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
193 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
198 for (i=0;i<numops;i++) {
199 unsigned n = (unsigned)sys_random()%10;
201 printf("%d\r", i); fflush(stdout);
203 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
205 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
209 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
211 printf("open failed (%s)\n", cli_errstr(c));
215 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
216 printf("write failed (%s)\n", cli_errstr(c));
220 if (cli_write(c, fnum, 0, (char *)buf,
221 sizeof(pid)+(j*sizeof(buf)),
222 sizeof(buf)) != sizeof(buf)) {
223 printf("write failed (%s)\n", cli_errstr(c));
229 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
230 printf("read failed (%s)\n", cli_errstr(c));
234 printf("data corruption!\n");
237 if (!cli_close(c, fnum)) {
238 printf("close failed (%s)\n", cli_errstr(c));
241 if (!cli_unlink(c, fname)) {
242 printf("unlink failed (%s)\n", cli_errstr(c));
245 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) {
246 printf("unlock failed (%s)\n", cli_errstr(c));
251 cli_unlink(c, lockfname);
258 static void run_torture(int dummy)
260 struct cli_state cli;
264 cli_sockopt(&cli, sockops);
268 close_connection(&cli);
273 /* run a test that simulates an approximate netbench client load */
274 static void run_netbench(int client)
276 struct cli_state cli;
286 cli_sockopt(&cli, sockops);
290 slprintf(cname,sizeof(fname), "CLIENT%d", client);
292 f = fopen("client.txt", "r");
295 perror("client.txt");
299 while (fgets(line, sizeof(line)-1, f)) {
302 line[strlen(line)-1] = 0;
304 /* printf("[%d] %s\n", line_count, line); */
306 all_string_sub(line,"CLIENT1", cname, sizeof(line));
308 for (i=0;i<20;i++) params[i] = "";
310 /* parse the command parameters */
311 params[0] = strtok(line," ");
313 while (params[i]) params[++i] = strtok(NULL," ");
319 if (strcmp(params[1],"REQUEST") == 0) {
320 if (!strcmp(params[0],"SMBopenX")) {
321 fstrcpy(fname, params[5]);
322 } else if (!strcmp(params[0],"SMBclose")) {
323 nb_close(atoi(params[3]));
324 } else if (!strcmp(params[0],"SMBmkdir")) {
326 } else if (!strcmp(params[0],"CREATE")) {
327 nb_create(params[3], atoi(params[5]));
328 } else if (!strcmp(params[0],"SMBrmdir")) {
330 } else if (!strcmp(params[0],"SMBunlink")) {
331 fstrcpy(fname, params[3]);
332 } else if (!strcmp(params[0],"SMBmv")) {
333 nb_rename(params[3], params[5]);
334 } else if (!strcmp(params[0],"SMBgetatr")) {
335 fstrcpy(fname, params[3]);
336 } else if (!strcmp(params[0],"SMBwrite")) {
337 nb_write(atoi(params[3]),
338 atoi(params[5]), atoi(params[7]));
339 } else if (!strcmp(params[0],"SMBwritebraw")) {
340 nb_write(atoi(params[3]),
341 atoi(params[7]), atoi(params[5]));
342 } else if (!strcmp(params[0],"SMBreadbraw")) {
343 nb_read(atoi(params[3]),
344 atoi(params[7]), atoi(params[5]));
345 } else if (!strcmp(params[0],"SMBread")) {
346 nb_read(atoi(params[3]),
347 atoi(params[5]), atoi(params[7]));
350 if (!strcmp(params[0],"SMBopenX")) {
351 if (!strncmp(params[2], "ERR", 3)) continue;
352 nb_open(fname, atoi(params[3]), atoi(params[5]));
353 } else if (!strcmp(params[0],"SMBgetatr")) {
354 if (!strncmp(params[2], "ERR", 3)) continue;
355 nb_stat(fname, atoi(params[3]));
356 } else if (!strcmp(params[0],"SMBunlink")) {
357 if (!strncmp(params[2], "ERR", 3)) continue;
364 slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
370 close_connection(&cli);
374 /* run a test that simulates an approximate netbench w9X client load */
375 static void run_nbw95(int dummy)
378 t = create_procs(run_netbench);
379 /* to produce a netbench result we scale accoding to the
380 netbench measured throughput for the run that produced the
381 sniff that was used to produce client.txt. That run used 2
382 clients and ran for 660 seconds to produce a result of
384 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
385 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
388 /* run a test that simulates an approximate netbench wNT client load */
389 static void run_nbwnt(int dummy)
392 t = create_procs(run_netbench);
393 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
394 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
400 This test checks for two things:
402 1) correct support for retaining locks over a close (ie. the server
403 must not use posix semantics)
404 2) support for lock timeouts
406 static void run_locktest1(int dummy)
408 static struct cli_state cli1, cli2;
409 char *fname = "\\lockt1.lck";
410 int fnum1, fnum2, fnum3;
413 if (!open_connection(&cli1) || !open_connection(&cli2)) {
416 cli_sockopt(&cli1, sockops);
417 cli_sockopt(&cli2, sockops);
419 printf("starting locktest1\n");
421 cli_unlink(&cli1, fname);
423 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
425 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
428 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
430 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
433 fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
435 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
439 if (!cli_lock(&cli1, fnum1, 0, 4, 0)) {
440 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
445 if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
446 printf("lock2 succeeded! This is a locking bug\n");
449 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
453 printf("Testing lock timeouts\n");
455 if (cli_lock(&cli2, fnum3, 0, 4, 10*1000)) {
456 printf("lock3 succeeded! This is a locking bug\n");
459 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
464 printf("error: This server appears not to support timed lock requests\n");
467 if (!cli_close(&cli1, fnum2)) {
468 printf("close1 failed (%s)\n", cli_errstr(&cli1));
472 if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
473 printf("lock4 succeeded! This is a locking bug\n");
476 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
479 if (!cli_close(&cli1, fnum1)) {
480 printf("close2 failed (%s)\n", cli_errstr(&cli1));
484 if (!cli_close(&cli2, fnum3)) {
485 printf("close3 failed (%s)\n", cli_errstr(&cli2));
489 if (!cli_unlink(&cli1, fname)) {
490 printf("unlink failed (%s)\n", cli_errstr(&cli1));
495 close_connection(&cli1);
496 close_connection(&cli2);
498 printf("Passed locktest1\n");
503 This test checks that
505 1) the server supports multiple locking contexts on the one SMB
506 connection, distinguished by PID.
508 2) the server correctly fails overlapping locks made by the same PID (this
509 goes against POSIX behaviour, which is why it is tricky to implement)
511 3) the server denies unlock requests by an incorrect client PID
513 static void run_locktest2(int dummy)
515 static struct cli_state cli;
516 char *fname = "\\lockt2.lck";
517 int fnum1, fnum2, fnum3;
519 if (!open_connection(&cli)) {
523 cli_sockopt(&cli, sockops);
525 printf("starting locktest2\n");
527 cli_unlink(&cli, fname);
531 fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
533 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
537 fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
539 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
545 fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
547 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
553 if (!cli_lock(&cli, fnum1, 0, 4, 0)) {
554 printf("lock1 failed (%s)\n", cli_errstr(&cli));
558 if (cli_lock(&cli, fnum2, 0, 4, 0)) {
559 printf("lock2 succeeded! This is a locking bug\n");
561 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
566 if (cli_unlock(&cli, fnum1, 0, 4, 0)) {
567 printf("unlock1 succeeded! This is a locking bug\n");
570 if (cli_lock(&cli, fnum3, 0, 4, 0)) {
571 printf("lock3 succeeded! This is a locking bug\n");
573 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
578 if (!cli_close(&cli, fnum1)) {
579 printf("close1 failed (%s)\n", cli_errstr(&cli));
583 if (!cli_close(&cli, fnum2)) {
584 printf("close2 failed (%s)\n", cli_errstr(&cli));
588 if (!cli_close(&cli, fnum3)) {
589 printf("close3 failed (%s)\n", cli_errstr(&cli));
593 close_connection(&cli);
595 printf("locktest2 finished\n");
600 This test checks that
602 1) the server supports the full offset range in lock requests
604 static void run_locktest3(int dummy)
606 static struct cli_state cli1, cli2;
607 char *fname = "\\lockt3.lck";
611 #define NEXT_OFFSET offset += (~(uint32)0) / numops
613 if (!open_connection(&cli1) || !open_connection(&cli2)) {
616 cli_sockopt(&cli1, sockops);
617 cli_sockopt(&cli2, sockops);
619 printf("starting locktest3\n");
621 cli_unlink(&cli1, fname);
623 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
625 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
628 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
630 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
634 for (offset=i=0;i<numops;i++) {
636 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
637 printf("lock1 %d failed (%s)\n",
643 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
644 printf("lock2 %d failed (%s)\n",
651 for (offset=i=0;i<numops;i++) {
654 if (cli_lock(&cli1, fnum1, offset-2, 1, 0)) {
655 printf("error: lock1 %d succeeded!\n", i);
659 if (cli_lock(&cli2, fnum2, offset-1, 1, 0)) {
660 printf("error: lock2 %d succeeded!\n", i);
664 if (cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
665 printf("error: lock3 %d succeeded!\n", i);
669 if (cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
670 printf("error: lock4 %d succeeded!\n", i);
675 for (offset=i=0;i<numops;i++) {
678 if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) {
679 printf("unlock1 %d failed (%s)\n",
685 if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) {
686 printf("unlock2 %d failed (%s)\n",
693 if (!cli_close(&cli1, fnum1)) {
694 printf("close1 failed (%s)\n", cli_errstr(&cli1));
697 if (!cli_close(&cli2, fnum2)) {
698 printf("close2 failed (%s)\n", cli_errstr(&cli2));
701 if (!cli_unlink(&cli1, fname)) {
702 printf("unlink failed (%s)\n", cli_errstr(&cli1));
706 close_connection(&cli1);
707 close_connection(&cli2);
709 printf("finished locktest3\n");
714 test whether fnums and tids open on one VC are available on another (a major
717 static void run_fdpasstest(int dummy)
719 static struct cli_state cli1, cli2;
720 char *fname = "\\fdpass.tst";
724 if (!open_connection(&cli1) || !open_connection(&cli2)) {
727 cli_sockopt(&cli1, sockops);
728 cli_sockopt(&cli2, sockops);
730 printf("starting fdpasstest\n");
732 cli_unlink(&cli1, fname);
734 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
736 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
740 if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
741 printf("write failed (%s)\n", cli_errstr(&cli1));
745 cli2.vuid = cli1.vuid;
746 cli2.cnum = cli1.cnum;
750 if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
751 printf("read succeeded! nasty security hole [%s]\n",
756 cli_close(&cli1, fnum1);
757 cli_unlink(&cli1, fname);
759 close_connection(&cli1);
760 close_connection(&cli2);
762 printf("finished fdpasstest\n");
767 This test checks that
769 1) the server does not allow an unlink on a file that is open
771 static void run_unlinktest(int dummy)
773 static struct cli_state cli;
774 char *fname = "\\unlink.tst";
777 if (!open_connection(&cli)) {
781 cli_sockopt(&cli, sockops);
783 printf("starting unlink test\n");
785 cli_unlink(&cli, fname);
789 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
791 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
795 if (cli_unlink(&cli, fname)) {
796 printf("error: server allowed unlink on an open file\n");
799 cli_close(&cli, fnum);
800 cli_unlink(&cli, fname);
802 close_connection(&cli);
804 printf("unlink test finished\n");
809 test how many open files this server supports on the one socket
811 static void run_maxfidtest(int dummy)
813 static struct cli_state cli;
814 char *template = "\\maxfid.%d.%d";
823 printf("failed to connect\n");
827 cli_sockopt(&cli, sockops);
831 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
832 if (cli_open(&cli, fname,
833 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
835 printf("open of %s failed (%s)\n",
836 fname, cli_errstr(&cli));
837 printf("maximum fnum is %d\n", fnum);
843 printf("cleaning up\n");
846 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
847 if (cli_unlink(&cli, fname)) {
848 printf("unlink of %s failed (%s)\n",
849 fname, cli_errstr(&cli));
853 printf("maxfid test finished\n");
854 close_connection(&cli);
857 /* generate a random buffer */
858 static void rand_buf(char *buf, int len)
861 *buf = (char)sys_random();
866 /* send random IPC commands */
867 static void run_randomipc(int dummy)
873 int api, param_len, i;
874 static struct cli_state cli;
876 printf("starting random ipc test\n");
878 if (!open_connection(&cli)) {
882 for (i=0;i<50000;i++) {
883 api = sys_random() % 500;
884 param_len = (sys_random() % 64);
886 rand_buf(param, param_len);
892 NULL, 0, BUFFER_SIZE,
897 close_connection(&cli);
899 printf("finished random ipc test\n");
904 static void browse_callback(const char *sname, uint32 stype,
907 printf("\t%20.20s %08x %s\n", sname, stype, comment);
913 This test checks the browse list code
916 static void run_browsetest(int dummy)
918 static struct cli_state cli;
920 printf("starting browse test\n");
922 if (!open_connection(&cli)) {
926 printf("domain list:\n");
927 cli_NetServerEnum(&cli, cli.server_domain,
931 printf("machine list:\n");
932 cli_NetServerEnum(&cli, cli.server_domain,
936 close_connection(&cli);
938 printf("browse test finished\n");
943 This checks how the getatr calls works
945 static void run_attrtest(int dummy)
947 static struct cli_state cli;
950 char *fname = "\\attrib.tst";
952 printf("starting attrib test\n");
954 if (!open_connection(&cli)) {
958 cli_unlink(&cli, fname);
959 fnum = cli_open(&cli, fname,
960 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
961 cli_close(&cli, fnum);
962 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
963 printf("getatr failed (%s)\n", cli_errstr(&cli));
966 if (abs(t - time(NULL)) > 2) {
967 printf("ERROR: SMBgetatr bug. time is %s",
972 t2 = t-60*60*24; /* 1 day ago */
974 if (!cli_setatr(&cli, fname, 0, t2)) {
975 printf("setatr failed (%s)\n", cli_errstr(&cli));
978 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
979 printf("getatr failed (%s)\n", cli_errstr(&cli));
983 printf("ERROR: getatr/setatr bug. times are\n%s",
985 printf("%s", ctime(&t2));
988 cli_unlink(&cli, fname);
990 close_connection(&cli);
992 printf("attrib test finished\n");
997 This checks a couple of trans2 calls
999 static void run_trans2test(int dummy)
1001 static struct cli_state cli;
1004 time_t c_time, a_time, m_time, w_time, m_time2;
1005 char *fname = "\\trans2.tst";
1006 char *dname = "\\trans2";
1007 char *fname2 = "\\trans2\\trans2.tst";
1009 printf("starting trans2 test\n");
1011 if (!open_connection(&cli)) {
1015 cli_unlink(&cli, fname);
1016 fnum = cli_open(&cli, fname,
1017 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1018 if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1020 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1022 cli_close(&cli, fnum);
1026 cli_unlink(&cli, fname);
1027 fnum = cli_open(&cli, fname,
1028 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1029 cli_close(&cli, fnum);
1031 if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1032 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1034 if (c_time != m_time) {
1035 printf("create time=%s", ctime(&c_time));
1036 printf("modify time=%s", ctime(&m_time));
1037 printf("This system appears to have sticky create times\n");
1039 if (a_time % (60*60) == 0) {
1040 printf("access time=%s", ctime(&a_time));
1041 printf("This system appears to set a midnight access time\n");
1044 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1045 printf("ERROR: totally incorrect times - maybe word reversed?\n");
1050 cli_unlink(&cli, fname);
1051 fnum = cli_open(&cli, fname,
1052 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1053 cli_close(&cli, fnum);
1054 if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
1055 &w_time, &size, NULL, NULL)) {
1056 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1058 if (w_time < 60*60*24*2) {
1059 printf("write time=%s", ctime(&w_time));
1060 printf("This system appears to set a initial 0 write time\n");
1064 cli_unlink(&cli, fname);
1067 /* check if the server updates the directory modification time
1068 when creating a new file */
1069 if (!cli_mkdir(&cli, dname)) {
1070 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1073 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
1074 &w_time, &size, NULL, NULL)) {
1075 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1078 fnum = cli_open(&cli, fname2,
1079 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1080 cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
1081 cli_close(&cli, fnum);
1082 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
1083 &w_time, &size, NULL, NULL)) {
1084 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1086 if (m_time2 == m_time)
1087 printf("This system does not update directory modification times\n");
1089 cli_unlink(&cli, fname2);
1090 cli_rmdir(&cli, dname);
1093 close_connection(&cli);
1095 printf("trans2 test finished\n");
1100 this is a harness for some oplock tests
1102 static void run_oplock(int dummy)
1104 static struct cli_state cli1, cli2;
1105 char *fname = "\\lockt1.lck";
1106 char *fname2 = "\\lockt2.lck";
1109 printf("starting oplock test\n");
1111 if (!open_connection(&cli1)) {
1115 cli_unlink(&cli1, fname);
1117 cli_sockopt(&cli1, sockops);
1119 cli1.use_oplocks = True;
1121 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1123 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1127 cli1.use_oplocks = False;
1129 cli_unlink(&cli1, fname);
1130 cli_unlink(&cli1, fname);
1132 if (!cli_close(&cli1, fnum1)) {
1133 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1137 if (!cli_unlink(&cli1, fname)) {
1138 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1143 close_connection(&cli1);
1145 printf("finished oplock test\n");
1149 static void list_fn(file_info *finfo, const char *name)
1155 test directory listing speed
1157 static void run_dirtest(int dummy)
1160 static struct cli_state cli;
1164 printf("starting directory test\n");
1166 if (!open_connection(&cli)) {
1170 cli_sockopt(&cli, sockops);
1173 for (i=0;i<numops;i++) {
1175 slprintf(fname, sizeof(fname), "%x", random());
1176 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1178 fprintf(stderr,"Failed to open %s\n", fname);
1181 cli_close(&cli, fnum);
1186 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1187 printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1188 printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1190 printf("dirtest core %g seconds\n", end_timer() - t1);
1193 for (i=0;i<numops;i++) {
1195 slprintf(fname, sizeof(fname), "%x", random());
1196 cli_unlink(&cli, fname);
1199 close_connection(&cli);
1201 printf("finished dirtest\n");
1206 static double create_procs(void (*fn)(int))
1209 volatile int *child_status;
1217 child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1218 if (!child_status) {
1219 printf("Failed to setup shared memory\n");
1223 memset((char *)child_status, 0, sizeof(int)*nprocs);
1225 for (i=0;i<nprocs;i++) {
1227 pid_t mypid = getpid();
1228 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1230 slprintf(myname,sizeof(myname),"CLIENT%d", i);
1233 memset(¤t_cli, 0, sizeof(current_cli));
1234 if (open_connection(¤t_cli)) break;
1236 printf("pid %d failed to start\n", (int)getpid());
1242 child_status[i] = getpid();
1244 while (child_status[i]) msleep(2);
1253 for (i=0;i<nprocs;i++) {
1254 if (child_status[i]) synccount++;
1256 if (synccount == nprocs) break;
1258 } while (end_timer() < 30);
1260 if (synccount != nprocs) {
1261 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1265 /* start the client load */
1268 for (i=0;i<nprocs;i++) {
1269 child_status[i] = 0;
1272 printf("%d clients started\n", nprocs);
1274 for (i=0;i<nprocs;i++) {
1275 waitpid(0, &status, 0);
1283 #define FLAG_MULTIPROC 1
1290 {"FDPASS", run_fdpasstest, 0},
1291 {"LOCK1", run_locktest1, 0},
1292 {"LOCK2", run_locktest2, 0},
1293 {"LOCK3", run_locktest3, 0},
1294 {"UNLINK", run_unlinktest, 0},
1295 {"BROWSE", run_browsetest, 0},
1296 {"ATTR", run_attrtest, 0},
1297 {"TRANS2", run_trans2test, 0},
1298 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1299 {"TORTURE",run_torture, FLAG_MULTIPROC},
1300 {"RANDOMIPC", run_randomipc, 0},
1301 {"NBW95", run_nbw95, 0},
1302 {"NBWNT", run_nbwnt, 0},
1303 {"OPLOCK", run_oplock, 0},
1304 {"DIR", run_dirtest, 0},
1308 /****************************************************************************
1309 run a specified test or "ALL"
1310 ****************************************************************************/
1311 static void run_test(char *name)
1314 if (strequal(name,"ALL")) {
1315 for (i=0;torture_ops[i].name;i++) {
1316 run_test(torture_ops[i].name);
1320 for (i=0;torture_ops[i].name;i++) {
1321 if (strequal(name, torture_ops[i].name)) {
1323 printf("Running %s\n", name);
1324 if (torture_ops[i].flags & FLAG_MULTIPROC) {
1325 create_procs(torture_ops[i].fn);
1327 torture_ops[i].fn(0);
1329 printf("%s took %g secs\n\n", name, end_timer());
1335 static void usage(void)
1339 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1341 printf("\t-U user%%pass\n");
1342 printf("\t-N numprocs\n");
1343 printf("\t-n my_netbios_name\n");
1344 printf("\t-W workgroup\n");
1345 printf("\t-o num_operations\n");
1346 printf("\t-O socket_options\n");
1347 printf("\t-m maximum protocol\n");
1350 printf("tests are:");
1351 for (i=0;torture_ops[i].name;i++) {
1352 printf(" %s", torture_ops[i].name);
1356 printf("default test is ALL\n");
1365 /****************************************************************************
1367 ****************************************************************************/
1368 int main(int argc,char *argv[])
1373 extern char *optarg;
1376 static pstring servicesf = CONFIGFILE;
1380 setbuffer(stdout, NULL, 0);
1382 charset_initialise();
1384 lp_load(servicesf,True,False,False);
1391 for(p = argv[1]; *p; p++)
1395 if (strncmp(argv[1], "//", 2)) {
1399 fstrcpy(host, &argv[1][2]);
1400 p = strchr(&host[2],'/');
1405 fstrcpy(share, p+1);
1409 if (*username == 0 && getenv("LOGNAME")) {
1410 pstrcpy(username,getenv("LOGNAME"));
1417 fstrcpy(workgroup, lp_workgroup());
1419 while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1422 fstrcpy(workgroup,optarg);
1425 max_protocol = interpret_protocol(optarg, max_protocol);
1428 nprocs = atoi(optarg);
1431 numops = atoi(optarg);
1437 fstrcpy(myname, optarg);
1440 pstrcpy(username,optarg);
1441 p = strchr(username,'%');
1444 pstrcpy(password, p+1);
1449 printf("Unknown option %c (%d)\n", (char)opt, opt);
1456 p = getpass("Password:");
1458 pstrcpy(password, p);
1463 printf("host=%s share=%s user=%s myname=%s\n",
1464 host, share, username, myname);
1469 for (i=1;i<argc;i++) {