added a tcon test: make two tconXs with the same user/pass, open a file
[nivanova/samba-autobuild/.git] / source3 / utils / torture.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB torture tester
5    Copyright (C) Andrew Tridgell 1997-1998
6    
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.
11    
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.
16    
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.
20 */
21
22 #define NO_SYSLOG
23
24 #include "includes.h"
25
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;
31
32 static double create_procs(void (*fn)(int));
33
34
35 static struct timeval tp1,tp2;
36
37 static void start_timer(void)
38 {
39         gettimeofday(&tp1,NULL);
40 }
41
42 static double end_timer(void)
43 {
44         gettimeofday(&tp2,NULL);
45         return((tp2.tv_sec - tp1.tv_sec) + 
46                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
47 }
48
49
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
52    exit 
53
54    The memory is not zeroed 
55
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
58    */
59 static void *shm_setup(int size)
60 {
61         int shmid;
62         void *ret;
63
64         shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
65         if (shmid == -1) {
66                 printf("can't get shared memory\n");
67                 exit(1);
68         }
69         ret = (void *)shmat(shmid, 0, 0);
70         if (!ret || ret == (void *)-1) {
71                 printf("can't attach to shared memory\n");
72                 return NULL;
73         }
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 
78
79            See Stevens "advanced programming in unix env" for details
80            */
81         shmctl(shmid, IPC_RMID, 0);
82         
83         return ret;
84 }
85
86
87 static BOOL open_connection(struct cli_state *c)
88 {
89         struct nmb_name called, calling;
90         struct in_addr ip;
91         extern struct in_addr ipzero;
92
93         ZERO_STRUCTP(c);
94
95         make_nmb_name(&calling, myname, 0x0);
96         make_nmb_name(&called , host, 0x20);
97
98         ip = ipzero;
99
100         if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
101                 printf("Failed to connect with %s\n", host);
102                 return False;
103         }
104
105         c->timeout = 120000; /* set a really long timeout (2 minutes) */
106
107         if (!cli_session_request(c, &calling, &called)) {
108                 printf("%s rejected the session\n",host);
109                 cli_shutdown(c);
110                 return False;
111         }
112
113         if (!cli_negprot(c)) {
114                 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
115                 cli_shutdown(c);
116                 return False;
117         }
118
119         if (!cli_session_setup(c, username, 
120                                password, strlen(password),
121                                password, strlen(password),
122                                workgroup)) {
123                 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
124                 cli_shutdown(c);
125                 return False;
126         }
127
128         if (!cli_send_tconX(c, share, "?????",
129                             password, strlen(password)+1)) {
130                 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
131                 cli_shutdown(c);
132                 return False;
133         }
134
135         return True;
136 }
137
138
139
140 static void close_connection(struct cli_state *c)
141 {
142         if (!cli_tdis(c)) {
143                 printf("tdis failed (%s)\n", cli_errstr(c));
144         }
145
146         cli_shutdown(c);
147 }
148
149
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)
153 {
154         uint8 class;
155         uint32 num;
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);
163                 return False;
164         }
165         return True;
166 }
167
168
169 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
170 {
171         while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
172                 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
173         }
174         return True;
175 }
176
177
178 static BOOL rw_torture(struct cli_state *c)
179 {
180         char *lockfname = "\\torture.lck";
181         fstring fname;
182         int fnum;
183         int fnum2;
184         pid_t pid2, pid = getpid();
185         int i, j;
186         char buf[1024];
187
188         fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
189                          DENY_NONE);
190         if (fnum2 == -1)
191                 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
192         if (fnum2 == -1) {
193                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
194                 return False;
195         }
196
197
198         for (i=0;i<numops;i++) {
199                 unsigned n = (unsigned)sys_random()%10;
200                 if (i % 10 == 0) {
201                         printf("%d\r", i); fflush(stdout);
202                 }
203                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
204
205                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
206                         return False;
207                 }
208
209                 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
210                 if (fnum == -1) {
211                         printf("open failed (%s)\n", cli_errstr(c));
212                         break;
213                 }
214
215                 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
216                         printf("write failed (%s)\n", cli_errstr(c));
217                 }
218
219                 for (j=0;j<50;j++) {
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));
224                         }
225                 }
226
227                 pid2 = 0;
228
229                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
230                         printf("read failed (%s)\n", cli_errstr(c));
231                 }
232
233                 if (pid2 != pid) {
234                         printf("data corruption!\n");
235                 }
236
237                 if (!cli_close(c, fnum)) {
238                         printf("close failed (%s)\n", cli_errstr(c));
239                 }
240
241                 if (!cli_unlink(c, fname)) {
242                         printf("unlink failed (%s)\n", cli_errstr(c));
243                 }
244
245                 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
246                         printf("unlock failed (%s)\n", cli_errstr(c));
247                 }
248         }
249
250         cli_close(c, fnum2);
251         cli_unlink(c, lockfname);
252
253         printf("%d\n", i);
254
255         return True;
256 }
257
258 static void run_torture(int dummy)
259 {
260         struct cli_state cli;
261
262         cli = current_cli;
263
264         cli_sockopt(&cli, sockops);
265
266         rw_torture(&cli);
267         
268         close_connection(&cli);
269 }
270
271 int line_count = 0;
272
273 /* run a test that simulates an approximate netbench client load */
274 static void run_netbench(int client)
275 {
276         struct cli_state cli;
277         int i;
278         fstring fname;
279         pstring line;
280         char cname[20];
281         FILE *f;
282         char *params[20];
283
284         cli = current_cli;
285
286         cli_sockopt(&cli, sockops);
287
288         nb_setup(&cli);
289
290         slprintf(cname,sizeof(fname), "CLIENT%d", client);
291
292         f = fopen("client.txt", "r");
293
294         if (!f) {
295                 perror("client.txt");
296                 return;
297         }
298
299         while (fgets(line, sizeof(line)-1, f)) {
300                 line_count++;
301
302                 line[strlen(line)-1] = 0;
303
304                 /* printf("[%d] %s\n", line_count, line); */
305
306                 all_string_sub(line,"CLIENT1", cname, sizeof(line));
307                 
308                 for (i=0;i<20;i++) params[i] = "";
309
310                 /* parse the command parameters */
311                 params[0] = strtok(line," ");
312                 i = 0;
313                 while (params[i]) params[++i] = strtok(NULL," ");
314
315                 params[i] = "";
316
317                 if (i < 2) continue;
318
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")) {
325                                 nb_mkdir(params[3]);
326                         } else if (!strcmp(params[0],"CREATE")) {
327                                 nb_create(params[3], atoi(params[5]));
328                         } else if (!strcmp(params[0],"SMBrmdir")) {
329                                 nb_rmdir(params[3]);
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]));
348                         }
349                 } else {
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;
358                                 nb_unlink(fname);
359                         }
360                 }
361         }
362         fclose(f);
363
364         slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
365         rmdir(fname);
366         rmdir("CLIENTS");
367
368         printf("+");    
369
370         close_connection(&cli);
371 }
372
373
374 /* run a test that simulates an approximate netbench w9X client load */
375 static void run_nbw95(int dummy)
376 {
377         double t;
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
383            4MBit/sec. */
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);
386 }
387
388 /* run a test that simulates an approximate netbench wNT client load */
389 static void run_nbwnt(int dummy)
390 {
391         double t;
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);
395 }
396
397
398
399 /*
400   This test checks for two things:
401
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
405  */
406 static void run_locktest1(int dummy)
407 {
408         static struct cli_state cli1, cli2;
409         char *fname = "\\lockt1.lck";
410         int fnum1, fnum2, fnum3;
411         time_t t1, t2;
412
413         if (!open_connection(&cli1) || !open_connection(&cli2)) {
414                 return;
415         }
416         cli_sockopt(&cli1, sockops);
417         cli_sockopt(&cli2, sockops);
418
419         printf("starting locktest1\n");
420
421         cli_unlink(&cli1, fname);
422
423         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
424         if (fnum1 == -1) {
425                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
426                 return;
427         }
428         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
429         if (fnum2 == -1) {
430                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
431                 return;
432         }
433         fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
434         if (fnum3 == -1) {
435                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
436                 return;
437         }
438
439         if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
440                 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
441                 return;
442         }
443
444
445         if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
446                 printf("lock2 succeeded! This is a locking bug\n");
447                 return;
448         } else {
449                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
450         }
451
452
453         printf("Testing lock timeouts\n");
454         t1 = time(NULL);
455         if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
456                 printf("lock3 succeeded! This is a locking bug\n");
457                 return;
458         } else {
459                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
460         }
461         t2 = time(NULL);
462
463         if (t2 - t1 < 5) {
464                 printf("error: This server appears not to support timed lock requests\n");
465         }
466
467         if (!cli_close(&cli1, fnum2)) {
468                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
469                 return;
470         }
471
472         if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
473                 printf("lock4 succeeded! This is a locking bug\n");
474                 return;
475         } else {
476                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
477         }
478
479         if (!cli_close(&cli1, fnum1)) {
480                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
481                 return;
482         }
483
484         if (!cli_close(&cli2, fnum3)) {
485                 printf("close3 failed (%s)\n", cli_errstr(&cli2));
486                 return;
487         }
488
489         if (!cli_unlink(&cli1, fname)) {
490                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
491                 return;
492         }
493
494
495         close_connection(&cli1);
496         close_connection(&cli2);
497
498         printf("Passed locktest1\n");
499 }
500
501 /*
502  checks for correct tconX support
503  */
504 static void run_tcon_test(int dummy)
505 {
506         static struct cli_state cli1;
507         char *fname = "\\tcontest.tmp";
508         int fnum1;
509         uint16 cnum;
510         char buf[4];
511
512         if (!open_connection(&cli1)) {
513                 return;
514         }
515         cli_sockopt(&cli1, sockops);
516
517         printf("starting tcontest\n");
518
519         cli_unlink(&cli1, fname);
520
521         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
522         if (fnum1 == -1)
523         {
524                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
525                 return;
526         }
527
528         cnum = cli1.cnum;
529
530         if (cli_write(&cli1, fnum1, 0, buf, 130, 4) != 4)
531         {
532                 printf("write failed (%s)", cli_errstr(&cli1));
533                 return;
534         }
535
536         if (!cli_send_tconX(&cli1, share, "?????",
537                             password, strlen(password)+1)) {
538                 printf("%s refused 2nd tree connect (%s)\n", host,
539                            cli_errstr(&cli1));
540                 cli_shutdown(&cli1);
541                 return ;
542         }
543
544         if (cli_write(&cli1, fnum1, 0, buf, 130, 4) == 4)
545         {
546                 printf("write succeeded (%s)", cli_errstr(&cli1));
547                 return;
548         }
549
550         if (cli_close(&cli1, fnum1)) {
551                 printf("close2 succeeded (%s)\n", cli_errstr(&cli1));
552                 return;
553         }
554
555         if (!cli_tdis(&cli1)) {
556                 printf("tdis failed (%s)\n", cli_errstr(&cli1));
557                 return;
558         }
559
560         cli1.cnum = cnum;
561
562         if (!cli_close(&cli1, fnum1)) {
563                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
564                 return;
565         }
566
567         close_connection(&cli1);
568
569         printf("Passed tcontest\n");
570 }
571
572
573 /*
574   This test checks that 
575
576   1) the server supports multiple locking contexts on the one SMB
577   connection, distinguished by PID.  
578
579   2) the server correctly fails overlapping locks made by the same PID (this
580      goes against POSIX behaviour, which is why it is tricky to implement)
581
582   3) the server denies unlock requests by an incorrect client PID
583 */
584 static void run_locktest2(int dummy)
585 {
586         static struct cli_state cli;
587         char *fname = "\\lockt2.lck";
588         int fnum1, fnum2, fnum3;
589
590         if (!open_connection(&cli)) {
591                 return;
592         }
593
594         cli_sockopt(&cli, sockops);
595
596         printf("starting locktest2\n");
597
598         cli_unlink(&cli, fname);
599
600         cli_setpid(&cli, 1);
601
602         fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
603         if (fnum1 == -1) {
604                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
605                 return;
606         }
607
608         fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
609         if (fnum2 == -1) {
610                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
611                 return;
612         }
613
614         cli_setpid(&cli, 2);
615
616         fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
617         if (fnum3 == -1) {
618                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
619                 return;
620         }
621
622         cli_setpid(&cli, 1);
623
624         if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
625                 printf("lock1 failed (%s)\n", cli_errstr(&cli));
626                 return;
627         }
628
629         if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
630                 printf("lock2 succeeded! This is a locking bug\n");
631         } else {
632                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
633         }
634
635         cli_setpid(&cli, 2);
636
637         if (cli_unlock(&cli, fnum1, 0, 8)) {
638                 printf("unlock1 succeeded! This is a locking bug\n");
639         }
640
641         if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
642                 printf("lock3 succeeded! This is a locking bug\n");
643         } else {
644                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
645         }
646
647         cli_setpid(&cli, 1);
648
649         if (!cli_close(&cli, fnum1)) {
650                 printf("close1 failed (%s)\n", cli_errstr(&cli));
651                 return;
652         }
653
654         if (!cli_close(&cli, fnum2)) {
655                 printf("close2 failed (%s)\n", cli_errstr(&cli));
656                 return;
657         }
658
659         if (!cli_close(&cli, fnum3)) {
660                 printf("close3 failed (%s)\n", cli_errstr(&cli));
661                 return;
662         }
663
664         close_connection(&cli);
665
666         printf("locktest2 finished\n");
667 }
668
669
670 /*
671   This test checks that 
672
673   1) the server supports the full offset range in lock requests
674 */
675 static void run_locktest3(int dummy)
676 {
677         static struct cli_state cli1, cli2;
678         char *fname = "\\lockt3.lck";
679         int fnum1, fnum2, i;
680         uint32 offset;
681
682 #define NEXT_OFFSET offset += (~(uint32)0) / numops
683
684         if (!open_connection(&cli1) || !open_connection(&cli2)) {
685                 return;
686         }
687         cli_sockopt(&cli1, sockops);
688         cli_sockopt(&cli2, sockops);
689
690         printf("starting locktest3\n");
691
692         cli_unlink(&cli1, fname);
693
694         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
695         if (fnum1 == -1) {
696                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
697                 return;
698         }
699         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
700         if (fnum2 == -1) {
701                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
702                 return;
703         }
704
705         for (offset=i=0;i<numops;i++) {
706                 NEXT_OFFSET;
707                 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
708                         printf("lock1 %d failed (%s)\n", 
709                                i,
710                                cli_errstr(&cli1));
711                         return;
712                 }
713
714                 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
715                         printf("lock2 %d failed (%s)\n", 
716                                i,
717                                cli_errstr(&cli1));
718                         return;
719                 }
720         }
721
722         for (offset=i=0;i<numops;i++) {
723                 NEXT_OFFSET;
724
725                 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
726                         printf("error: lock1 %d succeeded!\n", i);
727                         return;
728                 }
729
730                 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
731                         printf("error: lock2 %d succeeded!\n", i);
732                         return;
733                 }
734
735                 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
736                         printf("error: lock3 %d succeeded!\n", i);
737                         return;
738                 }
739
740                 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
741                         printf("error: lock4 %d succeeded!\n", i);
742                         return;
743                 }
744         }
745
746         for (offset=i=0;i<numops;i++) {
747                 NEXT_OFFSET;
748
749                 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
750                         printf("unlock1 %d failed (%s)\n", 
751                                i,
752                                cli_errstr(&cli1));
753                         return;
754                 }
755
756                 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
757                         printf("unlock2 %d failed (%s)\n", 
758                                i,
759                                cli_errstr(&cli1));
760                         return;
761                 }
762         }
763
764         if (!cli_close(&cli1, fnum1)) {
765                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
766         }
767
768         if (!cli_close(&cli2, fnum2)) {
769                 printf("close2 failed (%s)\n", cli_errstr(&cli2));
770         }
771
772         if (!cli_unlink(&cli1, fname)) {
773                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
774                 return;
775         }
776
777         close_connection(&cli1);
778         close_connection(&cli2);
779
780         printf("finished locktest3\n");
781 }
782
783 #define EXPECTED(ret, v) if ((ret) != (v)) printf("** ")
784
785 /*
786   looks at overlapping locks
787 */
788 static void run_locktest4(int dummy)
789 {
790         static struct cli_state cli1, cli2;
791         char *fname = "\\lockt4.lck";
792         int fnum1, fnum2;
793         BOOL ret;
794         char buf[1000];
795
796         if (!open_connection(&cli1) || !open_connection(&cli2)) {
797                 return;
798         }
799
800         cli_sockopt(&cli1, sockops);
801         cli_sockopt(&cli2, sockops);
802
803         printf("starting locktest4\n");
804
805         cli_unlink(&cli1, fname);
806
807         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
808         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
809
810         memset(buf, 0, sizeof(buf));
811
812         if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
813                 printf("Failed to create file\n");
814                 goto fail;
815         }
816
817         ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
818               cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
819         EXPECTED(ret, False);
820         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
821             
822         ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
823               cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
824         EXPECTED(ret, True);
825         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
826
827         ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
828               cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
829         EXPECTED(ret, False);
830         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
831             
832         ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
833               cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
834         EXPECTED(ret, True);
835         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
836         
837         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
838               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
839         EXPECTED(ret, False);
840         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
841             
842         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
843               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
844         EXPECTED(ret, True);
845         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
846
847         ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
848               cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
849         EXPECTED(ret, True);
850         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
851
852         ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
853               cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
854         EXPECTED(ret, False);
855         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
856
857         ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
858               cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
859         EXPECTED(ret, False);
860         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
861
862         ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
863               cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
864         EXPECTED(ret, True);
865         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
866
867         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
868               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
869         EXPECTED(ret, False);
870         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
871
872         ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
873               cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
874               cli_unlock(&cli1, fnum1, 110, 6);
875         EXPECTED(ret, False);
876         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
877
878
879         ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
880               (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
881         EXPECTED(ret, False);
882         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
883
884         ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
885               (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
886         EXPECTED(ret, False);
887         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
888
889
890         ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
891               cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
892               cli_unlock(&cli1, fnum1, 140, 4) &&
893               cli_unlock(&cli1, fnum1, 140, 4);
894         EXPECTED(ret, True);
895         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
896
897
898         ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
899               cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
900               cli_unlock(&cli1, fnum1, 150, 4) &&
901               (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
902               !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
903               cli_unlock(&cli1, fnum1, 150, 4);
904         EXPECTED(ret, True);
905         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
906
907         ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
908               cli_unlock(&cli1, fnum1, 160, 4) &&
909               (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&         
910               (cli_read(&cli2, fnum2, buf, 160, 4) == 4);               
911         EXPECTED(ret, True);
912         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
913
914         ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
915               cli_unlock(&cli1, fnum1, 170, 4) &&
916               (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&         
917               (cli_read(&cli2, fnum2, buf, 170, 4) == 4);               
918         EXPECTED(ret, True);
919         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
920
921         ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
922               cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
923               cli_unlock(&cli1, fnum1, 190, 4) &&
924               !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&                
925               (cli_read(&cli2, fnum2, buf, 190, 4) == 4);               
926         EXPECTED(ret, True);
927         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
928
929  fail:
930         cli_close(&cli1, fnum1);
931         cli_close(&cli1, fnum2);
932         cli_unlink(&cli1, fname);
933         close_connection(&cli1);
934         close_connection(&cli2);
935
936         printf("finished locktest4\n");
937 }
938
939
940 /*
941   this produces a matrix of deny mode behaviour
942  */
943 static void run_denytest1(int dummy)
944 {
945         static struct cli_state cli1, cli2;
946         int fnum1, fnum2;
947         int f, d1, d2, o1, o2, x=0;
948         char *fnames[] = {"denytest1.exe", "denytest1.dat", NULL};
949         struct {
950                 int v;
951                 char *name; 
952         } deny_modes[] = {
953                 {DENY_DOS, "DENY_DOS"},
954                 {DENY_ALL, "DENY_ALL"},
955                 {DENY_WRITE, "DENY_WRITE"},
956                 {DENY_READ, "DENY_READ"},
957                 {DENY_NONE, "DENY_NONE"},
958                 {DENY_FCB, "DENY_FCB"},
959                 {-1, NULL}};
960         struct {
961                 int v;
962                 char *name; 
963         } open_modes[] = {
964                 {O_RDWR, "O_RDWR"},
965                 {O_RDONLY, "O_RDONLY"},
966                 {O_WRONLY, "O_WRONLY"},
967                 {-1, NULL}};
968
969         if (!open_connection(&cli1) || !open_connection(&cli2)) {
970                 return;
971         }
972         cli_sockopt(&cli1, sockops);
973         cli_sockopt(&cli2, sockops);
974
975         printf("starting denytest1\n");
976
977         for (f=0;fnames[f];f++) {
978                 cli_unlink(&cli1, fnames[f]);
979
980                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
981                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
982                 cli_close(&cli1, fnum1);
983
984                 for (d1=0;deny_modes[d1].name;d1++) 
985                 for (o1=0;open_modes[o1].name;o1++) 
986                 for (d2=0;deny_modes[d2].name;d2++) 
987                 for (o2=0;open_modes[o2].name;o2++) {
988                         fnum1 = cli_open(&cli1, fnames[f], 
989                                          open_modes[o1].v, 
990                                          deny_modes[d1].v);
991                         fnum2 = cli_open(&cli2, fnames[f], 
992                                          open_modes[o2].v, 
993                                          deny_modes[d2].v);
994
995                         printf("%s %8s %10s    %8s %10s     ",
996                                fnames[f],
997                                open_modes[o1].name,
998                                deny_modes[d1].name,
999                                open_modes[o2].name,
1000                                deny_modes[d2].name);
1001
1002                         if (fnum1 == -1) {
1003                                 printf("X");
1004                         } else if (fnum2 == -1) {
1005                                 printf("-");
1006                         } else {
1007                                 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
1008                                         printf("R");
1009                                 }
1010                                 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
1011                                         printf("W");
1012                                 }
1013                         }
1014
1015                         printf("\n");
1016                         cli_close(&cli1, fnum1);
1017                         cli_close(&cli2, fnum2);
1018                 }
1019                 
1020                 cli_unlink(&cli1, fnames[f]);
1021         }
1022
1023         close_connection(&cli1);
1024         close_connection(&cli2);
1025         
1026         printf("finshed denytest1\n");
1027 }
1028
1029
1030 /*
1031   this produces a matrix of deny mode behaviour for two opens on the
1032   same connection
1033  */
1034 static void run_denytest2(int dummy)
1035 {
1036         static struct cli_state cli1;
1037         int fnum1, fnum2;
1038         int f, d1, d2, o1, o2, x=0;
1039         char *fnames[] = {"denytest2.exe", "denytest2.dat", NULL};
1040         struct {
1041                 int v;
1042                 char *name; 
1043         } deny_modes[] = {
1044                 {DENY_DOS, "DENY_DOS"},
1045                 {DENY_ALL, "DENY_ALL"},
1046                 {DENY_WRITE, "DENY_WRITE"},
1047                 {DENY_READ, "DENY_READ"},
1048                 {DENY_NONE, "DENY_NONE"},
1049                 {DENY_FCB, "DENY_FCB"},
1050                 {-1, NULL}};
1051         struct {
1052                 int v;
1053                 char *name; 
1054         } open_modes[] = {
1055                 {O_RDWR, "O_RDWR"},
1056                 {O_RDONLY, "O_RDONLY"},
1057                 {O_WRONLY, "O_WRONLY"},
1058                 {-1, NULL}};
1059
1060         if (!open_connection(&cli1)) {
1061                 return;
1062         }
1063         cli_sockopt(&cli1, sockops);
1064
1065         printf("starting denytest2\n");
1066
1067         for (f=0;fnames[f];f++) {
1068                 cli_unlink(&cli1, fnames[f]);
1069
1070                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1071                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1072                 cli_close(&cli1, fnum1);
1073
1074                 for (d1=0;deny_modes[d1].name;d1++) 
1075                 for (o1=0;open_modes[o1].name;o1++) 
1076                 for (d2=0;deny_modes[d2].name;d2++) 
1077                 for (o2=0;open_modes[o2].name;o2++) {
1078                         fnum1 = cli_open(&cli1, fnames[f], 
1079                                          open_modes[o1].v, 
1080                                          deny_modes[d1].v);
1081                         fnum2 = cli_open(&cli1, fnames[f], 
1082                                          open_modes[o2].v, 
1083                                          deny_modes[d2].v);
1084
1085                         printf("%s %8s %10s    %8s %10s     ",
1086                                fnames[f],
1087                                open_modes[o1].name,
1088                                deny_modes[d1].name,
1089                                open_modes[o2].name,
1090                                deny_modes[d2].name);
1091
1092                         if (fnum1 == -1) {
1093                                 printf("X");
1094                         } else if (fnum2 == -1) {
1095                                 printf("-");
1096                         } else {
1097                                 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1098                                         printf("R");
1099                                 }
1100                                 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1101                                         printf("W");
1102                                 }
1103                         }
1104
1105                         printf("\n");
1106                         cli_close(&cli1, fnum1);
1107                         cli_close(&cli1, fnum2);
1108                 }
1109                 
1110                 cli_unlink(&cli1, fnames[f]);
1111         }
1112
1113         close_connection(&cli1);
1114         
1115         printf("finshed denytest2\n");
1116 }
1117
1118 /*
1119 test whether fnums and tids open on one VC are available on another (a major
1120 security hole)
1121 */
1122 static void run_fdpasstest(int dummy)
1123 {
1124         static struct cli_state cli1, cli2;
1125         char *fname = "\\fdpass.tst";
1126         int fnum1;
1127         pstring buf;
1128
1129         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1130                 return;
1131         }
1132         cli_sockopt(&cli1, sockops);
1133         cli_sockopt(&cli2, sockops);
1134
1135         printf("starting fdpasstest\n");
1136
1137         cli_unlink(&cli1, fname);
1138
1139         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1140         if (fnum1 == -1) {
1141                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1142                 return;
1143         }
1144
1145         if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1146                 printf("write failed (%s)\n", cli_errstr(&cli1));
1147                 return;
1148         }
1149
1150         cli2.vuid = cli1.vuid;
1151         cli2.cnum = cli1.cnum;
1152         cli2.pid = cli1.pid;
1153
1154
1155         if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
1156                 printf("read succeeded! nasty security hole [%s]\n",
1157                        buf);
1158                 return;
1159         }
1160
1161         cli_close(&cli1, fnum1);
1162         cli_unlink(&cli1, fname);
1163
1164         close_connection(&cli1);
1165         close_connection(&cli2);
1166
1167         printf("finished fdpasstest\n");
1168 }
1169
1170
1171 /*
1172   This test checks that 
1173
1174   1) the server does not allow an unlink on a file that is open
1175 */
1176 static void run_unlinktest(int dummy)
1177 {
1178         static struct cli_state cli;
1179         char *fname = "\\unlink.tst";
1180         int fnum;
1181
1182         if (!open_connection(&cli)) {
1183                 return;
1184         }
1185
1186         cli_sockopt(&cli, sockops);
1187
1188         printf("starting unlink test\n");
1189
1190         cli_unlink(&cli, fname);
1191
1192         cli_setpid(&cli, 1);
1193
1194         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1195         if (fnum == -1) {
1196                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1197                 return;
1198         }
1199
1200         if (cli_unlink(&cli, fname)) {
1201                 printf("error: server allowed unlink on an open file\n");
1202         }
1203
1204         cli_close(&cli, fnum);
1205         cli_unlink(&cli, fname);
1206
1207         close_connection(&cli);
1208
1209         printf("unlink test finished\n");
1210 }
1211
1212
1213 /*
1214 test how many open files this server supports on the one socket
1215 */
1216 static void run_maxfidtest(int dummy)
1217 {
1218         static struct cli_state cli;
1219         char *template = "\\maxfid.%d.%d";
1220         fstring fname;
1221         int fnum;
1222         int retries=4;
1223         int n = numops;
1224
1225         cli = current_cli;
1226
1227         if (retries <= 0) {
1228                 printf("failed to connect\n");
1229                 return;
1230         }
1231
1232         cli_sockopt(&cli, sockops);
1233
1234         fnum = 0;
1235         while (1) {
1236                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1237                 if (cli_open(&cli, fname, 
1238                              O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
1239                     -1) {
1240                         printf("open of %s failed (%s)\n", 
1241                                fname, cli_errstr(&cli));
1242                         printf("maximum fnum is %d\n", fnum);
1243                         break;
1244                 }
1245                 fnum++;
1246         }
1247
1248         printf("cleaning up\n");
1249         while (fnum > n) {
1250                 fnum--;
1251                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1252                 if (cli_unlink(&cli, fname)) {
1253                         printf("unlink of %s failed (%s)\n", 
1254                                fname, cli_errstr(&cli));
1255                 }
1256         }
1257
1258         printf("maxfid test finished\n");
1259         close_connection(&cli);
1260 }
1261
1262 /* generate a random buffer */
1263 static void rand_buf(char *buf, int len)
1264 {
1265         while (len--) {
1266                 *buf = (char)sys_random();
1267                 buf++;
1268         }
1269 }
1270
1271 /* send random IPC commands */
1272 static void run_randomipc(int dummy)
1273 {
1274         char *rparam = NULL;
1275         char *rdata = NULL;
1276         int rdrcnt,rprcnt;
1277         pstring param;
1278         int api, param_len, i;
1279         static struct cli_state cli;
1280
1281         printf("starting random ipc test\n");
1282
1283         if (!open_connection(&cli)) {
1284                 return;
1285         }
1286
1287         for (i=0;i<50000;i++) {
1288                 api = sys_random() % 500;
1289                 param_len = (sys_random() % 64);
1290
1291                 rand_buf(param, param_len);
1292   
1293                 SSVAL(param,0,api); 
1294
1295                 cli_api(&cli, 
1296                         param, param_len, 8,  
1297                         NULL, 0, BUFFER_SIZE, 
1298                         &rparam, &rprcnt,     
1299                         &rdata, &rdrcnt);
1300         }
1301
1302         close_connection(&cli);
1303
1304         printf("finished random ipc test\n");
1305 }
1306
1307
1308
1309 static void browse_callback(const char *sname, uint32 stype, 
1310                             const char *comment)
1311 {
1312         printf("\t%20.20s %08x %s\n", sname, stype, comment);
1313 }
1314
1315
1316
1317 /*
1318   This test checks the browse list code
1319
1320 */
1321 static void run_browsetest(int dummy)
1322 {
1323         static struct cli_state cli;
1324
1325         printf("starting browse test\n");
1326
1327         if (!open_connection(&cli)) {
1328                 return;
1329         }
1330
1331         printf("domain list:\n");
1332         cli_NetServerEnum(&cli, cli.server_domain, 
1333                           SV_TYPE_DOMAIN_ENUM,
1334                           browse_callback);
1335
1336         printf("machine list:\n");
1337         cli_NetServerEnum(&cli, cli.server_domain, 
1338                           SV_TYPE_ALL,
1339                           browse_callback);
1340
1341         close_connection(&cli);
1342
1343         printf("browse test finished\n");
1344 }
1345
1346
1347 /*
1348   This checks how the getatr calls works
1349 */
1350 static void run_attrtest(int dummy)
1351 {
1352         static struct cli_state cli;
1353         int fnum;
1354         time_t t, t2;
1355         char *fname = "\\attrib.tst";
1356
1357         printf("starting attrib test\n");
1358
1359         if (!open_connection(&cli)) {
1360                 return;
1361         }
1362
1363         cli_unlink(&cli, fname);
1364         fnum = cli_open(&cli, fname, 
1365                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1366         cli_close(&cli, fnum);
1367         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1368                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1369         }
1370
1371         if (abs(t - time(NULL)) > 2) {
1372                 printf("ERROR: SMBgetatr bug. time is %s",
1373                        ctime(&t));
1374                 t = time(NULL);
1375         }
1376
1377         t2 = t-60*60*24; /* 1 day ago */
1378
1379         if (!cli_setatr(&cli, fname, 0, t2)) {
1380                 printf("setatr failed (%s)\n", cli_errstr(&cli));
1381         }
1382
1383         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1384                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1385         }
1386
1387         if (t != t2) {
1388                 printf("ERROR: getatr/setatr bug. times are\n%s",
1389                        ctime(&t));
1390                 printf("%s", ctime(&t2));
1391         }
1392
1393         cli_unlink(&cli, fname);
1394
1395         close_connection(&cli);
1396
1397         printf("attrib test finished\n");
1398 }
1399
1400
1401 /*
1402   This checks a couple of trans2 calls
1403 */
1404 static void run_trans2test(int dummy)
1405 {
1406         static struct cli_state cli;
1407         int fnum;
1408         size_t size;
1409         time_t c_time, a_time, m_time, w_time, m_time2;
1410         char *fname = "\\trans2.tst";
1411         char *dname = "\\trans2";
1412         char *fname2 = "\\trans2\\trans2.tst";
1413
1414         printf("starting trans2 test\n");
1415
1416         if (!open_connection(&cli)) {
1417                 return;
1418         }
1419
1420         cli_unlink(&cli, fname);
1421         fnum = cli_open(&cli, fname, 
1422                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1423         if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1424                            NULL, NULL)) {
1425                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1426         }
1427         cli_close(&cli, fnum);
1428
1429         sleep(2);
1430
1431         cli_unlink(&cli, fname);
1432         fnum = cli_open(&cli, fname, 
1433                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1434         cli_close(&cli, fnum);
1435
1436         if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1437                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1438         } else {
1439                 if (c_time != m_time) {
1440                         printf("create time=%s", ctime(&c_time));
1441                         printf("modify time=%s", ctime(&m_time));
1442                         printf("This system appears to have sticky create times\n");
1443                 }
1444                 if (a_time % (60*60) == 0) {
1445                         printf("access time=%s", ctime(&a_time));
1446                         printf("This system appears to set a midnight access time\n");
1447                 }
1448
1449                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1450                         printf("ERROR: totally incorrect times - maybe word reversed?\n");
1451                 }
1452         }
1453
1454
1455         cli_unlink(&cli, fname);
1456         fnum = cli_open(&cli, fname, 
1457                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1458         cli_close(&cli, fnum);
1459         if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, 
1460                             &w_time, &size, NULL, NULL)) {
1461                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1462         } else {
1463                 if (w_time < 60*60*24*2) {
1464                         printf("write time=%s", ctime(&w_time));
1465                         printf("This system appears to set a initial 0 write time\n");
1466                 }
1467         }
1468
1469         cli_unlink(&cli, fname);
1470
1471
1472         /* check if the server updates the directory modification time
1473            when creating a new file */
1474         if (!cli_mkdir(&cli, dname)) {
1475                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1476         }
1477         sleep(3);
1478         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, 
1479                             &w_time, &size, NULL, NULL)) {
1480                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1481         }
1482
1483         fnum = cli_open(&cli, fname2, 
1484                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1485         cli_write(&cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
1486         cli_close(&cli, fnum);
1487         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, 
1488                             &w_time, &size, NULL, NULL)) {
1489                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1490         } else {
1491                 if (m_time2 == m_time)
1492                         printf("This system does not update directory modification times\n");
1493         }
1494         cli_unlink(&cli, fname2);
1495         cli_rmdir(&cli, dname);
1496
1497
1498         close_connection(&cli);
1499
1500         printf("trans2 test finished\n");
1501 }
1502
1503
1504 /*
1505   this is a harness for some oplock tests
1506  */
1507 static void run_oplock(int dummy)
1508 {
1509         static struct cli_state cli1;
1510         char *fname = "\\lockt1.lck";
1511         int fnum1;
1512
1513         printf("starting oplock test\n");
1514
1515         if (!open_connection(&cli1)) {
1516                 return;
1517         }
1518
1519         cli_unlink(&cli1, fname);
1520
1521         cli_sockopt(&cli1, sockops);
1522
1523         cli1.use_oplocks = True;
1524
1525         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1526         if (fnum1 == -1) {
1527                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1528                 return;
1529         }
1530
1531         cli1.use_oplocks = False;
1532
1533         cli_unlink(&cli1, fname);
1534         cli_unlink(&cli1, fname);
1535
1536         if (!cli_close(&cli1, fnum1)) {
1537                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1538                 return;
1539         }
1540
1541         if (!cli_unlink(&cli1, fname)) {
1542                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1543                 return;
1544         }
1545
1546
1547         close_connection(&cli1);
1548
1549         printf("finished oplock test\n");
1550 }
1551
1552
1553 static void list_fn(file_info *finfo, const char *name)
1554 {
1555         
1556 }
1557
1558 /*
1559   test directory listing speed
1560  */
1561 static void run_dirtest(int dummy)
1562 {
1563         int i;
1564         static struct cli_state cli;
1565         int fnum;
1566         double t1;
1567
1568         printf("starting directory test\n");
1569
1570         if (!open_connection(&cli)) {
1571                 return;
1572         }
1573
1574         cli_sockopt(&cli, sockops);
1575
1576         srandom(0);
1577         for (i=0;i<numops;i++) {
1578                 fstring fname;
1579                 slprintf(fname, sizeof(fname), "%x", (int)random());
1580                 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1581                 if (fnum == -1) {
1582                         fprintf(stderr,"Failed to open %s\n", fname);
1583                         return;
1584                 }
1585                 cli_close(&cli, fnum);
1586         }
1587
1588         t1 = end_timer();
1589
1590         printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1591         printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1592         printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1593
1594         printf("dirtest core %g seconds\n", end_timer() - t1);
1595
1596         srandom(0);
1597         for (i=0;i<numops;i++) {
1598                 fstring fname;
1599                 slprintf(fname, sizeof(fname), "%x", (int)random());
1600                 cli_unlink(&cli, fname);
1601         }
1602
1603         close_connection(&cli);
1604
1605         printf("finished dirtest\n");
1606 }
1607
1608
1609
1610 static double create_procs(void (*fn)(int))
1611 {
1612         int i, status;
1613         volatile int *child_status;
1614         int synccount;
1615         int tries = 8;
1616
1617         start_timer();
1618
1619         synccount = 0;
1620
1621         child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1622         if (!child_status) {
1623                 printf("Failed to setup shared memory\n");
1624                 return end_timer();
1625         }
1626
1627         memset((char *)child_status, 0, sizeof(int)*nprocs);
1628
1629         for (i=0;i<nprocs;i++) {
1630                 if (fork() == 0) {
1631                         pid_t mypid = getpid();
1632                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1633
1634                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
1635
1636                         while (1) {
1637                                 memset(&current_cli, 0, sizeof(current_cli));
1638                                 if (open_connection(&current_cli)) break;
1639                                 if (tries-- == 0) {
1640                                         printf("pid %d failed to start\n", (int)getpid());
1641                                         _exit(1);
1642                                 }
1643                                 msleep(10);
1644                         }
1645
1646                         child_status[i] = getpid();
1647
1648                         while (child_status[i]) msleep(2);
1649
1650                         fn(i);
1651                         _exit(0);
1652                 }
1653         }
1654
1655         do {
1656                 synccount = 0;
1657                 for (i=0;i<nprocs;i++) {
1658                         if (child_status[i]) synccount++;
1659                 }
1660                 if (synccount == nprocs) break;
1661                 msleep(10);
1662         } while (end_timer() < 30);
1663
1664         if (synccount != nprocs) {
1665                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1666                 return end_timer();
1667         }
1668
1669         /* start the client load */
1670         start_timer();
1671
1672         for (i=0;i<nprocs;i++) {
1673                 child_status[i] = 0;
1674         }
1675
1676         printf("%d clients started\n", nprocs);
1677
1678         for (i=0;i<nprocs;i++) {
1679                 waitpid(0, &status, 0);
1680                 printf("*");
1681         }
1682         printf("\n");
1683         return end_timer();
1684 }
1685
1686
1687 #define FLAG_MULTIPROC 1
1688
1689 static struct {
1690         char *name;
1691         void (*fn)(int);
1692         unsigned flags;
1693 } torture_ops[] = {
1694         {"FDPASS", run_fdpasstest, 0},
1695         {"LOCK1",  run_locktest1,  0},
1696         {"LOCK2",  run_locktest2,  0},
1697         {"LOCK3",  run_locktest3,  0},
1698         {"LOCK4",  run_locktest4,  0},
1699         {"UNLINK", run_unlinktest, 0},
1700         {"BROWSE", run_browsetest, 0},
1701         {"ATTR",   run_attrtest,   0},
1702         {"TRANS2", run_trans2test, 0},
1703         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1704         {"TORTURE",run_torture,    FLAG_MULTIPROC},
1705         {"RANDOMIPC", run_randomipc, 0},
1706         {"NBW95",  run_nbw95, 0},
1707         {"NBWNT",  run_nbwnt, 0},
1708         {"OPLOCK",  run_oplock, 0},
1709         {"DIR",  run_dirtest, 0},
1710         {"DENY1",  run_denytest1, 0},
1711         {"DENY2",  run_denytest2, 0},
1712         {"TCON",  run_tcon_test, 0},
1713         {NULL, NULL, 0}};
1714
1715
1716 /****************************************************************************
1717 run a specified test or "ALL"
1718 ****************************************************************************/
1719 static void run_test(char *name)
1720 {
1721         int i;
1722         if (strequal(name,"ALL")) {
1723                 for (i=0;torture_ops[i].name;i++) {
1724                         run_test(torture_ops[i].name);
1725                 }
1726         }
1727         
1728         for (i=0;torture_ops[i].name;i++) {
1729                 if (strequal(name, torture_ops[i].name)) {
1730                         start_timer();
1731                         printf("Running %s\n", name);
1732                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
1733                                 create_procs(torture_ops[i].fn);
1734                         } else {
1735                                 torture_ops[i].fn(0);
1736                         }
1737                         printf("%s took %g secs\n\n", name, end_timer());
1738                 }
1739         }
1740 }
1741
1742
1743 static void usage(void)
1744 {
1745         int i;
1746
1747         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1748
1749         printf("\t-U user%%pass\n");
1750         printf("\t-N numprocs\n");
1751         printf("\t-n my_netbios_name\n");
1752         printf("\t-W workgroup\n");
1753         printf("\t-o num_operations\n");
1754         printf("\t-O socket_options\n");
1755         printf("\t-m maximum protocol\n");
1756         printf("\n\n");
1757
1758         printf("tests are:");
1759         for (i=0;torture_ops[i].name;i++) {
1760                 printf(" %s", torture_ops[i].name);
1761         }
1762         printf("\n");
1763
1764         printf("default test is ALL\n");
1765         
1766         exit(1);
1767 }
1768
1769
1770
1771
1772
1773 /****************************************************************************
1774   main program
1775 ****************************************************************************/
1776  int main(int argc,char *argv[])
1777 {
1778         int opt, i;
1779         char *p;
1780         int gotpass = 0;
1781         extern char *optarg;
1782         extern int optind;
1783         extern FILE *dbf;
1784         static pstring servicesf = CONFIGFILE;
1785
1786         dbf = stdout;
1787
1788         setbuffer(stdout, NULL, 0);
1789
1790         charset_initialise();
1791
1792         lp_load(servicesf,True,False,False);
1793         load_interfaces();
1794
1795         if (argc < 2) {
1796                 usage();
1797         }
1798
1799         for(p = argv[1]; *p; p++)
1800           if(*p == '\\')
1801             *p = '/';
1802  
1803         if (strncmp(argv[1], "//", 2)) {
1804                 usage();
1805         }
1806
1807         fstrcpy(host, &argv[1][2]);
1808         p = strchr(&host[2],'/');
1809         if (!p) {
1810                 usage();
1811         }
1812         *p = 0;
1813         fstrcpy(share, p+1);
1814
1815         get_myname(myname);
1816
1817         if (*username == 0 && getenv("LOGNAME")) {
1818           pstrcpy(username,getenv("LOGNAME"));
1819         }
1820
1821         argc--;
1822         argv++;
1823
1824
1825         fstrcpy(workgroup, lp_workgroup());
1826
1827         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1828                 switch (opt) {
1829                 case 'W':
1830                         fstrcpy(workgroup,optarg);
1831                         break;
1832                 case 'm':
1833                         max_protocol = interpret_protocol(optarg, max_protocol);
1834                         break;
1835                 case 'N':
1836                         nprocs = atoi(optarg);
1837                         break;
1838                 case 'o':
1839                         numops = atoi(optarg);
1840                         break;
1841                 case 'O':
1842                         sockops = optarg;
1843                         break;
1844                 case 'n':
1845                         fstrcpy(myname, optarg);
1846                         break;
1847                 case 'U':
1848                         pstrcpy(username,optarg);
1849                         p = strchr(username,'%');
1850                         if (p) {
1851                                 *p = 0;
1852                                 pstrcpy(password, p+1);
1853                                 gotpass = 1;
1854                         }
1855                         break;
1856                 default:
1857                         printf("Unknown option %c (%d)\n", (char)opt, opt);
1858                         usage();
1859                 }
1860         }
1861
1862
1863         while (!gotpass) {
1864                 p = getpass("Password:");
1865                 if (p) {
1866                         pstrcpy(password, p);
1867                         gotpass = 1;
1868                 }
1869         }
1870
1871         printf("host=%s share=%s user=%s myname=%s\n", 
1872                host, share, username, myname);
1873
1874         if (argc == 1) {
1875                 run_test("ALL");
1876         } else {
1877                 for (i=1;i<argc;i++) {
1878                         run_test(argv[i]);
1879                 }
1880         }
1881
1882         return(0);
1883 }