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 this produces a matrix of deny mode behaviour
716 static void run_denytest(int dummy)
718 static struct cli_state cli1, cli2;
719 char *fname = "\\lockt1.lck";
721 int d1, d2, o1, o2, x=0;
726 {DENY_DOS, "DENY_DOS"},
727 {DENY_ALL, "DENY_ALL"},
728 {DENY_WRITE, "DENY_WRITE"},
729 {DENY_READ, "DENY_READ"},
730 {DENY_NONE, "DENY_NONE"},
731 {DENY_FCB, "DENY_FCB"},
738 {O_RDONLY, "O_RDONLY"},
739 {O_WRONLY, "O_WRONLY"},
742 if (!open_connection(&cli1) || !open_connection(&cli2)) {
745 cli_sockopt(&cli1, sockops);
746 cli_sockopt(&cli2, sockops);
748 printf("starting denytest\n");
750 cli_unlink(&cli1, fname);
752 fnum1 = cli_open(&cli1, fname, O_WRONLY|O_CREAT, DENY_NONE);
753 cli_write(&cli1, fnum1, 0, fname, 0, strlen(fname));
754 cli_close(&cli1, fnum1);
756 for (d1=0;deny_modes[d1].name;d1++) for (o1=0;open_modes[o1].name;o1++)
757 for (d2=0;deny_modes[d2].name;d2++) for (o2=0;open_modes[o2].name;o2++) {
759 fnum1 = cli_open(&cli1, fname, open_modes[o1].v, deny_modes[d1].v);
760 fnum2 = cli_open(&cli2, fname,
761 open_modes[o2].v | O_CREAT,
764 printf("%8s %10s %8s %10s ",
768 deny_modes[d2].name);
772 } else if (fnum2 == -1) {
775 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
778 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
784 cli_close(&cli1, fnum1);
785 cli_close(&cli2, fnum2);
788 cli_unlink(&cli1, fname);
790 close_connection(&cli1);
791 close_connection(&cli2);
793 printf("finshed denytest\n");
797 test whether fnums and tids open on one VC are available on another (a major
800 static void run_fdpasstest(int dummy)
802 static struct cli_state cli1, cli2;
803 char *fname = "\\fdpass.tst";
807 if (!open_connection(&cli1) || !open_connection(&cli2)) {
810 cli_sockopt(&cli1, sockops);
811 cli_sockopt(&cli2, sockops);
813 printf("starting fdpasstest\n");
815 cli_unlink(&cli1, fname);
817 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
819 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
823 if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
824 printf("write failed (%s)\n", cli_errstr(&cli1));
828 cli2.vuid = cli1.vuid;
829 cli2.cnum = cli1.cnum;
833 if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
834 printf("read succeeded! nasty security hole [%s]\n",
839 cli_close(&cli1, fnum1);
840 cli_unlink(&cli1, fname);
842 close_connection(&cli1);
843 close_connection(&cli2);
845 printf("finished fdpasstest\n");
850 This test checks that
852 1) the server does not allow an unlink on a file that is open
854 static void run_unlinktest(int dummy)
856 static struct cli_state cli;
857 char *fname = "\\unlink.tst";
860 if (!open_connection(&cli)) {
864 cli_sockopt(&cli, sockops);
866 printf("starting unlink test\n");
868 cli_unlink(&cli, fname);
872 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
874 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
878 if (cli_unlink(&cli, fname)) {
879 printf("error: server allowed unlink on an open file\n");
882 cli_close(&cli, fnum);
883 cli_unlink(&cli, fname);
885 close_connection(&cli);
887 printf("unlink test finished\n");
892 test how many open files this server supports on the one socket
894 static void run_maxfidtest(int dummy)
896 static struct cli_state cli;
897 char *template = "\\maxfid.%d.%d";
906 printf("failed to connect\n");
910 cli_sockopt(&cli, sockops);
914 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
915 if (cli_open(&cli, fname,
916 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
918 printf("open of %s failed (%s)\n",
919 fname, cli_errstr(&cli));
920 printf("maximum fnum is %d\n", fnum);
926 printf("cleaning up\n");
929 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
930 if (cli_unlink(&cli, fname)) {
931 printf("unlink of %s failed (%s)\n",
932 fname, cli_errstr(&cli));
936 printf("maxfid test finished\n");
937 close_connection(&cli);
940 /* generate a random buffer */
941 static void rand_buf(char *buf, int len)
944 *buf = (char)sys_random();
949 /* send random IPC commands */
950 static void run_randomipc(int dummy)
956 int api, param_len, i;
957 static struct cli_state cli;
959 printf("starting random ipc test\n");
961 if (!open_connection(&cli)) {
965 for (i=0;i<50000;i++) {
966 api = sys_random() % 500;
967 param_len = (sys_random() % 64);
969 rand_buf(param, param_len);
975 NULL, 0, BUFFER_SIZE,
980 close_connection(&cli);
982 printf("finished random ipc test\n");
987 static void browse_callback(const char *sname, uint32 stype,
990 printf("\t%20.20s %08x %s\n", sname, stype, comment);
996 This test checks the browse list code
999 static void run_browsetest(int dummy)
1001 static struct cli_state cli;
1003 printf("starting browse test\n");
1005 if (!open_connection(&cli)) {
1009 printf("domain list:\n");
1010 cli_NetServerEnum(&cli, cli.server_domain,
1011 SV_TYPE_DOMAIN_ENUM,
1014 printf("machine list:\n");
1015 cli_NetServerEnum(&cli, cli.server_domain,
1019 close_connection(&cli);
1021 printf("browse test finished\n");
1026 This checks how the getatr calls works
1028 static void run_attrtest(int dummy)
1030 static struct cli_state cli;
1033 char *fname = "\\attrib.tst";
1035 printf("starting attrib test\n");
1037 if (!open_connection(&cli)) {
1041 cli_unlink(&cli, fname);
1042 fnum = cli_open(&cli, fname,
1043 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1044 cli_close(&cli, fnum);
1045 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1046 printf("getatr failed (%s)\n", cli_errstr(&cli));
1049 if (abs(t - time(NULL)) > 2) {
1050 printf("ERROR: SMBgetatr bug. time is %s",
1055 t2 = t-60*60*24; /* 1 day ago */
1057 if (!cli_setatr(&cli, fname, 0, t2)) {
1058 printf("setatr failed (%s)\n", cli_errstr(&cli));
1061 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1062 printf("getatr failed (%s)\n", cli_errstr(&cli));
1066 printf("ERROR: getatr/setatr bug. times are\n%s",
1068 printf("%s", ctime(&t2));
1071 cli_unlink(&cli, fname);
1073 close_connection(&cli);
1075 printf("attrib test finished\n");
1080 This checks a couple of trans2 calls
1082 static void run_trans2test(int dummy)
1084 static struct cli_state cli;
1087 time_t c_time, a_time, m_time, w_time, m_time2;
1088 char *fname = "\\trans2.tst";
1089 char *dname = "\\trans2";
1090 char *fname2 = "\\trans2\\trans2.tst";
1092 printf("starting trans2 test\n");
1094 if (!open_connection(&cli)) {
1098 cli_unlink(&cli, fname);
1099 fnum = cli_open(&cli, fname,
1100 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1101 if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1103 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1105 cli_close(&cli, fnum);
1109 cli_unlink(&cli, fname);
1110 fnum = cli_open(&cli, fname,
1111 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1112 cli_close(&cli, fnum);
1114 if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1115 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1117 if (c_time != m_time) {
1118 printf("create time=%s", ctime(&c_time));
1119 printf("modify time=%s", ctime(&m_time));
1120 printf("This system appears to have sticky create times\n");
1122 if (a_time % (60*60) == 0) {
1123 printf("access time=%s", ctime(&a_time));
1124 printf("This system appears to set a midnight access time\n");
1127 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1128 printf("ERROR: totally incorrect times - maybe word reversed?\n");
1133 cli_unlink(&cli, fname);
1134 fnum = cli_open(&cli, fname,
1135 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1136 cli_close(&cli, fnum);
1137 if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
1138 &w_time, &size, NULL, NULL)) {
1139 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1141 if (w_time < 60*60*24*2) {
1142 printf("write time=%s", ctime(&w_time));
1143 printf("This system appears to set a initial 0 write time\n");
1147 cli_unlink(&cli, fname);
1150 /* check if the server updates the directory modification time
1151 when creating a new file */
1152 if (!cli_mkdir(&cli, dname)) {
1153 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1156 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
1157 &w_time, &size, NULL, NULL)) {
1158 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1161 fnum = cli_open(&cli, fname2,
1162 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1163 cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
1164 cli_close(&cli, fnum);
1165 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
1166 &w_time, &size, NULL, NULL)) {
1167 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1169 if (m_time2 == m_time)
1170 printf("This system does not update directory modification times\n");
1172 cli_unlink(&cli, fname2);
1173 cli_rmdir(&cli, dname);
1176 close_connection(&cli);
1178 printf("trans2 test finished\n");
1183 this is a harness for some oplock tests
1185 static void run_oplock(int dummy)
1187 static struct cli_state cli1, cli2;
1188 char *fname = "\\lockt1.lck";
1189 char *fname2 = "\\lockt2.lck";
1192 printf("starting oplock test\n");
1194 if (!open_connection(&cli1)) {
1198 cli_unlink(&cli1, fname);
1200 cli_sockopt(&cli1, sockops);
1202 cli1.use_oplocks = True;
1204 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1206 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1210 cli1.use_oplocks = False;
1212 cli_unlink(&cli1, fname);
1213 cli_unlink(&cli1, fname);
1215 if (!cli_close(&cli1, fnum1)) {
1216 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1220 if (!cli_unlink(&cli1, fname)) {
1221 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1226 close_connection(&cli1);
1228 printf("finished oplock test\n");
1232 static void list_fn(file_info *finfo, const char *name)
1238 test directory listing speed
1240 static void run_dirtest(int dummy)
1243 static struct cli_state cli;
1247 printf("starting directory test\n");
1249 if (!open_connection(&cli)) {
1253 cli_sockopt(&cli, sockops);
1256 for (i=0;i<numops;i++) {
1258 slprintf(fname, sizeof(fname), "%x", random());
1259 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1261 fprintf(stderr,"Failed to open %s\n", fname);
1264 cli_close(&cli, fnum);
1269 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1270 printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1271 printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1273 printf("dirtest core %g seconds\n", end_timer() - t1);
1276 for (i=0;i<numops;i++) {
1278 slprintf(fname, sizeof(fname), "%x", random());
1279 cli_unlink(&cli, fname);
1282 close_connection(&cli);
1284 printf("finished dirtest\n");
1289 static double create_procs(void (*fn)(int))
1292 volatile int *child_status;
1300 child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1301 if (!child_status) {
1302 printf("Failed to setup shared memory\n");
1306 memset((char *)child_status, 0, sizeof(int)*nprocs);
1308 for (i=0;i<nprocs;i++) {
1310 pid_t mypid = getpid();
1311 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1313 slprintf(myname,sizeof(myname),"CLIENT%d", i);
1316 memset(¤t_cli, 0, sizeof(current_cli));
1317 if (open_connection(¤t_cli)) break;
1319 printf("pid %d failed to start\n", (int)getpid());
1325 child_status[i] = getpid();
1327 while (child_status[i]) msleep(2);
1336 for (i=0;i<nprocs;i++) {
1337 if (child_status[i]) synccount++;
1339 if (synccount == nprocs) break;
1341 } while (end_timer() < 30);
1343 if (synccount != nprocs) {
1344 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1348 /* start the client load */
1351 for (i=0;i<nprocs;i++) {
1352 child_status[i] = 0;
1355 printf("%d clients started\n", nprocs);
1357 for (i=0;i<nprocs;i++) {
1358 waitpid(0, &status, 0);
1366 #define FLAG_MULTIPROC 1
1373 {"FDPASS", run_fdpasstest, 0},
1374 {"LOCK1", run_locktest1, 0},
1375 {"LOCK2", run_locktest2, 0},
1376 {"LOCK3", run_locktest3, 0},
1377 {"UNLINK", run_unlinktest, 0},
1378 {"BROWSE", run_browsetest, 0},
1379 {"ATTR", run_attrtest, 0},
1380 {"TRANS2", run_trans2test, 0},
1381 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1382 {"TORTURE",run_torture, FLAG_MULTIPROC},
1383 {"RANDOMIPC", run_randomipc, 0},
1384 {"NBW95", run_nbw95, 0},
1385 {"NBWNT", run_nbwnt, 0},
1386 {"OPLOCK", run_oplock, 0},
1387 {"DIR", run_dirtest, 0},
1388 {"DENY", run_denytest, 0},
1392 /****************************************************************************
1393 run a specified test or "ALL"
1394 ****************************************************************************/
1395 static void run_test(char *name)
1398 if (strequal(name,"ALL")) {
1399 for (i=0;torture_ops[i].name;i++) {
1400 run_test(torture_ops[i].name);
1404 for (i=0;torture_ops[i].name;i++) {
1405 if (strequal(name, torture_ops[i].name)) {
1407 printf("Running %s\n", name);
1408 if (torture_ops[i].flags & FLAG_MULTIPROC) {
1409 create_procs(torture_ops[i].fn);
1411 torture_ops[i].fn(0);
1413 printf("%s took %g secs\n\n", name, end_timer());
1419 static void usage(void)
1423 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1425 printf("\t-U user%%pass\n");
1426 printf("\t-N numprocs\n");
1427 printf("\t-n my_netbios_name\n");
1428 printf("\t-W workgroup\n");
1429 printf("\t-o num_operations\n");
1430 printf("\t-O socket_options\n");
1431 printf("\t-m maximum protocol\n");
1434 printf("tests are:");
1435 for (i=0;torture_ops[i].name;i++) {
1436 printf(" %s", torture_ops[i].name);
1440 printf("default test is ALL\n");
1449 /****************************************************************************
1451 ****************************************************************************/
1452 int main(int argc,char *argv[])
1457 extern char *optarg;
1460 static pstring servicesf = CONFIGFILE;
1464 setbuffer(stdout, NULL, 0);
1466 charset_initialise();
1468 lp_load(servicesf,True,False,False);
1475 for(p = argv[1]; *p; p++)
1479 if (strncmp(argv[1], "//", 2)) {
1483 fstrcpy(host, &argv[1][2]);
1484 p = strchr(&host[2],'/');
1489 fstrcpy(share, p+1);
1493 if (*username == 0 && getenv("LOGNAME")) {
1494 pstrcpy(username,getenv("LOGNAME"));
1501 fstrcpy(workgroup, lp_workgroup());
1503 while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1506 fstrcpy(workgroup,optarg);
1509 max_protocol = interpret_protocol(optarg, max_protocol);
1512 nprocs = atoi(optarg);
1515 numops = atoi(optarg);
1521 fstrcpy(myname, optarg);
1524 pstrcpy(username,optarg);
1525 p = strchr(username,'%');
1528 pstrcpy(password, p+1);
1533 printf("Unknown option %c (%d)\n", (char)opt, opt);
1540 p = getpass("Password:");
1542 pstrcpy(password, p);
1547 printf("host=%s share=%s user=%s myname=%s\n",
1548 host, share, username, myname);
1553 for (i=1;i<argc;i++) {