a simple SMB torture tester. This will allow us to evaluate locking
[abartlet/samba.git/.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_EXCL, DENY_NONE);
121         if (fnum2 == -1)
122                 fnum2 = cli_open(&cli, lockfname, O_RDWR, DENY_NONE);
123         if (fnum2 == -1) {
124                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(&cli));
125                 return -1;
126         }
127
128
129         for (i=0;i<numops;i++) {
130                 unsigned n = (unsigned)random()%10;
131                 printf("%d\r", i); fflush(stdout);
132                 sprintf(fname,"\\torture.%u", n);
133
134                 if (!wait_lock(fnum2, n*sizeof(int), sizeof(int))) {
135                         return -1;
136                 }
137
138                 fnum = cli_open(&cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
139                 if (fnum == -1) {
140                         printf("open failed (%s)\n", cli_errstr(&cli));
141                         break;
142                 }
143
144                 if (cli_write(&cli, fnum, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
145                         printf("write failed (%s)\n", cli_errstr(&cli));
146                 }
147
148                 pid2 = 0;
149
150                 if (cli_read(&cli, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
151                         printf("read failed (%s)\n", cli_errstr(&cli));
152                 }
153
154                 if (pid2 != pid) {
155                         printf("data corruption!\n");
156                 }
157
158                 if (!cli_close(&cli, fnum)) {
159                         printf("close failed (%s)\n", cli_errstr(&cli));
160                 }
161
162                 if (!cli_unlink(&cli, fname)) {
163                         printf("unlink failed (%s)\n", cli_errstr(&cli));
164                 }
165
166                 if (!cli_unlock(&cli, fnum2, n*sizeof(int), sizeof(int), -1)) {
167                         printf("unlock failed (%s)\n", cli_errstr(&cli));
168                 }
169         }
170
171         printf("%d\n", i);
172
173         return 0;
174 }
175
176 static void usage(void)
177 {
178         printf("Usage: smbtorture \\\\server\\share <options>\n");
179
180         printf("\t-U user%%pass\n");
181         printf("\t-N numprocs\n");
182         printf("\t-n my_netbios_name\n");
183         printf("\t-W workgroup\n");
184         printf("\t-o num_operations\n");
185         printf("\t-O socket_options\n");
186         printf("\n");
187
188         exit(1);
189 }
190
191
192
193 static void run_torture(int numops)
194 {
195         if (open_connection() == 0) {
196                 cli_sockopt(&cli, sockops);
197
198                 printf("pid %d OK\n", getpid());
199
200                 rw_torture(numops);
201
202                 close_connection();
203         }
204 }
205
206
207 static void create_procs(int nprocs, int numops)
208 {
209         int i, status;
210
211         for (i=0;i<nprocs;i++) {
212                 if (fork() == 0) {
213                         int mypid = getpid();
214                         srandom(mypid ^ time(NULL));
215                         run_torture(numops);
216                         _exit(0);
217                 }
218         }
219
220         for (i=0;i<nprocs;i++)
221                 waitpid(0, &status, 0);
222 }
223
224
225
226 /****************************************************************************
227   main program
228 ****************************************************************************/
229  int main(int argc,char *argv[])
230 {
231         int nprocs=1, numops=100;
232         int opt;
233         char *p;
234         int gotpass = 0;
235         extern char *optarg;
236         extern int optind;
237         extern FILE *dbf;
238
239         dbf = stdout;
240
241         charset_initialise();
242
243         if (argc < 2) {
244                 usage();
245         }
246
247         if (strncmp(argv[1], "\\\\", 2)) {
248                 usage();
249         }
250
251         fstrcpy(host, &argv[1][2]);
252         p = strchr(&host[2],'\\');
253         if (!p) {
254                 usage();
255         }
256         *p = 0;
257         fstrcpy(share, p+1);
258
259         get_myname(myname,NULL);
260
261         argc--;
262         argv++;
263
264
265         while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:")) != EOF) {
266                 switch (opt) {
267                 case 'W':
268                         fstrcpy(workgroup,optarg);
269                         break;
270                 case 'N':
271                         nprocs = atoi(optarg);
272                         break;
273                 case 'o':
274                         numops = atoi(optarg);
275                         break;
276                 case 'O':
277                         sockops = optarg;
278                         break;
279                 case 'n':
280                         fstrcpy(myname, optarg);
281                         break;
282                 case 'U':
283                         strcpy(username,optarg);
284                         p = strchr(username,'%');
285                         if (p) {
286                                 *p = 0;
287                                 strcpy(password, p+1);
288                                 gotpass = 1;
289                         }
290                         break;
291                 default:
292                         printf("Unknown option %c (%d)\n", (char)opt, opt);
293                         usage();
294                 }
295         }
296
297
298         while (!gotpass) {
299                 p = getpass("Password:");
300                 if (p) {
301                         strcpy(password, p);
302                         gotpass = 1;
303                 }
304         }
305
306         printf("host=%s share=%s user=%s myname=%s\n", 
307                host, share, username, myname);
308
309         start_timer();
310         create_procs(nprocs, numops);
311         printf("rw_torture: %g secs\n", end_timer());
312
313         return(0);
314 }
315
316