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