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