selftest: split out failing owner related subtest from samba3.raw.acls.create_file|dir
[amitay/samba.git] / source4 / torture / raw / rename.c
1 /* 
2    Unix SMB/CIFS implementation.
3    rename test suite
4    Copyright (C) Andrew Tridgell 2003
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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "libcli/libcli.h"
22 #include "torture/util.h"
23 #include "torture/raw/proto.h"
24
25 #define CHECK_STATUS(status, correct) do { \
26         if (!NT_STATUS_EQUAL(status, correct)) { \
27                 torture_result(tctx, TORTURE_FAIL, \
28                         "(%s) Incorrect status %s - should be %s\n", \
29                         __location__, nt_errstr(status), nt_errstr(correct)); \
30                 ret = false; \
31                 goto done; \
32         }} while (0)
33
34 #define CHECK_VALUE(v, correct) do { \
35         if ((v) != (correct)) { \
36                 torture_result(tctx, TORTURE_FAIL, \
37                         "(%s) Incorrect %s %d - should be %d\n", \
38                         __location__, #v, (int)v, (int)correct); \
39                 ret = false; \
40         }} while (0)
41
42 #define BASEDIR "\\testrename"
43
44 /*
45   test SMBmv ops
46 */
47 static bool test_mv(struct torture_context *tctx, 
48                                         struct smbcli_state *cli)
49 {
50         union smb_rename io;
51         NTSTATUS status;
52         bool ret = true;
53         int fnum = -1;
54         const char *fname1 = BASEDIR "\\test1.txt";
55         const char *fname2 = BASEDIR "\\test2.txt";
56         const char *Fname1 = BASEDIR "\\Test1.txt";
57         union smb_fileinfo finfo;
58         union smb_open op;
59
60         torture_comment(tctx, "Testing SMBmv\n");
61
62         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
63
64         torture_comment(tctx, "Trying simple rename\n");
65
66         op.generic.level = RAW_OPEN_NTCREATEX;
67         op.ntcreatex.in.root_fid.fnum = 0;
68         op.ntcreatex.in.flags = 0;
69         op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
70         op.ntcreatex.in.create_options = 0;
71         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
72         op.ntcreatex.in.share_access = 
73                 NTCREATEX_SHARE_ACCESS_READ | 
74                 NTCREATEX_SHARE_ACCESS_WRITE;
75         op.ntcreatex.in.alloc_size = 0;
76         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
77         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
78         op.ntcreatex.in.security_flags = 0;
79         op.ntcreatex.in.fname = fname1;
80
81         status = smb_raw_open(cli->tree, tctx, &op);
82         CHECK_STATUS(status, NT_STATUS_OK);
83         fnum = op.ntcreatex.out.file.fnum;
84
85         io.generic.level = RAW_RENAME_RENAME;
86         io.rename.in.pattern1 = fname1;
87         io.rename.in.pattern2 = fname2;
88         io.rename.in.attrib = 0;
89         
90         torture_comment(tctx, "trying rename while first file open\n");
91         status = smb_raw_rename(cli->tree, &io);
92         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
93
94         smbcli_close(cli->tree, fnum);
95
96         op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
97         op.ntcreatex.in.share_access = 
98                 NTCREATEX_SHARE_ACCESS_DELETE | 
99                 NTCREATEX_SHARE_ACCESS_READ |
100                 NTCREATEX_SHARE_ACCESS_WRITE;
101         status = smb_raw_open(cli->tree, tctx, &op);
102         CHECK_STATUS(status, NT_STATUS_OK);
103         fnum = op.ntcreatex.out.file.fnum;
104
105         torture_comment(tctx, "trying rename while first file open with SHARE_ACCESS_DELETE\n");
106         status = smb_raw_rename(cli->tree, &io);
107         CHECK_STATUS(status, NT_STATUS_OK);
108
109         io.rename.in.pattern1 = fname2;
110         io.rename.in.pattern2 = fname1;
111         status = smb_raw_rename(cli->tree, &io);
112         CHECK_STATUS(status, NT_STATUS_OK);
113
114         torture_comment(tctx, "Trying case-changing rename\n");
115         io.rename.in.pattern1 = fname1;
116         io.rename.in.pattern2 = Fname1;
117         status = smb_raw_rename(cli->tree, &io);
118         CHECK_STATUS(status, NT_STATUS_OK);
119
120         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
121         finfo.all_info.in.file.path = fname1;
122         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
123         CHECK_STATUS(status, NT_STATUS_OK);
124         if (strcmp(finfo.all_info.out.fname.s, Fname1) != 0) {
125                 torture_warning(tctx, "(%s) Incorrect filename [%s] after case-changing "
126                        "rename, should be [%s]\n", __location__,
127                        finfo.all_info.out.fname.s, Fname1);
128         }
129
130         io.rename.in.pattern1 = fname1;
131         io.rename.in.pattern2 = fname2;
132
133         torture_comment(tctx, "trying rename while not open\n");
134         smb_raw_exit(cli->session);
135         status = smb_raw_rename(cli->tree, &io);
136         CHECK_STATUS(status, NT_STATUS_OK);
137         
138         torture_comment(tctx, "Trying self rename\n");
139         io.rename.in.pattern1 = fname2;
140         io.rename.in.pattern2 = fname2;
141         status = smb_raw_rename(cli->tree, &io);
142         CHECK_STATUS(status, NT_STATUS_OK);
143
144         io.rename.in.pattern1 = fname1;
145         io.rename.in.pattern2 = fname1;
146         status = smb_raw_rename(cli->tree, &io);
147         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
148
149
150         torture_comment(tctx, "trying wildcard rename\n");
151         io.rename.in.pattern1 = BASEDIR "\\*.txt";
152         io.rename.in.pattern2 = fname1;
153         
154         status = smb_raw_rename(cli->tree, &io);
155         CHECK_STATUS(status, NT_STATUS_OK);
156
157         torture_comment(tctx, "and again\n");
158         status = smb_raw_rename(cli->tree, &io);
159         CHECK_STATUS(status, NT_STATUS_OK);
160
161         torture_comment(tctx, "Trying extension change\n");
162         io.rename.in.pattern1 = BASEDIR "\\*.txt";
163         io.rename.in.pattern2 = BASEDIR "\\*.bak";
164         status = smb_raw_rename(cli->tree, &io);
165         CHECK_STATUS(status, NT_STATUS_OK);
166
167         status = smb_raw_rename(cli->tree, &io);
168         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
169
170         torture_comment(tctx, "Checking attrib handling\n");
171         torture_set_file_attribute(cli->tree, BASEDIR "\\test1.bak", FILE_ATTRIBUTE_HIDDEN);
172         io.rename.in.pattern1 = BASEDIR "\\test1.bak";
173         io.rename.in.pattern2 = BASEDIR "\\*.txt";
174         io.rename.in.attrib = 0;
175         status = smb_raw_rename(cli->tree, &io);
176         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
177
178         io.rename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
179         status = smb_raw_rename(cli->tree, &io);
180         CHECK_STATUS(status, NT_STATUS_OK);
181
182 done:
183         smbcli_close(cli->tree, fnum);
184         smb_raw_exit(cli->session);
185         smbcli_deltree(cli->tree, BASEDIR);
186         return ret;
187 }
188
189
190 static bool test_osxrename(struct torture_context *tctx,
191                            struct smbcli_state *cli)
192 {
193         union smb_rename io;
194         union smb_unlink io_un;
195         NTSTATUS status;
196         bool ret = true;
197         int fnum = -1;
198         const char *fname1 = BASEDIR "\\test1";
199         const char *FNAME1 = BASEDIR "\\TEST1";
200         union smb_fileinfo finfo;
201         union smb_open op;
202
203         torture_comment(tctx, "\nTesting OSX Rename\n");
204         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
205         op.generic.level = RAW_OPEN_NTCREATEX;
206         op.ntcreatex.in.root_fid.fnum = 0;
207         op.ntcreatex.in.flags = 0;
208         op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
209         op.ntcreatex.in.create_options = 0;
210         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
211         op.ntcreatex.in.share_access =
212                 NTCREATEX_SHARE_ACCESS_READ |
213                 NTCREATEX_SHARE_ACCESS_WRITE;
214         op.ntcreatex.in.alloc_size = 0;
215         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
216         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
217         op.ntcreatex.in.security_flags = 0;
218         op.ntcreatex.in.fname = fname1;
219
220         status = smb_raw_open(cli->tree, tctx, &op);
221         CHECK_STATUS(status, NT_STATUS_OK);
222         fnum = op.ntcreatex.out.file.fnum;
223
224         io.generic.level = RAW_RENAME_RENAME;
225         io.rename.in.attrib = 0;
226
227         smbcli_close(cli->tree, fnum);
228
229         /* Rename by changing case. First check for the
230          * existence of the file with the "newname".
231          * If we find one and both the output and input are same case,
232          * delete it. */
233
234         torture_comment(tctx, "Checking os X rename (case changing)\n");
235
236         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
237         finfo.all_info.in.file.path = FNAME1;
238         torture_comment(tctx, "Looking for file %s \n",FNAME1);
239         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
240
241         if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
242                 torture_comment(tctx, "Name of the file found %s \n", finfo.all_info.out.fname.s);
243                 if (strcmp(finfo.all_info.out.fname.s, finfo.all_info.in.file.path) == 0) {
244                         /* If file is found with the same case delete it */
245                         torture_comment(tctx, "Deleting File %s \n", finfo.all_info.out.fname.s);
246                         io_un.unlink.in.pattern = finfo.all_info.out.fname.s;
247                         io_un.unlink.in.attrib = 0;
248                         status = smb_raw_unlink(cli->tree, &io_un);
249                         CHECK_STATUS(status, NT_STATUS_OK);
250                 }
251         }
252
253         io.rename.in.pattern1 = fname1;
254         io.rename.in.pattern2 = FNAME1;
255         status = smb_raw_rename(cli->tree, &io);
256         CHECK_STATUS(status, NT_STATUS_OK);
257
258         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
259         finfo.all_info.in.file.path = fname1;
260         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
261         CHECK_STATUS(status, NT_STATUS_OK);
262         torture_comment(tctx, "File name after rename %s \n",finfo.all_info.out.fname.s);
263
264 done:
265         smbcli_close(cli->tree, fnum);
266         smb_raw_exit(cli->session);
267         smbcli_deltree(cli->tree, BASEDIR);
268         return ret;
269 }
270
271 /*
272   test SMBntrename ops
273 */
274 static bool test_ntrename(struct torture_context *tctx, 
275                                                   struct smbcli_state *cli)
276 {
277         union smb_rename io;
278         NTSTATUS status;
279         bool ret = true;
280         int fnum, i;
281         const char *fname1 = BASEDIR "\\test1.txt";
282         const char *fname2 = BASEDIR "\\test2.txt";
283         union smb_fileinfo finfo;
284
285         torture_comment(tctx, "Testing SMBntrename\n");
286
287         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
288
289         torture_comment(tctx, "Trying simple rename\n");
290
291         fnum = create_complex_file(cli, tctx, fname1);
292         
293         io.generic.level = RAW_RENAME_NTRENAME;
294         io.ntrename.in.old_name = fname1;
295         io.ntrename.in.new_name = fname2;
296         io.ntrename.in.attrib = 0;
297         io.ntrename.in.cluster_size = 0;
298         io.ntrename.in.flags = RENAME_FLAG_RENAME;
299         
300         status = smb_raw_rename(cli->tree, &io);
301         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
302         
303         smbcli_close(cli->tree, fnum);
304         status = smb_raw_rename(cli->tree, &io);
305         CHECK_STATUS(status, NT_STATUS_OK);
306
307         torture_comment(tctx, "Trying self rename\n");
308         io.ntrename.in.old_name = fname2;
309         io.ntrename.in.new_name = fname2;
310         status = smb_raw_rename(cli->tree, &io);
311         CHECK_STATUS(status, NT_STATUS_OK);
312
313         io.ntrename.in.old_name = fname1;
314         io.ntrename.in.new_name = fname1;
315         status = smb_raw_rename(cli->tree, &io);
316         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
317
318         torture_comment(tctx, "trying wildcard rename\n");
319         io.ntrename.in.old_name = BASEDIR "\\*.txt";
320         io.ntrename.in.new_name = fname1;
321         
322         status = smb_raw_rename(cli->tree, &io);
323         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
324
325         torture_comment(tctx, "Checking attrib handling\n");
326         torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN);
327         io.ntrename.in.old_name = fname2;
328         io.ntrename.in.new_name = fname1;
329         io.ntrename.in.attrib = 0;
330         status = smb_raw_rename(cli->tree, &io);
331         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
332
333         io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
334         status = smb_raw_rename(cli->tree, &io);
335         CHECK_STATUS(status, NT_STATUS_OK);
336
337         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
338
339         torture_comment(tctx, "Checking hard link\n");
340         io.ntrename.in.old_name = fname1;
341         io.ntrename.in.new_name = fname2;
342         io.ntrename.in.attrib = 0;
343         io.ntrename.in.flags = RENAME_FLAG_HARD_LINK;
344         status = smb_raw_rename(cli->tree, &io);
345         CHECK_STATUS(status, NT_STATUS_OK);
346
347         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
348
349         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
350         finfo.generic.in.file.path = fname2;
351         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
352         CHECK_STATUS(status, NT_STATUS_OK);
353         CHECK_VALUE(finfo.all_info.out.nlink, 2);
354         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
355
356         finfo.generic.in.file.path = fname1;
357         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
358         CHECK_STATUS(status, NT_STATUS_OK);
359         CHECK_VALUE(finfo.all_info.out.nlink, 2);
360         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
361
362         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
363
364         smbcli_unlink(cli->tree, fname2);
365
366         finfo.generic.in.file.path = fname1;
367         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
368         CHECK_STATUS(status, NT_STATUS_OK);
369         CHECK_VALUE(finfo.all_info.out.nlink, 1);
370         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
371
372         torture_comment(tctx, "Checking copy\n");
373         io.ntrename.in.old_name = fname1;
374         io.ntrename.in.new_name = fname2;
375         io.ntrename.in.attrib = 0;
376         io.ntrename.in.flags = RENAME_FLAG_COPY;
377         status = smb_raw_rename(cli->tree, &io);
378         CHECK_STATUS(status, NT_STATUS_OK);
379
380         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
381         finfo.generic.in.file.path = fname1;
382         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
383         CHECK_STATUS(status, NT_STATUS_OK);
384         CHECK_VALUE(finfo.all_info.out.nlink, 1);
385         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
386
387         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
388         finfo.generic.in.file.path = fname2;
389         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
390         CHECK_STATUS(status, NT_STATUS_OK);
391         CHECK_VALUE(finfo.all_info.out.nlink, 1);
392         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
393
394         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
395
396         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
397         finfo.generic.in.file.path = fname2;
398         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
399         CHECK_STATUS(status, NT_STATUS_OK);
400         CHECK_VALUE(finfo.all_info.out.nlink, 1);
401         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
402
403         finfo.generic.in.file.path = fname1;
404         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
405         CHECK_STATUS(status, NT_STATUS_OK);
406         CHECK_VALUE(finfo.all_info.out.nlink, 1);
407         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
408
409         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
410
411         smbcli_unlink(cli->tree, fname2);
412
413         finfo.generic.in.file.path = fname1;
414         status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
415         CHECK_STATUS(status, NT_STATUS_OK);
416         CHECK_VALUE(finfo.all_info.out.nlink, 1);
417
418         torture_comment(tctx, "Checking invalid flags\n");
419         io.ntrename.in.old_name = fname1;
420         io.ntrename.in.new_name = fname2;
421         io.ntrename.in.attrib = 0;
422         io.ntrename.in.flags = 0;
423         status = smb_raw_rename(cli->tree, &io);
424         if (TARGET_IS_WIN7(tctx)) {
425                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
426         } else {
427                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
428         }
429
430         io.ntrename.in.flags = 300;
431         status = smb_raw_rename(cli->tree, &io);
432         if (TARGET_IS_WIN7(tctx)) {
433                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
434         } else {
435                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
436         }
437
438         io.ntrename.in.flags = 0x106;
439         status = smb_raw_rename(cli->tree, &io);
440         if (TARGET_IS_WIN7(tctx)) {
441                 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
442         } else {
443                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
444         }
445
446         torture_comment(tctx, "Checking unknown field\n");
447         io.ntrename.in.old_name = fname1;
448         io.ntrename.in.new_name = fname2;
449         io.ntrename.in.attrib = 0;
450         io.ntrename.in.flags = RENAME_FLAG_RENAME;
451         io.ntrename.in.cluster_size = 0xff;
452         status = smb_raw_rename(cli->tree, &io);
453         CHECK_STATUS(status, NT_STATUS_OK);
454
455         torture_comment(tctx, "Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n");
456
457         io.ntrename.in.old_name = fname2;
458         io.ntrename.in.new_name = fname1;
459         io.ntrename.in.attrib = 0;
460         io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
461         io.ntrename.in.cluster_size = 1;
462         status = smb_raw_rename(cli->tree, &io);
463         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
464
465         io.ntrename.in.flags = RENAME_FLAG_COPY;
466         status = smb_raw_rename(cli->tree, &io);
467         CHECK_STATUS(status, NT_STATUS_OK);
468
469 #if 0
470         {
471                 char buf[16384];
472                 fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE);
473                 memset(buf, 1, sizeof(buf));
474                 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
475                 smbcli_close(cli->tree, fnum);
476
477                 fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE);
478                 memset(buf, 1, sizeof(buf));
479                 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1);
480                 smbcli_close(cli->tree, fnum);
481
482                 torture_all_info(cli->tree, fname1);
483                 torture_all_info(cli->tree, fname2);
484         }
485         
486
487         io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
488         status = smb_raw_rename(cli->tree, &io);
489         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
490
491         for (i=0;i<20000;i++) {
492                 io.ntrename.in.cluster_size = i;
493                 status = smb_raw_rename(cli->tree, &io);
494                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
495                         torture_warning(tctx, "i=%d status=%s\n", i, nt_errstr(status));
496                 }
497         }
498 #endif
499
500         torture_comment(tctx, "Checking other flags\n");
501
502         for (i=0;i<0xFFF;i++) {
503                 if (i == RENAME_FLAG_RENAME ||
504                     i == RENAME_FLAG_HARD_LINK ||
505                     i == RENAME_FLAG_COPY) {
506                         continue;
507                 }
508
509                 io.ntrename.in.old_name = fname2;
510                 io.ntrename.in.new_name = fname1;
511                 io.ntrename.in.flags = i;
512                 io.ntrename.in.attrib = 0;
513                 io.ntrename.in.cluster_size = 0;
514                 status = smb_raw_rename(cli->tree, &io);
515                 if (TARGET_IS_WIN7(tctx)){
516                         if (!NT_STATUS_EQUAL(status,
517                                              NT_STATUS_INVALID_PARAMETER)) {
518                                 torture_warning(tctx, "flags=0x%x status=%s\n",
519                                                 i, nt_errstr(status));
520                         }
521                 } else {
522                         if (!NT_STATUS_EQUAL(status,
523                                              NT_STATUS_ACCESS_DENIED)) {
524                                 torture_warning(tctx, "flags=0x%x status=%s\n",
525                                                 i, nt_errstr(status));
526                         }
527                 }
528         }
529         
530 done:
531         smb_raw_exit(cli->session);
532         smbcli_deltree(cli->tree, BASEDIR);
533         return ret;
534 }
535
536 /*
537   test dir rename.
538 */
539 static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli)
540 {
541         union smb_open io;
542         union smb_rename ren_io;
543         NTSTATUS status;
544         const char *dname1 = BASEDIR "\\dir_for_rename";
545         const char *dname2 = BASEDIR "\\renamed_dir";
546         const char *dname1_long = BASEDIR "\\dir_for_rename_long";
547         const char *fname = BASEDIR "\\dir_for_rename\\file.txt";
548         const char *sname = BASEDIR "\\renamed_dir:a stream:$DATA";
549         bool ret = true;
550         int fnum = -1;
551
552         torture_comment(tctx, "Checking rename on a directory containing an open file.\n");
553
554         torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
555
556         /* create a directory */
557         smbcli_rmdir(cli->tree, dname1);
558         smbcli_rmdir(cli->tree, dname2);
559         smbcli_rmdir(cli->tree, dname1_long);
560         smbcli_unlink(cli->tree, dname1);
561         smbcli_unlink(cli->tree, dname2);
562         smbcli_unlink(cli->tree, dname1_long);
563
564         ZERO_STRUCT(io);
565         io.generic.level = RAW_OPEN_NTCREATEX;
566         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
567         io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
568         io.ntcreatex.in.alloc_size = 0;
569         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
570         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
571         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
572         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
573         io.ntcreatex.in.fname = dname1;
574         status = smb_raw_open(cli->tree, tctx, &io);
575         CHECK_STATUS(status, NT_STATUS_OK);
576
577         fnum = io.ntcreatex.out.file.fnum;
578         smbcli_close(cli->tree, fnum);
579
580         /* create the longname directory */
581         io.ntcreatex.in.fname = dname1_long;
582         status = smb_raw_open(cli->tree, tctx, &io);
583         CHECK_STATUS(status, NT_STATUS_OK);
584
585         fnum = io.ntcreatex.out.file.fnum;
586         smbcli_close(cli->tree, fnum);
587
588         /* Now create and hold open a file. */
589         ZERO_STRUCT(io);
590
591         io.generic.level = RAW_OPEN_NTCREATEX;
592         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
593         io.ntcreatex.in.root_fid.fnum = 0;
594         io.ntcreatex.in.alloc_size = 0;
595         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
596         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
597         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
598         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
599         io.ntcreatex.in.create_options = 0;
600         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
601         io.ntcreatex.in.security_flags = 0;
602         io.ntcreatex.in.fname = fname;
603
604         /* Create the file. */
605
606         status = smb_raw_open(cli->tree, tctx, &io);
607         CHECK_STATUS(status, NT_STATUS_OK);
608         fnum = io.ntcreatex.out.file.fnum;
609
610         /* Now try and rename the directory. */
611
612         ZERO_STRUCT(ren_io);
613         ren_io.generic.level = RAW_RENAME_RENAME;
614         ren_io.rename.in.pattern1 = dname1;
615         ren_io.rename.in.pattern2 = dname2;
616         ren_io.rename.in.attrib = 0;
617         
618         status = smb_raw_rename(cli->tree, &ren_io);
619         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
620
621         /* Close the file and try the rename. */
622         smbcli_close(cli->tree, fnum);
623
624         status = smb_raw_rename(cli->tree, &ren_io);
625         CHECK_STATUS(status, NT_STATUS_OK);
626
627         /*
628          * Now try just holding a second handle on the directory and holding
629          * it open across a rename.  This should be allowed.
630          */
631         io.ntcreatex.in.fname = dname2;
632         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
633
634         io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
635             SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
636
637         status = smb_raw_open(cli->tree, tctx, &io);
638         CHECK_STATUS(status, NT_STATUS_OK);
639         fnum = io.ntcreatex.out.file.fnum;
640
641         ren_io.generic.level = RAW_RENAME_RENAME;
642         ren_io.rename.in.pattern1 = dname2;
643         ren_io.rename.in.pattern2 = dname1;
644         ren_io.rename.in.attrib = 0;
645
646         status = smb_raw_rename(cli->tree, &ren_io);
647         CHECK_STATUS(status, NT_STATUS_OK);
648
649         /* close our handle to the directory. */
650         smbcli_close(cli->tree, fnum);
651
652         /* Open a handle on the long name, and then
653          * try a rename. This would catch a regression
654          * in bug #6781.
655          */
656         io.ntcreatex.in.fname = dname1_long;
657         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
658
659         io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
660             SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
661
662         status = smb_raw_open(cli->tree, tctx, &io);
663         CHECK_STATUS(status, NT_STATUS_OK);
664         fnum = io.ntcreatex.out.file.fnum;
665
666         ren_io.generic.level = RAW_RENAME_RENAME;
667         ren_io.rename.in.pattern1 = dname1;
668         ren_io.rename.in.pattern2 = dname2;
669         ren_io.rename.in.attrib = 0;
670
671         status = smb_raw_rename(cli->tree, &ren_io);
672         CHECK_STATUS(status, NT_STATUS_OK);
673
674         /* close our handle to the longname directory. */
675         smbcli_close(cli->tree, fnum);
676
677         /*
678          * Now try opening a stream on the directory and holding it open
679          * across a rename.  This should be allowed.
680          */
681         io.ntcreatex.in.fname = sname;
682
683         status = smb_raw_open(cli->tree, tctx, &io);
684         CHECK_STATUS(status, NT_STATUS_OK);
685         fnum = io.ntcreatex.out.file.fnum;
686
687         ren_io.generic.level = RAW_RENAME_RENAME;
688         ren_io.rename.in.pattern1 = dname2;
689         ren_io.rename.in.pattern2 = dname1;
690         ren_io.rename.in.attrib = 0;
691
692         status = smb_raw_rename(cli->tree, &ren_io);
693         CHECK_STATUS(status, NT_STATUS_OK);
694
695 done:
696
697         if (fnum != -1) {
698                 smbcli_close(cli->tree, fnum);
699         }
700         smb_raw_exit(cli->session);
701         smbcli_deltree(cli->tree, BASEDIR);
702         return ret;
703 }
704
705 extern bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2);
706 extern bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1);
707
708 /* 
709    basic testing of rename calls
710 */
711 struct torture_suite *torture_raw_rename(TALLOC_CTX *mem_ctx)
712 {
713         struct torture_suite *suite = torture_suite_create(mem_ctx, "rename");
714
715         torture_suite_add_1smb_test(suite, "mv", test_mv);
716         /* test_trans2rename and test_nttransrename are actually in torture/raw/oplock.c to
717            use the handlers and macros there. */
718         torture_suite_add_2smb_test(suite, "trans2rename", test_trans2rename);
719         torture_suite_add_1smb_test(suite, "nttransrename", test_nttransrename);
720         torture_suite_add_1smb_test(suite, "ntrename", test_ntrename);
721         torture_suite_add_1smb_test(suite, "osxrename", test_osxrename);
722         torture_suite_add_1smb_test(suite, "directory rename", test_dir_rename);
723
724         return suite;
725 }