renamed DENY to DENY1
[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 /*
503   This test checks that 
504
505   1) the server supports multiple locking contexts on the one SMB
506   connection, distinguished by PID.  
507
508   2) the server correctly fails overlapping locks made by the same PID (this
509      goes against POSIX behaviour, which is why it is tricky to implement)
510
511   3) the server denies unlock requests by an incorrect client PID
512 */
513 static void run_locktest2(int dummy)
514 {
515         static struct cli_state cli;
516         char *fname = "\\lockt2.lck";
517         int fnum1, fnum2, fnum3;
518
519         if (!open_connection(&cli)) {
520                 return;
521         }
522
523         cli_sockopt(&cli, sockops);
524
525         printf("starting locktest2\n");
526
527         cli_unlink(&cli, fname);
528
529         cli_setpid(&cli, 1);
530
531         fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
532         if (fnum1 == -1) {
533                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
534                 return;
535         }
536
537         fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
538         if (fnum2 == -1) {
539                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
540                 return;
541         }
542
543         cli_setpid(&cli, 2);
544
545         fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
546         if (fnum3 == -1) {
547                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
548                 return;
549         }
550
551         cli_setpid(&cli, 1);
552
553         if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
554                 printf("lock1 failed (%s)\n", cli_errstr(&cli));
555                 return;
556         }
557
558         if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
559                 printf("lock2 succeeded! This is a locking bug\n");
560         } else {
561                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
562         }
563
564         cli_setpid(&cli, 2);
565
566         if (cli_unlock(&cli, fnum1, 0, 8)) {
567                 printf("unlock1 succeeded! This is a locking bug\n");
568         }
569
570         if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
571                 printf("lock3 succeeded! This is a locking bug\n");
572         } else {
573                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
574         }
575
576         cli_setpid(&cli, 1);
577
578         if (!cli_close(&cli, fnum1)) {
579                 printf("close1 failed (%s)\n", cli_errstr(&cli));
580                 return;
581         }
582
583         if (!cli_close(&cli, fnum2)) {
584                 printf("close2 failed (%s)\n", cli_errstr(&cli));
585                 return;
586         }
587
588         if (!cli_close(&cli, fnum3)) {
589                 printf("close3 failed (%s)\n", cli_errstr(&cli));
590                 return;
591         }
592
593         close_connection(&cli);
594
595         printf("locktest2 finished\n");
596 }
597
598
599 /*
600   This test checks that 
601
602   1) the server supports the full offset range in lock requests
603 */
604 static void run_locktest3(int dummy)
605 {
606         static struct cli_state cli1, cli2;
607         char *fname = "\\lockt3.lck";
608         int fnum1, fnum2, i;
609         uint32 offset;
610
611 #define NEXT_OFFSET offset += (~(uint32)0) / numops
612
613         if (!open_connection(&cli1) || !open_connection(&cli2)) {
614                 return;
615         }
616         cli_sockopt(&cli1, sockops);
617         cli_sockopt(&cli2, sockops);
618
619         printf("starting locktest3\n");
620
621         cli_unlink(&cli1, fname);
622
623         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
624         if (fnum1 == -1) {
625                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
626                 return;
627         }
628         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
629         if (fnum2 == -1) {
630                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
631                 return;
632         }
633
634         for (offset=i=0;i<numops;i++) {
635                 NEXT_OFFSET;
636                 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
637                         printf("lock1 %d failed (%s)\n", 
638                                i,
639                                cli_errstr(&cli1));
640                         return;
641                 }
642
643                 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
644                         printf("lock2 %d failed (%s)\n", 
645                                i,
646                                cli_errstr(&cli1));
647                         return;
648                 }
649         }
650
651         for (offset=i=0;i<numops;i++) {
652                 NEXT_OFFSET;
653
654                 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
655                         printf("error: lock1 %d succeeded!\n", i);
656                         return;
657                 }
658
659                 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
660                         printf("error: lock2 %d succeeded!\n", i);
661                         return;
662                 }
663
664                 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
665                         printf("error: lock3 %d succeeded!\n", i);
666                         return;
667                 }
668
669                 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
670                         printf("error: lock4 %d succeeded!\n", i);
671                         return;
672                 }
673         }
674
675         for (offset=i=0;i<numops;i++) {
676                 NEXT_OFFSET;
677
678                 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
679                         printf("unlock1 %d failed (%s)\n", 
680                                i,
681                                cli_errstr(&cli1));
682                         return;
683                 }
684
685                 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
686                         printf("unlock2 %d failed (%s)\n", 
687                                i,
688                                cli_errstr(&cli1));
689                         return;
690                 }
691         }
692
693         if (!cli_close(&cli1, fnum1)) {
694                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
695         }
696
697         if (!cli_close(&cli2, fnum2)) {
698                 printf("close2 failed (%s)\n", cli_errstr(&cli2));
699         }
700
701         if (!cli_unlink(&cli1, fname)) {
702                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
703                 return;
704         }
705
706         close_connection(&cli1);
707         close_connection(&cli2);
708
709         printf("finished locktest3\n");
710 }
711
712 #define EXPECTED(ret, v) if ((ret) != (v)) printf("** ")
713
714 /*
715   looks at overlapping locks
716 */
717 static void run_locktest4(int dummy)
718 {
719         static struct cli_state cli1, cli2;
720         char *fname = "\\lockt4.lck";
721         int fnum1, fnum2;
722         BOOL ret;
723         char buf[1000];
724
725         if (!open_connection(&cli1) || !open_connection(&cli2)) {
726                 return;
727         }
728
729         cli_sockopt(&cli1, sockops);
730         cli_sockopt(&cli2, sockops);
731
732         printf("starting locktest4\n");
733
734         cli_unlink(&cli1, fname);
735
736         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
737         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
738
739         memset(buf, 0, sizeof(buf));
740
741         if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
742                 printf("Failed to create file\n");
743                 goto fail;
744         }
745
746         ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
747               cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
748         EXPECTED(ret, False);
749         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
750             
751         ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
752               cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
753         EXPECTED(ret, True);
754         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
755
756         ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
757               cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
758         EXPECTED(ret, False);
759         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
760             
761         ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
762               cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
763         EXPECTED(ret, True);
764         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
765         
766         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
767               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
768         EXPECTED(ret, False);
769         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
770             
771         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
772               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
773         EXPECTED(ret, True);
774         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
775
776         ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
777               cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
778         EXPECTED(ret, True);
779         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
780
781         ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
782               cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
783         EXPECTED(ret, False);
784         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
785
786         ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
787               cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
788         EXPECTED(ret, False);
789         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
790
791         ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
792               cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
793         EXPECTED(ret, True);
794         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
795
796         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
797               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
798         EXPECTED(ret, False);
799         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
800
801         ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
802               cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
803               cli_unlock(&cli1, fnum1, 110, 6);
804         EXPECTED(ret, False);
805         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
806
807
808         ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
809               (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
810         EXPECTED(ret, False);
811         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
812
813         ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
814               (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
815         EXPECTED(ret, False);
816         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
817
818
819         ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
820               cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
821               cli_unlock(&cli1, fnum1, 140, 4) &&
822               cli_unlock(&cli1, fnum1, 140, 4);
823         EXPECTED(ret, True);
824         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
825
826
827         ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
828               cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
829               cli_unlock(&cli1, fnum1, 150, 4) &&
830               (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
831               !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
832               cli_unlock(&cli1, fnum1, 150, 4);
833         EXPECTED(ret, True);
834         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
835
836         ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
837               cli_unlock(&cli1, fnum1, 160, 4) &&
838               (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&         
839               (cli_read(&cli2, fnum2, buf, 160, 4) == 4);               
840         EXPECTED(ret, True);
841         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
842
843         ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
844               cli_unlock(&cli1, fnum1, 170, 4) &&
845               (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&         
846               (cli_read(&cli2, fnum2, buf, 170, 4) == 4);               
847         EXPECTED(ret, True);
848         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
849
850         ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
851               cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
852               cli_unlock(&cli1, fnum1, 190, 4) &&
853               !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&                
854               (cli_read(&cli2, fnum2, buf, 190, 4) == 4);               
855         EXPECTED(ret, True);
856         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
857
858  fail:
859         cli_close(&cli1, fnum1);
860         cli_close(&cli1, fnum2);
861         cli_unlink(&cli1, fname);
862         close_connection(&cli1);
863         close_connection(&cli2);
864
865         printf("finished locktest4\n");
866 }
867
868
869 /*
870   this produces a matrix of deny mode behaviour
871  */
872 static void run_denytest1(int dummy)
873 {
874         static struct cli_state cli1, cli2;
875         int fnum1, fnum2;
876         int f, d1, d2, o1, o2, x=0;
877         char *fnames[] = {"denytest1.exe", "denytest1.dat", NULL};
878         struct {
879                 int v;
880                 char *name; 
881         } deny_modes[] = {
882                 {DENY_DOS, "DENY_DOS"},
883                 {DENY_ALL, "DENY_ALL"},
884                 {DENY_WRITE, "DENY_WRITE"},
885                 {DENY_READ, "DENY_READ"},
886                 {DENY_NONE, "DENY_NONE"},
887                 {DENY_FCB, "DENY_FCB"},
888                 {-1, NULL}};
889         struct {
890                 int v;
891                 char *name; 
892         } open_modes[] = {
893                 {O_RDWR, "O_RDWR"},
894                 {O_RDONLY, "O_RDONLY"},
895                 {O_WRONLY, "O_WRONLY"},
896                 {-1, NULL}};
897
898         if (!open_connection(&cli1) || !open_connection(&cli2)) {
899                 return;
900         }
901         cli_sockopt(&cli1, sockops);
902         cli_sockopt(&cli2, sockops);
903
904         printf("starting denytest1\n");
905
906         for (f=0;fnames[f];f++) {
907                 cli_unlink(&cli1, fnames[f]);
908
909                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
910                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
911                 cli_close(&cli1, fnum1);
912
913                 for (d1=0;deny_modes[d1].name;d1++) 
914                 for (o1=0;open_modes[o1].name;o1++) 
915                 for (d2=0;deny_modes[d2].name;d2++) 
916                 for (o2=0;open_modes[o2].name;o2++) {
917                         fnum1 = cli_open(&cli1, fnames[f], 
918                                          open_modes[o1].v, 
919                                          deny_modes[d1].v);
920                         fnum2 = cli_open(&cli2, fnames[f], 
921                                          open_modes[o2].v, 
922                                          deny_modes[d2].v);
923
924                         printf("%s %8s %10s    %8s %10s     ",
925                                fnames[f],
926                                open_modes[o1].name,
927                                deny_modes[d1].name,
928                                open_modes[o2].name,
929                                deny_modes[d2].name);
930
931                         if (fnum1 == -1) {
932                                 printf("X");
933                         } else if (fnum2 == -1) {
934                                 printf("-");
935                         } else {
936                                 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
937                                         printf("R");
938                                 }
939                                 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
940                                         printf("W");
941                                 }
942                         }
943
944                         printf("\n");
945                         cli_close(&cli1, fnum1);
946                         cli_close(&cli2, fnum2);
947                 }
948                 
949                 cli_unlink(&cli1, fnames[f]);
950         }
951
952         close_connection(&cli1);
953         close_connection(&cli2);
954         
955         printf("finshed denytest1\n");
956 }
957
958
959 /*
960   this produces a matrix of deny mode behaviour for two opens on the
961   same connection
962  */
963 static void run_denytest2(int dummy)
964 {
965         static struct cli_state cli1;
966         int fnum1, fnum2;
967         int f, d1, d2, o1, o2, x=0;
968         char *fnames[] = {"denytest2.exe", "denytest2.dat", NULL};
969         struct {
970                 int v;
971                 char *name; 
972         } deny_modes[] = {
973                 {DENY_DOS, "DENY_DOS"},
974                 {DENY_ALL, "DENY_ALL"},
975                 {DENY_WRITE, "DENY_WRITE"},
976                 {DENY_READ, "DENY_READ"},
977                 {DENY_NONE, "DENY_NONE"},
978                 {DENY_FCB, "DENY_FCB"},
979                 {-1, NULL}};
980         struct {
981                 int v;
982                 char *name; 
983         } open_modes[] = {
984                 {O_RDWR, "O_RDWR"},
985                 {O_RDONLY, "O_RDONLY"},
986                 {O_WRONLY, "O_WRONLY"},
987                 {-1, NULL}};
988
989         if (!open_connection(&cli1)) {
990                 return;
991         }
992         cli_sockopt(&cli1, sockops);
993
994         printf("starting denytest2\n");
995
996         for (f=0;fnames[f];f++) {
997                 cli_unlink(&cli1, fnames[f]);
998
999                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1000                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1001                 cli_close(&cli1, fnum1);
1002
1003                 for (d1=0;deny_modes[d1].name;d1++) 
1004                 for (o1=0;open_modes[o1].name;o1++) 
1005                 for (d2=0;deny_modes[d2].name;d2++) 
1006                 for (o2=0;open_modes[o2].name;o2++) {
1007                         fnum1 = cli_open(&cli1, fnames[f], 
1008                                          open_modes[o1].v, 
1009                                          deny_modes[d1].v);
1010                         fnum2 = cli_open(&cli1, fnames[f], 
1011                                          open_modes[o2].v, 
1012                                          deny_modes[d2].v);
1013
1014                         printf("%s %8s %10s    %8s %10s     ",
1015                                fnames[f],
1016                                open_modes[o1].name,
1017                                deny_modes[d1].name,
1018                                open_modes[o2].name,
1019                                deny_modes[d2].name);
1020
1021                         if (fnum1 == -1) {
1022                                 printf("X");
1023                         } else if (fnum2 == -1) {
1024                                 printf("-");
1025                         } else {
1026                                 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1027                                         printf("R");
1028                                 }
1029                                 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1030                                         printf("W");
1031                                 }
1032                         }
1033
1034                         printf("\n");
1035                         cli_close(&cli1, fnum1);
1036                         cli_close(&cli1, fnum2);
1037                 }
1038                 
1039                 cli_unlink(&cli1, fnames[f]);
1040         }
1041
1042         close_connection(&cli1);
1043         
1044         printf("finshed denytest2\n");
1045 }
1046
1047 /*
1048 test whether fnums and tids open on one VC are available on another (a major
1049 security hole)
1050 */
1051 static void run_fdpasstest(int dummy)
1052 {
1053         static struct cli_state cli1, cli2;
1054         char *fname = "\\fdpass.tst";
1055         int fnum1;
1056         pstring buf;
1057
1058         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1059                 return;
1060         }
1061         cli_sockopt(&cli1, sockops);
1062         cli_sockopt(&cli2, sockops);
1063
1064         printf("starting fdpasstest\n");
1065
1066         cli_unlink(&cli1, fname);
1067
1068         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1069         if (fnum1 == -1) {
1070                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1071                 return;
1072         }
1073
1074         if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1075                 printf("write failed (%s)\n", cli_errstr(&cli1));
1076                 return;
1077         }
1078
1079         cli2.vuid = cli1.vuid;
1080         cli2.cnum = cli1.cnum;
1081         cli2.pid = cli1.pid;
1082
1083
1084         if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
1085                 printf("read succeeded! nasty security hole [%s]\n",
1086                        buf);
1087                 return;
1088         }
1089
1090         cli_close(&cli1, fnum1);
1091         cli_unlink(&cli1, fname);
1092
1093         close_connection(&cli1);
1094         close_connection(&cli2);
1095
1096         printf("finished fdpasstest\n");
1097 }
1098
1099
1100 /*
1101   This test checks that 
1102
1103   1) the server does not allow an unlink on a file that is open
1104 */
1105 static void run_unlinktest(int dummy)
1106 {
1107         static struct cli_state cli;
1108         char *fname = "\\unlink.tst";
1109         int fnum;
1110
1111         if (!open_connection(&cli)) {
1112                 return;
1113         }
1114
1115         cli_sockopt(&cli, sockops);
1116
1117         printf("starting unlink test\n");
1118
1119         cli_unlink(&cli, fname);
1120
1121         cli_setpid(&cli, 1);
1122
1123         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1124         if (fnum == -1) {
1125                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1126                 return;
1127         }
1128
1129         if (cli_unlink(&cli, fname)) {
1130                 printf("error: server allowed unlink on an open file\n");
1131         }
1132
1133         cli_close(&cli, fnum);
1134         cli_unlink(&cli, fname);
1135
1136         close_connection(&cli);
1137
1138         printf("unlink test finished\n");
1139 }
1140
1141
1142 /*
1143 test how many open files this server supports on the one socket
1144 */
1145 static void run_maxfidtest(int dummy)
1146 {
1147         static struct cli_state cli;
1148         char *template = "\\maxfid.%d.%d";
1149         fstring fname;
1150         int fnum;
1151         int retries=4;
1152         int n = numops;
1153
1154         cli = current_cli;
1155
1156         if (retries <= 0) {
1157                 printf("failed to connect\n");
1158                 return;
1159         }
1160
1161         cli_sockopt(&cli, sockops);
1162
1163         fnum = 0;
1164         while (1) {
1165                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1166                 if (cli_open(&cli, fname, 
1167                              O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
1168                     -1) {
1169                         printf("open of %s failed (%s)\n", 
1170                                fname, cli_errstr(&cli));
1171                         printf("maximum fnum is %d\n", fnum);
1172                         break;
1173                 }
1174                 fnum++;
1175         }
1176
1177         printf("cleaning up\n");
1178         while (fnum > n) {
1179                 fnum--;
1180                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1181                 if (cli_unlink(&cli, fname)) {
1182                         printf("unlink of %s failed (%s)\n", 
1183                                fname, cli_errstr(&cli));
1184                 }
1185         }
1186
1187         printf("maxfid test finished\n");
1188         close_connection(&cli);
1189 }
1190
1191 /* generate a random buffer */
1192 static void rand_buf(char *buf, int len)
1193 {
1194         while (len--) {
1195                 *buf = (char)sys_random();
1196                 buf++;
1197         }
1198 }
1199
1200 /* send random IPC commands */
1201 static void run_randomipc(int dummy)
1202 {
1203         char *rparam = NULL;
1204         char *rdata = NULL;
1205         int rdrcnt,rprcnt;
1206         pstring param;
1207         int api, param_len, i;
1208         static struct cli_state cli;
1209
1210         printf("starting random ipc test\n");
1211
1212         if (!open_connection(&cli)) {
1213                 return;
1214         }
1215
1216         for (i=0;i<50000;i++) {
1217                 api = sys_random() % 500;
1218                 param_len = (sys_random() % 64);
1219
1220                 rand_buf(param, param_len);
1221   
1222                 SSVAL(param,0,api); 
1223
1224                 cli_api(&cli, 
1225                         param, param_len, 8,  
1226                         NULL, 0, BUFFER_SIZE, 
1227                         &rparam, &rprcnt,     
1228                         &rdata, &rdrcnt);
1229         }
1230
1231         close_connection(&cli);
1232
1233         printf("finished random ipc test\n");
1234 }
1235
1236
1237
1238 static void browse_callback(const char *sname, uint32 stype, 
1239                             const char *comment)
1240 {
1241         printf("\t%20.20s %08x %s\n", sname, stype, comment);
1242 }
1243
1244
1245
1246 /*
1247   This test checks the browse list code
1248
1249 */
1250 static void run_browsetest(int dummy)
1251 {
1252         static struct cli_state cli;
1253
1254         printf("starting browse test\n");
1255
1256         if (!open_connection(&cli)) {
1257                 return;
1258         }
1259
1260         printf("domain list:\n");
1261         cli_NetServerEnum(&cli, cli.server_domain, 
1262                           SV_TYPE_DOMAIN_ENUM,
1263                           browse_callback);
1264
1265         printf("machine list:\n");
1266         cli_NetServerEnum(&cli, cli.server_domain, 
1267                           SV_TYPE_ALL,
1268                           browse_callback);
1269
1270         close_connection(&cli);
1271
1272         printf("browse test finished\n");
1273 }
1274
1275
1276 /*
1277   This checks how the getatr calls works
1278 */
1279 static void run_attrtest(int dummy)
1280 {
1281         static struct cli_state cli;
1282         int fnum;
1283         time_t t, t2;
1284         char *fname = "\\attrib.tst";
1285
1286         printf("starting attrib test\n");
1287
1288         if (!open_connection(&cli)) {
1289                 return;
1290         }
1291
1292         cli_unlink(&cli, fname);
1293         fnum = cli_open(&cli, fname, 
1294                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1295         cli_close(&cli, fnum);
1296         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1297                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1298         }
1299
1300         if (abs(t - time(NULL)) > 2) {
1301                 printf("ERROR: SMBgetatr bug. time is %s",
1302                        ctime(&t));
1303                 t = time(NULL);
1304         }
1305
1306         t2 = t-60*60*24; /* 1 day ago */
1307
1308         if (!cli_setatr(&cli, fname, 0, t2)) {
1309                 printf("setatr failed (%s)\n", cli_errstr(&cli));
1310         }
1311
1312         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1313                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1314         }
1315
1316         if (t != t2) {
1317                 printf("ERROR: getatr/setatr bug. times are\n%s",
1318                        ctime(&t));
1319                 printf("%s", ctime(&t2));
1320         }
1321
1322         cli_unlink(&cli, fname);
1323
1324         close_connection(&cli);
1325
1326         printf("attrib test finished\n");
1327 }
1328
1329
1330 /*
1331   This checks a couple of trans2 calls
1332 */
1333 static void run_trans2test(int dummy)
1334 {
1335         static struct cli_state cli;
1336         int fnum;
1337         size_t size;
1338         time_t c_time, a_time, m_time, w_time, m_time2;
1339         char *fname = "\\trans2.tst";
1340         char *dname = "\\trans2";
1341         char *fname2 = "\\trans2\\trans2.tst";
1342
1343         printf("starting trans2 test\n");
1344
1345         if (!open_connection(&cli)) {
1346                 return;
1347         }
1348
1349         cli_unlink(&cli, fname);
1350         fnum = cli_open(&cli, fname, 
1351                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1352         if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
1353                            NULL, NULL)) {
1354                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
1355         }
1356         cli_close(&cli, fnum);
1357
1358         sleep(2);
1359
1360         cli_unlink(&cli, fname);
1361         fnum = cli_open(&cli, fname, 
1362                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1363         cli_close(&cli, fnum);
1364
1365         if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
1366                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
1367         } else {
1368                 if (c_time != m_time) {
1369                         printf("create time=%s", ctime(&c_time));
1370                         printf("modify time=%s", ctime(&m_time));
1371                         printf("This system appears to have sticky create times\n");
1372                 }
1373                 if (a_time % (60*60) == 0) {
1374                         printf("access time=%s", ctime(&a_time));
1375                         printf("This system appears to set a midnight access time\n");
1376                 }
1377
1378                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1379                         printf("ERROR: totally incorrect times - maybe word reversed?\n");
1380                 }
1381         }
1382
1383
1384         cli_unlink(&cli, fname);
1385         fnum = cli_open(&cli, fname, 
1386                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1387         cli_close(&cli, fnum);
1388         if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, 
1389                             &w_time, &size, NULL, NULL)) {
1390                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1391         } else {
1392                 if (w_time < 60*60*24*2) {
1393                         printf("write time=%s", ctime(&w_time));
1394                         printf("This system appears to set a initial 0 write time\n");
1395                 }
1396         }
1397
1398         cli_unlink(&cli, fname);
1399
1400
1401         /* check if the server updates the directory modification time
1402            when creating a new file */
1403         if (!cli_mkdir(&cli, dname)) {
1404                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
1405         }
1406         sleep(3);
1407         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, 
1408                             &w_time, &size, NULL, NULL)) {
1409                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1410         }
1411
1412         fnum = cli_open(&cli, fname2, 
1413                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1414         cli_write(&cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
1415         cli_close(&cli, fnum);
1416         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, 
1417                             &w_time, &size, NULL, NULL)) {
1418                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
1419         } else {
1420                 if (m_time2 == m_time)
1421                         printf("This system does not update directory modification times\n");
1422         }
1423         cli_unlink(&cli, fname2);
1424         cli_rmdir(&cli, dname);
1425
1426
1427         close_connection(&cli);
1428
1429         printf("trans2 test finished\n");
1430 }
1431
1432
1433 /*
1434   this is a harness for some oplock tests
1435  */
1436 static void run_oplock(int dummy)
1437 {
1438         static struct cli_state cli1;
1439         char *fname = "\\lockt1.lck";
1440         int fnum1;
1441
1442         printf("starting oplock test\n");
1443
1444         if (!open_connection(&cli1)) {
1445                 return;
1446         }
1447
1448         cli_unlink(&cli1, fname);
1449
1450         cli_sockopt(&cli1, sockops);
1451
1452         cli1.use_oplocks = True;
1453
1454         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1455         if (fnum1 == -1) {
1456                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1457                 return;
1458         }
1459
1460         cli1.use_oplocks = False;
1461
1462         cli_unlink(&cli1, fname);
1463         cli_unlink(&cli1, fname);
1464
1465         if (!cli_close(&cli1, fnum1)) {
1466                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
1467                 return;
1468         }
1469
1470         if (!cli_unlink(&cli1, fname)) {
1471                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1472                 return;
1473         }
1474
1475
1476         close_connection(&cli1);
1477
1478         printf("finished oplock test\n");
1479 }
1480
1481
1482 static void list_fn(file_info *finfo, const char *name)
1483 {
1484         
1485 }
1486
1487 /*
1488   test directory listing speed
1489  */
1490 static void run_dirtest(int dummy)
1491 {
1492         int i;
1493         static struct cli_state cli;
1494         int fnum;
1495         double t1;
1496
1497         printf("starting directory test\n");
1498
1499         if (!open_connection(&cli)) {
1500                 return;
1501         }
1502
1503         cli_sockopt(&cli, sockops);
1504
1505         srandom(0);
1506         for (i=0;i<numops;i++) {
1507                 fstring fname;
1508                 slprintf(fname, sizeof(fname), "%x", (int)random());
1509                 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
1510                 if (fnum == -1) {
1511                         fprintf(stderr,"Failed to open %s\n", fname);
1512                         return;
1513                 }
1514                 cli_close(&cli, fnum);
1515         }
1516
1517         t1 = end_timer();
1518
1519         printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn));
1520         printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn));
1521         printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn));
1522
1523         printf("dirtest core %g seconds\n", end_timer() - t1);
1524
1525         srandom(0);
1526         for (i=0;i<numops;i++) {
1527                 fstring fname;
1528                 slprintf(fname, sizeof(fname), "%x", (int)random());
1529                 cli_unlink(&cli, fname);
1530         }
1531
1532         close_connection(&cli);
1533
1534         printf("finished dirtest\n");
1535 }
1536
1537
1538
1539 static double create_procs(void (*fn)(int))
1540 {
1541         int i, status;
1542         volatile int *child_status;
1543         int synccount;
1544         int tries = 8;
1545
1546         start_timer();
1547
1548         synccount = 0;
1549
1550         child_status = (volatile int *)shm_setup(sizeof(int)*nprocs);
1551         if (!child_status) {
1552                 printf("Failed to setup shared memory\n");
1553                 return end_timer();
1554         }
1555
1556         memset((char *)child_status, 0, sizeof(int)*nprocs);
1557
1558         for (i=0;i<nprocs;i++) {
1559                 if (fork() == 0) {
1560                         pid_t mypid = getpid();
1561                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
1562
1563                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
1564
1565                         while (1) {
1566                                 memset(&current_cli, 0, sizeof(current_cli));
1567                                 if (open_connection(&current_cli)) break;
1568                                 if (tries-- == 0) {
1569                                         printf("pid %d failed to start\n", (int)getpid());
1570                                         _exit(1);
1571                                 }
1572                                 msleep(10);
1573                         }
1574
1575                         child_status[i] = getpid();
1576
1577                         while (child_status[i]) msleep(2);
1578
1579                         fn(i);
1580                         _exit(0);
1581                 }
1582         }
1583
1584         do {
1585                 synccount = 0;
1586                 for (i=0;i<nprocs;i++) {
1587                         if (child_status[i]) synccount++;
1588                 }
1589                 if (synccount == nprocs) break;
1590                 msleep(10);
1591         } while (end_timer() < 30);
1592
1593         if (synccount != nprocs) {
1594                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
1595                 return end_timer();
1596         }
1597
1598         /* start the client load */
1599         start_timer();
1600
1601         for (i=0;i<nprocs;i++) {
1602                 child_status[i] = 0;
1603         }
1604
1605         printf("%d clients started\n", nprocs);
1606
1607         for (i=0;i<nprocs;i++) {
1608                 waitpid(0, &status, 0);
1609                 printf("*");
1610         }
1611         printf("\n");
1612         return end_timer();
1613 }
1614
1615
1616 #define FLAG_MULTIPROC 1
1617
1618 static struct {
1619         char *name;
1620         void (*fn)(int);
1621         unsigned flags;
1622 } torture_ops[] = {
1623         {"FDPASS", run_fdpasstest, 0},
1624         {"LOCK1",  run_locktest1,  0},
1625         {"LOCK2",  run_locktest2,  0},
1626         {"LOCK3",  run_locktest3,  0},
1627         {"LOCK4",  run_locktest4,  0},
1628         {"UNLINK", run_unlinktest, 0},
1629         {"BROWSE", run_browsetest, 0},
1630         {"ATTR",   run_attrtest,   0},
1631         {"TRANS2", run_trans2test, 0},
1632         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
1633         {"TORTURE",run_torture,    FLAG_MULTIPROC},
1634         {"RANDOMIPC", run_randomipc, 0},
1635         {"NBW95",  run_nbw95, 0},
1636         {"NBWNT",  run_nbwnt, 0},
1637         {"OPLOCK",  run_oplock, 0},
1638         {"DIR",  run_dirtest, 0},
1639         {"DENY1",  run_denytest1, 0},
1640         {"DENY2",  run_denytest2, 0},
1641         {NULL, NULL, 0}};
1642
1643
1644 /****************************************************************************
1645 run a specified test or "ALL"
1646 ****************************************************************************/
1647 static void run_test(char *name)
1648 {
1649         int i;
1650         if (strequal(name,"ALL")) {
1651                 for (i=0;torture_ops[i].name;i++) {
1652                         run_test(torture_ops[i].name);
1653                 }
1654         }
1655         
1656         for (i=0;torture_ops[i].name;i++) {
1657                 if (strequal(name, torture_ops[i].name)) {
1658                         start_timer();
1659                         printf("Running %s\n", name);
1660                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
1661                                 create_procs(torture_ops[i].fn);
1662                         } else {
1663                                 torture_ops[i].fn(0);
1664                         }
1665                         printf("%s took %g secs\n\n", name, end_timer());
1666                 }
1667         }
1668 }
1669
1670
1671 static void usage(void)
1672 {
1673         int i;
1674
1675         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
1676
1677         printf("\t-U user%%pass\n");
1678         printf("\t-N numprocs\n");
1679         printf("\t-n my_netbios_name\n");
1680         printf("\t-W workgroup\n");
1681         printf("\t-o num_operations\n");
1682         printf("\t-O socket_options\n");
1683         printf("\t-m maximum protocol\n");
1684         printf("\n\n");
1685
1686         printf("tests are:");
1687         for (i=0;torture_ops[i].name;i++) {
1688                 printf(" %s", torture_ops[i].name);
1689         }
1690         printf("\n");
1691
1692         printf("default test is ALL\n");
1693         
1694         exit(1);
1695 }
1696
1697
1698
1699
1700
1701 /****************************************************************************
1702   main program
1703 ****************************************************************************/
1704  int main(int argc,char *argv[])
1705 {
1706         int opt, i;
1707         char *p;
1708         int gotpass = 0;
1709         extern char *optarg;
1710         extern int optind;
1711         extern FILE *dbf;
1712         static pstring servicesf = CONFIGFILE;
1713
1714         dbf = stdout;
1715
1716         setbuffer(stdout, NULL, 0);
1717
1718         charset_initialise();
1719
1720         lp_load(servicesf,True,False,False);
1721         load_interfaces();
1722
1723         if (argc < 2) {
1724                 usage();
1725         }
1726
1727         for(p = argv[1]; *p; p++)
1728           if(*p == '\\')
1729             *p = '/';
1730  
1731         if (strncmp(argv[1], "//", 2)) {
1732                 usage();
1733         }
1734
1735         fstrcpy(host, &argv[1][2]);
1736         p = strchr(&host[2],'/');
1737         if (!p) {
1738                 usage();
1739         }
1740         *p = 0;
1741         fstrcpy(share, p+1);
1742
1743         get_myname(myname);
1744
1745         if (*username == 0 && getenv("LOGNAME")) {
1746           pstrcpy(username,getenv("LOGNAME"));
1747         }
1748
1749         argc--;
1750         argv++;
1751
1752
1753         fstrcpy(workgroup, lp_workgroup());
1754
1755         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1756                 switch (opt) {
1757                 case 'W':
1758                         fstrcpy(workgroup,optarg);
1759                         break;
1760                 case 'm':
1761                         max_protocol = interpret_protocol(optarg, max_protocol);
1762                         break;
1763                 case 'N':
1764                         nprocs = atoi(optarg);
1765                         break;
1766                 case 'o':
1767                         numops = atoi(optarg);
1768                         break;
1769                 case 'O':
1770                         sockops = optarg;
1771                         break;
1772                 case 'n':
1773                         fstrcpy(myname, optarg);
1774                         break;
1775                 case 'U':
1776                         pstrcpy(username,optarg);
1777                         p = strchr(username,'%');
1778                         if (p) {
1779                                 *p = 0;
1780                                 pstrcpy(password, p+1);
1781                                 gotpass = 1;
1782                         }
1783                         break;
1784                 default:
1785                         printf("Unknown option %c (%d)\n", (char)opt, opt);
1786                         usage();
1787                 }
1788         }
1789
1790
1791         while (!gotpass) {
1792                 p = getpass("Password:");
1793                 if (p) {
1794                         pstrcpy(password, p);
1795                         gotpass = 1;
1796                 }
1797         }
1798
1799         printf("host=%s share=%s user=%s myname=%s\n", 
1800                host, share, username, myname);
1801
1802         if (argc == 1) {
1803                 run_test("ALL");
1804         } else {
1805                 for (i=1;i<argc;i++) {
1806                         run_test(argv[i]);
1807                 }
1808         }
1809
1810         return(0);
1811 }