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 pid_t master_pid
;
31 static struct cli_state current_cli
;
33 static double create_procs(void (*fn
)(void));
36 static struct timeval tp1
,tp2
;
38 static void start_timer(void)
40 gettimeofday(&tp1
,NULL
);
43 static double end_timer(void)
45 gettimeofday(&tp2
,NULL
);
46 return((tp2
.tv_sec
- tp1
.tv_sec
) +
47 (tp2
.tv_usec
- tp1
.tv_usec
)*1.0e-6);
51 /* return a pointer to a anonymous shared memory segment of size "size"
52 which will persist across fork() but will disappear when all processes
55 The memory is not zeroed
57 This function uses system5 shared memory. It takes advantage of a property
58 that the memory is not destroyed if it is attached when the id is removed
60 static void *shm_setup(int size
)
65 shmid
= shmget(IPC_PRIVATE
, size
, SHM_R
| SHM_W
);
67 printf("can't get shared memory\n");
70 ret
= (void *)shmat(shmid
, 0, 0);
71 if (!ret
|| ret
== (void *)-1) {
72 printf("can't attach to shared memory\n");
75 /* the following releases the ipc, but note that this process
76 and all its children will still have access to the memory, its
77 just that the shmid is no longer valid for other shm calls. This
78 means we don't leave behind lots of shm segments after we exit
80 See Stevens "advanced programming in unix env" for details
82 shmctl(shmid
, IPC_RMID
, 0);
88 static BOOL
open_connection(struct cli_state
*c
)
90 struct nmb_name called
, calling
;
94 make_nmb_name(&calling
, myname
, 0x0, "");
95 make_nmb_name(&called
, host
, 0x20, "");
97 if (!cli_initialise(c
) || !cli_connect(c
, host
, NULL
)) {
98 printf("Failed to connect with %s\n", host
);
102 c
->timeout
= 120000; /* set a really long timeout (2 minutes) */
104 if (!cli_session_request(c
, &calling
, &called
)) {
105 printf("%s rejected the session\n",host
);
110 if (!cli_negprot(c
)) {
111 printf("%s rejected the negprot (%s)\n",host
, cli_errstr(c
));
116 if (!cli_session_setup(c
, username
,
117 password
, strlen(password
),
118 password
, strlen(password
),
120 printf("%s rejected the sessionsetup (%s)\n", host
, cli_errstr(c
));
125 if (!cli_send_tconX(c
, share
, "?????",
126 password
, strlen(password
)+1)) {
127 printf("%s refused tree connect (%s)\n", host
, cli_errstr(c
));
137 static void close_connection(struct cli_state
*c
)
140 printf("tdis failed (%s)\n", cli_errstr(c
));
147 /* check if the server produced the expected error code */
148 static BOOL
check_error(struct cli_state
*c
,
149 uint8 eclass
, uint32 ecode
, uint32 nterr
)
154 eno
= cli_error(c
, &class, &num
, NULL
);
155 if ((eclass
!= class || ecode
!= num
) &&
156 num
!= (nterr
&0xFFFFFF)) {
157 printf("unexpected error code class=%d code=%d\n",
158 (int)class, (int)num
);
159 printf(" expected %d/%d %d\n",
160 (int)eclass
, (int)ecode
, (int)nterr
);
167 static BOOL
wait_lock(struct cli_state
*c
, int fnum
, uint32 offset
, uint32 len
)
169 while (!cli_lock(c
, fnum
, offset
, len
, -1)) {
170 if (!check_error(c
, ERRDOS
, ERRlock
, 0)) return False
;
176 static BOOL
rw_torture(struct cli_state
*c
)
178 char *lockfname
= "\\torture.lck";
182 int pid2
, pid
= getpid();
186 fnum2
= cli_open(c
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
189 fnum2
= cli_open(c
, lockfname
, O_RDWR
, DENY_NONE
);
191 printf("open of %s failed (%s)\n", lockfname
, cli_errstr(c
));
196 for (i
=0;i
<numops
;i
++) {
197 unsigned n
= (unsigned)sys_random()%10;
199 printf("%d\r", i
); fflush(stdout
);
201 slprintf(fname
, sizeof(fstring
) - 1, "\\torture.%u", n
);
203 if (!wait_lock(c
, fnum2
, n
*sizeof(int), sizeof(int))) {
207 fnum
= cli_open(c
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_ALL
);
209 printf("open failed (%s)\n", cli_errstr(c
));
213 if (cli_write(c
, fnum
, 0, (char *)&pid
, 0, sizeof(pid
)) != sizeof(pid
)) {
214 printf("write failed (%s)\n", cli_errstr(c
));
218 if (cli_write(c
, fnum
, 0, (char *)buf
,
219 sizeof(pid
)+(j
*sizeof(buf
)),
220 sizeof(buf
)) != sizeof(buf
)) {
221 printf("write failed (%s)\n", cli_errstr(c
));
227 if (cli_read(c
, fnum
, (char *)&pid2
, 0, sizeof(pid
)) != sizeof(pid
)) {
228 printf("read failed (%s)\n", cli_errstr(c
));
232 printf("data corruption!\n");
235 if (!cli_close(c
, fnum
)) {
236 printf("close failed (%s)\n", cli_errstr(c
));
239 if (!cli_unlink(c
, fname
)) {
240 printf("unlink failed (%s)\n", cli_errstr(c
));
243 if (!cli_unlock(c
, fnum2
, n
*sizeof(int), sizeof(int), -1)) {
244 printf("unlock failed (%s)\n", cli_errstr(c
));
249 cli_unlink(c
, lockfname
);
256 static void run_torture(void)
258 struct cli_state cli
;
262 cli_sockopt(&cli
, sockops
);
266 close_connection(&cli
);
269 static int nbsize1
, nbsize2
, nbprob1
;
271 /* run a test that simulates an approximate netbench client load */
272 static void run_netbench(void)
274 struct cli_state cli
;
283 cli_sockopt(&cli
, sockops
);
285 for (i
=0;i
<numops
;i
++) {
286 slprintf(fname
, sizeof(fname
) - 1, "\\%03d%05d.doc", i
, pid
);
288 fnum
= cli_open(&cli
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_ALL
);
290 printf("open failed (%s)\n", cli_errstr(&cli
));
295 while (size
< 256*1024) {
297 if (((unsigned)random()) % 100 > nbprob1
) {
303 if (cli_smbwrite(&cli
, fnum
, buf
, size
, s
) != s
) {
304 printf("write failed (%s)\n", cli_errstr(&cli
));
309 cli_close(&cli
, fnum
);
310 printf("."); fflush(stdout
);
313 printf("+"); fflush(stdout
);
315 for (i
=0;i
<numops
;i
++) {
316 slprintf(fname
, sizeof(fname
) - 1, "\\%03d%05d.doc", i
, pid
);
317 cli_unlink(&cli
, fname
);
320 close_connection(&cli
);
324 /* run a test that simulates an approximate netbench w9X client load */
325 static void run_nbw95(void)
331 t
= create_procs(run_netbench
);
332 printf("Throughput %g MB/sec\n", nprocs
*numops
*256.0/(t
*1024));
335 /* run a test that simulates an approximate netbench wNT client load */
336 static void run_nbwnt(void)
342 t
= create_procs(run_netbench
);
343 printf("Throughput %g MB/sec\n", nprocs
*numops
*256.0/(t
*1024));
349 This test checks for two things:
351 1) correct support for retaining locks over a close (ie. the server
352 must not use posix semantics)
353 2) support for lock timeouts
355 static void run_locktest1(void)
357 static struct cli_state cli1
, cli2
;
358 char *fname
= "\\lockt1.lck";
359 int fnum1
, fnum2
, fnum3
;
362 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
365 cli_sockopt(&cli1
, sockops
);
366 cli_sockopt(&cli2
, sockops
);
368 printf("starting locktest1\n");
370 cli_unlink(&cli1
, fname
);
372 fnum1
= cli_open(&cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
);
374 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
377 fnum2
= cli_open(&cli1
, fname
, O_RDWR
, DENY_NONE
);
379 printf("open2 of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
382 fnum3
= cli_open(&cli2
, fname
, O_RDWR
, DENY_NONE
);
384 printf("open3 of %s failed (%s)\n", fname
, cli_errstr(&cli2
));
388 if (!cli_lock(&cli1
, fnum1
, 0, 4, 0)) {
389 printf("lock1 failed (%s)\n", cli_errstr(&cli1
));
394 if (cli_lock(&cli2
, fnum3
, 0, 4, 0)) {
395 printf("lock2 succeeded! This is a locking bug\n");
398 if (!check_error(&cli2
, ERRDOS
, ERRlock
, 0)) return;
402 printf("Testing lock timeouts\n");
404 if (cli_lock(&cli2
, fnum3
, 0, 4, 10*1000)) {
405 printf("lock3 succeeded! This is a locking bug\n");
408 if (!check_error(&cli2
, ERRDOS
, ERRlock
, 0)) return;
413 printf("error: This server appears not to support timed lock requests\n");
416 if (!cli_close(&cli1
, fnum2
)) {
417 printf("close1 failed (%s)\n", cli_errstr(&cli1
));
421 if (cli_lock(&cli2
, fnum3
, 0, 4, 0)) {
422 printf("lock4 succeeded! This is a locking bug\n");
425 if (!check_error(&cli2
, ERRDOS
, ERRlock
, 0)) return;
428 if (!cli_close(&cli1
, fnum1
)) {
429 printf("close2 failed (%s)\n", cli_errstr(&cli1
));
433 if (!cli_close(&cli2
, fnum3
)) {
434 printf("close3 failed (%s)\n", cli_errstr(&cli2
));
438 if (!cli_unlink(&cli1
, fname
)) {
439 printf("unlink failed (%s)\n", cli_errstr(&cli1
));
444 close_connection(&cli1
);
445 close_connection(&cli2
);
447 printf("Passed locktest1\n");
452 This test checks that
454 1) the server supports multiple locking contexts on the one SMB
455 connection, distinguished by PID.
457 2) the server correctly fails overlapping locks made by the same PID (this
458 goes against POSIX behaviour, which is why it is tricky to implement)
460 3) the server denies unlock requests by an incorrect client PID
462 static void run_locktest2(void)
464 static struct cli_state cli
;
465 char *fname
= "\\lockt2.lck";
466 int fnum1
, fnum2
, fnum3
;
468 if (!open_connection(&cli
)) {
472 cli_sockopt(&cli
, sockops
);
474 printf("starting locktest2\n");
476 cli_unlink(&cli
, fname
);
480 fnum1
= cli_open(&cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
);
482 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli
));
486 fnum2
= cli_open(&cli
, fname
, O_RDWR
, DENY_NONE
);
488 printf("open2 of %s failed (%s)\n", fname
, cli_errstr(&cli
));
494 fnum3
= cli_open(&cli
, fname
, O_RDWR
, DENY_NONE
);
496 printf("open3 of %s failed (%s)\n", fname
, cli_errstr(&cli
));
502 if (!cli_lock(&cli
, fnum1
, 0, 4, 0)) {
503 printf("lock1 failed (%s)\n", cli_errstr(&cli
));
507 if (cli_lock(&cli
, fnum2
, 0, 4, 0)) {
508 printf("lock2 succeeded! This is a locking bug\n");
510 if (!check_error(&cli
, ERRDOS
, ERRlock
, 0)) return;
515 if (cli_unlock(&cli
, fnum1
, 0, 4, 0)) {
516 printf("unlock1 succeeded! This is a locking bug\n");
519 if (cli_lock(&cli
, fnum3
, 0, 4, 0)) {
520 printf("lock3 succeeded! This is a locking bug\n");
522 if (!check_error(&cli
, ERRDOS
, ERRlock
, 0)) return;
527 if (!cli_close(&cli
, fnum1
)) {
528 printf("close1 failed (%s)\n", cli_errstr(&cli
));
532 if (!cli_close(&cli
, fnum2
)) {
533 printf("close2 failed (%s)\n", cli_errstr(&cli
));
537 if (!cli_close(&cli
, fnum3
)) {
538 printf("close3 failed (%s)\n", cli_errstr(&cli
));
542 close_connection(&cli
);
544 printf("locktest2 finished\n");
549 This test checks that
551 1) the server supports the full offset range in lock requests
553 static void run_locktest3(void)
555 static struct cli_state cli1
, cli2
;
556 char *fname
= "\\lockt3.lck";
560 #define NEXT_OFFSET offset += (~(uint32)0) / numops
562 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
565 cli_sockopt(&cli1
, sockops
);
566 cli_sockopt(&cli2
, sockops
);
568 printf("starting locktest3\n");
570 cli_unlink(&cli1
, fname
);
572 fnum1
= cli_open(&cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
);
574 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
577 fnum2
= cli_open(&cli2
, fname
, O_RDWR
, DENY_NONE
);
579 printf("open2 of %s failed (%s)\n", fname
, cli_errstr(&cli2
));
583 for (offset
=i
=0;i
<numops
;i
++) {
585 if (!cli_lock(&cli1
, fnum1
, offset
-1, 1, 0)) {
586 printf("lock1 %d failed (%s)\n",
592 if (!cli_lock(&cli2
, fnum2
, offset
-2, 1, 0)) {
593 printf("lock2 %d failed (%s)\n",
600 for (offset
=i
=0;i
<numops
;i
++) {
603 if (cli_lock(&cli1
, fnum1
, offset
-2, 1, 0)) {
604 printf("error: lock1 %d succeeded!\n", i
);
608 if (cli_lock(&cli2
, fnum2
, offset
-1, 1, 0)) {
609 printf("error: lock2 %d succeeded!\n", i
);
613 if (cli_lock(&cli1
, fnum1
, offset
-1, 1, 0)) {
614 printf("error: lock3 %d succeeded!\n", i
);
618 if (cli_lock(&cli2
, fnum2
, offset
-2, 1, 0)) {
619 printf("error: lock4 %d succeeded!\n", i
);
624 for (offset
=i
=0;i
<numops
;i
++) {
627 if (!cli_unlock(&cli1
, fnum1
, offset
-1, 1, 0)) {
628 printf("unlock1 %d failed (%s)\n",
634 if (!cli_unlock(&cli2
, fnum2
, offset
-2, 1, 0)) {
635 printf("unlock2 %d failed (%s)\n",
642 if (!cli_close(&cli1
, fnum1
)) {
643 printf("close1 failed (%s)\n", cli_errstr(&cli1
));
646 if (!cli_close(&cli2
, fnum2
)) {
647 printf("close2 failed (%s)\n", cli_errstr(&cli2
));
650 if (!cli_unlink(&cli1
, fname
)) {
651 printf("unlink failed (%s)\n", cli_errstr(&cli1
));
655 close_connection(&cli1
);
656 close_connection(&cli2
);
658 printf("finished locktest3\n");
663 test whether fnums and tids open on one VC are available on another (a major
666 static void run_fdpasstest(void)
668 static struct cli_state cli1
, cli2
;
669 char *fname
= "\\fdpass.tst";
673 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
676 cli_sockopt(&cli1
, sockops
);
677 cli_sockopt(&cli2
, sockops
);
679 printf("starting fdpasstest\n");
681 cli_unlink(&cli1
, fname
);
683 fnum1
= cli_open(&cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
);
685 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
689 if (cli_write(&cli1
, fnum1
, 0, "hello world\n", 0, 13) != 13) {
690 printf("write failed (%s)\n", cli_errstr(&cli1
));
694 cli2
.vuid
= cli1
.vuid
;
695 cli2
.cnum
= cli1
.cnum
;
699 if (cli_read(&cli2
, fnum1
, buf
, 0, 13) == 13) {
700 printf("read succeeded! nasty security hole [%s]\n",
705 cli_close(&cli1
, fnum1
);
706 cli_unlink(&cli1
, fname
);
708 close_connection(&cli1
);
709 close_connection(&cli2
);
711 printf("finished fdpasstest\n");
716 This test checks that
718 1) the server does not allow an unlink on a file that is open
720 static void run_unlinktest(void)
722 static struct cli_state cli
;
723 char *fname
= "\\unlink.tst";
726 if (!open_connection(&cli
)) {
730 cli_sockopt(&cli
, sockops
);
732 printf("starting unlink test\n");
734 cli_unlink(&cli
, fname
);
738 fnum
= cli_open(&cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
);
740 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli
));
744 if (cli_unlink(&cli
, fname
)) {
745 printf("error: server allowed unlink on an open file\n");
748 cli_close(&cli
, fnum
);
749 cli_unlink(&cli
, fname
);
751 close_connection(&cli
);
753 printf("unlink test finished\n");
758 test how many open files this server supports on the one socket
760 static void run_maxfidtest(void)
762 static struct cli_state cli
;
763 char *template = "\\maxfid.%d.%d";
772 printf("failed to connect\n");
776 cli_sockopt(&cli
, sockops
);
780 slprintf(fname
,sizeof(fname
)-1,template, fnum
,getpid());
781 if (cli_open(&cli
, fname
,
782 O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
) ==
784 printf("open of %s failed (%s)\n",
785 fname
, cli_errstr(&cli
));
786 printf("maximum fnum is %d\n", fnum
);
792 printf("cleaning up\n");
795 slprintf(fname
,sizeof(fname
)-1,template, fnum
,getpid());
796 if (cli_unlink(&cli
, fname
)) {
797 printf("unlink of %s failed (%s)\n",
798 fname
, cli_errstr(&cli
));
802 printf("maxfid test finished\n");
803 close_connection(&cli
);
806 /* generate a random buffer */
807 static void rand_buf(char *buf
, int len
)
815 /* send random IPC commands */
816 static void run_randomipc(void)
822 int api
, param_len
, i
;
823 static struct cli_state cli
;
825 printf("starting random ipc test\n");
827 if (!open_connection(&cli
)) {
831 for (i
=0;i
<50000;i
++) {
832 api
= sys_random() % 500;
833 param_len
= (sys_random() % 64);
835 rand_buf(param
, param_len
);
841 NULL
, 0, BUFFER_SIZE
,
846 close_connection(&cli
);
848 printf("finished random ipc test\n");
853 static void browse_callback(const char *sname
, uint32 stype
,
856 printf("\t%20.20s %08x %s\n", sname
, stype
, comment
);
862 This test checks the browse list code
865 static void run_browsetest(void)
867 static struct cli_state cli
;
869 printf("starting browse test\n");
871 if (!open_connection(&cli
)) {
875 printf("domain list:\n");
876 cli_NetServerEnum(&cli
, workgroup
,
880 printf("machine list:\n");
881 cli_NetServerEnum(&cli
, workgroup
,
885 close_connection(&cli
);
887 printf("browse test finished\n");
892 This checks how the getatr calls works
894 static void run_attrtest(void)
896 static struct cli_state cli
;
899 char *fname
= "\\attrib.tst";
901 printf("starting attrib test\n");
903 if (!open_connection(&cli
)) {
907 cli_unlink(&cli
, fname
);
908 fnum
= cli_open(&cli
, fname
,
909 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
);
910 cli_close(&cli
, fnum
);
911 if (!cli_getatr(&cli
, fname
, NULL
, NULL
, &t
)) {
912 printf("getatr failed (%s)\n", cli_errstr(&cli
));
915 if (abs(t
- time(NULL
)) > 2) {
916 printf("ERROR: SMBgetatr bug. time is %s",
921 t2
= t
-60*60*24; /* 1 day ago */
923 if (!cli_setatr(&cli
, fname
, 0, t2
)) {
924 printf("setatr failed (%s)\n", cli_errstr(&cli
));
927 if (!cli_getatr(&cli
, fname
, NULL
, NULL
, &t
)) {
928 printf("getatr failed (%s)\n", cli_errstr(&cli
));
932 printf("ERROR: getatr/setatr bug. times are\n%s",
934 printf("%s", ctime(&t2
));
937 cli_unlink(&cli
, fname
);
939 close_connection(&cli
);
941 printf("attrib test finished\n");
946 This checks a couple of trans2 calls
948 static void run_trans2test(void)
950 static struct cli_state cli
;
953 time_t c_time
, a_time
, m_time
, w_time
, m_time2
;
954 char *fname
= "\\trans2.tst";
955 char *dname
= "\\trans2";
956 char *fname2
= "\\trans2\\trans2.tst";
958 printf("starting trans2 test\n");
960 if (!open_connection(&cli
)) {
964 cli_unlink(&cli
, fname
);
965 fnum
= cli_open(&cli
, fname
,
966 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
);
967 if (!cli_qfileinfo(&cli
, fnum
, NULL
, &size
, &c_time
, &a_time
, &m_time
,
969 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli
));
971 cli_close(&cli
, fnum
);
975 cli_unlink(&cli
, fname
);
976 fnum
= cli_open(&cli
, fname
,
977 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
);
978 cli_close(&cli
, fnum
);
980 if (!cli_qpathinfo(&cli
, fname
, &c_time
, &a_time
, &m_time
, &size
, NULL
)) {
981 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli
));
983 if (c_time
!= m_time
) {
984 printf("create time=%s", ctime(&c_time
));
985 printf("modify time=%s", ctime(&m_time
));
986 printf("This system appears to have sticky create times\n");
988 if (a_time
% (60*60) == 0) {
989 printf("access time=%s", ctime(&a_time
));
990 printf("This system appears to set a midnight access time\n");
993 if (abs(m_time
- time(NULL
)) > 60*60*24*7) {
994 printf("ERROR: totally incorrect times - maybe word reversed?\n");
999 cli_unlink(&cli
, fname
);
1000 fnum
= cli_open(&cli
, fname
,
1001 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
);
1002 cli_close(&cli
, fnum
);
1003 if (!cli_qpathinfo2(&cli
, fname
, &c_time
, &a_time
, &m_time
,
1004 &w_time
, &size
, NULL
, NULL
)) {
1005 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli
));
1007 if (w_time
< 60*60*24*2) {
1008 printf("write time=%s", ctime(&w_time
));
1009 printf("This system appears to set a initial 0 write time\n");
1013 cli_unlink(&cli
, fname
);
1016 /* check if the server updates the directory modification time
1017 when creating a new file */
1018 if (!cli_mkdir(&cli
, dname
)) {
1019 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli
));
1022 if (!cli_qpathinfo2(&cli
, "\\trans2\\", &c_time
, &a_time
, &m_time
,
1023 &w_time
, &size
, NULL
, NULL
)) {
1024 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli
));
1027 fnum
= cli_open(&cli
, fname2
,
1028 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
);
1029 cli_write(&cli
, fnum
, 0, (char *)&fnum
, 0, sizeof(fnum
));
1030 cli_close(&cli
, fnum
);
1031 if (!cli_qpathinfo2(&cli
, "\\trans2\\", &c_time
, &a_time
, &m_time2
,
1032 &w_time
, &size
, NULL
, NULL
)) {
1033 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli
));
1035 if (m_time2
== m_time
)
1036 printf("This system does not update directory modification times\n");
1038 cli_unlink(&cli
, fname2
);
1039 cli_rmdir(&cli
, dname
);
1042 close_connection(&cli
);
1044 printf("trans2 test finished\n");
1047 static double create_procs(void (*fn
)(void))
1050 volatile int *child_status
;
1056 master_pid
= getpid();
1059 child_status
= (volatile int *)shm_setup(sizeof(int)*nprocs
);
1060 if (!child_status
) {
1061 printf("Failed to setup shared memory\n");
1065 memset(child_status
, 0, sizeof(int)*nprocs
);
1067 for (i
=0;i
<nprocs
;i
++) {
1069 int mypid
= getpid();
1070 sys_srandom(mypid
^ time(NULL
));
1073 memset(¤t_cli
, 0, sizeof(current_cli
));
1074 if (open_connection(¤t_cli
)) break;
1076 printf("pid %d failed to start\n", getpid());
1082 child_status
[i
] = getpid();
1084 while (child_status
[i
]) msleep(2);
1093 for (i
=0;i
<nprocs
;i
++) {
1094 if (child_status
[i
]) synccount
++;
1096 if (synccount
== nprocs
) break;
1098 } while (end_timer() < 30);
1100 if (synccount
!= nprocs
) {
1101 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs
, synccount
);
1105 /* start the client load */
1108 for (i
=0;i
<nprocs
;i
++) {
1109 child_status
[i
] = 0;
1112 printf("%d clients started\n", nprocs
);
1114 for (i
=0;i
<nprocs
;i
++) {
1115 waitpid(0, &status
, 0);
1123 #define FLAG_MULTIPROC 1
1130 {"FDPASS", run_fdpasstest
, 0},
1131 {"LOCK1", run_locktest1
, 0},
1132 {"LOCK2", run_locktest2
, 0},
1133 {"LOCK3", run_locktest3
, 0},
1134 {"UNLINK", run_unlinktest
, 0},
1135 {"BROWSE", run_browsetest
, 0},
1136 {"ATTR", run_attrtest
, 0},
1137 {"TRANS2", run_trans2test
, 0},
1138 {"MAXFID", run_maxfidtest
, FLAG_MULTIPROC
},
1139 {"TORTURE",run_torture
, FLAG_MULTIPROC
},
1140 {"RANDOMIPC", run_randomipc
, 0},
1141 {"NBW95", run_nbw95
, 0},
1142 {"NBWNT", run_nbwnt
, 0},
1146 /****************************************************************************
1147 run a specified test or "ALL"
1148 ****************************************************************************/
1149 static void run_test(char *name
)
1152 if (strequal(name
,"ALL")) {
1153 for (i
=0;torture_ops
[i
].name
;i
++) {
1154 run_test(torture_ops
[i
].name
);
1158 for (i
=0;torture_ops
[i
].name
;i
++) {
1159 if (strequal(name
, torture_ops
[i
].name
)) {
1161 printf("Running %s\n", name
);
1162 if (torture_ops
[i
].flags
& FLAG_MULTIPROC
) {
1163 create_procs(torture_ops
[i
].fn
);
1165 torture_ops
[i
].fn();
1167 printf("%s took %g secs\n\n", name
, end_timer());
1173 static void usage(void)
1177 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1179 printf("\t-U user%%pass\n");
1180 printf("\t-N numprocs\n");
1181 printf("\t-n my_netbios_name\n");
1182 printf("\t-W workgroup\n");
1183 printf("\t-o num_operations\n");
1184 printf("\t-O socket_options\n");
1185 printf("\t-m maximum protocol\n");
1188 printf("tests are:");
1189 for (i
=0;torture_ops
[i
].name
;i
++) {
1190 printf(" %s", torture_ops
[i
].name
);
1194 printf("default test is ALL\n");
1203 /****************************************************************************
1205 ****************************************************************************/
1206 int main(int argc
,char *argv
[])
1211 extern char *optarg
;
1217 setbuffer(stdout
, NULL
, 0);
1219 charset_initialise();
1225 for(p
= argv
[1]; *p
; p
++)
1229 if (strncmp(argv
[1], "//", 2)) {
1233 fstrcpy(host
, &argv
[1][2]);
1234 p
= strchr(&host
[2],'/');
1239 fstrcpy(share
, p
+1);
1241 get_myname(myname
,NULL
);
1243 if (*username
== 0 && getenv("LOGNAME")) {
1244 pstrcpy(username
,getenv("LOGNAME"));
1251 while ((opt
= getopt(argc
, argv
, "hW:U:n:N:O:o:m:")) != EOF
) {
1254 fstrcpy(workgroup
,optarg
);
1257 max_protocol
= interpret_protocol(optarg
, max_protocol
);
1260 nprocs
= atoi(optarg
);
1263 numops
= atoi(optarg
);
1269 fstrcpy(myname
, optarg
);
1272 pstrcpy(username
,optarg
);
1273 p
= strchr(username
,'%');
1276 pstrcpy(password
, p
+1);
1281 printf("Unknown option %c (%d)\n", (char)opt
, opt
);
1288 p
= getpass("Password:");
1290 pstrcpy(password
, p
);
1295 printf("host=%s share=%s user=%s myname=%s\n",
1296 host
, share
, username
, myname
);
1301 for (i
=1;i
<argc
;i
++) {