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.
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
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
)
70 shmid
= shmget(IPC_PRIVATE
, size
, SHM_R
| SHM_W
);
72 printf("can't get shared memory\n");
75 ret
= (void *)shmat(shmid
, 0, 0);
76 if (!ret
|| ret
== (void *)-1) {
77 printf("can't attach to shared memory\n");
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);
93 static BOOL
open_nbt_connection(struct cli_state
*c
)
95 struct nmb_name called
, calling
;
97 extern struct in_addr ipzero
;
101 make_nmb_name(&calling
, myname
, 0x0);
102 make_nmb_name(&called
, host
, 0x20);
106 if (!cli_initialise(c
) || !cli_connect(c
, host
, &ip
)) {
107 printf("Failed to connect with %s\n", host
);
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
);
124 static BOOL
open_connection(struct cli_state
*c
)
128 if (!open_nbt_connection(c
)) {
132 if (!cli_negprot(c
)) {
133 printf("%s rejected the negprot (%s)\n",host
, cli_errstr(c
));
138 if (!cli_session_setup(c
, username
,
139 password
, strlen(password
),
140 password
, strlen(password
),
142 printf("%s rejected the sessionsetup (%s)\n", host
, cli_errstr(c
));
147 if (!cli_send_tconX(c
, share
, "?????",
148 password
, strlen(password
)+1)) {
149 printf("%s refused tree connect (%s)\n", host
, cli_errstr(c
));
158 static void close_connection(struct cli_state
*c
)
161 printf("tdis failed (%s)\n", cli_errstr(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
)
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
);
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
;
196 static BOOL
rw_torture(struct cli_state
*c
)
198 char *lockfname
= "\\torture.lck";
202 pid_t pid2
, pid
= getpid();
206 fnum2
= cli_open(c
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
209 fnum2
= cli_open(c
, lockfname
, O_RDWR
, DENY_NONE
);
211 printf("open of %s failed (%s)\n", lockfname
, cli_errstr(c
));
216 for (i
=0;i
<numops
;i
++) {
217 unsigned n
= (unsigned)sys_random()%10;
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))) {
227 fnum
= cli_open(c
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_ALL
);
229 printf("open failed (%s)\n", cli_errstr(c
));
233 if (cli_write(c
, fnum
, 0, (char *)&pid
, 0, sizeof(pid
)) != sizeof(pid
)) {
234 printf("write failed (%s)\n", cli_errstr(c
));
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
));
247 if (cli_read(c
, fnum
, (char *)&pid2
, 0, sizeof(pid
)) != sizeof(pid
)) {
248 printf("read failed (%s)\n", cli_errstr(c
));
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
));
269 cli_unlink(c
, lockfname
);
276 static void run_torture(int dummy
)
278 struct cli_state cli
;
282 cli_sockopt(&cli
, sockops
);
286 close_connection(&cli
);
289 static BOOL
rw_torture3(struct cli_state
*c
, char *lockfname
)
296 unsigned countprev
= 0;
300 for (i
= 0; i
< sizeof(buf
); i
+= sizeof(uint32
))
302 SIVAL(buf
, i
, sys_random());
307 fnum
= cli_open(c
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
310 printf("first open read/write of %s failed (%s)\n",
311 lockfname
, cli_errstr(c
));
317 for (i
= 0; i
< 500 && fnum
== -1; i
++)
319 fnum
= cli_open(c
, lockfname
, O_RDONLY
,
324 printf("second open read-only of %s failed (%s)\n",
325 lockfname
, cli_errstr(c
));
331 for (count
= 0; count
< sizeof(buf
); count
+= sent
)
333 if (count
>= countprev
) {
334 printf("%d %8d\r", i
, count
);
337 countprev
+= (sizeof(buf
) / 20);
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
));
354 sent
= cli_read(c
, fnum
, buf_rd
+count
, count
,
358 printf("read failed offset:%d size:%d (%s)\n",
359 count
, sizeof(buf
)-count
,
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
);
377 if (!cli_close(c
, fnum
)) {
378 printf("close failed (%s)\n", cli_errstr(c
));
384 static BOOL
rw_torture2(struct cli_state
*c1
, struct cli_state
*c2
)
386 char *lockfname
= "\\torture.lck";
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
,
400 printf("first open read/write of %s failed (%s)\n",
401 lockfname
, cli_errstr(c1
));
404 fnum2
= cli_open(c2
, lockfname
, O_RDONLY
,
407 printf("second open read-only of %s failed (%s)\n",
408 lockfname
, cli_errstr(c2
));
409 cli_close(c1
, fnum1
);
413 for (i
=0;i
<numops
;i
++)
415 unsigned buf_size
= ((unsigned)sys_random()%(sizeof(buf
)-1))+ 1;
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
));
450 static void run_readwritetest(int dummy
)
452 static struct cli_state cli1
, cli2
;
455 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
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
;
480 cli_sockopt(&cli
, sockops
);
482 printf("run_readwritemulti: fname %s\n", randomfname
);
483 test
= rw_torture3(&cli
, randomfname
);
485 close_connection(&cli
);
490 /* run a test that simulates an approximate netbench client load */
491 static void run_netbench(int client
)
493 struct cli_state cli
;
503 cli_sockopt(&cli
, sockops
);
507 slprintf(cname
,sizeof(fname
), "CLIENT%d", client
);
509 f
= fopen("client.txt", "r");
512 perror("client.txt");
516 while (fgets(line
, sizeof(line
)-1, f
)) {
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
," ");
530 while (params
[i
]) params
[++i
] = strtok(NULL
," ");
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")) {
543 } else if (!strcmp(params
[0],"CREATE")) {
544 nb_create(params
[3], atoi(params
[5]));
545 } else if (!strcmp(params
[0],"SMBrmdir")) {
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]));
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;
581 slprintf(fname
,sizeof(fname
), "CLIENTS/CLIENT%d", client
);
587 close_connection(&cli
);
591 /* run a test that simulates an approximate netbench w9X client load */
592 static void run_nbw95(int dummy
)
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
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
)
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
;
630 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
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
);
642 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
645 fnum2
= cli_open(&cli1
, fname
, O_RDWR
, DENY_NONE
);
647 printf("open2 of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
650 fnum3
= cli_open(&cli2
, fname
, O_RDWR
, DENY_NONE
);
652 printf("open3 of %s failed (%s)\n", fname
, cli_errstr(&cli2
));
656 if (!cli_lock(&cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
)) {
657 printf("lock1 failed (%s)\n", cli_errstr(&cli1
));
662 if (cli_lock(&cli2
, fnum3
, 0, 4, 0, WRITE_LOCK
)) {
663 printf("lock2 succeeded! This is a locking bug\n");
666 if (!check_error(&cli2
, ERRDOS
, ERRlock
, 0)) return;
670 printf("Testing lock timeouts\n");
672 if (cli_lock(&cli2
, fnum3
, 0, 4, 10*1000, WRITE_LOCK
)) {
673 printf("lock3 succeeded! This is a locking bug\n");
676 if (!check_error(&cli2
, ERRDOS
, ERRlock
, 0)) return;
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
));
689 if (cli_lock(&cli2
, fnum3
, 0, 4, 0, WRITE_LOCK
)) {
690 printf("lock4 succeeded! This is a locking bug\n");
693 if (!check_error(&cli2
, ERRDOS
, ERRlock
, 0)) return;
696 if (!cli_close(&cli1
, fnum1
)) {
697 printf("close2 failed (%s)\n", cli_errstr(&cli1
));
701 if (!cli_close(&cli2
, fnum3
)) {
702 printf("close3 failed (%s)\n", cli_errstr(&cli2
));
706 if (!cli_unlink(&cli1
, fname
)) {
707 printf("unlink failed (%s)\n", cli_errstr(&cli1
));
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";
729 if (!open_connection(&cli1
)) {
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
);
741 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
747 if (cli_write(&cli1
, fnum1
, 0, buf
, 130, 4) != 4)
749 printf("write failed (%s)", cli_errstr(&cli1
));
753 if (!cli_send_tconX(&cli1
, share
, "?????",
754 password
, strlen(password
)+1)) {
755 printf("%s refused 2nd tree connect (%s)\n", host
,
761 if (cli_write(&cli1
, fnum1
, 0, buf
, 130, 4) == 4)
763 printf("write succeeded (%s)", cli_errstr(&cli1
));
767 if (cli_close(&cli1
, fnum1
)) {
768 printf("close2 succeeded (%s)\n", cli_errstr(&cli1
));
772 if (!cli_tdis(&cli1
)) {
773 printf("tdis failed (%s)\n", cli_errstr(&cli1
));
779 if (!cli_close(&cli1
, fnum1
)) {
780 printf("close2 failed (%s)\n", cli_errstr(&cli1
));
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
)) {
811 cli_sockopt(&cli
, sockops
);
813 printf("starting locktest2\n");
815 cli_unlink(&cli
, fname
);
819 fnum1
= cli_open(&cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
);
821 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli
));
825 fnum2
= cli_open(&cli
, fname
, O_RDWR
, DENY_NONE
);
827 printf("open2 of %s failed (%s)\n", fname
, cli_errstr(&cli
));
833 fnum3
= cli_open(&cli
, fname
, O_RDWR
, DENY_NONE
);
835 printf("open3 of %s failed (%s)\n", fname
, cli_errstr(&cli
));
841 if (!cli_lock(&cli
, fnum1
, 0, 4, 0, WRITE_LOCK
)) {
842 printf("lock1 failed (%s)\n", cli_errstr(&cli
));
846 if (cli_lock(&cli
, fnum1
, 0, 4, 0, WRITE_LOCK
)) {
847 printf("WRITE lock1 succeeded! This is a locking bug\n");
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");
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");
861 if (!check_error(&cli
, ERRDOS
, ERRlock
, 0)) return;
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");
873 if (!check_error(&cli
, ERRDOS
, ERRlock
, 0)) return;
878 if (!cli_close(&cli
, fnum1
)) {
879 printf("close1 failed (%s)\n", cli_errstr(&cli
));
883 if (!cli_close(&cli
, fnum2
)) {
884 printf("close2 failed (%s)\n", cli_errstr(&cli
));
888 if (!cli_close(&cli
, fnum3
)) {
889 printf("close3 failed (%s)\n", cli_errstr(&cli
));
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";
911 #define NEXT_OFFSET offset += (~(uint32)0) / numops
913 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
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
);
925 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
928 fnum2
= cli_open(&cli2
, fname
, O_RDWR
, DENY_NONE
);
930 printf("open2 of %s failed (%s)\n", fname
, cli_errstr(&cli2
));
934 for (offset
=i
=0;i
<numops
;i
++) {
936 if (!cli_lock(&cli1
, fnum1
, offset
-1, 1, 0, WRITE_LOCK
)) {
937 printf("lock1 %d failed (%s)\n",
943 if (!cli_lock(&cli2
, fnum2
, offset
-2, 1, 0, WRITE_LOCK
)) {
944 printf("lock2 %d failed (%s)\n",
951 for (offset
=i
=0;i
<numops
;i
++) {
954 if (cli_lock(&cli1
, fnum1
, offset
-2, 1, 0, WRITE_LOCK
)) {
955 printf("error: lock1 %d succeeded!\n", i
);
959 if (cli_lock(&cli2
, fnum2
, offset
-1, 1, 0, WRITE_LOCK
)) {
960 printf("error: lock2 %d succeeded!\n", i
);
964 if (cli_lock(&cli1
, fnum1
, offset
-1, 1, 0, WRITE_LOCK
)) {
965 printf("error: lock3 %d succeeded!\n", i
);
969 if (cli_lock(&cli2
, fnum2
, offset
-2, 1, 0, WRITE_LOCK
)) {
970 printf("error: lock4 %d succeeded!\n", i
);
975 for (offset
=i
=0;i
<numops
;i
++) {
978 if (!cli_unlock(&cli1
, fnum1
, offset
-1, 1)) {
979 printf("unlock1 %d failed (%s)\n",
985 if (!cli_unlock(&cli2
, fnum2
, offset
-2, 1)) {
986 printf("unlock2 %d failed (%s)\n",
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
));
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
;
1025 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
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");
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");
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
;
1194 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
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");
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
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");
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
;
1306 int f
, d1
, d2
, o1
, o2
, x
=0;
1307 char *fnames
[] = {"\\denytest1.exe", "\\denytest1.dat", NULL
};
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"},
1324 {O_RDONLY
, "O_RDONLY"},
1325 {O_WRONLY
, "O_WRONLY"},
1328 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
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
],
1350 fnum2
= cli_open(&cli2
, fnames
[f
],
1354 printf("%s %8s %10s %8s %10s ",
1356 open_modes
[o1
].name
,
1357 deny_modes
[d1
].name
,
1358 open_modes
[o2
].name
,
1359 deny_modes
[d2
].name
);
1363 } else if (fnum2
== -1) {
1366 if (cli_read(&cli2
, fnum2
, (void *)&x
, 0, 1) == 1) {
1369 if (cli_write(&cli2
, fnum2
, 0, (void *)&x
, 0, 1) == 1) {
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
1393 static void run_denytest2(int dummy
)
1395 static struct cli_state cli1
;
1397 int f
, d1
, d2
, o1
, o2
, x
=0;
1398 char *fnames
[] = {"\\denytest2.exe", "\\denytest2.dat", NULL
};
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"},
1415 {O_RDONLY
, "O_RDONLY"},
1416 {O_WRONLY
, "O_WRONLY"},
1419 if (!open_connection(&cli1
)) {
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
],
1440 fnum2
= cli_open(&cli1
, fnames
[f
],
1444 printf("%s %8s %10s %8s %10s ",
1446 open_modes
[o1
].name
,
1447 deny_modes
[d1
].name
,
1448 open_modes
[o2
].name
,
1449 deny_modes
[d2
].name
);
1453 } else if (fnum2
== -1) {
1456 if (cli_read(&cli1
, fnum2
, (void *)&x
, 0, 1) == 1) {
1459 if (cli_write(&cli1
, fnum2
, 0, (void *)&x
, 0, 1) == 1) {
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
1481 static void run_fdpasstest(int dummy
)
1483 static struct cli_state cli1
, cli2
, cli3
;
1484 char *fname
= "\\fdpass.tst";
1488 if (!open_connection(&cli1
) || !open_connection(&cli2
)) {
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
);
1500 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
1504 if (cli_write(&cli1
, fnum1
, 0, "hello world\n", 0, 13) != 13) {
1505 printf("write failed (%s)\n", cli_errstr(&cli1
));
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",
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";
1541 if (!open_connection(&cli
)) {
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
);
1555 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli
));
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";
1586 printf("failed to connect\n");
1590 cli_sockopt(&cli
, sockops
);
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
) ==
1598 printf("open of %s failed (%s)\n",
1599 fname
, cli_errstr(&cli
));
1600 printf("maximum fnum is %d\n", fnum
);
1604 if (fnum
% 100 == 0) printf("%d\r", fnum
);
1606 printf("%d\n", fnum
);
1608 printf("cleaning up\n");
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
)
1627 *buf
= (char)sys_random();
1632 /* send smb negprot commands, not reading the response */
1633 static void run_negprot_nowait(int dummy
)
1636 static struct cli_state cli
;
1638 printf("starting negprot nowait test\n");
1640 if (!open_nbt_connection(&cli
)) {
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
;
1661 int api
, param_len
, i
;
1662 static struct cli_state cli
;
1664 printf("starting random ipc test\n");
1666 if (!open_connection(&cli
)) {
1670 for (i
=0;i
<50000;i
++) {
1671 api
= sys_random() % 500;
1672 param_len
= (sys_random() % 64);
1674 rand_buf(param
, param_len
);
1679 param
, param_len
, 8,
1680 NULL
, 0, BUFFER_SIZE
,
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
)) {
1714 printf("domain list:\n");
1715 cli_NetServerEnum(&cli
, cli
.server_domain
,
1716 SV_TYPE_DOMAIN_ENUM
,
1719 printf("machine list:\n");
1720 cli_NetServerEnum(&cli
, cli
.server_domain
,
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
;
1738 char *fname
= "\\attrib.tst";
1740 printf("starting attrib test\n");
1742 if (!open_connection(&cli
)) {
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",
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
));
1771 printf("ERROR: getatr/setatr bug. times are\n%s",
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
;
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
)) {
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
,
1808 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli
));
1810 cli_close(&cli
, fnum
);
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
));
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
));
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
));
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
));
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";
1896 printf("starting oplock test 1\n");
1898 if (!open_connection(&cli1
)) {
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
);
1910 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
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
));
1924 if (!cli_unlink(&cli1
, fname
)) {
1925 printf("unlink failed (%s)\n", cli_errstr(&cli1
));
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";
1940 int saved_use_oplocks
= use_oplocks
;
1943 use_level_II_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
;
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
;
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
);
1973 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
1977 /* Don't need the globals any more. */
1978 use_level_II_oplocks
= False
;
1979 use_oplocks
= saved_use_oplocks
;
1983 fnum2
= cli_open(&cli2
, fname
, O_RDWR
, DENY_NONE
);
1985 printf("second open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
1991 if (!cli_close(&cli2
, fnum2
)) {
1992 printf("close2 failed (%s)\n", cli_errstr(&cli1
));
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);
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);
2025 cli_read(&cli1
, fnum1
, buf
, 0, 4);
2028 if (cli_write(&cli1
, fnum1
, 0, buf
, 0, 4) != 4) {
2029 printf("write on fnum1 failed (%s)\n", cli_errstr(&cli1
));
2033 if (!cli_close(&cli1
, fnum1
)) {
2034 printf("close1 failed (%s)\n", cli_errstr(&cli1
));
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";
2059 printf("starting open test\n");
2061 if (!open_connection(&cli1
)) {
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
);
2072 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
2076 if (!cli_close(&cli1
, fnum1
)) {
2077 printf("close2 failed (%s)\n", cli_errstr(&cli1
));
2081 if (!cli_setatr(&cli1
, fname
, aRONLY
, 0)) {
2082 printf("cli_setatr failed (%s)\n", cli_errstr(&cli1
));
2086 fnum1
= cli_open(&cli1
, fname
, O_RDONLY
, DENY_WRITE
);
2088 printf("open of %s failed (%s)\n", fname
, cli_errstr(&cli1
));
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
) );
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
)
2126 static struct cli_state cli
;
2130 printf("starting directory test\n");
2132 if (!open_connection(&cli
)) {
2136 cli_sockopt(&cli
, sockops
);
2139 for (i
=0;i
<numops
;i
++) {
2141 slprintf(fname
, sizeof(fname
), "%x", (int)random());
2142 fnum
= cli_open(&cli
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2144 fprintf(stderr
,"Failed to open %s\n", fname
);
2147 cli_close(&cli
, fnum
);
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
);
2159 for (i
=0;i
<numops
;i
++) {
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))
2175 volatile int *child_status
;
2183 child_status
= (volatile int *)shm_setup(sizeof(int)*nprocs
);
2184 if (!child_status
) {
2185 printf("Failed to setup shared memory\n");
2189 memset((char *)child_status
, 0, sizeof(int)*nprocs
);
2191 for (i
=0;i
<nprocs
;i
++) {
2194 pid_t mypid
= getpid();
2195 sys_srandom(((int)mypid
) ^ ((int)time(NULL
)));
2197 slprintf(myname
,sizeof(myname
),"CLIENT%d", i
);
2200 memset(¤t_cli
, 0, sizeof(current_cli
));
2201 if (open_connection(¤t_cli
)) break;
2203 printf("pid %d failed to start\n", (int)getpid());
2209 child_status
[i
] = getpid();
2211 while (child_status
[i
]) msleep(2);
2220 for (i
=0;i
<nprocs
;i
++) {
2221 if (child_status
[i
]) synccount
++;
2223 if (synccount
== nprocs
) break;
2225 } while (end_timer() < 30);
2227 if (synccount
!= nprocs
) {
2228 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs
, synccount
);
2232 /* start the client load */
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);
2250 #define FLAG_MULTIPROC 1
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},
2286 /****************************************************************************
2287 run a specified test or "ALL"
2288 ****************************************************************************/
2289 static void run_test(char *name
)
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
)) {
2304 printf("Running %s\n", name
);
2305 if (torture_ops
[i
].flags
& FLAG_MULTIPROC
) {
2306 create_procs(torture_ops
[i
].fn
);
2308 torture_ops
[i
].fn(0);
2310 printf("%s took %g secs\n\n", name
, end_timer());
2316 static void usage(void)
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");
2333 printf("tests are:");
2334 for (i
=0;torture_ops
[i
].name
;i
++) {
2335 printf(" %s", torture_ops
[i
].name
);
2339 printf("default test is ALL\n");
2348 /****************************************************************************
2350 ****************************************************************************/
2351 int main(int argc
,char *argv
[])
2356 extern char *optarg
;
2359 static pstring servicesf
= CONFIGFILE
;
2363 setbuffer(stdout
, NULL
, 0);
2365 charset_initialise();
2367 lp_load(servicesf
,True
,False
,False
);
2374 for(p
= argv
[1]; *p
; p
++)
2378 if (strncmp(argv
[1], "//", 2)) {
2382 fstrcpy(host
, &argv
[1][2]);
2383 p
= strchr(&host
[2],'/');
2388 fstrcpy(share
, p
+1);
2392 if (*username
== 0 && getenv("LOGNAME")) {
2393 pstrcpy(username
,getenv("LOGNAME"));
2400 fstrcpy(workgroup
, lp_workgroup());
2402 while ((opt
= getopt(argc
, argv
, "hW:U:n:N:O:o:m:Ld:")) != EOF
) {
2405 fstrcpy(workgroup
,optarg
);
2408 max_protocol
= interpret_protocol(optarg
, max_protocol
);
2411 nprocs
= atoi(optarg
);
2414 numops
= atoi(optarg
);
2417 DEBUGLEVEL
= atoi(optarg
);
2426 fstrcpy(myname
, optarg
);
2429 pstrcpy(username
,optarg
);
2430 p
= strchr(username
,'%');
2433 pstrcpy(password
, p
+1);
2438 printf("Unknown option %c (%d)\n", (char)opt
, opt
);
2445 p
= getpass("Password:");
2447 pstrcpy(password
, p
);
2452 printf("host=%s share=%s user=%s myname=%s\n",
2453 host
, share
, username
, myname
);
2458 for (i
=1;i
<argc
;i
++) {