fixed a connection bug in torture test
[samba.git] / source3 / utils / torture.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    SMB torture tester
5    Copyright (C) Andrew Tridgell 1997-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #define NO_SYSLOG
23
24 #include "includes.h"
25
26 static fstring host, workgroup, share, password, username, myname;
27 static int max_protocol = PROTOCOL_NT1;
28 static char *sockops="";
29
30
31 static struct timeval tp1,tp2;
32
33 static void start_timer(void)
34 {
35         gettimeofday(&tp1,NULL);
36 }
37
38 static double end_timer(void)
39 {
40         gettimeofday(&tp2,NULL);
41         return((tp2.tv_sec - tp1.tv_sec) + 
42                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
43 }
44
45
46 static BOOL open_connection(struct cli_state *c)
47 {
48         struct nmb_name called, calling;
49
50         ZERO_STRUCTP(c);
51
52         make_nmb_name(&calling, myname, 0x0, "");
53         make_nmb_name(&called , host, 0x20, "");
54
55         if (!cli_initialise(c) || !cli_connect(c, host, NULL)) {
56                 printf("Failed to connect with %s\n", host);
57                 return False;
58         }
59
60         if (!cli_session_request(c, &calling, &called)) {
61                 cli_shutdown(c);
62                 printf("%s rejected the session\n",host);
63                 return False;
64         }
65
66         if (!cli_negprot(c)) {
67                 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
68                 cli_shutdown(c);
69                 return False;
70         }
71
72         if (!cli_session_setup(c, username, 
73                                password, strlen(password),
74                                password, strlen(password),
75                                workgroup)) {
76                 cli_shutdown(c);
77                 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
78                 return False;
79         }
80
81         if (!cli_send_tconX(c, share, "?????",
82                             password, strlen(password)+1)) {
83                 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
84                 cli_shutdown(c);
85                 return False;
86         }
87
88         return True;
89 }
90
91
92
93 static void close_connection(struct cli_state *c)
94 {
95         if (!cli_tdis(c)) {
96                 printf("tdis failed (%s)\n", cli_errstr(c));
97         }
98
99         cli_shutdown(c);
100 }
101
102
103 /* check if the server produced the expected error code */
104 static BOOL check_error(struct cli_state *c, 
105                         uint8 eclass, uint32 ecode, uint32 nterr)
106 {
107         uint8 class;
108         uint32 num;
109         int eno;
110         eno = cli_error(c, &class, &num);
111         if ((eclass != class || ecode != num) &&
112             num != (nterr&0xFFFFFF)) {
113                 printf("unexpected error code class=%d code=%d\n", 
114                          (int)class, (int)num);
115                 printf(" expected %d/%d %d\n", 
116                        (int)eclass, (int)ecode, (int)nterr);
117                 return False;
118         }
119         return True;
120 }
121
122
123 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
124 {
125         while (!cli_lock(c, fnum, offset, len, -1)) {
126                 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
127         }
128         return True;
129 }
130
131
132 static BOOL rw_torture(struct cli_state *c, int numops)
133 {
134         char *lockfname = "\\torture.lck";
135         fstring fname;
136         int fnum;
137         int fnum2;
138         int pid2, pid = getpid();
139         int i, j;
140         char buf[1024];
141
142         fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
143                          DENY_NONE);
144         if (fnum2 == -1)
145                 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
146         if (fnum2 == -1) {
147                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
148                 return False;
149         }
150
151
152         for (i=0;i<numops;i++) {
153                 unsigned n = (unsigned)sys_random()%10;
154                 if (i % 10 == 0) {
155                         printf("%d\r", i); fflush(stdout);
156                 }
157                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
158
159                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
160                         return False;
161                 }
162
163                 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
164                 if (fnum == -1) {
165                         printf("open failed (%s)\n", cli_errstr(c));
166                         break;
167                 }
168
169                 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
170                         printf("write failed (%s)\n", cli_errstr(c));
171                 }
172
173                 for (j=0;j<50;j++) {
174                         if (cli_write(c, fnum, 0, (char *)buf, 
175                                       sizeof(pid)+(j*sizeof(buf)), 
176                                       sizeof(buf)) != sizeof(buf)) {
177                                 printf("write failed (%s)\n", cli_errstr(c));
178                         }
179                 }
180
181                 pid2 = 0;
182
183                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
184                         printf("read failed (%s)\n", cli_errstr(c));
185                 }
186
187                 if (pid2 != pid) {
188                         printf("data corruption!\n");
189                 }
190
191                 if (!cli_close(c, fnum)) {
192                         printf("close failed (%s)\n", cli_errstr(c));
193                 }
194
195                 if (!cli_unlink(c, fname)) {
196                         printf("unlink failed (%s)\n", cli_errstr(c));
197                 }
198
199                 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) {
200                         printf("unlock failed (%s)\n", cli_errstr(c));
201                 }
202         }
203
204         cli_close(c, fnum2);
205         cli_unlink(c, lockfname);
206
207         printf("%d\n", i);
208
209         return True;
210 }
211
212 static void usage(void)
213 {
214         printf("Usage: smbtorture //server/share <options>\n");
215
216         printf("\t-U user%%pass\n");
217         printf("\t-N numprocs\n");
218         printf("\t-n my_netbios_name\n");
219         printf("\t-W workgroup\n");
220         printf("\t-o num_operations\n");
221         printf("\t-O socket_options\n");
222         printf("\t-m maximum protocol\n");
223         printf("\n");
224
225         exit(1);
226 }
227
228
229
230 static void run_torture(int numops)
231 {
232         static struct cli_state cli;
233
234         if (open_connection(&cli)) {
235                 cli_sockopt(&cli, sockops);
236
237                 printf("pid %d OK\n", getpid());
238
239                 rw_torture(&cli, numops);
240
241                 close_connection(&cli);
242         }
243 }
244
245 /*
246   This test checks for two things:
247
248   1) correct support for retaining locks over a close (ie. the server
249      must not use posix semantics)
250   2) support for lock timeouts
251  */
252 static void run_locktest1(void)
253 {
254         static struct cli_state cli1, cli2;
255         char *fname = "\\lockt1.lck";
256         int fnum1, fnum2, fnum3;
257         time_t t1, t2;
258
259         if (!open_connection(&cli1) || !open_connection(&cli2)) {
260                 return;
261         }
262         cli_sockopt(&cli1, sockops);
263         cli_sockopt(&cli2, sockops);
264
265         printf("starting locktest1\n");
266
267         cli_unlink(&cli1, fname);
268
269         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
270         if (fnum1 == -1) {
271                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
272                 return;
273         }
274         fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
275         if (fnum2 == -1) {
276                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
277                 return;
278         }
279         fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
280         if (fnum3 == -1) {
281                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
282                 return;
283         }
284
285         if (!cli_lock(&cli1, fnum1, 0, 4, 0)) {
286                 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
287                 return;
288         }
289
290
291         if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
292                 printf("lock2 succeeded! This is a locking bug\n");
293                 return;
294         } else {
295                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
296         }
297
298
299         printf("Testing lock timeouts\n");
300         t1 = time(NULL);
301         if (cli_lock(&cli2, fnum3, 0, 4, 10*1000)) {
302                 printf("lock3 succeeded! This is a locking bug\n");
303                 return;
304         } else {
305                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
306         }
307         t2 = time(NULL);
308
309         if (t2 - t1 < 5) {
310                 printf("error: This server appears not to support timed lock requests\n");
311         }
312
313         if (!cli_close(&cli1, fnum2)) {
314                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
315                 return;
316         }
317
318         if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
319                 printf("lock4 succeeded! This is a locking bug\n");
320                 return;
321         } else {
322                 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return;
323         }
324
325         if (!cli_close(&cli1, fnum1)) {
326                 printf("close2 failed (%s)\n", cli_errstr(&cli1));
327                 return;
328         }
329
330         if (!cli_close(&cli2, fnum3)) {
331                 printf("close3 failed (%s)\n", cli_errstr(&cli2));
332                 return;
333         }
334
335         if (!cli_unlink(&cli1, fname)) {
336                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
337                 return;
338         }
339
340
341         close_connection(&cli1);
342         close_connection(&cli2);
343
344         printf("Passed locktest1\n");
345 }
346
347
348 /*
349   This test checks that 
350
351   1) the server supports multiple locking contexts on the one SMB
352   connection, distinguished by PID.  
353
354   2) the server correctly fails overlapping locks made by the same PID (this
355      goes against POSIX behaviour, which is why it is tricky to implement)
356
357   3) the server denies unlock requests by an incorrect client PID
358 */
359 static void run_locktest2(void)
360 {
361         static struct cli_state cli;
362         char *fname = "\\lockt2.lck";
363         int fnum1, fnum2, fnum3;
364
365         if (!open_connection(&cli)) {
366                 return;
367         }
368
369         cli_sockopt(&cli, sockops);
370
371         printf("starting locktest2\n");
372
373         cli_unlink(&cli, fname);
374
375         cli_setpid(&cli, 1);
376
377         fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
378         if (fnum1 == -1) {
379                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
380                 return;
381         }
382
383         fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
384         if (fnum2 == -1) {
385                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
386                 return;
387         }
388
389         cli_setpid(&cli, 2);
390
391         fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
392         if (fnum3 == -1) {
393                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
394                 return;
395         }
396
397         cli_setpid(&cli, 1);
398
399         if (!cli_lock(&cli, fnum1, 0, 4, 0)) {
400                 printf("lock1 failed (%s)\n", cli_errstr(&cli));
401                 return;
402         }
403
404         if (cli_lock(&cli, fnum2, 0, 4, 0)) {
405                 printf("lock2 succeeded! This is a locking bug\n");
406         } else {
407                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
408         }
409
410         cli_setpid(&cli, 2);
411
412         if (cli_unlock(&cli, fnum1, 0, 4, 0)) {
413                 printf("unlock1 succeeded! This is a locking bug\n");
414         }
415
416         if (cli_lock(&cli, fnum3, 0, 4, 0)) {
417                 printf("lock3 succeeded! This is a locking bug\n");
418         } else {
419                 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
420         }
421
422         cli_setpid(&cli, 1);
423
424         if (!cli_close(&cli, fnum1)) {
425                 printf("close1 failed (%s)\n", cli_errstr(&cli));
426                 return;
427         }
428
429         if (!cli_close(&cli, fnum2)) {
430                 printf("close2 failed (%s)\n", cli_errstr(&cli));
431                 return;
432         }
433
434         if (!cli_close(&cli, fnum3)) {
435                 printf("close3 failed (%s)\n", cli_errstr(&cli));
436                 return;
437         }
438
439         close_connection(&cli);
440
441         printf("locktest2 finished\n");
442 }
443
444
445 /*
446   This test checks that 
447
448   1) the server supports the full offset range in lock requests
449 */
450 static void run_locktest3(int numops)
451 {
452         static struct cli_state cli1, cli2;
453         char *fname = "\\lockt3.lck";
454         int fnum1, fnum2, i;
455         uint32 offset;
456
457 #define NEXT_OFFSET offset += (~(uint32)0) / numops
458
459         if (!open_connection(&cli1) || !open_connection(&cli2)) {
460                 return;
461         }
462         cli_sockopt(&cli1, sockops);
463         cli_sockopt(&cli2, sockops);
464
465         printf("starting locktest3\n");
466
467         cli_unlink(&cli1, fname);
468
469         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
470         if (fnum1 == -1) {
471                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
472                 return;
473         }
474         fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
475         if (fnum2 == -1) {
476                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
477                 return;
478         }
479
480         for (offset=i=0;i<numops;i++) {
481                 NEXT_OFFSET;
482                 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
483                         printf("lock1 %d failed (%s)\n", 
484                                i,
485                                cli_errstr(&cli1));
486                         return;
487                 }
488
489                 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
490                         printf("lock2 %d failed (%s)\n", 
491                                i,
492                                cli_errstr(&cli1));
493                         return;
494                 }
495         }
496
497         for (offset=i=0;i<numops;i++) {
498                 NEXT_OFFSET;
499
500                 if (cli_lock(&cli1, fnum1, offset-2, 1, 0)) {
501                         printf("error: lock1 %d succeeded!\n", i);
502                         return;
503                 }
504
505                 if (cli_lock(&cli2, fnum2, offset-1, 1, 0)) {
506                         printf("error: lock2 %d succeeded!\n", i);
507                         return;
508                 }
509
510                 if (cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
511                         printf("error: lock3 %d succeeded!\n", i);
512                         return;
513                 }
514
515                 if (cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
516                         printf("error: lock4 %d succeeded!\n", i);
517                         return;
518                 }
519         }
520
521         for (offset=i=0;i<numops;i++) {
522                 NEXT_OFFSET;
523
524                 if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) {
525                         printf("unlock1 %d failed (%s)\n", 
526                                i,
527                                cli_errstr(&cli1));
528                         return;
529                 }
530
531                 if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) {
532                         printf("unlock2 %d failed (%s)\n", 
533                                i,
534                                cli_errstr(&cli1));
535                         return;
536                 }
537         }
538
539         if (!cli_close(&cli1, fnum1)) {
540                 printf("close1 failed (%s)\n", cli_errstr(&cli1));
541         }
542
543         if (!cli_close(&cli2, fnum2)) {
544                 printf("close2 failed (%s)\n", cli_errstr(&cli2));
545         }
546
547         if (!cli_unlink(&cli1, fname)) {
548                 printf("unlink failed (%s)\n", cli_errstr(&cli1));
549                 return;
550         }
551
552         close_connection(&cli1);
553         close_connection(&cli2);
554
555         printf("finished locktest3\n");
556 }
557
558
559 /*
560 test whether fnums and tids open on one VC are available on another (a major
561 security hole)
562 */
563 static void run_fdpasstest(void)
564 {
565         static struct cli_state cli1, cli2;
566         char *fname = "\\fdpass.tst";
567         int fnum1;
568         pstring buf;
569
570         if (!open_connection(&cli1) || !open_connection(&cli2)) {
571                 return;
572         }
573         cli_sockopt(&cli1, sockops);
574         cli_sockopt(&cli2, sockops);
575
576         printf("starting fdpasstest\n");
577
578         cli_unlink(&cli1, fname);
579
580         fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
581         if (fnum1 == -1) {
582                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
583                 return;
584         }
585
586         if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
587                 printf("write failed (%s)\n", cli_errstr(&cli1));
588                 return;
589         }
590
591         cli2.vuid = cli1.vuid;
592         cli2.cnum = cli1.cnum;
593         cli2.pid = cli1.pid;
594
595
596         if (cli_read(&cli2, fnum1, buf, 0, 13) == 13) {
597                 printf("read succeeded! nasty security hole [%s]\n",
598                        buf);
599                 return;
600         }
601
602         cli_close(&cli1, fnum1);
603         cli_unlink(&cli1, fname);
604
605         close_connection(&cli1);
606         close_connection(&cli2);
607
608         printf("finished fdpasstest\n");
609 }
610
611
612 /*
613   This test checks that 
614
615   1) the server does not allow an unlink on a file that is open
616 */
617 static void run_unlinktest(void)
618 {
619         static struct cli_state cli;
620         char *fname = "\\unlink.tst";
621         int fnum;
622
623         if (!open_connection(&cli)) {
624                 return;
625         }
626
627         cli_sockopt(&cli, sockops);
628
629         printf("starting unlink test\n");
630
631         cli_unlink(&cli, fname);
632
633         cli_setpid(&cli, 1);
634
635         fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
636         if (fnum == -1) {
637                 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
638                 return;
639         }
640
641         if (cli_unlink(&cli, fname)) {
642                 printf("error: server allowed unlink on an open file\n");
643         }
644
645         cli_close(&cli, fnum);
646         cli_unlink(&cli, fname);
647
648         close_connection(&cli);
649
650         printf("unlink test finished\n");
651 }
652
653
654 /*
655 test how many open files this server supports on the one socket
656 */
657 static void run_maxfidtest(int n)
658 {
659         static struct cli_state cli;
660         char *template = "\\maxfid.%d.%d";
661         fstring fname;
662         int fnum;
663         int retries=4;
664
665         srandom(getpid());
666
667         while (!open_connection(&cli) && retries--) msleep(random() % 2000);
668
669         if (retries <= 0) {
670                 printf("failed to connect\n");
671                 return;
672         }
673
674         cli_sockopt(&cli, sockops);
675
676         printf("starting maxfid test\n");
677
678         fnum = 0;
679         while (1) {
680                 slprintf(fname,sizeof(fname)-1,template, fnum,getpid());
681                 if (cli_open(&cli, fname, 
682                              O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
683                     -1) {
684                         printf("open of %s failed (%s)\n", 
685                                fname, cli_errstr(&cli));
686                         printf("maximum fnum is %d\n", fnum);
687                         break;
688                 }
689                 fnum++;
690         }
691
692         printf("cleaning up\n");
693         while (fnum > n) {
694                 fnum--;
695                 slprintf(fname,sizeof(fname)-1,template, fnum,getpid());
696                 if (cli_unlink(&cli, fname)) {
697                         printf("unlink of %s failed (%s)\n", 
698                                fname, cli_errstr(&cli));
699                 }
700         }
701
702         printf("maxfid test finished\n");
703         close_connection(&cli);
704 }
705
706 /* generate a random buffer */
707 static void rand_buf(char *buf, int len)
708 {
709         while (len--) {
710                 *buf = sys_random();
711                 buf++;
712         }
713 }
714
715 /* send random IPC commands */
716 static void run_randomipc(void)
717 {
718         char *rparam = NULL;
719         char *rdata = NULL;
720         int rdrcnt,rprcnt;
721         pstring param;
722         int api, param_len, i;
723         static struct cli_state cli;
724
725         printf("starting random ipc test\n");
726
727         if (!open_connection(&cli)) {
728                 return;
729         }
730
731         for (i=0;i<50000;i++) {
732                 api = sys_random() % 500;
733                 param_len = (sys_random() % 64);
734
735                 rand_buf(param, param_len);
736   
737                 SSVAL(param,0,api); 
738
739                 cli_api(&cli, 
740                         param, param_len, 8,  
741                         NULL, 0, BUFFER_SIZE, 
742                         &rparam, &rprcnt,     
743                         &rdata, &rdrcnt);
744         }
745
746         close_connection(&cli);
747
748         printf("finished random ipc test\n");
749 }
750
751
752
753 static void browse_callback(const char *sname, uint32 stype, 
754                             const char *comment)
755 {
756         printf("\t%20.20s %08x %s\n", sname, stype, comment);
757 }
758
759
760
761 /*
762   This test checks the browse list code
763
764 */
765 static void run_browsetest(void)
766 {
767         static struct cli_state cli;
768
769         printf("starting browse test\n");
770
771         if (!open_connection(&cli)) {
772                 return;
773         }
774
775         printf("domain list:\n");
776         cli_NetServerEnum(&cli, workgroup, 
777                           SV_TYPE_DOMAIN_ENUM,
778                           browse_callback);
779
780         printf("machine list:\n");
781         cli_NetServerEnum(&cli, workgroup, 
782                           SV_TYPE_ALL,
783                           browse_callback);
784
785         close_connection(&cli);
786
787         printf("browse test finished\n");
788 }
789
790
791 /*
792   This checks how the getatr calls works
793 */
794 static void run_attrtest(void)
795 {
796         static struct cli_state cli;
797         int fnum;
798         time_t t, t2;
799         char *fname = "\\attrib.tst";
800
801         printf("starting attrib test\n");
802
803         if (!open_connection(&cli)) {
804                 return;
805         }
806
807         cli_unlink(&cli, fname);
808         fnum = cli_open(&cli, fname, 
809                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
810         cli_close(&cli, fnum);
811         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
812                 printf("getatr failed (%s)\n", cli_errstr(&cli));
813         }
814
815         if (abs(t - time(NULL)) > 2) {
816                 printf("ERROR: SMBgetatr bug. time is %s",
817                        ctime(&t));
818                 t = time(NULL);
819         }
820
821         t2 = t-60*60*24; /* 1 day ago */
822
823         if (!cli_setatr(&cli, fname, 0, t2)) {
824                 printf("setatr failed (%s)\n", cli_errstr(&cli));
825         }
826
827         if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
828                 printf("getatr failed (%s)\n", cli_errstr(&cli));
829         }
830
831         if (t != t2) {
832                 printf("ERROR: getatr/setatr bug. times are\n%s",
833                        ctime(&t));
834                 printf("%s", ctime(&t2));
835         }
836
837         cli_unlink(&cli, fname);
838
839         close_connection(&cli);
840
841         printf("attrib test finished\n");
842 }
843
844
845 /*
846   This checks a couple of trans2 calls
847 */
848 static void run_trans2test(void)
849 {
850         static struct cli_state cli;
851         int fnum;
852         size_t size;
853         time_t c_time, a_time, m_time, w_time, m_time2;
854         char *fname = "\\trans2.tst";
855         char *dname = "\\trans2";
856         char *fname2 = "\\trans2\\trans2.tst";
857
858         printf("starting trans2 test\n");
859
860         if (!open_connection(&cli)) {
861                 return;
862         }
863
864         cli_unlink(&cli, fname);
865         fnum = cli_open(&cli, fname, 
866                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
867         if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time)) {
868                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
869         }
870         cli_close(&cli, fnum);
871
872         sleep(2);
873
874         cli_unlink(&cli, fname);
875         fnum = cli_open(&cli, fname, 
876                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
877         cli_close(&cli, fnum);
878
879         if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
880                 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
881         } else {
882                 if (c_time != m_time) {
883                         printf("create time=%s", ctime(&c_time));
884                         printf("modify time=%s", ctime(&m_time));
885                         printf("This system appears to have sticky create times\n");
886                 }
887                 if (a_time % (60*60) == 0) {
888                         printf("access time=%s", ctime(&a_time));
889                         printf("This system appears to set a midnight access time\n");
890                 }
891
892                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
893                         printf("ERROR: totally incorrect times - maybe word reversed?\n");
894                 }
895         }
896
897
898         cli_unlink(&cli, fname);
899         fnum = cli_open(&cli, fname, 
900                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
901         cli_close(&cli, fnum);
902         if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time, 
903                             &w_time, &size, NULL)) {
904                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
905         } else {
906                 if (w_time < 60*60*24*2) {
907                         printf("write time=%s", ctime(&w_time));
908                         printf("This system appears to set a initial 0 write time\n");
909                 }
910         }
911
912         cli_unlink(&cli, fname);
913
914
915         /* check if the server updates the directory modification time
916            when creating a new file */
917         if (!cli_mkdir(&cli, dname)) {
918                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
919         }
920         sleep(3);
921         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time, 
922                             &w_time, &size, NULL)) {
923                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
924         }
925
926         fnum = cli_open(&cli, fname2, 
927                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
928         cli_write(&cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
929         cli_close(&cli, fnum);
930         if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2, 
931                             &w_time, &size, NULL)) {
932                 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
933         } else {
934                 if (m_time2 == m_time)
935                         printf("This system does not update directory modification times\n");
936         }
937         cli_unlink(&cli, fname2);
938         cli_rmdir(&cli, dname);
939
940
941         close_connection(&cli);
942
943         printf("trans2 test finished\n");
944 }
945
946
947 static void create_procs(int nprocs, int numops, void (*fn)(int ))
948 {
949         int i, status;
950
951         for (i=0;i<nprocs;i++) {
952                 if (fork() == 0) {
953                         int mypid = getpid();
954                         sys_srandom(mypid ^ time(NULL));
955                         fn(numops);
956                         _exit(0);
957                 }
958         }
959
960         for (i=0;i<nprocs;i++)
961                 waitpid(0, &status, 0);
962 }
963
964
965
966 /****************************************************************************
967   main program
968 ****************************************************************************/
969  int main(int argc,char *argv[])
970 {
971         int nprocs=1, numops=100;
972         int opt;
973         char *p;
974         int gotpass = 0;
975         extern char *optarg;
976         extern int optind;
977         extern FILE *dbf;
978
979         dbf = stdout;
980
981         charset_initialise();
982
983         if (argc < 2) {
984                 usage();
985         }
986
987         for(p = argv[1]; *p; p++)
988           if(*p == '\\')
989             *p = '/';
990  
991         if (strncmp(argv[1], "//", 2)) {
992                 usage();
993         }
994
995         fstrcpy(host, &argv[1][2]);
996         p = strchr(&host[2],'/');
997         if (!p) {
998                 usage();
999         }
1000         *p = 0;
1001         fstrcpy(share, p+1);
1002
1003         get_myname(myname,NULL);
1004
1005         if (*username == 0 && getenv("LOGNAME")) {
1006           pstrcpy(username,getenv("LOGNAME"));
1007         }
1008
1009         argc--;
1010         argv++;
1011
1012
1013         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
1014                 switch (opt) {
1015                 case 'W':
1016                         fstrcpy(workgroup,optarg);
1017                         break;
1018                 case 'm':
1019                         max_protocol = interpret_protocol(optarg, max_protocol);
1020                         break;
1021                 case 'N':
1022                         nprocs = atoi(optarg);
1023                         break;
1024                 case 'o':
1025                         numops = atoi(optarg);
1026                         break;
1027                 case 'O':
1028                         sockops = optarg;
1029                         break;
1030                 case 'n':
1031                         fstrcpy(myname, optarg);
1032                         break;
1033                 case 'U':
1034                         pstrcpy(username,optarg);
1035                         p = strchr(username,'%');
1036                         if (p) {
1037                                 *p = 0;
1038                                 pstrcpy(password, p+1);
1039                                 gotpass = 1;
1040                         }
1041                         break;
1042                 default:
1043                         printf("Unknown option %c (%d)\n", (char)opt, opt);
1044                         usage();
1045                 }
1046         }
1047
1048
1049         while (!gotpass) {
1050                 p = getpass("Password:");
1051                 if (p) {
1052                         pstrcpy(password, p);
1053                         gotpass = 1;
1054                 }
1055         }
1056
1057         printf("host=%s share=%s user=%s myname=%s\n", 
1058                host, share, username, myname);
1059
1060         run_fdpasstest();
1061         run_locktest1();
1062         run_locktest2();
1063         run_locktest3(numops);
1064         run_unlinktest();
1065         run_browsetest();
1066         run_attrtest();
1067         run_trans2test();
1068
1069         create_procs(nprocs, numops, run_maxfidtest);
1070
1071         start_timer();
1072         create_procs(nprocs, numops, run_torture);
1073         printf("rw_torture: %g secs\n", end_timer());
1074
1075         run_randomipc();        
1076
1077         return(0);
1078 }
1079
1080