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