Not all OSs have setbuffer, so we better check for it.
[gd/samba-autobuild/.git] / source3 / torture / 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 int procnum; /* records process count number when forking */
31 static struct cli_state current_cli;
32 static fstring randomfname;
33 static BOOL use_oplocks;
34 static BOOL use_level_II_oplocks;
35
36 static double create_procs(BOOL (*fn)(int), BOOL *result);
37
38
39 static struct timeval tp1,tp2;
40
41 static void start_timer(void)
42 {
43         gettimeofday(&tp1,NULL);
44 }
45
46 static double end_timer(void)
47 {
48         gettimeofday(&tp2,NULL);
49         return((tp2.tv_sec - tp1.tv_sec) + 
50                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
51 }
52
53
54 /* return a pointer to a anonymous shared memory segment of size "size"
55    which will persist across fork() but will disappear when all processes
56    exit 
57
58    The memory is not zeroed 
59
60    This function uses system5 shared memory. It takes advantage of a property
61    that the memory is not destroyed if it is attached when the id is removed
62    */
63 static void *shm_setup(int size)
64 {
65         int shmid;
66         void *ret;
67
68         shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
69         if (shmid == -1) {
70                 printf("can't get shared memory\n");
71                 exit(1);
72         }
73         ret = (void *)shmat(shmid, 0, 0);
74         if (!ret || ret == (void *)-1) {
75                 printf("can't attach to shared memory\n");
76                 return NULL;
77         }
78         /* the following releases the ipc, but note that this process
79            and all its children will still have access to the memory, its
80            just that the shmid is no longer valid for other shm calls. This
81            means we don't leave behind lots of shm segments after we exit 
82
83            See Stevens "advanced programming in unix env" for details
84            */
85         shmctl(shmid, IPC_RMID, 0);
86         
87         return ret;
88 }
89
90
91 static BOOL open_nbt_connection(struct cli_state *c)
92 {
93         struct nmb_name called, calling;
94         struct in_addr ip;
95         extern struct in_addr ipzero;
96
97         ZERO_STRUCTP(c);
98
99         make_nmb_name(&calling, myname, 0x0);
100         make_nmb_name(&called , host, 0x20);
101
102         ip = ipzero;
103
104         if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
105                 printf("Failed to connect with %s\n", host);
106                 return False;
107         }
108
109         c->timeout = 120000; /* set a really long timeout (2 minutes) */
110         if (use_oplocks) c->use_oplocks = True;
111         if (use_level_II_oplocks) c->use_level_II_oplocks = True;
112
113         if (!cli_session_request(c, &calling, &called)) {
114                 printf("%s rejected the session\n",host);
115                 cli_shutdown(c);
116                 return False;
117         }
118
119         return True;
120 }
121
122 static BOOL open_connection(struct cli_state *c)
123 {
124         ZERO_STRUCTP(c);
125
126         if (!open_nbt_connection(c)) {
127                 return False;
128         }
129
130         if (!cli_negprot(c)) {
131                 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
132                 cli_shutdown(c);
133                 return False;
134         }
135
136         if (!cli_session_setup(c, username, 
137                                password, strlen(password),
138                                password, strlen(password),
139                                workgroup)) {
140                 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
141                 cli_shutdown(c);
142                 return False;
143         }
144
145         if (!cli_send_tconX(c, share, "?????",
146                             password, strlen(password)+1)) {
147                 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
148                 cli_shutdown(c);
149                 return False;
150         }
151
152         return True;
153 }
154
155
156 static BOOL close_connection(struct cli_state *c)
157 {
158         BOOL ret = True;
159         if (!cli_tdis(c)) {
160                 printf("tdis failed (%s)\n", cli_errstr(c));
161                 ret = False;
162         }
163
164         cli_shutdown(c);
165
166         return ret;
167 }
168
169
170 /* check if the server produced the expected error code */
171 static BOOL check_error(struct cli_state *c, 
172                         uint8 eclass, uint32 ecode, uint32 nterr)
173 {
174         uint8 class;
175         uint32 num;
176         (void)cli_error(c, &class, &num, NULL);
177         if ((eclass != class || ecode != num) &&
178             num != (nterr&0xFFFFFF)) {
179                 printf("unexpected error code class=%d code=%d\n", 
180                          (int)class, (int)num);
181                 printf(" expected %d/%d %d\n", 
182                        (int)eclass, (int)ecode, (int)nterr);
183                 return False;
184         }
185         return True;
186 }
187
188
189 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
190 {
191         while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
192                 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
193         }
194         return True;
195 }
196
197
198 static BOOL rw_torture(struct cli_state *c)
199 {
200         char *lockfname = "\\torture.lck";
201         fstring fname;
202         int fnum;
203         int fnum2;
204         pid_t pid2, pid = getpid();
205         int i, j;
206         char buf[1024];
207         BOOL correct = True;
208
209         fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
210                          DENY_NONE);
211         if (fnum2 == -1)
212                 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
213         if (fnum2 == -1) {
214                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
215                 return False;
216         }
217
218
219         for (i=0;i<numops;i++) {
220                 unsigned n = (unsigned)sys_random()%10;
221                 if (i % 10 == 0) {
222                         printf("%d\r", i); fflush(stdout);
223                 }
224                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
225
226                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
227                         return False;
228                 }
229
230                 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
231                 if (fnum == -1) {
232                         printf("open failed (%s)\n", cli_errstr(c));
233                         correct = False;
234                         break;
235                 }
236
237                 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
238                         printf("write failed (%s)\n", cli_errstr(c));
239                         correct = False;
240                 }
241
242                 for (j=0;j<50;j++) {
243                         if (cli_write(c, fnum, 0, (char *)buf, 
244                                       sizeof(pid)+(j*sizeof(buf)), 
245                                       sizeof(buf)) != sizeof(buf)) {
246                                 printf("write failed (%s)\n", cli_errstr(c));
247                                 correct = False;
248                         }
249                 }
250
251                 pid2 = 0;
252
253                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
254                         printf("read failed (%s)\n", cli_errstr(c));
255                         correct = False;
256                 }
257
258                 if (pid2 != pid) {
259                         printf("data corruption!\n");
260                         correct = False;
261                 }
262
263                 if (!cli_close(c, fnum)) {
264                         printf("close failed (%s)\n", cli_errstr(c));
265                         correct = False;
266                 }
267
268                 if (!cli_unlink(c, fname)) {
269                         printf("unlink failed (%s)\n", cli_errstr(c));
270                         correct = False;
271                 }
272
273                 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
274                         printf("unlock failed (%s)\n", cli_errstr(c));
275                         correct = False;
276                 }
277         }
278
279         cli_close(c, fnum2);
280         cli_unlink(c, lockfname);
281
282         printf("%d\n", i);
283
284         return correct;
285 }
286
287 static BOOL run_torture(int dummy)
288 {
289         struct cli_state cli;
290         BOOL ret;
291
292         cli = current_cli;
293
294         cli_sockopt(&cli, sockops);
295
296         ret = rw_torture(&cli);
297         
298         if (!close_connection(&cli)) {
299                 ret = False;
300         }
301
302         return ret;
303 }
304
305 static BOOL rw_torture3(struct cli_state *c, char *lockfname)
306 {
307         int fnum = -1;
308         int i = 0;
309         char buf[131072];
310         char buf_rd[131072];
311         unsigned count;
312         unsigned countprev = 0;
313         unsigned sent = 0;
314         BOOL correct = True;
315
316         srandom(1);
317         for (i = 0; i < sizeof(buf); i += sizeof(uint32))
318         {
319                 SIVAL(buf, i, sys_random());
320         }
321
322         if (procnum == 0)
323         {
324                 fnum = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
325                                  DENY_NONE);
326                 if (fnum == -1) {
327                         printf("first open read/write of %s failed (%s)\n",
328                                         lockfname, cli_errstr(c));
329                         return False;
330                 }
331         }
332         else
333         {
334                 for (i = 0; i < 500 && fnum == -1; i++)
335                 {
336                         fnum = cli_open(c, lockfname, O_RDONLY, 
337                                          DENY_NONE);
338                         msleep(10);
339                 }
340                 if (fnum == -1) {
341                         printf("second open read-only of %s failed (%s)\n",
342                                         lockfname, cli_errstr(c));
343                         return False;
344                 }
345         }
346
347         i = 0;
348         for (count = 0; count < sizeof(buf); count += sent)
349         {
350                 if (count >= countprev) {
351                         printf("%d %8d\r", i, count);
352                         fflush(stdout);
353                         i++;
354                         countprev += (sizeof(buf) / 20);
355                 }
356
357                 if (procnum == 0)
358                 {
359                         sent = ((unsigned)sys_random()%(20))+ 1;
360                         if (sent > sizeof(buf) - count)
361                         {
362                                 sent = sizeof(buf) - count;
363                         }
364
365                         if (cli_write(c, fnum, 0, buf+count, count, sent) != sent) {
366                                 printf("write failed (%s)\n", cli_errstr(c));
367                                 correct = False;
368                         }
369                 }
370                 else
371                 {
372                         sent = cli_read(c, fnum, buf_rd+count, count,
373                                                   sizeof(buf)-count);
374                         if (sent < 0)
375                         {
376                                 printf("read failed offset:%d size:%d (%s)\n",
377                                                 count, sizeof(buf)-count,
378                                                 cli_errstr(c));
379                                 correct = False;
380                                 sent = 0;
381                         }
382                         if (sent > 0)
383                         {
384                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
385                                 {
386                                         printf("read/write compare failed\n");
387                                         printf("offset: %d req %d recvd %d\n",
388                                                 count, sizeof(buf)-count, sent);
389                                         correct = False;
390                                         break;
391                                 }
392                         }
393                 }
394
395         }
396
397         if (!cli_close(c, fnum)) {
398                 printf("close failed (%s)\n", cli_errstr(c));
399                 correct = False;
400         }
401
402         return correct;
403 }
404
405 static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
406 {
407         char *lockfname = "\\torture.lck";
408         int fnum1;
409         int fnum2;
410         int i;
411         char buf[131072];
412         char buf_rd[131072];
413         BOOL correct = True;
414         ssize_t bytes_read;
415
416         if (!cli_unlink(c1, lockfname)) {
417                 printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c1));
418         }
419
420         fnum1 = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL, 
421                          DENY_NONE);
422         if (fnum1 == -1) {
423                 printf("first open read/write of %s failed (%s)\n",
424                                 lockfname, cli_errstr(c1));
425                 return False;
426         }
427         fnum2 = cli_open(c2, lockfname, O_RDONLY, 
428                          DENY_NONE);
429         if (fnum2 == -1) {
430                 printf("second open read-only of %s failed (%s)\n",
431                                 lockfname, cli_errstr(c2));
432                 cli_close(c1, fnum1);
433                 return False;
434         }
435
436         for (i=0;i<numops;i++)
437         {
438                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
439                 if (i % 10 == 0) {
440                         printf("%d\r", i); fflush(stdout);
441                 }
442
443                 generate_random_buffer(buf, buf_size, False);
444
445                 if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
446                         printf("write failed (%s)\n", cli_errstr(c1));
447                         correct = False;
448                 }
449
450                 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
451                         printf("read failed (%s)\n", cli_errstr(c2));
452                         printf("read %d, expected %d\n", bytes_read, buf_size); 
453                         correct = False;
454                 }
455
456                 if (memcmp(buf_rd, buf, buf_size) != 0)
457                 {
458                         printf("read/write compare failed\n");
459                         correct = False;
460                 }
461         }
462
463         if (!cli_close(c2, fnum2)) {
464                 printf("close failed (%s)\n", cli_errstr(c2));
465                 correct = False;
466         }
467         if (!cli_close(c1, fnum1)) {
468                 printf("close failed (%s)\n", cli_errstr(c1));
469                 correct = False;
470         }
471
472         if (!cli_unlink(c1, lockfname)) {
473                 printf("unlink failed (%s)\n", cli_errstr(c1));
474                 correct = False;
475         }
476
477         return correct;
478 }
479
480 static BOOL run_readwritetest(int dummy)
481 {
482         static struct cli_state cli1, cli2;
483         BOOL test1, test2;
484
485         if (!open_connection(&cli1) || !open_connection(&cli2)) {
486                 return False;
487         }
488         cli_sockopt(&cli1, sockops);
489         cli_sockopt(&cli2, sockops);
490
491         printf("starting readwritetest\n");
492
493         test1 = rw_torture2(&cli1, &cli2);
494         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
495
496         test2 = rw_torture2(&cli1, &cli1);
497         printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
498
499         if (!close_connection(&cli1)) {
500                 test1 = False;
501         }
502
503         if (!close_connection(&cli2)) {
504                 test2 = False;
505         }
506
507         return (test1 && test2);
508 }
509
510 static BOOL run_readwritemulti(int dummy)
511 {
512         static struct cli_state cli;
513         BOOL test;
514
515         cli = current_cli;
516
517         cli_sockopt(&cli, sockops);
518
519         printf("run_readwritemulti: fname %s\n", randomfname);
520         test = rw_torture3(&cli, randomfname);
521
522         if (!close_connection(&cli)) {
523                 test = False;
524         }
525         
526         return test;
527 }
528
529 static BOOL run_readwritelarge(int dummy)
530 {
531         static struct cli_state cli1;
532         int fnum1;
533         char *lockfname = "\\large.dat";
534         size_t fsize;
535         char buf[0x10000];
536         BOOL correct = True;
537  
538         if (!open_connection(&cli1)) {
539                 return False;
540         }
541         cli_sockopt(&cli1, sockops);
542         memset(buf,'\0',sizeof(buf));
543         
544         cli1.max_xmit = 0x11000;
545         
546         printf("starting readwritelarge\n");
547  
548         cli_unlink(&cli1, lockfname);
549
550         fnum1 = cli_open(&cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE);
551         if (fnum1 == -1) {
552                 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(&cli1));
553                 return False;
554         }
555    
556         cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf));
557
558         if (!cli_close(&cli1, fnum1)) {
559                 printf("close failed (%s)\n", cli_errstr(&cli1));
560                 correct = False;
561         }
562
563         if (!cli_qpathinfo(&cli1, lockfname, NULL, NULL, NULL, &fsize, NULL)) {
564                 printf("qpathinfo failed (%s)\n", cli_errstr(&cli1));
565                 correct = False;
566         }
567
568         if (fsize == sizeof(buf))
569                 printf("readwritelarge test succeeded (size = %x)\n", fsize);
570         else {
571                printf("readwritelarge test failed (size = %x)\n", fsize);
572                correct = False;
573         }
574
575         if (!cli_unlink(&cli1, lockfname)) {
576                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
577                 correct = False;
578         }
579
580         if (!close_connection(&cli1)) {
581                 correct = False;
582         }
583         return correct;
584 }
585
586 int line_count = 0;
587
588 /* run a test that simulates an approximate netbench client load */
589 static BOOL run_netbench(int client)
590 {
591         struct cli_state cli;
592         int i;
593         fstring fname;
594         pstring line;
595         char cname[20];
596         FILE *f;
597         char *params[20];
598         BOOL correct = True;
599
600         cli = current_cli;
601
602         cli_sockopt(&cli, sockops);
603
604         nb_setup(&cli);
605
606         slprintf(cname,sizeof(fname), "CLIENT%d", client);
607
608         f = fopen("client.txt", "r");
609
610         if (!f) {
611                 perror("client.txt");
612                 return False;
613         }
614
615         while (fgets(line, sizeof(line)-1, f)) {
616                 line_count++;
617
618                 line[strlen(line)-1] = 0;
619
620                 /* printf("[%d] %s\n", line_count, line); */
621
622                 all_string_sub(line,"CLIENT1", cname, sizeof(line));
623                 
624                 for (i=0;i<20;i++) params[i] = "";
625
626                 /* parse the command parameters */
627                 params[0] = strtok(line," ");
628                 i = 0;
629                 while (params[i]) params[++i] = strtok(NULL," ");
630
631                 params[i] = "";
632
633                 if (i < 2) continue;
634
635                 if (strcmp(params[1],"REQUEST") == 0) {
636                         if (!strcmp(params[0],"SMBopenX")) {
637                                 fstrcpy(fname, params[5]);
638                         } else if (!strcmp(params[0],"SMBclose")) {
639                                 nb_close(atoi(params[3]));
640                         } else if (!strcmp(params[0],"SMBmkdir")) {
641                                 nb_mkdir(params[3]);
642                         } else if (!strcmp(params[0],"CREATE")) {
643                                 nb_create(params[3], atoi(params[5]));
644                         } else if (!strcmp(params[0],"SMBrmdir")) {
645                                 nb_rmdir(params[3]);
646                         } else if (!strcmp(params[0],"SMBunlink")) {
647                                 fstrcpy(fname, params[3]);
648                         } else if (!strcmp(params[0],"SMBmv")) {
649                                 nb_rename(params[3], params[5]);
650                         } else if (!strcmp(params[0],"SMBgetatr")) {
651                                 fstrcpy(fname, params[3]);
652                         } else if (!strcmp(params[0],"SMBwrite")) {
653                                 nb_write(atoi(params[3]), 
654                                          atoi(params[5]), atoi(params[7]));
655                         } else if (!strcmp(params[0],"SMBwritebraw")) {
656                                 nb_write(atoi(params[3]), 
657                                          atoi(params[7]), atoi(params[5]));
658                         } else if (!strcmp(params[0],"SMBreadbraw")) {
659                                 nb_read(atoi(params[3]), 
660                                          atoi(params[7]), atoi(params[5]));
661                         } else if (!strcmp(params[0],"SMBread")) {
662                                 nb_read(atoi(params[3]), 
663                                          atoi(params[5]), atoi(params[7]));
664                         }
665                 } else {
666                         if (!strcmp(params[0],"SMBopenX")) {
667                                 if (!strncmp(params[2], "ERR", 3)) continue;
668                                 nb_open(fname, atoi(params[3]), atoi(params[5]));
669                         } else if (!strcmp(params[0],"SMBgetatr")) {
670                                 if (!strncmp(params[2], "ERR", 3)) continue;
671                                 nb_stat(fname, atoi(params[3]));
672                         } else if (!strcmp(params[0],"SMBunlink")) {
673                                 if (!strncmp(params[2], "ERR", 3)) continue;
674                                 nb_unlink(fname);
675                         }
676                 }
677         }
678         fclose(f);
679
680         slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
681         rmdir(fname);
682         rmdir("CLIENTS");
683
684         printf("+");    
685
686         if (!close_connection(&cli)) {
687                 correct = False;
688         }
689         
690         return correct;
691 }
692
693
694 /* run a test that simulates an approximate netbench w9X client load */
695 static BOOL run_nbw95(int dummy)
696 {
697         double t;
698         BOOL correct = True;
699         t = create_procs(run_netbench, &correct);
700         /* to produce a netbench result we scale accoding to the
701            netbench measured throughput for the run that produced the
702            sniff that was used to produce client.txt. That run used 2
703            clients and ran for 660 seconds to produce a result of
704            4MBit/sec. */
705         printf("Throughput %g MB/sec (NB=%g MB/sec  %g MBit/sec)\n", 
706                132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
707         return correct;
708 }
709
710 /* run a test that simulates an approximate netbench wNT client load */
711 static BOOL run_nbwnt(int dummy)
712 {
713         double t;
714         BOOL correct = True;
715         t = create_procs(run_netbench, &correct);
716         printf("Throughput %g MB/sec (NB=%g MB/sec  %g MBit/sec)\n", 
717                132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
718         return correct;
719 }
720
721
722
723 /*
724   This test checks for two things:
725
726   1) correct support for retaining locks over a close (ie. the server
727      must not use posix semantics)
728   2) support for lock timeouts
729  */
730 static BOOL run_locktest1(int dummy)
731 {
732         static struct cli_state cli1, cli2;
733         char *fname = "\\lockt1.lck";
734         int fnum1, fnum2, fnum3;
735         time_t t1, t2;
736
737         if (!open_connection(&cli1) || !open_connection(&cli2)) {
738                 return False;
739         }
740         cli_sockopt(&cli1, sockops);
741         cli_sockopt(&cli2, sockops);
742
743         printf("starting locktest1\n");
744
745         cli_unlink(&cli1, fname);
746
747         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
748         if (fnum1 == -1) {
749                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
750                 return False;
751         }
752         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
753         if (fnum2 == -1) {
754                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
755                 return False;
756         }
757         fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
758         if (fnum3 == -1) {
759                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
760                 return False;
761         }
762
763         if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
764                 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
765                 return False;
766         }
767
768
769         if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
770                 printf("lock2 succeeded! This is a locking bug\n");
771                 return False;
772         } else {
773                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
774         }
775
776
777         printf("Testing lock timeouts\n");
778         t1 = time(NULL);
779         if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
780                 printf("lock3 succeeded! This is a locking bug\n");
781                 return False;
782         } else {
783                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
784         }
785         t2 = time(NULL);
786
787         if (t2 - t1 < 5) {
788                 printf("error: This server appears not to support timed lock requests\n");
789         }
790
791         if (!cli_close(&cli1, fnum2)) {
792                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
793                 return False;
794         }
795
796         if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
797                 printf("lock4 succeeded! This is a locking bug\n");
798                 return False;
799         } else {
800                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
801         }
802
803         if (!cli_close(&cli1, fnum1)) {
804                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
805                 return False;
806         }
807
808         if (!cli_close(&cli2, fnum3)) {
809                 printf("close3 failed (%s)\n", cli_errstr(&cli2));
810                 return False;
811         }
812
813         if (!cli_unlink(&cli1, fname)) {
814                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
815                 return False;
816         }
817
818
819         if (!close_connection(&cli1)) {
820                 return False;
821         }
822
823         if (!close_connection(&cli2)) {
824                 return False;
825         }
826
827         printf("Passed locktest1\n");
828         return True;
829 }
830
831 /*
832  checks for correct tconX support
833  */
834 static BOOL run_tcon_test(int dummy)
835 {
836         static struct cli_state cli1;
837         char *fname = "\\tcontest.tmp";
838         int fnum1;
839         uint16 cnum;
840         char buf[4];
841
842         if (!open_connection(&cli1)) {
843                 return False;
844         }
845         cli_sockopt(&cli1, sockops);
846
847         printf("starting tcontest\n");
848
849         cli_unlink(&cli1, fname);
850
851         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
852         if (fnum1 == -1)
853         {
854                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
855                 return False;
856         }
857
858         cnum = cli1.cnum;
859
860         if (cli_write(&cli1, fnum1, 0, buf, 130, 4) != 4)
861         {
862                 printf("write failed (%s)", cli_errstr(&cli1));
863                 return False;
864         }
865
866         if (!cli_send_tconX(&cli1, share, "?????",
867                             password, strlen(password)+1)) {
868                 printf("%s refused 2nd tree connect (%s)\n", host,
869                            cli_errstr(&cli1));
870                 cli_shutdown(&cli1);
871                 return False;
872         }
873
874         if (cli_write(&cli1, fnum1, 0, buf, 130, 4) == 4)
875         {
876                 printf("write succeeded (%s)", cli_errstr(&cli1));
877                 return False;
878         }
879
880         if (cli_close(&cli1, fnum1)) {
881                 printf("close2 succeeded (%s)\n", cli_errstr(&cli1));
882                 return False;
883         }
884
885         if (!cli_tdis(&cli1)) {
886                 printf("tdis failed (%s)\n", cli_errstr(&cli1));
887                 return False;
888         }
889
890         cli1.cnum = cnum;
891
892         if (!cli_close(&cli1, fnum1)) {
893                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
894                 return False;
895         }
896
897         if (!close_connection(&cli1)) {
898                 return False;
899         }
900
901         printf("Passed tcontest\n");
902         return True;
903 }
904
905
906 /*
907   This test checks that 
908
909   1) the server supports multiple locking contexts on the one SMB
910   connection, distinguished by PID.  
911
912   2) the server correctly fails overlapping locks made by the same PID (this
913      goes against POSIX behaviour, which is why it is tricky to implement)
914
915   3) the server denies unlock requests by an incorrect client PID
916 */
917 static BOOL run_locktest2(int dummy)
918 {
919         static struct cli_state cli;
920         char *fname = "\\lockt2.lck";
921         int fnum1, fnum2, fnum3;
922         BOOL correct = True;
923
924         if (!open_connection(&cli)) {
925                 return False;
926         }
927
928         cli_sockopt(&cli, sockops);
929
930         printf("starting locktest2\n");
931
932         cli_unlink(&cli, fname);
933
934         cli_setpid(&cli, 1);
935
936         fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
937         if (fnum1 == -1) {
938                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
939                 return False;
940         }
941
942         fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
943         if (fnum2 == -1) {
944                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
945                 return False;
946         }
947
948         cli_setpid(&cli, 2);
949
950         fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
951         if (fnum3 == -1) {
952                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
953                 return False;
954         }
955
956         cli_setpid(&cli, 1);
957
958         if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
959                 printf("lock1 failed (%s)\n", cli_errstr(&cli));
960                 return False;
961         }
962
963         if (cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
964                 printf("WRITE lock1 succeeded! This is a locking bug\n");
965                 correct = False;
966         } else {
967                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
968         }
969
970         if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
971                 printf("WRITE lock2 succeeded! This is a locking bug\n");
972                 correct = False;
973         } else {
974                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
975         }
976
977         if (cli_lock(&cli, fnum2, 0, 4, 0, READ_LOCK)) {
978                 printf("READ lock2 succeeded! This is a locking bug\n");
979                 correct = False;
980         } else {
981                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
982         }
983
984         cli_setpid(&cli, 2);
985
986         if (cli_unlock(&cli, fnum1, 0, 8)) {
987                 printf("unlock1 succeeded! This is a locking bug\n");
988                 correct = False;
989         }
990
991         if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
992                 printf("lock3 succeeded! This is a locking bug\n");
993                 correct = False;
994         } else {
995                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
996         }
997
998         cli_setpid(&cli, 1);
999
1000         if (!cli_close(&cli, fnum1)) {
1001                 printf("close1 failed (%s)\n", cli_errstr(&cli));
1002                 return False;
1003         }
1004
1005         if (!cli_close(&cli, fnum2)) {
1006                 printf("close2 failed (%s)\n", cli_errstr(&cli));
1007                 return False;
1008         }
1009
1010         if (!cli_close(&cli, fnum3)) {
1011                 printf("close3 failed (%s)\n", cli_errstr(&cli));
1012                 return False;
1013         }
1014
1015         if (!close_connection(&cli)) {
1016                 correct = False;
1017         }
1018
1019         printf("locktest2 finished\n");
1020
1021         return correct;
1022 }
1023
1024
1025 /*
1026   This test checks that 
1027
1028   1) the server supports the full offset range in lock requests
1029 */
1030 static BOOL run_locktest3(int dummy)
1031 {
1032         static struct cli_state cli1, cli2;
1033         char *fname = "\\lockt3.lck";
1034         int fnum1, fnum2, i;
1035         uint32 offset;
1036         BOOL correct = True;
1037
1038 #define NEXT_OFFSET offset += (~(uint32)0) / numops
1039
1040         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1041                 return False;
1042         }
1043         cli_sockopt(&cli1, sockops);
1044         cli_sockopt(&cli2, sockops);
1045
1046         printf("starting locktest3\n");
1047
1048         cli_unlink(&cli1, fname);
1049
1050         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1051         if (fnum1 == -1) {
1052                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1053                 return False;
1054         }
1055         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1056         if (fnum2 == -1) {
1057                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
1058                 return False;
1059         }
1060
1061         for (offset=i=0;i<numops;i++) {
1062                 NEXT_OFFSET;
1063                 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1064                         printf("lock1 %d failed (%s)\n", 
1065                                i,
1066                                cli_errstr(&cli1));
1067                         return False;
1068                 }
1069
1070                 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1071                         printf("lock2 %d failed (%s)\n", 
1072                                i,
1073                                cli_errstr(&cli1));
1074                         return False;
1075                 }
1076         }
1077
1078         for (offset=i=0;i<numops;i++) {
1079                 NEXT_OFFSET;
1080
1081                 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1082                         printf("error: lock1 %d succeeded!\n", i);
1083                         return False;
1084                 }
1085
1086                 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1087                         printf("error: lock2 %d succeeded!\n", i);
1088                         return False;
1089                 }
1090
1091                 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1092                         printf("error: lock3 %d succeeded!\n", i);
1093                         return False;
1094                 }
1095
1096                 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1097                         printf("error: lock4 %d succeeded!\n", i);
1098                         return False;
1099                 }
1100         }
1101
1102         for (offset=i=0;i<numops;i++) {
1103                 NEXT_OFFSET;
1104
1105                 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
1106                         printf("unlock1 %d failed (%s)\n", 
1107                                i,
1108                                cli_errstr(&cli1));
1109                         return False;
1110                 }
1111
1112                 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
1113                         printf("unlock2 %d failed (%s)\n", 
1114                                i,
1115                                cli_errstr(&cli1));
1116                         return False;
1117                 }
1118         }
1119
1120         if (!cli_close(&cli1, fnum1)) {
1121                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
1122                 return False;
1123         }
1124
1125         if (!cli_close(&cli2, fnum2)) {
1126                 printf("close2 failed (%s)\n", cli_errstr(&cli2));
1127                 return False;
1128         }
1129
1130         if (!cli_unlink(&cli1, fname)) {
1131                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1132                 return False;
1133         }
1134
1135         if (!close_connection(&cli1)) {
1136                 correct = False;
1137         }
1138         
1139         if (!close_connection(&cli2)) {
1140                 correct = False;
1141         }
1142
1143         printf("finished locktest3\n");
1144
1145         return correct;
1146 }
1147
1148 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1149         printf("** "); correct = False; \
1150         }
1151
1152 /*
1153   looks at overlapping locks
1154 */
1155 static BOOL run_locktest4(int dummy)
1156 {
1157         static struct cli_state cli1, cli2;
1158         char *fname = "\\lockt4.lck";
1159         int fnum1, fnum2, f;
1160         BOOL ret;
1161         char buf[1000];
1162         BOOL correct = True;
1163
1164         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1165                 return False;
1166         }
1167
1168         cli_sockopt(&cli1, sockops);
1169         cli_sockopt(&cli2, sockops);
1170
1171         printf("starting locktest4\n");
1172
1173         cli_unlink(&cli1, fname);
1174
1175         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1176         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1177
1178         memset(buf, 0, sizeof(buf));
1179
1180         if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1181                 printf("Failed to create file\n");
1182                 correct = False;
1183                 goto fail;
1184         }
1185
1186         ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1187               cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1188         EXPECTED(ret, False);
1189         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1190             
1191         ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1192               cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
1193         EXPECTED(ret, True);
1194         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1195
1196         ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1197               cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1198         EXPECTED(ret, False);
1199         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1200             
1201         ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1202               cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
1203         EXPECTED(ret, True);
1204         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1205         
1206         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1207               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1208         EXPECTED(ret, False);
1209         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1210             
1211         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1212               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
1213         EXPECTED(ret, True);
1214         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1215
1216         ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1217               cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
1218         EXPECTED(ret, True);
1219         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1220
1221         ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1222               cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1223         EXPECTED(ret, False);
1224         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1225
1226         ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1227               cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1228         EXPECTED(ret, False);
1229         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1230
1231         ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1232               cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
1233         EXPECTED(ret, True);
1234         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1235
1236         ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1237               (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
1238         EXPECTED(ret, False);
1239         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1240
1241         ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1242               cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1243               cli_unlock(&cli1, fnum1, 110, 6);
1244         EXPECTED(ret, False);
1245         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1246
1247
1248         ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1249               (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
1250         EXPECTED(ret, False);
1251         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1252
1253         ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
1254               (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
1255         EXPECTED(ret, False);
1256         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1257
1258
1259         ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1260               cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1261               cli_unlock(&cli1, fnum1, 140, 4) &&
1262               cli_unlock(&cli1, fnum1, 140, 4);
1263         EXPECTED(ret, True);
1264         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1265
1266
1267         ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1268               cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1269               cli_unlock(&cli1, fnum1, 150, 4) &&
1270               (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
1271               !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
1272               cli_unlock(&cli1, fnum1, 150, 4);
1273         EXPECTED(ret, True);
1274         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1275
1276         ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1277               cli_unlock(&cli1, fnum1, 160, 4) &&
1278               (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&         
1279               (cli_read(&cli2, fnum2, buf, 160, 4) == 4);               
1280         EXPECTED(ret, True);
1281         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1282
1283         ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
1284               cli_unlock(&cli1, fnum1, 170, 4) &&
1285               (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&         
1286               (cli_read(&cli2, fnum2, buf, 170, 4) == 4);               
1287         EXPECTED(ret, True);
1288         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1289
1290         ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
1291               cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
1292               cli_unlock(&cli1, fnum1, 190, 4) &&
1293               !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&                
1294               (cli_read(&cli2, fnum2, buf, 190, 4) == 4);               
1295         EXPECTED(ret, True);
1296         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1297
1298         cli_close(&cli1, fnum1);
1299         cli_close(&cli2, fnum2);
1300         fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1301         f = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1302         ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1303               cli_lock(&cli1, f, 0, 1, 0, READ_LOCK) &&
1304               cli_close(&cli1, fnum1) &&
1305               ((fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE)) != -1) &&
1306               cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1307         cli_close(&cli1, f);
1308         EXPECTED(ret, True);
1309         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1310         
1311  fail:
1312         cli_close(&cli1, fnum1);
1313         cli_close(&cli2, fnum2);
1314         cli_unlink(&cli1, fname);
1315         close_connection(&cli1);
1316         close_connection(&cli2);
1317
1318         printf("finished locktest4\n");
1319         return correct;
1320 }
1321
1322 /*
1323   looks at lock upgrade/downgrade.
1324 */
1325 static BOOL run_locktest5(int dummy)
1326 {
1327         static struct cli_state cli1, cli2;
1328         char *fname = "\\lockt5.lck";
1329         int fnum1, fnum2, fnum3;
1330         BOOL ret;
1331         char buf[1000];
1332         BOOL correct = True;
1333
1334         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1335                 return False;
1336         }
1337
1338         cli_sockopt(&cli1, sockops);
1339         cli_sockopt(&cli2, sockops);
1340
1341         printf("starting locktest5\n");
1342
1343         cli_unlink(&cli1, fname);
1344
1345         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1346         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1347         fnum3 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1348
1349         memset(buf, 0, sizeof(buf));
1350
1351         if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1352                 printf("Failed to create file\n");
1353                 correct = False;
1354                 goto fail;
1355         }
1356
1357         /* Check for NT bug... */
1358         ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1359                   cli_lock(&cli1, fnum3, 0, 1, 0, READ_LOCK);
1360         cli_close(&cli1, fnum1);
1361         fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1362         ret = cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1363         EXPECTED(ret, True);
1364         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1365         cli_close(&cli1, fnum1);
1366         fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1367         cli_unlock(&cli1, fnum3, 0, 1);
1368
1369         ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1370               cli_lock(&cli1, fnum1, 1, 1, 0, READ_LOCK);
1371         EXPECTED(ret, True);
1372         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1373
1374         ret = cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1375         EXPECTED(ret, False);
1376
1377         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1378
1379         /* Unlock the process 2 lock. */
1380         cli_unlock(&cli2, fnum2, 0, 4);
1381
1382         ret = cli_lock(&cli1, fnum3, 0, 4, 0, READ_LOCK);
1383         EXPECTED(ret, False);
1384
1385         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1386
1387         /* Unlock the process 1 fnum3 lock. */
1388         cli_unlock(&cli1, fnum3, 0, 4);
1389
1390         /* Stack 2 more locks here. */
1391         ret = cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1392                   cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK);
1393
1394         EXPECTED(ret, True);
1395         printf("the same process %s stack read locks\n", ret?"can":"cannot");
1396
1397         /* Unlock the first process lock, then check this was the WRITE lock that was
1398                 removed. */
1399
1400         ret = cli_unlock(&cli1, fnum1, 0, 4) &&
1401                         cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1402
1403         EXPECTED(ret, True);
1404         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1405
1406         /* Unlock the process 2 lock. */
1407         cli_unlock(&cli2, fnum2, 0, 4);
1408
1409         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1410
1411         ret = cli_unlock(&cli1, fnum1, 1, 1) &&
1412                   cli_unlock(&cli1, fnum1, 0, 4) &&
1413                   cli_unlock(&cli1, fnum1, 0, 4);
1414
1415         EXPECTED(ret, True);
1416         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
1417
1418         /* Ensure the next unlock fails. */
1419         ret = cli_unlock(&cli1, fnum1, 0, 4);
1420         EXPECTED(ret, False);
1421         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
1422
1423         /* Ensure connection 2 can get a write lock. */
1424         ret = cli_lock(&cli2, fnum2, 0, 4, 0, WRITE_LOCK);
1425         EXPECTED(ret, True);
1426
1427         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1428
1429
1430  fail:
1431         cli_close(&cli1, fnum1);
1432         cli_close(&cli2, fnum2);
1433         cli_unlink(&cli1, fname);
1434         if (!close_connection(&cli1)) {
1435                 correct = False;
1436         }
1437         if (!close_connection(&cli2)) {
1438                 correct = False;
1439         }
1440
1441         printf("finished locktest5\n");
1442        
1443         return correct;
1444 }
1445
1446
1447 /*
1448   this produces a matrix of deny mode behaviour
1449  */
1450 static BOOL run_denytest1(int dummy)
1451 {
1452         static struct cli_state cli1, cli2;
1453         int fnum1, fnum2;
1454         int f, d1, d2, o1, o2, x=0;
1455         char *fnames[] = {"\\denytest1.exe", "\\denytest1.dat", NULL};
1456         struct {
1457                 int v;
1458                 char *name; 
1459         } deny_modes[] = {
1460                 {DENY_DOS, "DENY_DOS"},
1461                 {DENY_ALL, "DENY_ALL"},
1462                 {DENY_WRITE, "DENY_WRITE"},
1463                 {DENY_READ, "DENY_READ"},
1464                 {DENY_NONE, "DENY_NONE"},
1465                 {DENY_FCB, "DENY_FCB"},
1466                 {-1, NULL}};
1467         struct {
1468                 int v;
1469                 char *name; 
1470         } open_modes[] = {
1471                 {O_RDWR, "O_RDWR"},
1472                 {O_RDONLY, "O_RDONLY"},
1473                 {O_WRONLY, "O_WRONLY"},
1474                 {-1, NULL}};
1475         BOOL correct = True;
1476
1477         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1478                 return False;
1479         }
1480         cli_sockopt(&cli1, sockops);
1481         cli_sockopt(&cli2, sockops);
1482
1483         printf("starting denytest1\n");
1484
1485         for (f=0;fnames[f];f++) {
1486                 cli_unlink(&cli1, fnames[f]);
1487
1488                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1489                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1490                 cli_close(&cli1, fnum1);
1491
1492                 for (d1=0;deny_modes[d1].name;d1++) 
1493                 for (o1=0;open_modes[o1].name;o1++) 
1494                 for (d2=0;deny_modes[d2].name;d2++) 
1495                 for (o2=0;open_modes[o2].name;o2++) {
1496                         fnum1 = cli_open(&cli1, fnames[f], 
1497                                          open_modes[o1].v, 
1498                                          deny_modes[d1].v);
1499                         fnum2 = cli_open(&cli2, fnames[f], 
1500                                          open_modes[o2].v, 
1501                                          deny_modes[d2].v);
1502
1503                         printf("%s %8s %10s    %8s %10s     ",
1504                                fnames[f],
1505                                open_modes[o1].name,
1506                                deny_modes[d1].name,
1507                                open_modes[o2].name,
1508                                deny_modes[d2].name);
1509
1510                         if (fnum1 == -1) {
1511                                 printf("X");
1512                         } else if (fnum2 == -1) {
1513                                 printf("-");
1514                         } else {
1515                                 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
1516                                         printf("R");
1517                                 }
1518                                 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
1519                                         printf("W");
1520                                 }
1521                         }
1522
1523                         printf("\n");
1524                         cli_close(&cli1, fnum1);
1525                         cli_close(&cli2, fnum2);
1526                 }
1527                 
1528                 cli_unlink(&cli1, fnames[f]);
1529         }
1530
1531         if (!close_connection(&cli1)) {
1532                 correct = False;
1533         }
1534         if (!close_connection(&cli2)) {
1535                 correct = False;
1536         }
1537         
1538         printf("finshed denytest1\n");
1539         return correct;
1540 }
1541
1542
1543 /*
1544   this produces a matrix of deny mode behaviour for two opens on the
1545   same connection
1546  */
1547 static BOOL run_denytest2(int dummy)
1548 {
1549         static struct cli_state cli1;
1550         int fnum1, fnum2;
1551         int f, d1, d2, o1, o2, x=0;
1552         char *fnames[] = {"\\denytest2.exe", "\\denytest2.dat", NULL};
1553         struct {
1554                 int v;
1555                 char *name; 
1556         } deny_modes[] = {
1557                 {DENY_DOS, "DENY_DOS"},
1558                 {DENY_ALL, "DENY_ALL"},
1559                 {DENY_WRITE, "DENY_WRITE"},
1560                 {DENY_READ, "DENY_READ"},
1561                 {DENY_NONE, "DENY_NONE"},
1562                 {DENY_FCB, "DENY_FCB"},
1563                 {-1, NULL}};
1564         struct {
1565                 int v;
1566                 char *name; 
1567         } open_modes[] = {
1568                 {O_RDWR, "O_RDWR"},
1569                 {O_RDONLY, "O_RDONLY"},
1570                 {O_WRONLY, "O_WRONLY"},
1571                 {-1, NULL}};
1572         BOOL correct = True;
1573
1574         if (!open_connection(&cli1)) {
1575                 return False;
1576         }
1577         cli_sockopt(&cli1, sockops);
1578
1579         printf("starting denytest2\n");
1580
1581         for (f=0;fnames[f];f++) {
1582                 cli_unlink(&cli1, fnames[f]);
1583
1584                 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1585                 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1586                 cli_close(&cli1, fnum1);
1587
1588                 for (d1=0;deny_modes[d1].name;d1++) 
1589                 for (o1=0;open_modes[o1].name;o1++) 
1590                 for (d2=0;deny_modes[d2].name;d2++) 
1591                 for (o2=0;open_modes[o2].name;o2++) {
1592                         fnum1 = cli_open(&cli1, fnames[f], 
1593                                          open_modes[o1].v, 
1594                                          deny_modes[d1].v);
1595                         fnum2 = cli_open(&cli1, fnames[f], 
1596                                          open_modes[o2].v, 
1597                                          deny_modes[d2].v);
1598
1599                         printf("%s %8s %10s    %8s %10s     ",
1600                                fnames[f],
1601                                open_modes[o1].name,
1602                                deny_modes[d1].name,
1603                                open_modes[o2].name,
1604                                deny_modes[d2].name);
1605
1606                         if (fnum1 == -1) {
1607                                 printf("X");
1608                         } else if (fnum2 == -1) {
1609                                 printf("-");
1610                         } else {
1611                                 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1612                                         printf("R");
1613                                 }
1614                                 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1615                                         printf("W");
1616                                 }
1617                         }
1618
1619                         printf("\n");
1620                         cli_close(&cli1, fnum1);
1621                         cli_close(&cli1, fnum2);
1622                 }
1623                 
1624                 cli_unlink(&cli1, fnames[f]);
1625         }
1626
1627         if (!close_connection(&cli1)) {
1628                 correct = False;
1629         }
1630         
1631         printf("finshed denytest2\n");
1632         return correct;
1633 }
1634
1635 /*
1636 test whether fnums and tids open on one VC are available on another (a major
1637 security hole)
1638 */
1639 static BOOL run_fdpasstest(int dummy)
1640 {
1641         static struct cli_state cli1, cli2, cli3;
1642         char *fname = "\\fdpass.tst";
1643         int fnum1;
1644         pstring buf;
1645
1646         if (!open_connection(&cli1) || !open_connection(&cli2)) {
1647                 return False;
1648         }
1649         cli_sockopt(&cli1, sockops);
1650         cli_sockopt(&cli2, sockops);
1651
1652         printf("starting fdpasstest\n");
1653
1654         cli_unlink(&cli1, fname);
1655
1656         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1657         if (fnum1 == -1) {
1658                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1659                 return False;
1660         }
1661
1662         if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1663                 printf("write failed (%s)\n", cli_errstr(&cli1));
1664                 return False;
1665         }
1666
1667         cli3 = cli2;
1668         cli3.vuid = cli1.vuid;
1669         cli3.cnum = cli1.cnum;
1670         cli3.pid = cli1.pid;
1671
1672         if (cli_read(&cli3, fnum1, buf, 0, 13) == 13) {
1673                 printf("read succeeded! nasty security hole [%s]\n",
1674                        buf);
1675                 return False;
1676         }
1677
1678         cli_close(&cli1, fnum1);
1679         cli_unlink(&cli1, fname);
1680
1681         close_connection(&cli1);
1682         close_connection(&cli2);
1683
1684         printf("finished fdpasstest\n");
1685         return True;
1686 }
1687
1688
1689 /*
1690   This test checks that 
1691
1692   1) the server does not allow an unlink on a file that is open
1693 */
1694 static BOOL run_unlinktest(int dummy)
1695 {
1696         static struct cli_state cli;
1697         char *fname = "\\unlink.tst";
1698         int fnum;
1699         BOOL correct = True;
1700
1701         if (!open_connection(&cli)) {
1702                 return False;
1703         }
1704
1705         cli_sockopt(&cli, sockops);
1706
1707         printf("starting unlink test\n");
1708
1709         cli_unlink(&cli, fname);
1710
1711         cli_setpid(&cli, 1);
1712
1713         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1714         if (fnum == -1) {
1715                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
1716                 return False;
1717         }
1718
1719         if (cli_unlink(&cli, fname)) {
1720                 printf("error: server allowed unlink on an open file\n");
1721                 correct = False;
1722         }
1723
1724         cli_close(&cli, fnum);
1725         cli_unlink(&cli, fname);
1726
1727         if (!close_connection(&cli)) {
1728                 correct = False;
1729         }
1730
1731         printf("unlink test finished\n");
1732         
1733         return correct;
1734 }
1735
1736
1737 /*
1738 test how many open files this server supports on the one socket
1739 */
1740 static BOOL run_maxfidtest(int dummy)
1741 {
1742         static struct cli_state cli;
1743         char *template = "\\maxfid.%d.%d";
1744         fstring fname;
1745         int fnum;
1746         int retries=4;
1747         BOOL correct = True;
1748
1749         cli = current_cli;
1750
1751         if (retries <= 0) {
1752                 printf("failed to connect\n");
1753                 return False;
1754         }
1755
1756         cli_sockopt(&cli, sockops);
1757
1758         fnum = 0;
1759         while (1) {
1760                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1761                 if (cli_open(&cli, fname, 
1762                              O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
1763                     -1) {
1764                         printf("open of %s failed (%s)\n", 
1765                                fname, cli_errstr(&cli));
1766                         printf("maximum fnum is %d\n", fnum);
1767                         break;
1768                 }
1769                 fnum++;
1770                 if (fnum % 100 == 0) printf("%d\r", fnum);
1771         }
1772         printf("%d\n", fnum);
1773
1774         printf("cleaning up\n");
1775         while (fnum > 0) {
1776                 fnum--;
1777                 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
1778                 cli_close(&cli, fnum);
1779                 if (!cli_unlink(&cli, fname)) {
1780                         printf("unlink of %s failed (%s)\n", 
1781                                fname, cli_errstr(&cli));
1782                         correct = False;
1783                 }
1784         }
1785
1786         printf("maxfid test finished\n");
1787         if (!close_connection(&cli)) {
1788                 correct = False;
1789         }
1790         return correct;
1791 }
1792
1793 /* generate a random buffer */
1794 static void rand_buf(char *buf, int len)
1795 {
1796         while (len--) {
1797                 *buf = (char)sys_random();
1798                 buf++;
1799         }
1800 }
1801
1802 /* send smb negprot commands, not reading the response */
1803 static BOOL run_negprot_nowait(int dummy)
1804 {
1805         int i;
1806         static struct cli_state cli;
1807         BOOL correct = True;
1808
1809         printf("starting negprot nowait test\n");
1810
1811         if (!open_nbt_connection(&cli)) {
1812                 return False;
1813         }
1814
1815         for (i=0;i<50000;i++) {
1816                 cli_negprot_send(&cli);
1817         }
1818
1819         if (!close_connection(&cli)) {
1820                 correct = False;
1821         }
1822
1823         printf("finished negprot nowait test\n");
1824
1825         return correct;
1826 }
1827
1828
1829 /* send random IPC commands */
1830 static BOOL run_randomipc(int dummy)
1831 {
1832         char *rparam = NULL;
1833         char *rdata = NULL;
1834         int rdrcnt,rprcnt;
1835         pstring param;
1836         int api, param_len, i;
1837         static struct cli_state cli;
1838         BOOL correct = True;
1839
1840         printf("starting random ipc test\n");
1841
1842         if (!open_connection(&cli)) {
1843                 return False;
1844         }
1845
1846         for (i=0;i<50000;i++) {
1847                 api = sys_random() % 500;
1848                 param_len = (sys_random() % 64);
1849
1850                 rand_buf(param, param_len);
1851   
1852                 SSVAL(param,0,api); 
1853
1854                 cli_api(&cli, 
1855                         param, param_len, 8,  
1856                         NULL, 0, BUFFER_SIZE, 
1857                         &rparam, &rprcnt,     
1858                         &rdata, &rdrcnt);
1859         }
1860
1861         if (!close_connection(&cli)) {
1862                 correct = False;
1863         }
1864
1865         printf("finished random ipc test\n");
1866
1867         return correct;
1868 }
1869
1870
1871
1872 static void browse_callback(const char *sname, uint32 stype, 
1873                             const char *comment, void *state)
1874 {
1875         printf("\t%20.20s %08x %s\n", sname, stype, comment);
1876 }
1877
1878
1879
1880 /*
1881   This test checks the browse list code
1882
1883 */
1884 static BOOL run_browsetest(int dummy)
1885 {
1886         static struct cli_state cli;
1887         BOOL correct = True;
1888
1889         printf("starting browse test\n");
1890
1891         if (!open_connection(&cli)) {
1892                 return False;
1893         }
1894
1895         printf("domain list:\n");
1896         cli_NetServerEnum(&cli, cli.server_domain, 
1897                           SV_TYPE_DOMAIN_ENUM,
1898                           browse_callback, NULL);
1899
1900         printf("machine list:\n");
1901         cli_NetServerEnum(&cli, cli.server_domain, 
1902                           SV_TYPE_ALL,
1903                           browse_callback, NULL);
1904
1905         if (!close_connection(&cli)) {
1906                 correct = False;
1907         }
1908
1909         printf("browse test finished\n");
1910
1911         return correct;
1912
1913 }
1914
1915
1916 /*
1917   This checks how the getatr calls works
1918 */
1919 static BOOL run_attrtest(int dummy)
1920 {
1921         static struct cli_state cli;
1922         int fnum;
1923         time_t t, t2;
1924         char *fname = "\\attrib.tst";
1925         BOOL correct = True;
1926
1927         printf("starting attrib test\n");
1928
1929         if (!open_connection(&cli)) {
1930                 return False;
1931         }
1932
1933         cli_unlink(&cli, fname);
1934         fnum = cli_open(&cli, fname, 
1935                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1936         cli_close(&cli, fnum);
1937         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1938                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1939                 correct = False;
1940         }
1941
1942         if (abs(t - time(NULL)) > 2) {
1943                 printf("ERROR: SMBgetatr bug. time is %s",
1944                        ctime(&t));
1945                 t = time(NULL);
1946                 correct = True;
1947         }
1948
1949         t2 = t-60*60*24; /* 1 day ago */
1950
1951         if (!cli_setatr(&cli, fname, 0, t2)) {
1952                 printf("setatr failed (%s)\n", cli_errstr(&cli));
1953                 correct = True;
1954         }
1955
1956         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
1957                 printf("getatr failed (%s)\n", cli_errstr(&cli));
1958                 correct = True;
1959         }
1960
1961         if (t != t2) {
1962                 printf("ERROR: getatr/setatr bug. times are\n%s",
1963                        ctime(&t));
1964                 printf("%s", ctime(&t2));
1965                 correct = True;
1966         }
1967
1968         cli_unlink(&cli, fname);
1969
1970         if (!close_connection(&cli)) {
1971                 correct = False;
1972         }
1973
1974         printf("attrib test finished\n");
1975
1976         return correct;
1977 }
1978
1979
1980 /*
1981   This checks a couple of trans2 calls
1982 */
1983 static BOOL run_trans2test(int dummy)
1984 {
1985         static struct cli_state cli;
1986         int fnum;
1987         size_t size;
1988         time_t c_time, a_time, m_time, w_time, m_time2;
1989         char *fname = "\\trans2.tst";
1990         char *dname = "\\trans2";
1991         char *fname2 = "\\trans2\\trans2.tst";
1992         BOOL correct = True;
1993
1994         printf("starting trans2 test\n");
1995
1996         if (!open_connection(&cli)) {
1997                 return False;
1998         }
1999
2000         cli_unlink(&cli, fname);
2001         fnum = cli_open(&cli, fname, 
2002                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2003         if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
2004                            NULL, NULL)) {
2005                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
2006                 correct = False;
2007         }
2008         cli_close(&cli, fnum);
2009
2010         sleep(2);
2011
2012         cli_unlink(&cli, fname);
2013         fnum = cli_open(&cli, fname, 
2014                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2015         cli_close(&cli, fnum);
2016
2017         if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
2018                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
2019                 correct = False;
2020         } else {
2021                 if (c_time != m_time) {
2022                         printf("create time=%s", ctime(&c_time));
2023                         printf("modify time=%s", ctime(&m_time));
2024                         printf("This system appears to have sticky create times\n");
2025                         correct = False;
2026                 }
2027                 if (a_time % (60*60) == 0) {
2028                         printf("access time=%s", ctime(&a_time));
2029                         printf("This system appears to set a midnight access time\n");
2030                         correct = False;
2031                 }
2032
2033                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
2034                         printf("ERROR: totally incorrect times - maybe word reversed?\n");
2035                         correct = False;
2036                 }
2037         }
2038
2039
2040         cli_unlink(&cli, fname);
2041         fnum = cli_open(&cli, fname, 
2042                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2043         cli_close(&cli, fnum);
2044         if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, 
2045                             &w_time, &size, NULL, NULL)) {
2046                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
2047                 correct = False;
2048         } else {
2049                 if (w_time < 60*60*24*2) {
2050                         printf("write time=%s", ctime(&w_time));
2051                         printf("This system appears to set a initial 0 write time\n");
2052                         correct = False;
2053                 }
2054         }
2055
2056         cli_unlink(&cli, fname);
2057
2058
2059         /* check if the server updates the directory modification time
2060            when creating a new file */
2061         if (!cli_mkdir(&cli, dname)) {
2062                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
2063                 correct = False;
2064         }
2065         sleep(3);
2066         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, 
2067                             &w_time, &size, NULL, NULL)) {
2068                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
2069                 correct = False;
2070         }
2071
2072         fnum = cli_open(&cli, fname2, 
2073                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
2074         cli_write(&cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
2075         cli_close(&cli, fnum);
2076         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, 
2077                             &w_time, &size, NULL, NULL)) {
2078                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
2079                 correct = False;
2080         } else {
2081                 if (m_time2 == m_time) {
2082                         printf("This system does not update directory modification times\n");
2083                         correct = False;
2084                 }
2085         }
2086         cli_unlink(&cli, fname2);
2087         cli_rmdir(&cli, dname);
2088
2089         if (!close_connection(&cli)) {
2090                 correct = False;
2091         }
2092
2093         printf("trans2 test finished\n");
2094
2095         return correct;
2096 }
2097
2098 /*
2099   This checks new W2K calls.
2100 */
2101
2102 static BOOL new_trans(struct cli_state *pcli, int fnum, int level)
2103 {
2104         char buf[4096];
2105         BOOL correct = True;
2106
2107         memset(buf, 0xff, sizeof(buf));
2108
2109         if (!cli_qfileinfo_test(pcli, fnum, level, buf)) {
2110                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level, cli_errstr(pcli));
2111                 correct = False;
2112         } else {
2113                 printf("qfileinfo: level %d\n", level);
2114                 dump_data(0, buf, 256);
2115                 printf("\n");
2116         }
2117         return correct;
2118 }
2119
2120 static BOOL run_w2ktest(int dummy)
2121 {
2122         static struct cli_state cli;
2123         int fnum;
2124         char *fname = "\\w2ktest\\w2k.tst";
2125         int level;
2126         BOOL correct = True;
2127
2128         printf("starting w2k test\n");
2129
2130         if (!open_connection(&cli)) {
2131                 return False;
2132         }
2133
2134         fnum = cli_open(&cli, fname, 
2135                         O_RDWR | O_CREAT , DENY_NONE);
2136
2137         for (level = 1004; level < 1040; level++) {
2138                 if (!new_trans(&cli, fnum, level)) {
2139                         correct = False;
2140                 }
2141         }
2142
2143         cli_close(&cli, fnum);
2144
2145         if (!close_connection(&cli)) {
2146                 correct = False;
2147         }
2148
2149         printf("w2k test finished\n");
2150         
2151         return correct;
2152 }
2153
2154
2155 /*
2156   this is a harness for some oplock tests
2157  */
2158 static BOOL run_oplock1(int dummy)
2159 {
2160         static struct cli_state cli1;
2161         char *fname = "\\lockt1.lck";
2162         int fnum1;
2163         BOOL correct = True;
2164
2165         printf("starting oplock test 1\n");
2166
2167         if (!open_connection(&cli1)) {
2168                 return False;
2169         }
2170
2171         cli_unlink(&cli1, fname);
2172
2173         cli_sockopt(&cli1, sockops);
2174
2175         cli1.use_oplocks = True;
2176
2177         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2178         if (fnum1 == -1) {
2179                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2180                 return False;
2181         }
2182
2183         cli1.use_oplocks = False;
2184
2185         cli_unlink(&cli1, fname);
2186         cli_unlink(&cli1, fname);
2187
2188         if (!cli_close(&cli1, fnum1)) {
2189                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
2190                 return False;
2191         }
2192
2193         if (!cli_unlink(&cli1, fname)) {
2194                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
2195                 return False;
2196         }
2197
2198         if (!close_connection(&cli1)) {
2199                 correct = False;
2200         }
2201
2202         printf("finished oplock test 1\n");
2203
2204         return correct;
2205 }
2206
2207 static BOOL run_oplock2(int dummy)
2208 {
2209         static struct cli_state cli1, cli2;
2210         char *fname = "\\lockt2.lck";
2211         int fnum1, fnum2;
2212         int saved_use_oplocks = use_oplocks;
2213         char buf[4];
2214         BOOL correct = True;
2215         volatile BOOL *shared_correct;
2216
2217         shared_correct = (volatile BOOL *)shm_setup(sizeof(BOOL));
2218         *shared_correct = True;
2219
2220         use_level_II_oplocks = True;
2221         use_oplocks = True;
2222
2223         printf("starting oplock test 2\n");
2224
2225         if (!open_connection(&cli1)) {
2226                 use_level_II_oplocks = False;
2227                 use_oplocks = saved_use_oplocks;
2228                 return False;
2229         }
2230
2231         cli1.use_oplocks = True;
2232         cli1.use_level_II_oplocks = True;
2233
2234         if (!open_connection(&cli2)) {
2235                 use_level_II_oplocks = False;
2236                 use_oplocks = saved_use_oplocks;
2237                 return False;
2238         }
2239
2240         cli2.use_oplocks = True;
2241         cli2.use_level_II_oplocks = True;
2242
2243         cli_unlink(&cli1, fname);
2244
2245         cli_sockopt(&cli1, sockops);
2246         cli_sockopt(&cli2, sockops);
2247
2248         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2249         if (fnum1 == -1) {
2250                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2251                 return False;
2252         }
2253
2254         /* Don't need the globals any more. */
2255         use_level_II_oplocks = False;
2256         use_oplocks = saved_use_oplocks;
2257
2258         if (fork() == 0) {
2259                 /* Child code */
2260                 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
2261                 if (fnum2 == -1) {
2262                         printf("second open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2263                         *shared_correct = False;
2264                         exit(0);
2265                 }
2266
2267                 sleep(2);
2268
2269                 if (!cli_close(&cli2, fnum2)) {
2270                         printf("close2 failed (%s)\n", cli_errstr(&cli1));
2271                         *shared_correct = False;
2272                 }
2273
2274                 exit(0);
2275         }
2276
2277         sleep(2);
2278
2279         /* Ensure cli1 processes the break. */
2280
2281         if (cli_read(&cli1, fnum1, buf, 0, 4) != 4) {
2282                 printf("read on fnum1 failed (%s)\n", cli_errstr(&cli1));
2283                 correct = False;
2284         }
2285
2286         /* Should now be at level II. */
2287         /* Test if sending a write locks causes a break to none. */
2288
2289         if (!cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK)) {
2290                 printf("lock failed (%s)\n", cli_errstr(&cli1));
2291                 correct = False;
2292         }
2293
2294         cli_unlock(&cli1, fnum1, 0, 4);
2295
2296         sleep(2);
2297
2298         if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
2299                 printf("lock failed (%s)\n", cli_errstr(&cli1));
2300                 correct = False;
2301         }
2302
2303         cli_unlock(&cli1, fnum1, 0, 4);
2304
2305         sleep(2);
2306
2307         cli_read(&cli1, fnum1, buf, 0, 4);
2308
2309 #if 0
2310         if (cli_write(&cli1, fnum1, 0, buf, 0, 4) != 4) {
2311                 printf("write on fnum1 failed (%s)\n", cli_errstr(&cli1));
2312                 correct = False;
2313         }
2314 #endif
2315
2316         if (!cli_close(&cli1, fnum1)) {
2317                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
2318                 correct = False;
2319         }
2320
2321         sleep(4);
2322
2323         if (!cli_unlink(&cli1, fname)) {
2324                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
2325                 correct = False;
2326         }
2327
2328         if (!close_connection(&cli1)) {
2329                 correct = False;
2330         }
2331
2332         if (!*shared_correct) {
2333                 correct = False;
2334         }
2335
2336         printf("finished oplock test 2\n");
2337
2338         return correct;
2339 }
2340
2341 /* handler for oplock 3 tests */
2342 static BOOL oplock3_handler(struct cli_state *cli, int fnum, unsigned char level)
2343 {
2344         printf("got oplock break fnum=%d level=%d\n",
2345                fnum, level);
2346         return cli_oplock_ack(cli, fnum, level);
2347 }
2348
2349 static BOOL run_oplock3(int dummy)
2350 {
2351         static struct cli_state cli;
2352         char *fname = "\\oplockt3.dat";
2353         int fnum;
2354         char buf[4] = "abcd";
2355         BOOL correct = True;
2356         volatile BOOL *shared_correct;
2357
2358         shared_correct = (volatile BOOL *)shm_setup(sizeof(BOOL));
2359         *shared_correct = True;
2360
2361         printf("starting oplock test 3\n");
2362
2363         if (fork() == 0) {
2364                 /* Child code */
2365                 use_oplocks = True;
2366                 use_level_II_oplocks = True;
2367                 if (!open_connection(&cli)) {
2368                         *shared_correct = False;
2369                         exit(0);
2370                 } 
2371                 sleep(2);
2372                 /* try to trigger a oplock break in parent */
2373                 fnum = cli_open(&cli, fname, O_RDWR, DENY_NONE);
2374                 cli_write(&cli, fnum, 0, buf, 0, 4);
2375                 exit(0);
2376         }
2377
2378         /* parent code */
2379         use_oplocks = True;
2380         use_level_II_oplocks = True;
2381         if (!open_connection(&cli)) { 
2382                 return False;
2383         }
2384         cli_oplock_handler(&cli, oplock3_handler);
2385         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
2386         cli_write(&cli, fnum, 0, buf, 0, 4);
2387         cli_close(&cli, fnum);
2388         fnum = cli_open(&cli, fname, O_RDWR, DENY_NONE);
2389         cli.timeout = 20000;
2390         cli_receive_smb(&cli);
2391         printf("finished oplock test 3\n");
2392
2393         return (correct && *shared_correct);
2394
2395 /* What are we looking for here?  What's sucess and what's FAILURE? */
2396 }
2397
2398
2399
2400 /*
2401   Test delete on close semantics.
2402  */
2403 static BOOL run_deletetest(int dummy)
2404 {
2405         static struct cli_state cli1;
2406         static struct cli_state cli2;
2407         char *fname = "\\delete.file";
2408         int fnum1, fnum2;
2409         BOOL correct = True;
2410         
2411         printf("starting delete test\n");
2412         
2413         if (!open_connection(&cli1)) {
2414                 return False;
2415         }
2416         
2417         cli_sockopt(&cli1, sockops);
2418         
2419         /* Test 1 - this should *NOT* delete the file on close. */
2420         
2421         cli_setatr(&cli1, fname, 0, 0);
2422         cli_unlink(&cli1, fname);
2423         
2424         fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2425                                    FILE_SHARE_DELETE, FILE_OVERWRITE_IF, DELETE_ON_CLOSE_FLAG);
2426         
2427         if (fnum1 == -1) {
2428                 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2429                 return False;
2430         }
2431         
2432         if (!cli_close(&cli1, fnum1)) {
2433                 printf("[1] close failed (%s)\n", cli_errstr(&cli1));
2434                 return False;
2435         }
2436
2437         fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
2438         if (fnum1 == -1) {
2439                 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2440                 return False;
2441         }
2442         
2443         if (!cli_close(&cli1, fnum1)) {
2444                 printf("[1] close failed (%s)\n", cli_errstr(&cli1));
2445                 return False;
2446         }
2447         
2448         printf("first delete on close test succeeded.\n");
2449         
2450         /* Test 2 - this should delete the file on close. */
2451         
2452         cli_setatr(&cli1, fname, 0, 0);
2453         cli_unlink(&cli1, fname);
2454         
2455         fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS,
2456                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0);
2457         
2458         if (fnum1 == -1) {
2459                 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2460                 return False;
2461         }
2462         
2463         if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
2464                 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
2465                 return False;
2466         }
2467         
2468         if (!cli_close(&cli1, fnum1)) {
2469                 printf("[2] close failed (%s)\n", cli_errstr(&cli1));
2470                 return False;
2471         }
2472         
2473         fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
2474         if (fnum1 != -1) {
2475                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
2476                 if (!cli_close(&cli1, fnum1)) {
2477                         printf("[2] close failed (%s)\n", cli_errstr(&cli1));
2478                         correct = False;
2479                 }
2480                 cli_unlink(&cli1, fname);
2481         } else
2482                 printf("second delete on close test succeeded.\n");
2483         
2484         
2485         /* Test 3 - ... */
2486         cli_setatr(&cli1, fname, 0, 0);
2487         cli_unlink(&cli1, fname);
2488
2489         fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
2490                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
2491
2492         if (fnum1 == -1) {
2493                 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(&cli1));
2494                 return False;
2495         }
2496
2497         /* This should fail with a sharing violation - open for delete is only compatible
2498            with SHARE_DELETE. */
2499
2500         fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
2501                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0);
2502
2503         if (fnum2 != -1) {
2504                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
2505                 return False;
2506         }
2507
2508         /* This should succeed. */
2509
2510         fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
2511                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
2512
2513         if (fnum2 == -1) {
2514                 printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
2515                 return False;
2516         }
2517
2518         if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
2519                 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
2520                 return False;
2521         }
2522         
2523         if (!cli_close(&cli1, fnum1)) {
2524                 printf("[3] close 1 failed (%s)\n", cli_errstr(&cli1));
2525                 return False;
2526         }
2527         
2528         if (!cli_close(&cli1, fnum2)) {
2529                 printf("[3] close 2 failed (%s)\n", cli_errstr(&cli1));
2530                 return False;
2531         }
2532         
2533         /* This should fail - file should no longer be there. */
2534
2535         fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
2536         if (fnum1 != -1) {
2537                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
2538                 if (!cli_close(&cli1, fnum1)) {
2539                         printf("[3] close failed (%s)\n", cli_errstr(&cli1));
2540                 }
2541                 cli_unlink(&cli1, fname);
2542                 correct = False;
2543         } else
2544                 printf("third delete on close test succeeded.\n");
2545
2546         /* Test 4 ... */
2547         cli_setatr(&cli1, fname, 0, 0);
2548         cli_unlink(&cli1, fname);
2549
2550         fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
2551                         FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
2552                                                                 
2553         if (fnum1 == -1) {
2554                 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2555                 return False;
2556         }
2557
2558         /* This should succeed. */
2559         fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
2560                         FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
2561         if (fnum2 == -1) {
2562                 printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
2563                 return False;
2564         }
2565         
2566         if (!cli_close(&cli1, fnum2)) {
2567                 printf("[4] close - 1 failed (%s)\n", cli_errstr(&cli1));
2568                 return False;
2569         }
2570         
2571         if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
2572                 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
2573                 return False;
2574         }
2575         
2576         /* This should fail - no more opens once delete on close set. */
2577         fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
2578                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
2579         if (fnum2 != -1) {
2580                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
2581                 return False;
2582         } else
2583                 printf("fourth delete on close test succeeded.\n");
2584         
2585         if (!cli_close(&cli1, fnum1)) {
2586                 printf("[4] close - 2 failed (%s)\n", cli_errstr(&cli1));
2587                 return False;
2588         }
2589         
2590         /* Test 5 ... */
2591         cli_setatr(&cli1, fname, 0, 0);
2592         cli_unlink(&cli1, fname);
2593         
2594         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT, DENY_NONE);
2595         if (fnum1 == -1) {
2596                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2597                 return False;
2598         }
2599
2600         /* This should fail - only allowed on NT opens with DELETE access. */
2601
2602         if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
2603                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
2604                 return False;
2605         }
2606
2607         if (!cli_close(&cli1, fnum1)) {
2608                 printf("[5] close - 2 failed (%s)\n", cli_errstr(&cli1));
2609                 return False;
2610         }
2611         
2612         printf("fifth delete on close test succeeded.\n");
2613         
2614         /* Test 6 ... */
2615         cli_setatr(&cli1, fname, 0, 0);
2616         cli_unlink(&cli1, fname);
2617         
2618         fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA,
2619                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
2620                                    FILE_OVERWRITE_IF, 0);
2621         
2622         if (fnum1 == -1) {
2623                 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2624                 return False;
2625         }
2626         
2627         /* This should fail - only allowed on NT opens with DELETE access. */
2628         
2629         if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
2630                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
2631                 return False;
2632         }
2633
2634         if (!cli_close(&cli1, fnum1)) {
2635                 printf("[6] close - 2 failed (%s)\n", cli_errstr(&cli1));
2636                 return False;
2637         }
2638
2639         printf("sixth delete on close test succeeded.\n");
2640         
2641         /* Test 7 ... */
2642         cli_setatr(&cli1, fname, 0, 0);
2643         cli_unlink(&cli1, fname);
2644         
2645         fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
2646                                    FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0);
2647                                                                 
2648         if (fnum1 == -1) {
2649                 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2650                 return False;
2651         }
2652
2653         if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
2654                 printf("[7] setting delete_on_close on file failed !\n");
2655                 return False;
2656         }
2657         
2658         if (!cli_nt_delete_on_close(&cli1, fnum1, False)) {
2659                 printf("[7] unsetting delete_on_close on file failed !\n");
2660                 return False;
2661         }
2662
2663         if (!cli_close(&cli1, fnum1)) {
2664                 printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
2665                 return False;
2666         }
2667         
2668         /* This next open should succeed - we reset the flag. */
2669         
2670         fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
2671         if (fnum1 == -1) {
2672                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2673                 return False;
2674         }
2675
2676         if (!cli_close(&cli1, fnum1)) {
2677                 printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
2678                 return False;
2679         }
2680
2681         printf("seventh delete on close test succeeded.\n");
2682         
2683         /* Test 7 ... */
2684         cli_setatr(&cli1, fname, 0, 0);
2685         cli_unlink(&cli1, fname);
2686         
2687         if (!open_connection(&cli2)) {
2688                 printf("[8] failed to open second connection.\n");
2689                 return False;
2690         }
2691
2692         cli_sockopt(&cli1, sockops);
2693         
2694         fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
2695                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0);
2696         
2697         if (fnum1 == -1) {
2698                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2699                 return False;
2700         }
2701
2702         fnum2 = cli_nt_create_full(&cli2, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
2703                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
2704         
2705         if (fnum2 == -1) {
2706                 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2707                 return False;
2708         }
2709
2710         if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
2711                 printf("[8] setting delete_on_close on file failed !\n");
2712                 return False;
2713         }
2714         
2715         if (!cli_close(&cli1, fnum1)) {
2716                 printf("[8] close - 1 failed (%s)\n", cli_errstr(&cli1));
2717                 return False;
2718         }
2719
2720         if (!cli_close(&cli2, fnum2)) {
2721                 printf("[8] close - 2 failed (%s)\n", cli_errstr(&cli2));
2722                 return False;
2723         }
2724
2725         /* This should fail.. */
2726         fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
2727         if (fnum1 != -1) {
2728                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
2729                 if (!cli_close(&cli1, fnum1)) {
2730                         printf("[8] close failed (%s)\n", cli_errstr(&cli1));
2731                 }
2732                 cli_unlink(&cli1, fname);
2733                 correct = False;
2734         } else
2735                 printf("eighth delete on close test succeeded.\n");
2736
2737         printf("finished delete test\n");
2738         
2739         cli_setatr(&cli1, fname, 0, 0);
2740         cli_unlink(&cli1, fname);
2741         
2742         if (!close_connection(&cli1)) {
2743                 correct = False;
2744         }
2745         if (!close_connection(&cli2)) {
2746                 correct = False;
2747         }
2748         return correct;
2749 }
2750
2751 /*
2752   Test open mode returns on read-only files.
2753  */
2754 static BOOL run_opentest(int dummy)
2755 {
2756         static struct cli_state cli1;
2757         char *fname = "\\readonly.file";
2758         int fnum1, fnum2;
2759         uint8 eclass;
2760         uint32 errnum;
2761         char buf[20];
2762         size_t fsize;
2763         BOOL correct = True;
2764
2765         printf("starting open test\n");
2766         
2767         if (!open_connection(&cli1)) {
2768                 return False;
2769         }
2770         
2771         cli_setatr(&cli1, fname, 0, 0);
2772         cli_unlink(&cli1, fname);
2773         
2774         cli_sockopt(&cli1, sockops);
2775         
2776         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2777         if (fnum1 == -1) {
2778                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2779                 return False;
2780         }
2781
2782         if (!cli_close(&cli1, fnum1)) {
2783                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
2784                 return False;
2785         }
2786         
2787         if (!cli_setatr(&cli1, fname, aRONLY, 0)) {
2788                 printf("cli_setatr failed (%s)\n", cli_errstr(&cli1));
2789                 return False;
2790         }
2791         
2792         fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
2793         if (fnum1 == -1) {
2794                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2795                 return False;
2796         }
2797         
2798         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
2799         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
2800         
2801         cli_error( &cli1, &eclass, &errnum, NULL);
2802         
2803         if (eclass != ERRDOS || errnum != ERRnoaccess) {
2804                 printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
2805                        (unsigned int)errnum, cli_errstr(&cli1) );
2806                 correct = False;
2807         } else {
2808                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
2809         }
2810         
2811         
2812         printf("finished open test 1\n");
2813         
2814         cli_close(&cli1, fnum1);
2815         
2816         /* Now try not readonly and ensure ERRbadshare is returned. */
2817         
2818         cli_setatr(&cli1, fname, 0, 0);
2819         
2820         fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
2821         if (fnum1 == -1) {
2822                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
2823                 return False;
2824         }
2825         
2826         /* This will fail - but the error should be ERRshare. */
2827         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
2828         
2829         cli_error( &cli1, &eclass, &errnum, NULL);
2830
2831         if (eclass != ERRDOS || errnum != ERRbadshare) {
2832                 printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
2833                        (unsigned int)errnum, cli_errstr(&cli1) );
2834                 correct = False;
2835         } else {
2836                 printf("correct error code ERRDOS/ERRbadshare returned\n");
2837         }
2838         
2839         if (!cli_close(&cli1, fnum1)) {
2840                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
2841                 return False;
2842         }
2843         
2844         cli_unlink(&cli1, fname);
2845         
2846         printf("finished open test 2\n");
2847         
2848         /* Test truncate open disposition on file opened for read. */
2849         
2850         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
2851         if (fnum1 == -1) {
2852                 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(&cli1));
2853                 return False;
2854         }
2855         
2856         /* write 20 bytes. */
2857         
2858         memset(buf, '\0', 20);
2859
2860         if (cli_write(&cli1, fnum1, 0, buf, 0, 20) != 20) {
2861                 printf("write failed (%s)\n", cli_errstr(&cli1));
2862                 correct = False;
2863         }
2864
2865         if (!cli_close(&cli1, fnum1)) {
2866                 printf("(3) close1 failed (%s)\n", cli_errstr(&cli1));
2867                 return False;
2868         }
2869         
2870         /* Ensure size == 20. */
2871         if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
2872                 printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
2873                 return False;
2874         }
2875         
2876         if (fsize != 20) {
2877                 printf("(3) file size != 20\n");
2878                 return False;
2879         }
2880
2881         /* Now test if we can truncate a file opened for readonly. */
2882         
2883         fnum1 = cli_open(&cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE);
2884         if (fnum1 == -1) {
2885                 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(&cli1));
2886                 return False;
2887         }
2888         
2889         if (!cli_close(&cli1, fnum1)) {
2890                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
2891                 return False;
2892         }
2893
2894         /* Ensure size == 0. */
2895         if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
2896                 printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
2897                 return False;
2898         }
2899
2900         if (fsize != 0) {
2901                 printf("(3) file size != 0\n");
2902                 return False;
2903         }
2904         printf("finished open test 3\n");
2905         
2906         cli_unlink(&cli1, fname);
2907
2908
2909         printf("testing ctemp\n");
2910         {
2911                 char *tmp_path;
2912                 fnum1 = cli_ctemp(&cli1, "\\", &tmp_path);
2913                 if (fnum1 == -1) {
2914                         printf("ctemp failed (%s)\n", cli_errstr(&cli1));
2915                         return False;
2916                 }
2917                 printf("ctemp gave path %s\n", tmp_path);
2918                 cli_close(&cli1, fnum1);
2919                 cli_unlink(&cli1, tmp_path);
2920         }
2921         
2922         if (!close_connection(&cli1)) {
2923                 correct = False;
2924         }
2925         
2926         return correct;
2927 }
2928
2929 static void list_fn(file_info *finfo, const char *name, void *state)
2930 {
2931         
2932 }
2933
2934 /*
2935   test directory listing speed
2936  */
2937 static BOOL run_dirtest(int dummy)
2938 {
2939         int i;
2940         static struct cli_state cli;
2941         int fnum;
2942         double t1;
2943         BOOL correct = True;
2944
2945         printf("starting directory test\n");
2946
2947         if (!open_connection(&cli)) {
2948                 return False;
2949         }
2950
2951         cli_sockopt(&cli, sockops);
2952
2953         srandom(0);
2954         for (i=0;i<numops;i++) {
2955                 fstring fname;
2956                 slprintf(fname, sizeof(fname), "%x", (int)random());
2957                 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
2958                 if (fnum == -1) {
2959                         fprintf(stderr,"Failed to open %s\n", fname);
2960                         return False;
2961                 }
2962                 cli_close(&cli, fnum);
2963         }
2964
2965         t1 = end_timer();
2966
2967         printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn, NULL));
2968         printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn, NULL));
2969         printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn, NULL));
2970
2971         printf("dirtest core %g seconds\n", end_timer() - t1);
2972
2973         srandom(0);
2974         for (i=0;i<numops;i++) {
2975                 fstring fname;
2976                 slprintf(fname, sizeof(fname), "%x", (int)random());
2977                 cli_unlink(&cli, fname);
2978         }
2979
2980         if (!close_connection(&cli)) {
2981                 correct = False;
2982         }
2983
2984         printf("finished dirtest\n");
2985
2986         return correct;
2987 }
2988
2989
2990
2991 static double create_procs(BOOL (*fn)(int), BOOL *result)
2992 {
2993         int i, status;
2994         volatile pid_t *child_status;
2995         volatile BOOL *child_status_out;
2996         int synccount;
2997         int tries = 8;
2998
2999         synccount = 0;
3000
3001         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
3002         if (!child_status) {
3003                 printf("Failed to setup shared memory\n");
3004                 return -1;
3005         }
3006
3007         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*nprocs);
3008         if (!child_status_out) {
3009                 printf("Failed to setup result status shared memory\n");
3010                 return -1;
3011         }
3012
3013         memset(child_status, 0, sizeof(pid_t)*nprocs);
3014         memset(child_status_out, True, sizeof(BOOL)*nprocs);
3015
3016         start_timer();
3017
3018         for (i=0;i<nprocs;i++) {
3019                 procnum = i;
3020                 if (fork() == 0) {
3021                         pid_t mypid = getpid();
3022                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
3023
3024                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
3025
3026                         while (1) {
3027                                 memset(&current_cli, 0, sizeof(current_cli));
3028                                 if (open_connection(&current_cli)) break;
3029                                 if (tries-- == 0) {
3030                                         printf("pid %d failed to start\n", (int)getpid());
3031                                         _exit(1);
3032                                 }
3033                                 msleep(10);     
3034                         }
3035
3036                         child_status[i] = getpid();
3037
3038                         while (child_status[i]) msleep(2);
3039
3040                         child_status_out[i] = fn(i);
3041                         _exit(0);
3042                 }
3043         }
3044
3045         do {
3046                 synccount = 0;
3047                 for (i=0;i<nprocs;i++) {
3048                         if (child_status[i]) synccount++;
3049                 }
3050                 if (synccount == nprocs) break;
3051                 msleep(10);
3052         } while (end_timer() < 30);
3053
3054         if (synccount != nprocs) {
3055                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
3056                 *result = False;
3057                 return end_timer();
3058         }
3059
3060         /* start the client load */
3061         start_timer();
3062
3063         for (i=0;i<nprocs;i++) {
3064                 child_status[i] = 0;
3065         }
3066
3067         printf("%d clients started\n", nprocs);
3068
3069         for (i=0;i<nprocs;i++) {
3070                 waitpid(0, &status, 0);
3071                 printf("*");
3072         }
3073
3074         printf("\n");
3075         
3076         for (i=0;i<nprocs;i++) {
3077                 if (!child_status_out[i]) {
3078                         *result = False;
3079                 }
3080         }
3081         return end_timer();
3082 }
3083
3084
3085 #define FLAG_MULTIPROC 1
3086
3087 static struct {
3088         char *name;
3089         BOOL (*fn)(int);
3090         unsigned flags;
3091 } torture_ops[] = {
3092         {"FDPASS", run_fdpasstest, 0},
3093         {"LOCK1",  run_locktest1,  0},
3094         {"LOCK2",  run_locktest2,  0},
3095         {"LOCK3",  run_locktest3,  0},
3096         {"LOCK4",  run_locktest4,  0},
3097         {"LOCK5",  run_locktest5,  0},
3098         {"UNLINK", run_unlinktest, 0},
3099         {"BROWSE", run_browsetest, 0},
3100         {"ATTR",   run_attrtest,   0},
3101         {"TRANS2", run_trans2test, 0},
3102         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
3103         {"TORTURE",run_torture,    FLAG_MULTIPROC},
3104         {"RANDOMIPC", run_randomipc, 0},
3105         {"NEGNOWAIT", run_negprot_nowait, 0},
3106         {"NBW95",  run_nbw95, 0},
3107         {"NBWNT",  run_nbwnt, 0},
3108         {"OPLOCK1",  run_oplock1, 0},
3109         {"OPLOCK2",  run_oplock2, 0},
3110         {"OPLOCK3",  run_oplock3, 0},
3111         {"DIR",  run_dirtest, 0},
3112         {"DENY1",  run_denytest1, 0},
3113         {"DENY2",  run_denytest2, 0},
3114         {"TCON",  run_tcon_test, 0},
3115         {"RW1",  run_readwritetest, 0},
3116         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
3117         {"RW3",  run_readwritelarge, 0},
3118         {"OPEN", run_opentest, 0},
3119         {"DELETE", run_deletetest, 0},
3120         {"W2K", run_w2ktest, 0},
3121         {NULL, NULL, 0}};
3122
3123
3124
3125 /****************************************************************************
3126 run a specified test or "ALL"
3127 ****************************************************************************/
3128 static BOOL run_test(char *name)
3129 {
3130         BOOL ret = True;
3131         BOOL result = True;
3132         int i;
3133         double t;
3134         if (strequal(name,"ALL")) {
3135                 for (i=0;torture_ops[i].name;i++) {
3136                         run_test(torture_ops[i].name);
3137                 }
3138         }
3139         
3140         for (i=0;torture_ops[i].name;i++) {
3141                 snprintf(randomfname, sizeof(randomfname), "\\XX%x", 
3142                          (unsigned)random());
3143
3144                 if (strequal(name, torture_ops[i].name)) {
3145                         printf("Running %s\n", name);
3146                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
3147                                 t = create_procs(torture_ops[i].fn, &result);
3148                                 if (!result) { 
3149                                         ret = False;
3150                                         printf("TEST %s FAILED!\n", name);
3151                                 }
3152                                          
3153                         } else {
3154                                 start_timer();
3155                                 if (!torture_ops[i].fn(0)) {
3156                                         ret = False;
3157                                         printf("TEST %s FAILED!\n", name);
3158                                 }
3159                                 t = end_timer();
3160                         }
3161                         printf("%s took %g secs\n\n", name, t);
3162                 }
3163         }
3164         return ret;
3165 }
3166
3167
3168 static void usage(void)
3169 {
3170         int i;
3171
3172         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
3173
3174         printf("\t-d debuglevel\n");
3175         printf("\t-U user%%pass\n");
3176         printf("\t-N numprocs\n");
3177         printf("\t-n my_netbios_name\n");
3178         printf("\t-W workgroup\n");
3179         printf("\t-o num_operations\n");
3180         printf("\t-O socket_options\n");
3181         printf("\t-m maximum protocol\n");
3182         printf("\t-L use oplocks\n");
3183         printf("\n\n");
3184
3185         printf("tests are:");
3186         for (i=0;torture_ops[i].name;i++) {
3187                 printf(" %s", torture_ops[i].name);
3188         }
3189         printf("\n");
3190
3191         printf("default test is ALL\n");
3192         
3193         exit(1);
3194 }
3195
3196
3197
3198
3199
3200 /****************************************************************************
3201   main program
3202 ****************************************************************************/
3203  int main(int argc,char *argv[])
3204 {
3205         int opt, i;
3206         char *p;
3207         int gotpass = 0;
3208         extern char *optarg;
3209         extern int optind;
3210         extern FILE *dbf;
3211         static pstring servicesf = CONFIGFILE;
3212         BOOL correct = True;
3213
3214         dbf = stdout;
3215
3216 #ifdef HAVE_SETBUFFER
3217         setbuffer(stdout, NULL, 0);
3218 #endif
3219
3220         charset_initialise();
3221
3222         codepage_initialise(lp_client_code_page());
3223
3224         codepage_initialise(lp_client_code_page());
3225
3226         lp_load(servicesf,True,False,False);
3227         load_interfaces();
3228
3229         if (argc < 2) {
3230                 usage();
3231         }
3232
3233         for(p = argv[1]; *p; p++)
3234           if(*p == '\\')
3235             *p = '/';
3236  
3237         if (strncmp(argv[1], "//", 2)) {
3238                 usage();
3239         }
3240
3241         fstrcpy(host, &argv[1][2]);
3242         p = strchr(&host[2],'/');
3243         if (!p) {
3244                 usage();
3245         }
3246         *p = 0;
3247         fstrcpy(share, p+1);
3248
3249         get_myname(myname);
3250
3251         if (*username == 0 && getenv("LOGNAME")) {
3252           pstrcpy(username,getenv("LOGNAME"));
3253         }
3254
3255         argc--;
3256         argv++;
3257
3258
3259         fstrcpy(workgroup, lp_workgroup());
3260
3261         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:Ld:")) != EOF) {
3262                 switch (opt) {
3263                 case 'W':
3264                         fstrcpy(workgroup,optarg);
3265                         break;
3266                 case 'm':
3267                         max_protocol = interpret_protocol(optarg, max_protocol);
3268                         break;
3269                 case 'N':
3270                         nprocs = atoi(optarg);
3271                         break;
3272                 case 'o':
3273                         numops = atoi(optarg);
3274                         break;
3275                 case 'd':
3276                         DEBUGLEVEL = atoi(optarg);
3277                         break;
3278                 case 'O':
3279                         sockops = optarg;
3280                         break;
3281                 case 'L':
3282                         use_oplocks = True;
3283                         break;
3284                 case 'n':
3285                         fstrcpy(myname, optarg);
3286                         break;
3287                 case 'U':
3288                         pstrcpy(username,optarg);
3289                         p = strchr(username,'%');
3290                         if (p) {
3291                                 *p = 0;
3292                                 pstrcpy(password, p+1);
3293                                 gotpass = 1;
3294                         }
3295                         break;
3296                 default:
3297                         printf("Unknown option %c (%d)\n", (char)opt, opt);
3298                         usage();
3299                 }
3300         }
3301
3302
3303         while (!gotpass) {
3304                 p = getpass("Password:");
3305                 if (p) {
3306                         pstrcpy(password, p);
3307                         gotpass = 1;
3308                 }
3309         }
3310
3311         printf("host=%s share=%s user=%s myname=%s\n", 
3312                host, share, username, myname);
3313
3314         if (argc == 1) {
3315                 correct = run_test("ALL");
3316         } else {
3317                 for (i=1;i<argc;i++) {
3318                         if (!run_test(argv[i])) {
3319                                 correct = False;
3320                         }
3321                 }
3322         }
3323
3324         if (correct) {
3325                 return(0);
3326         } else {
3327                 return(1);
3328         }
3329 }