set O_CREAT on lock file
[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
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 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
25
26 #include "includes.h"
27
28 static struct cli_state cli;
29 static fstring host, workgroup, share, password, username, myname;
30 static char *sockops="";
31
32
33 static struct timeval tp1,tp2;
34
35 static void start_timer()
36 {
37         gettimeofday(&tp1,NULL);
38 }
39
40 static double end_timer()
41 {
42         gettimeofday(&tp2,NULL);
43         return((tp2.tv_sec - tp1.tv_sec) + 
44                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
45 }
46
47
48 static int open_connection(void)
49 {
50         if (!cli_initialise(&cli) || !cli_connect(&cli, host, NULL)) {
51                 printf("Failed to connect with %s\n", host);
52         }
53
54         if (!cli_session_request(&cli, host, 0x20, myname)) {
55                 printf("%s rejected the session\n",host);
56                 cli_shutdown(&cli);
57                 return -1;
58         }
59
60         if (!cli_negprot(&cli)) {
61                 printf("%s rejected the negprot (%s)\n",host, cli_errstr(&cli));
62                 cli_shutdown(&cli);
63                 return -1;
64         }
65
66         if (!cli_session_setup(&cli, username, password, strlen(password),
67                                "", 0, workgroup)) {
68                 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(&cli));
69                 cli_shutdown(&cli);
70                 return -1;
71         }
72
73         if (!cli_send_tconX(&cli, share, "A:", password, strlen(password)+1)) {
74                 printf("%s refused tree connect (%s)\n", host, cli_errstr(&cli));
75                 cli_shutdown(&cli);
76                 return -1;
77         }
78
79         return 0;
80 }
81
82
83
84 static void close_connection(void)
85 {
86         if (!cli_tdis(&cli)) {
87                 printf("tdis failed (%s)\n", cli_errstr(&cli));
88         }
89
90         cli_shutdown(&cli);
91 }
92
93
94
95
96 static BOOL wait_lock(int fnum, uint32 offset, uint32 len)
97 {
98         while (!cli_lock(&cli, fnum, offset, len, -1)) {
99                 int eclass, num;
100                 cli_error(&cli, &eclass, &num);
101                 if (eclass != ERRDOS || num != ERRlock) {
102                         printf("lock failed (%s)\n", 
103                                cli_errstr(&cli));
104                         return False;
105                 }
106         }
107         return True;
108 }
109
110
111 static int rw_torture(int numops)
112 {
113         char *lockfname = "\\torture.lck";
114         fstring fname;
115         int fnum;
116         int fnum2;
117         int pid2, pid = getpid();
118         int i;
119
120         fnum2 = cli_open(&cli, lockfname, O_RDWR | O_CREAT | O_EXCL, 
121                          DENY_NONE);
122         if (fnum2 == -1)
123                 fnum2 = cli_open(&cli, lockfname, O_RDWR, DENY_NONE);
124         if (fnum2 == -1) {
125                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(&cli));
126                 return -1;
127         }
128
129
130         for (i=0;i<numops;i++) {
131                 unsigned n = (unsigned)random()%10;
132                 printf("%d\r", i); fflush(stdout);
133                 sprintf(fname,"\\torture.%u", n);
134
135                 if (!wait_lock(fnum2, n*sizeof(int), sizeof(int))) {
136                         return -1;
137                 }
138
139                 fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
140                 if (fnum == -1) {
141                         printf("open failed (%s)\n", cli_errstr(&cli));
142                         break;
143                 }
144
145                 if (cli_write(&cli, fnum, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
146                         printf("write failed (%s)\n", cli_errstr(&cli));
147                 }
148
149                 pid2 = 0;
150
151                 if (cli_read(&cli, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
152                         printf("read failed (%s)\n", cli_errstr(&cli));
153                 }
154
155                 if (pid2 != pid) {
156                         printf("data corruption!\n");
157                 }
158
159                 if (!cli_close(&cli, fnum)) {
160                         printf("close failed (%s)\n", cli_errstr(&cli));
161                 }
162
163                 if (!cli_unlink(&cli, fname)) {
164                         printf("unlink failed (%s)\n", cli_errstr(&cli));
165                 }
166
167                 if (!cli_unlock(&cli, fnum2, n*sizeof(int), sizeof(int), -1)) {
168                         printf("unlock failed (%s)\n", cli_errstr(&cli));
169                 }
170         }
171
172         printf("%d\n", i);
173
174         return 0;
175 }
176
177 static void usage(void)
178 {
179         printf("Usage: smbtorture \\\\server\\share <options>\n");
180
181         printf("\t-U user%%pass\n");
182         printf("\t-N numprocs\n");
183         printf("\t-n my_netbios_name\n");
184         printf("\t-W workgroup\n");
185         printf("\t-o num_operations\n");
186         printf("\t-O socket_options\n");
187         printf("\n");
188
189         exit(1);
190 }
191
192
193
194 static void run_torture(int numops)
195 {
196         if (open_connection() == 0) {
197                 cli_sockopt(&cli, sockops);
198
199                 printf("pid %d OK\n", getpid());
200
201                 rw_torture(numops);
202
203                 close_connection();
204         }
205 }
206
207
208 static void create_procs(int nprocs, int numops)
209 {
210         int i, status;
211
212         for (i=0;i<nprocs;i++) {
213                 if (fork() == 0) {
214                         int mypid = getpid();
215                         srandom(mypid ^ time(NULL));
216                         run_torture(numops);
217                         _exit(0);
218                 }
219         }
220
221         for (i=0;i<nprocs;i++)
222                 waitpid(0, &status, 0);
223 }
224
225
226
227 /****************************************************************************
228   main program
229 ****************************************************************************/
230  int main(int argc,char *argv[])
231 {
232         int nprocs=1, numops=100;
233         int opt;
234         char *p;
235         int gotpass = 0;
236         extern char *optarg;
237         extern int optind;
238         extern FILE *dbf;
239
240         dbf = stdout;
241
242         charset_initialise();
243
244         if (argc < 2) {
245                 usage();
246         }
247
248         if (strncmp(argv[1], "\\\\", 2)) {
249                 usage();
250         }
251
252         fstrcpy(host, &argv[1][2]);
253         p = strchr(&host[2],'\\');
254         if (!p) {
255                 usage();
256         }
257         *p = 0;
258         fstrcpy(share, p+1);
259
260         get_myname(myname,NULL);
261
262         argc--;
263         argv++;
264
265
266         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:")) != EOF) {
267                 switch (opt) {
268                 case 'W':
269                         fstrcpy(workgroup,optarg);
270                         break;
271                 case 'N':
272                         nprocs = atoi(optarg);
273                         break;
274                 case 'o':
275                         numops = atoi(optarg);
276                         break;
277                 case 'O':
278                         sockops = optarg;
279                         break;
280                 case 'n':
281                         fstrcpy(myname, optarg);
282                         break;
283                 case 'U':
284                         strcpy(username,optarg);
285                         p = strchr(username,'%');
286                         if (p) {
287                                 *p = 0;
288                                 strcpy(password, p+1);
289                                 gotpass = 1;
290                         }
291                         break;
292                 default:
293                         printf("Unknown option %c (%d)\n", (char)opt, opt);
294                         usage();
295                 }
296         }
297
298
299         while (!gotpass) {
300                 p = getpass("Password:");
301                 if (p) {
302                         strcpy(password, p);
303                         gotpass = 1;
304                 }
305         }
306
307         printf("host=%s share=%s user=%s myname=%s\n", 
308                host, share, username, myname);
309
310         start_timer();
311         create_procs(nprocs, numops);
312         printf("rw_torture: %g secs\n", end_timer());
313
314         return(0);
315 }
316
317