r3383: avoid multi-part SMBtrans and SMBtrans2 replies until our client library can...
[samba.git] / source / torture / basic / dfstest.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester - DFS tests
4    Copyright (C) James J Myers 2003  <myersjj@samba.org>
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 #define DFS_SERVER_COUNT 6
24 #define DFS_FILE_COUNT 8
25 extern char *host, *share, *password, *username;
26 static struct smbcli_client context;
27 static const char *sockops="TCP_NODELAY";
28
29 /*
30  checks for correct DFS cluster support
31  */
32 BOOL torture_dfs_basic(void)
33 {
34         int current_server = 0;
35         char *fname[DFS_FILE_COUNT];
36         int file_server[DFS_FILE_COUNT];
37         int fnum[DFS_FILE_COUNT];
38         int i;
39         const char *template = "\\\\%s\\%s\\dfstest%d.tmp";
40         char *filedata;
41         int server_count = 0;
42         int connection_flags = SMBCLI_FULL_CONNECTION_USE_KERBEROS
43                                 | SMBCLI_FULL_CONNECTION_USE_DFS
44                                 ;
45         
46         printf("starting dfs_basic_test\n");
47         smbcli_client_initialize(&context, sockops, username, password, lp_workgroup(), connection_flags);
48
49         if ((current_server = smbcli_dfs_open_connection(&context, host, share, connection_flags) < 0))
50                 return False;
51
52         for (i=0; i < DFS_FILE_COUNT ; i++) {
53                 file_server[i] = 0;
54                 DEBUG(4,("host=%s share=%s cli host=%s cli share=%s\n",
55                         host, share, smbcli_state_get_host(context.cli[file_server[i]]),
56                         smbcli_state_get_share(context.cli[file_server[i]])));
57                 host = smbcli_state_get_host(context.cli[file_server[i]]);
58                 share = smbcli_state_get_share(context.cli[file_server[i]]);
59                 asprintf(&fname[i], template, host, share, i);
60                 DEBUG(3,("unlinking %s\n", fname[i]));
61                 smbcli_nt_unlink(&context, &file_server[i], fname[i], 0);
62         }
63         
64         for (i=0; i < DFS_FILE_COUNT ; i++) {
65                 host = smbcli_state_get_host(context.cli[file_server[i]]);
66                 share = smbcli_state_get_share(context.cli[file_server[i]]);
67                 asprintf(&fname[i], template, host, share, i);
68                 DEBUG(3,("open %s on server %s(%d)\n",
69                         fname[i], host, file_server[i]));
70                 fnum[i] = smbcli_dfs_open(&context, &file_server[i], fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
71                 if (fnum[i] == -1)
72                 {
73                         printf("open of %s failed (%s)\n", fname[i], smbcli_errstr(context.cli[file_server[i]]));
74                         return False;
75                 }
76                 asprintf(&filedata, "%s %d", fname[i], fnum[i]);
77                 DEBUG(3,("write %d bytes (%s) to %s (fid %d) on server %s(%d)\n",
78                         strlen(filedata), filedata, fname[i], fnum[i],
79                         host, file_server[i]));
80                 if (smbcli_write(context.cli[file_server[i]], fnum[i], 0, filedata, 0, strlen(filedata)) != strlen(filedata))
81                 {
82                         printf("write failed (%s)\n", smbcli_errstr(context.cli[file_server[i]]));
83                         return False;
84                 }
85
86                 if (!smbcli_close(context.cli[file_server[i]], fnum[i])) {
87                         printf("close of %s failed (%s)\n", fname[i], smbcli_errstr(context.cli[file_server[i]]));
88                         return False;
89                 }
90         }
91         DEBUG(3,("used Dfs servers:"));
92         for (i=0; i < DFS_SERVER_COUNT ; i++) {
93                 server_count++;
94                 DEBUG(3,(" %s(%d)",     smbcli_state_get_host(context.cli[file_server[i]]), i));
95                 if (!torture_close_connection(context.cli[i]))
96                         return False;
97         }
98         DEBUG(3,("\n"));
99
100         printf("Passed dfstest, found and used %d Dfs servers\n", server_count);
101         return True;
102 }
103
104 /*
105  Check for correct DFS rename support.
106  First test is simple rename, a la command line, explorer.
107  Second test is simulation of MS Word edit/save file.
108  */
109 BOOL torture_dfs_rename(int dummy)
110 {
111         int current_server = -1;
112         char *fname[DFS_FILE_COUNT];
113         int file_server[DFS_FILE_COUNT];
114         int fnum[DFS_FILE_COUNT];
115         int i;
116         const char *template = "\\\\%s\\%s\\dfstest%d.tmp";
117         const char *template2orig = "\\\\%s\\%s\\dfstestorig.txt";
118         const char *template2old = "\\\\%s\\%s\\~dfstestold.txt";
119         const char *template2new = "\\\\%s\\%s\\~dfstestnew.txt";
120         char *filedata, *newdata;
121         int server_count = 0;
122         int connection_flags = SMBCLI_FULL_CONNECTION_USE_KERBEROS
123                                 | SMBCLI_FULL_CONNECTION_USE_DFS
124                                 ;
125
126         printf("starting dfs_rename_test\n");
127         smbcli_client_initialize(&context, sockops, username, password,
128                               lp_workgroup(), connection_flags);
129         
130         if ((current_server = smbcli_dfs_open_connection(&context, host, share, connection_flags)) < 0)
131                 return False;
132         
133         for (i=0; i < DFS_FILE_COUNT ; i++) {
134                 file_server[i] = 0;
135                 slprintf(fname[i],sizeof(fstring)-1,template, host, share, i);
136                 DEBUG(3,("unlinking %s\n", fname[i]));
137                 smbcli_nt_unlink(&context, &file_server[i], fname[i], 0);
138         }
139         /* Simple rename test */
140         for (i=0; i < 1 ; i++) {
141                 slprintf(fname[i],sizeof(fstring)-1,template,
142                         smbcli_state_get_host(context.cli[file_server[i]]),
143                         smbcli_state_get_share(context.cli[file_server[i]]), i);
144                 DEBUG(3,("open %s on server %s(%d)\n",
145                         fname[i], smbcli_state_get_host(context.cli[file_server[i]]), file_server[i]));
146                         
147                 fnum[i] = smbcli_dfs_open(&context, &file_server[i], fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
148                 if (fnum[i] == -1) {
149                         printf("open of %s failed (%s)\n", fname[i], smbcli_errstr(context.cli[file_server[i]]));
150                         return False;
151                 }
152                 asprintf(&filedata, "%s %d", fname[i], (int)getpid());
153                 DEBUG(3,("write %d bytes (%s) to %s (fid %d) on server %s(%d)\n",
154                         strlen(filedata), filedata, fname[i], fnum[i],
155                         smbcli_state_get_host(context.cli[file_server[i]]), file_server[i]));
156                 if (smbcli_write(context.cli[file_server[i]], fnum[i], 0, filedata, 0, strlen(filedata)) != strlen(filedata))
157                 {
158                         printf("write failed (%s)\n", smbcli_errstr(context.cli[file_server[i]]));
159                         return False;
160                 }
161
162                 if (!smbcli_close(context.cli[file_server[i]], fnum[i])) {
163                         printf("close of %s failed (%s)\n", fname[i], smbcli_errstr(context.cli[file_server[i]]));
164                         return False;
165                 }
166         }
167         // now attempt to rename the file
168         DEBUG(3,("rename %s to %s on server %s(%d)\n",
169                         fname[0], fname[1], smbcli_state_get_host(context.cli[file_server[i]]), file_server[0]));
170         if (!smbcli_dfs_rename(&context, &file_server[0], fname[0], fname[1])) {
171                 printf("rename of %s to %s failed (%s)\n", fname[0], fname[1], smbcli_errstr(context.cli[file_server[0]]));
172                 return False;
173         }
174         // clean up
175         DEBUG(3,("used Dfs servers:"));
176         for (i=0; i < DFS_SERVER_COUNT ; i++) {
177                 server_count++;
178                 DEBUG(3,(" %s(%d)",     smbcli_state_get_host(context.cli[file_server[i]]), i));
179                 if (!torture_close_connection(context.cli[i]))
180                         return False;
181         }
182         DEBUG(3,("\n"));
183         printf("Dfstest: passed simple rename test\n");
184         
185         /* Now try more complicated test, a la MS Word.
186          * Open existing file (x) and read file and close.
187          * Then open, write to new temp name file (~x.new), close.
188          * Then rename old file name to old temp name file (~x.old).
189          * Then rename new temp name file to oroginal name (x). */
190         smbcli_client_initialize(&context, sockops, username, password,
191                               lp_workgroup(), connection_flags);
192         
193         if ((current_server = smbcli_dfs_open_connection(&context, host, share, connection_flags)) < 0)
194                 return False;    
195         slprintf(fname[0],sizeof(fname[0])-1,template2orig, host, share);
196         slprintf(fname[1],sizeof(fname[1])-1,template2old, host, share);
197         slprintf(fname[2],sizeof(fname[2])-1,template2new, host, share);
198         for (i=0; i < DFS_FILE_COUNT ; i++) {
199                 file_server[i] = 0;
200                 fnum[i] = 0;
201                 DEBUG(3,("unlinking %s\n", fname[i]));
202                 smbcli_nt_unlink(&context, &file_server[i], fname[i], 0);
203         }
204         asprintf(&fname[0],template2orig,
205                         smbcli_state_get_host(context.cli[0]),
206                         smbcli_state_get_share(context.cli[0]), 0);
207         asprintf(&fname[1],template2old,
208                         smbcli_state_get_host(context.cli[1]),
209                         smbcli_state_get_share(context.cli[1]), 1);
210         asprintf(&fname[2],template2new,
211                         smbcli_state_get_host(context.cli[2]),
212                         smbcli_state_get_share(context.cli[2]), 2);
213         DEBUG(3,("edit(MS Word) %s on server %s(%d)\n",
214                         fname[0], smbcli_state_get_host(context.cli[0]), file_server[0]));
215         DEBUG(3,("open %s on server %s(%d)\n",
216                 fname[0], smbcli_state_get_host(context.cli[0]), file_server[0]));
217                         
218         fnum[0] = smbcli_dfs_open(&context, &file_server[0], fname[0], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
219         if (fnum[0] == -1)
220         {
221                 printf("open of %s failed (%s)\n", fname[0], smbcli_errstr(context.cli[file_server[0]]));
222                 return False;
223         }
224         slprintf(filedata, sizeof(fstring)-1, "%s %d", fname[0], (int)getpid());
225         DEBUG(3,("write %d bytes (%s) to %s (fid %d) on server %s(%d)\n",
226                 strlen(filedata), filedata, fname[0], fnum[0],
227                 smbcli_state_get_host(context.cli[0]), file_server[0]));
228         if (smbcli_write(context.cli[file_server[0]], fnum[0], 0, filedata, 0, strlen(filedata)) != strlen(filedata))
229         {
230                 printf("write failed (%s)\n", smbcli_errstr(context.cli[file_server[0]]));
231                 return False;
232         }
233         // read data from original file
234         DEBUG(3,("read %s (fid %d) on server %s(%d)\n",
235                 fname[0], fnum[0], smbcli_state_get_host(context.cli[0]), file_server[0]));
236         if (smbcli_read(context.cli[file_server[0]], fnum[0], filedata, 0, strlen(filedata)) != strlen(filedata))
237         {
238                 printf("read failed (%s)", smbcli_errstr(context.cli[file_server[0]]));
239                 return False;
240         }
241         DEBUG(3,("close %s on server %s(%d)\n",
242                 fname[0], smbcli_state_get_host(context.cli[0]), file_server[0]));
243         if (!smbcli_close(context.cli[file_server[0]], fnum[0])) {
244                 printf("close of %s failed (%s)\n", fname[0], smbcli_errstr(context.cli[file_server[0]]));
245                 return False;
246         }
247         // open new temp file, write data
248         DEBUG(3,("open %s on server %s(%d)\n",
249                 fname[2], smbcli_state_get_host(context.cli[2]), file_server[2]));
250         fnum[2] = smbcli_dfs_open(&context, &file_server[2], fname[2], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
251         if (fnum[2] == -1)
252         {
253                 printf("open of %s failed (%s)\n", fname[2], smbcli_errstr(context.cli[file_server[2]]));
254                 return False;
255         }
256         DEBUG(3,("write %d bytes (%s) to %s (fid %d) on server %s(%d)\n",
257                 strlen(filedata), filedata, fname[2], fnum[2],
258                 smbcli_state_get_host(context.cli[2]), file_server[2]));
259         if (smbcli_write(context.cli[file_server[2]], fnum[2], 0, filedata, 0, strlen(filedata)) != strlen(filedata))
260         {
261                 printf("write failed (%s)\n", smbcli_errstr(context.cli[file_server[2]]));
262                 return False;
263         }
264         slprintf(newdata, sizeof(fstring)-1, "new data: %s %d", fname[0], (int)getpid());
265         DEBUG(3,("write new data %d bytes (%s) to %s (fid %d) on server %s(%d)\n",
266                 strlen(newdata), newdata, fname[2], fnum[2],
267                 smbcli_state_get_host(context.cli[2]), file_server[2]));
268         if (smbcli_write(context.cli[file_server[2]], fnum[2], 0, newdata, strlen(filedata), strlen(newdata)) != strlen(newdata))
269         {
270                 printf("write failed (%s)\n", smbcli_errstr(context.cli[file_server[2]]));
271                 return False;
272         }
273         DEBUG(3,("close %s on server %s(%d)\n",
274                 fname[2], smbcli_state_get_host(context.cli[2]), file_server[2]));
275         if (!smbcli_close(context.cli[file_server[2]], fnum[2])) {
276                 printf("close of %s failed (%s)\n", fname[2], smbcli_errstr(context.cli[file_server[2]]));
277                 return False;
278         }
279         DEBUG(3,("close successful %s on server %s(%d)\n",
280                 fname[2], smbcli_state_get_host(context.cli[2]), file_server[2]));
281         // rename original file to temp 
282         DEBUG(4,("file_server[0]=%d\n", file_server[0]));
283         DEBUG(4,("context.cli[file_server[0]].desthost=%s\n", smbcli_state_get_host(context.cli[0])));
284         DEBUG(3,("rename %s to %s on server %s(%d)\n",
285                         fname[0], fname[1], smbcli_state_get_host(context.cli[0]), file_server[0]));
286         if (!smbcli_dfs_rename(&context, &file_server[0], fname[0], fname[1])) {
287                 printf("rename of %s to %s failed (%s)\n", fname[0], fname[1], smbcli_errstr(context.cli[file_server[0]]));
288                 return False;
289         }
290         // name new temp file to original
291         DEBUG(3,("rename %s to %s on server %s(%d)\n",
292                         fname[2], fname[0], smbcli_state_get_host(context.cli[2]), file_server[2]));
293         if (!smbcli_dfs_rename(&context, &file_server[2], fname[2], fname[0])) {
294                 printf("rename of %s to %s failed (%s)\n", fname[2], fname[0], smbcli_errstr(context.cli[file_server[2]]));
295                 return False;
296         }
297         printf("Dfstest: passed MS Word rename test\n");
298         // clean up
299         DEBUG(3,("used Dfs servers:"));
300         for (i=0; i < DFS_SERVER_COUNT ; i++) {
301                 server_count++;
302                 DEBUG(3,(" %s(%d)",     smbcli_state_get_host(context.cli[i]), i));
303                 if (!torture_close_connection(context.cli[i]))
304                         return False;
305         }
306         DEBUG(3,("\n"));
307
308         printf("Passed dfs_rename_test\n");
309         return True;
310 }
311 struct list_fn_parms {
312         struct smbcli_client *context;
313         char* rname;
314 } list_fn_parms;
315
316 void dfs_list_fn(file_info *finfo, const char *rname, void* parmsp);
317 void delete_file(file_info *finfo, const char *rname)
318 {
319         int server = 0;
320         char *fname;
321         
322         DEBUG(3,("deleting file %s in %s\n", finfo->name, rname));
323         asprintf(&fname, "%s\\%s", rname, finfo->name);
324         smbcli_nt_unlink(&context, &server, fname, 0);
325 }
326 void delete_directory(file_info *finfo, const char *rname)
327 {
328         int server = 0;
329         char *dname, *rname2;
330         
331         DEBUG(3,("deleting directory %s in %s\n", finfo->name, rname));
332         asprintf(&dname, "%s%s\\*", rname, finfo->name);
333         smbcli_nt_unlink(&context, &server, dname, 0);
334         asprintf(&dname, "%s%s\\*", rname, finfo->name);
335         asprintf(&rname2, "%s%s", rname, finfo->name);                  
336         smbcli_search(context.cli[0], dname, FILE_ATTRIBUTE_DIRECTORY,
337                 dfs_list_fn, (void*)rname2);
338         smbcli_dfs_rmdir(&context, &server, rname2);
339 }
340
341 void dfs_list_fn(file_info *finfo, const char *name, void* parmsp)
342 {
343         struct list_fn_parms *parms = (struct list_fn_parms*)parmsp;
344         
345         DEBUG(4,("processing %s in %s\n", finfo->name, parms->rname));
346         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
347                 delete_directory(finfo, parms->rname);
348         }
349         else {
350                 delete_file(finfo, parms->rname);
351         }
352 }
353
354 /*
355  checks for correct DFS cluster support creating random dirs/files.
356  */
357 #define DFS_RANDOM_FILE_COUNT 10
358 #define DFS_RANDOM_DIR_COUNT 3
359 #define DFS_RANDOM_DIR_LEVELS 2  
360 BOOL torture_dfs_random(void)
361 {
362         char *fname[DFS_RANDOM_FILE_COUNT];
363         int file_server[DFS_RANDOM_FILE_COUNT];
364         char *dname[DFS_RANDOM_DIR_COUNT];
365         int dir_server[DFS_RANDOM_DIR_COUNT];
366         char *rname;
367         int fnum[DFS_FILE_COUNT];
368         int i;
369         const char *ftemplate = "%s\\dfsfile%d.tmp";
370         const char *alltemplate = "\\\\%s\\%s\\dfs*.tmp";
371         char *filedata;
372         int server_count = 0;
373         int file_count;
374         int connection_flags = SMBCLI_FULL_CONNECTION_USE_KERBEROS
375                                 | SMBCLI_FULL_CONNECTION_USE_DFS
376                                 ;
377         
378         printf("starting dfs_random_test\n");
379         smbcli_client_initialize(&context, sockops, username, password,
380                               lp_workgroup(), connection_flags);
381
382         if ((dir_server[0] = smbcli_dfs_open_connection(&context, host, share, connection_flags)) < 0)
383                 return False;
384
385         // get list of directories named dfsdir*.
386         // delete all files in these directories using wild card,
387         // then delete directory.
388         asprintf(&rname, "\\\\%s\\%s\\",
389                         smbcli_state_get_host(context.cli[0]),
390                         smbcli_state_get_share(context.cli[0]));
391         asprintf(&fname[0], alltemplate,
392                         smbcli_state_get_host(context.cli[0]),
393                         smbcli_state_get_share(context.cli[0]));
394         DEBUG(3,("deleting files %s in %s on server %s(%d)\n",
395                 fname[0], rname, smbcli_state_get_host(context.cli[0]), dir_server[0]));
396         file_count = smbcli_search(context.cli[0], fname[0], FILE_ATTRIBUTE_DIRECTORY, dfs_list_fn, (void*)rname);
397
398         // create random directory names with 0-n levels
399         asprintf(&dname[0], "\\\\%s\\%s\\",
400                         smbcli_state_get_host(context.cli[0]),
401                         smbcli_state_get_share(context.cli[0]));
402         DEBUG(3,("creating directories in %s on server %s(%d)\n",
403                 rname, smbcli_state_get_host(context.cli[0]), dir_server[0]));
404         for (i=1; i < DFS_RANDOM_DIR_COUNT; i++) {
405                 dir_server[i] = 0;
406                 asprintf(&dname[i],
407                         "\\\\%s\\%s\\dfsdir%d.tmp",
408                         smbcli_state_get_host(context.cli[dir_server[i]]),
409                         smbcli_state_get_share(context.cli[dir_server[i]]),
410                         (int)sys_random()%10000);
411                 DEBUG(3,("mkdir %s on server %s(%d)\n",
412                         dname[i], smbcli_state_get_host(context.cli[dir_server[i]]), dir_server[i]));
413                 if (!smbcli_dfs_mkdir(&context, &dir_server[i], dname[i])) {
414                         printf("mkdir of %s failed (%s)\n", dname[i], smbcli_errstr(context.cli[dir_server[i]]));
415                         return False;
416                 }
417         }
418
419         for (i=0; i < DFS_RANDOM_FILE_COUNT ; i++) {
420                 // select a directory randomly, create a file in it.
421                 int dn = (int)sys_random()%DFS_RANDOM_DIR_COUNT;
422                 file_server[i] = dir_server[dn];
423                 asprintf(&fname[i], ftemplate, dname[dn], i);
424                 DEBUG(3,("open %s on server %s(%d)\n",
425                         fname[i], smbcli_state_get_host(context.cli[dir_server[i]]), file_server[i]));
426                 fnum[i] = smbcli_dfs_open(&context, &file_server[i], fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
427                 if (fnum[i] == -1)
428                 {
429                         printf("open of %s failed (%s)\n", fname[i], smbcli_errstr(context.cli[file_server[i]]));
430                         return False;
431                 }
432
433                 asprintf(&filedata, "%s %d", fname[i], fnum[i]);
434                 DEBUG(3,("write %d bytes (%s) to %s (fid %d) on server %s(%d)\n",
435                         strlen(filedata), filedata, fname[i], fnum[i],
436                         smbcli_state_get_host(context.cli[dir_server[i]]), file_server[i]));
437                 if (smbcli_write(context.cli[file_server[i]], fnum[i], 0, filedata, 0, strlen(filedata)) != strlen(filedata))
438                 {
439                         printf("write failed (%s)\n", smbcli_errstr(context.cli[file_server[i]]));
440                         return False;
441                 }
442
443                 if (!smbcli_close(context.cli[file_server[i]], fnum[i])) {
444                         printf("close of %s failed (%s)\n", fname[i], smbcli_errstr(context.cli[file_server[i]]));
445                         return False;
446                 }
447         }
448         DEBUG(3,("used Dfs servers:"));
449         for (i=0; i < DFS_SERVER_COUNT ; i++) {
450                 server_count++;
451                 DEBUG(3,(" %s(%d)",     smbcli_state_get_host(context.cli[i]), i));
452                 if (!torture_close_connection(context.cli[i]))
453                         return False;
454         }
455         DEBUG(3,("\n"));
456         
457         printf("Passed dfs_random_test\n");
458         return True;
459 }