s3: Fix bug #9085.
[Samba.git] / source4 / torture / raw / rename.c
blob5402feda555f5eb0067e967d5ec5bf8284b883c5
1 /*
2 Unix SMB/CIFS implementation.
3 rename test suite
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
20 #include "includes.h"
21 #include "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
26 #define CHECK_STATUS(status, correct) do { \
27 if (!NT_STATUS_EQUAL(status, correct)) { \
28 torture_result(tctx, TORTURE_FAIL, \
29 "(%s) Incorrect status %s - should be %s\n", \
30 __location__, nt_errstr(status), nt_errstr(correct)); \
31 ret = false; \
32 goto done; \
33 }} while (0)
35 #define CHECK_VALUE(v, correct) do { \
36 if ((v) != (correct)) { \
37 torture_result(tctx, TORTURE_FAIL, \
38 "(%s) Incorrect %s %d - should be %d\n", \
39 __location__, #v, (int)v, (int)correct); \
40 ret = false; \
41 }} while (0)
43 #define BASEDIR "\\testrename"
46 test SMBmv ops
48 static bool test_mv(struct torture_context *tctx,
49 struct smbcli_state *cli)
51 union smb_rename io;
52 NTSTATUS status;
53 bool ret = true;
54 int fnum = -1;
55 const char *fname1 = BASEDIR "\\test1.txt";
56 const char *fname2 = BASEDIR "\\test2.txt";
57 const char *Fname1 = BASEDIR "\\Test1.txt";
58 union smb_fileinfo finfo;
59 union smb_open op;
61 torture_comment(tctx, "Testing SMBmv\n");
63 if (!torture_setup_dir(cli, BASEDIR)) {
64 return false;
67 torture_comment(tctx, "Trying simple rename\n");
69 op.generic.level = RAW_OPEN_NTCREATEX;
70 op.ntcreatex.in.root_fid = 0;
71 op.ntcreatex.in.flags = 0;
72 op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
73 op.ntcreatex.in.create_options = 0;
74 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
75 op.ntcreatex.in.share_access =
76 NTCREATEX_SHARE_ACCESS_READ |
77 NTCREATEX_SHARE_ACCESS_WRITE;
78 op.ntcreatex.in.alloc_size = 0;
79 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
80 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
81 op.ntcreatex.in.security_flags = 0;
82 op.ntcreatex.in.fname = fname1;
84 status = smb_raw_open(cli->tree, tctx, &op);
85 CHECK_STATUS(status, NT_STATUS_OK);
86 fnum = op.ntcreatex.out.file.fnum;
88 io.generic.level = RAW_RENAME_RENAME;
89 io.rename.in.pattern1 = fname1;
90 io.rename.in.pattern2 = fname2;
91 io.rename.in.attrib = 0;
93 torture_comment(tctx, "trying rename while first file open\n");
94 status = smb_raw_rename(cli->tree, &io);
95 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
97 smbcli_close(cli->tree, fnum);
99 op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
100 op.ntcreatex.in.share_access =
101 NTCREATEX_SHARE_ACCESS_DELETE |
102 NTCREATEX_SHARE_ACCESS_READ |
103 NTCREATEX_SHARE_ACCESS_WRITE;
104 status = smb_raw_open(cli->tree, tctx, &op);
105 CHECK_STATUS(status, NT_STATUS_OK);
106 fnum = op.ntcreatex.out.file.fnum;
108 torture_comment(tctx, "trying rename while first file open with SHARE_ACCESS_DELETE\n");
109 status = smb_raw_rename(cli->tree, &io);
110 CHECK_STATUS(status, NT_STATUS_OK);
112 io.rename.in.pattern1 = fname2;
113 io.rename.in.pattern2 = fname1;
114 status = smb_raw_rename(cli->tree, &io);
115 CHECK_STATUS(status, NT_STATUS_OK);
117 torture_comment(tctx, "Trying case-changing rename\n");
118 io.rename.in.pattern1 = fname1;
119 io.rename.in.pattern2 = Fname1;
120 status = smb_raw_rename(cli->tree, &io);
121 CHECK_STATUS(status, NT_STATUS_OK);
123 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
124 finfo.all_info.in.file.path = fname1;
125 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
126 CHECK_STATUS(status, NT_STATUS_OK);
127 if (strcmp(finfo.all_info.out.fname.s, Fname1) != 0) {
128 torture_warning(tctx, "(%s) Incorrect filename [%s] after case-changing "
129 "rename, should be [%s]\n", __location__,
130 finfo.all_info.out.fname.s, Fname1);
133 io.rename.in.pattern1 = fname1;
134 io.rename.in.pattern2 = fname2;
136 torture_comment(tctx, "trying rename while not open\n");
137 smb_raw_exit(cli->session);
138 status = smb_raw_rename(cli->tree, &io);
139 CHECK_STATUS(status, NT_STATUS_OK);
141 torture_comment(tctx, "Trying self rename\n");
142 io.rename.in.pattern1 = fname2;
143 io.rename.in.pattern2 = fname2;
144 status = smb_raw_rename(cli->tree, &io);
145 CHECK_STATUS(status, NT_STATUS_OK);
147 io.rename.in.pattern1 = fname1;
148 io.rename.in.pattern2 = fname1;
149 status = smb_raw_rename(cli->tree, &io);
150 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
153 torture_comment(tctx, "trying wildcard rename\n");
154 io.rename.in.pattern1 = BASEDIR "\\*.txt";
155 io.rename.in.pattern2 = fname1;
157 status = smb_raw_rename(cli->tree, &io);
158 CHECK_STATUS(status, NT_STATUS_OK);
160 torture_comment(tctx, "and again\n");
161 status = smb_raw_rename(cli->tree, &io);
162 CHECK_STATUS(status, NT_STATUS_OK);
164 torture_comment(tctx, "Trying extension change\n");
165 io.rename.in.pattern1 = BASEDIR "\\*.txt";
166 io.rename.in.pattern2 = BASEDIR "\\*.bak";
167 status = smb_raw_rename(cli->tree, &io);
168 CHECK_STATUS(status, NT_STATUS_OK);
170 status = smb_raw_rename(cli->tree, &io);
171 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
173 torture_comment(tctx, "Checking attrib handling\n");
174 torture_set_file_attribute(cli->tree, BASEDIR "\\test1.bak", FILE_ATTRIBUTE_HIDDEN);
175 io.rename.in.pattern1 = BASEDIR "\\test1.bak";
176 io.rename.in.pattern2 = BASEDIR "\\*.txt";
177 io.rename.in.attrib = 0;
178 status = smb_raw_rename(cli->tree, &io);
179 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
181 io.rename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
182 status = smb_raw_rename(cli->tree, &io);
183 CHECK_STATUS(status, NT_STATUS_OK);
185 done:
186 smbcli_close(cli->tree, fnum);
187 smb_raw_exit(cli->session);
188 smbcli_deltree(cli->tree, BASEDIR);
189 return ret;
193 static bool test_osxrename(struct torture_context *tctx,
194 struct smbcli_state *cli)
196 union smb_rename io;
197 union smb_unlink io_un;
198 NTSTATUS status;
199 bool ret = true;
200 int fnum = -1;
201 const char *fname1 = BASEDIR "\\test1";
202 const char *FNAME1 = BASEDIR "\\TEST1";
203 union smb_fileinfo finfo;
204 union smb_open op;
206 torture_comment(tctx, "\nTesting OSX Rename\n");
207 if (!torture_setup_dir(cli, BASEDIR)) {
208 return false;
210 op.generic.level = RAW_OPEN_NTCREATEX;
211 op.ntcreatex.in.root_fid = 0;
212 op.ntcreatex.in.flags = 0;
213 op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
214 op.ntcreatex.in.create_options = 0;
215 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
216 op.ntcreatex.in.share_access =
217 NTCREATEX_SHARE_ACCESS_READ |
218 NTCREATEX_SHARE_ACCESS_WRITE;
219 op.ntcreatex.in.alloc_size = 0;
220 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
221 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
222 op.ntcreatex.in.security_flags = 0;
223 op.ntcreatex.in.fname = fname1;
225 status = smb_raw_open(cli->tree, tctx, &op);
226 CHECK_STATUS(status, NT_STATUS_OK);
227 fnum = op.ntcreatex.out.file.fnum;
229 io.generic.level = RAW_RENAME_RENAME;
230 io.rename.in.attrib = 0;
232 smbcli_close(cli->tree, fnum);
234 /* Rename by changing case. First check for the
235 * existence of the file with the "newname".
236 * If we find one and both the output and input are same case,
237 * delete it. */
239 torture_comment(tctx, "Checking os X rename (case changing)\n");
241 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
242 finfo.all_info.in.file.path = FNAME1;
243 torture_comment(tctx, "Looking for file %s \n",FNAME1);
244 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
246 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
247 torture_comment(tctx, "Name of the file found %s \n", finfo.all_info.out.fname.s);
248 if (strcmp(finfo.all_info.out.fname.s, finfo.all_info.in.file.path) == 0) {
249 /* If file is found with the same case delete it */
250 torture_comment(tctx, "Deleting File %s \n", finfo.all_info.out.fname.s);
251 io_un.unlink.in.pattern = finfo.all_info.out.fname.s;
252 io_un.unlink.in.attrib = 0;
253 status = smb_raw_unlink(cli->tree, &io_un);
254 CHECK_STATUS(status, NT_STATUS_OK);
258 io.rename.in.pattern1 = fname1;
259 io.rename.in.pattern2 = FNAME1;
260 status = smb_raw_rename(cli->tree, &io);
261 CHECK_STATUS(status, NT_STATUS_OK);
263 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
264 finfo.all_info.in.file.path = fname1;
265 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
266 CHECK_STATUS(status, NT_STATUS_OK);
267 torture_comment(tctx, "File name after rename %s \n",finfo.all_info.out.fname.s);
269 done:
270 smbcli_close(cli->tree, fnum);
271 smb_raw_exit(cli->session);
272 smbcli_deltree(cli->tree, BASEDIR);
273 return ret;
277 test SMBntrename ops
279 static bool test_ntrename(struct torture_context *tctx,
280 struct smbcli_state *cli)
282 union smb_rename io;
283 NTSTATUS status;
284 bool ret = true;
285 int fnum, i;
286 const char *fname1 = BASEDIR "\\test1.txt";
287 const char *fname2 = BASEDIR "\\test2.txt";
288 union smb_fileinfo finfo;
290 torture_comment(tctx, "Testing SMBntrename\n");
292 if (!torture_setup_dir(cli, BASEDIR)) {
293 return false;
296 torture_comment(tctx, "Trying simple rename\n");
298 fnum = create_complex_file(cli, tctx, fname1);
300 io.generic.level = RAW_RENAME_NTRENAME;
301 io.ntrename.in.old_name = fname1;
302 io.ntrename.in.new_name = fname2;
303 io.ntrename.in.attrib = 0;
304 io.ntrename.in.cluster_size = 0;
305 io.ntrename.in.flags = RENAME_FLAG_RENAME;
307 status = smb_raw_rename(cli->tree, &io);
308 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
310 smb_raw_exit(cli->session);
311 status = smb_raw_rename(cli->tree, &io);
312 CHECK_STATUS(status, NT_STATUS_OK);
314 torture_comment(tctx, "Trying self rename\n");
315 io.ntrename.in.old_name = fname2;
316 io.ntrename.in.new_name = fname2;
317 status = smb_raw_rename(cli->tree, &io);
318 CHECK_STATUS(status, NT_STATUS_OK);
320 io.ntrename.in.old_name = fname1;
321 io.ntrename.in.new_name = fname1;
322 status = smb_raw_rename(cli->tree, &io);
323 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
325 torture_comment(tctx, "trying wildcard rename\n");
326 io.ntrename.in.old_name = BASEDIR "\\*.txt";
327 io.ntrename.in.new_name = fname1;
329 status = smb_raw_rename(cli->tree, &io);
330 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
332 torture_comment(tctx, "Checking attrib handling\n");
333 torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN);
334 io.ntrename.in.old_name = fname2;
335 io.ntrename.in.new_name = fname1;
336 io.ntrename.in.attrib = 0;
337 status = smb_raw_rename(cli->tree, &io);
338 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
340 io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
341 status = smb_raw_rename(cli->tree, &io);
342 CHECK_STATUS(status, NT_STATUS_OK);
344 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
346 torture_comment(tctx, "Checking hard link\n");
347 io.ntrename.in.old_name = fname1;
348 io.ntrename.in.new_name = fname2;
349 io.ntrename.in.attrib = 0;
350 io.ntrename.in.flags = RENAME_FLAG_HARD_LINK;
351 status = smb_raw_rename(cli->tree, &io);
352 CHECK_STATUS(status, NT_STATUS_OK);
354 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
356 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
357 finfo.generic.in.file.path = fname2;
358 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
359 CHECK_STATUS(status, NT_STATUS_OK);
360 CHECK_VALUE(finfo.all_info.out.nlink, 2);
361 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
363 finfo.generic.in.file.path = fname1;
364 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
365 CHECK_STATUS(status, NT_STATUS_OK);
366 CHECK_VALUE(finfo.all_info.out.nlink, 2);
367 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
369 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
371 smbcli_unlink(cli->tree, fname2);
373 finfo.generic.in.file.path = fname1;
374 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
375 CHECK_STATUS(status, NT_STATUS_OK);
376 CHECK_VALUE(finfo.all_info.out.nlink, 1);
377 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
379 torture_comment(tctx, "Checking copy\n");
380 io.ntrename.in.old_name = fname1;
381 io.ntrename.in.new_name = fname2;
382 io.ntrename.in.attrib = 0;
383 io.ntrename.in.flags = RENAME_FLAG_COPY;
384 status = smb_raw_rename(cli->tree, &io);
385 CHECK_STATUS(status, NT_STATUS_OK);
387 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
388 finfo.generic.in.file.path = fname1;
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);
394 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
395 finfo.generic.in.file.path = fname2;
396 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
397 CHECK_STATUS(status, NT_STATUS_OK);
398 CHECK_VALUE(finfo.all_info.out.nlink, 1);
399 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
401 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
403 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
404 finfo.generic.in.file.path = fname2;
405 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
406 CHECK_STATUS(status, NT_STATUS_OK);
407 CHECK_VALUE(finfo.all_info.out.nlink, 1);
408 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
410 finfo.generic.in.file.path = fname1;
411 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
412 CHECK_STATUS(status, NT_STATUS_OK);
413 CHECK_VALUE(finfo.all_info.out.nlink, 1);
414 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
416 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
418 smbcli_unlink(cli->tree, fname2);
420 finfo.generic.in.file.path = fname1;
421 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
422 CHECK_STATUS(status, NT_STATUS_OK);
423 CHECK_VALUE(finfo.all_info.out.nlink, 1);
425 torture_comment(tctx, "Checking invalid flags\n");
426 io.ntrename.in.old_name = fname1;
427 io.ntrename.in.new_name = fname2;
428 io.ntrename.in.attrib = 0;
429 io.ntrename.in.flags = 0;
430 status = smb_raw_rename(cli->tree, &io);
431 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
433 io.ntrename.in.flags = 300;
434 status = smb_raw_rename(cli->tree, &io);
435 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
437 io.ntrename.in.flags = 0x106;
438 status = smb_raw_rename(cli->tree, &io);
439 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
441 torture_comment(tctx, "Checking unknown field\n");
442 io.ntrename.in.old_name = fname1;
443 io.ntrename.in.new_name = fname2;
444 io.ntrename.in.attrib = 0;
445 io.ntrename.in.flags = RENAME_FLAG_RENAME;
446 io.ntrename.in.cluster_size = 0xff;
447 status = smb_raw_rename(cli->tree, &io);
448 CHECK_STATUS(status, NT_STATUS_OK);
450 torture_comment(tctx, "Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n");
452 io.ntrename.in.old_name = fname2;
453 io.ntrename.in.new_name = fname1;
454 io.ntrename.in.attrib = 0;
455 io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
456 io.ntrename.in.cluster_size = 1;
457 status = smb_raw_rename(cli->tree, &io);
458 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
460 io.ntrename.in.flags = RENAME_FLAG_COPY;
461 status = smb_raw_rename(cli->tree, &io);
462 CHECK_STATUS(status, NT_STATUS_OK);
464 #if 0
466 char buf[16384];
467 fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE);
468 memset(buf, 1, sizeof(buf));
469 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
470 smbcli_close(cli->tree, fnum);
472 fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE);
473 memset(buf, 1, sizeof(buf));
474 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1);
475 smbcli_close(cli->tree, fnum);
477 torture_all_info(cli->tree, fname1);
478 torture_all_info(cli->tree, fname2);
482 io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
483 status = smb_raw_rename(cli->tree, &io);
484 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
486 for (i=0;i<20000;i++) {
487 io.ntrename.in.cluster_size = i;
488 status = smb_raw_rename(cli->tree, &io);
489 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
490 torture_warning(tctx, "i=%d status=%s\n", i, nt_errstr(status));
493 #endif
495 torture_comment(tctx, "Checking other flags\n");
497 for (i=0;i<0xFFF;i++) {
498 if (i == RENAME_FLAG_RENAME ||
499 i == RENAME_FLAG_HARD_LINK ||
500 i == RENAME_FLAG_COPY) {
501 continue;
504 io.ntrename.in.old_name = fname2;
505 io.ntrename.in.new_name = fname1;
506 io.ntrename.in.flags = i;
507 io.ntrename.in.attrib = 0;
508 io.ntrename.in.cluster_size = 0;
509 status = smb_raw_rename(cli->tree, &io);
510 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
511 torture_warning(tctx, "flags=0x%x status=%s\n", i, nt_errstr(status));
515 done:
516 smb_raw_exit(cli->session);
517 smbcli_deltree(cli->tree, BASEDIR);
518 return ret;
522 test dir rename.
524 static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli)
526 union smb_open io;
527 union smb_rename ren_io;
528 NTSTATUS status;
529 const char *dname1 = BASEDIR "\\dir_for_rename";
530 const char *dname2 = BASEDIR "\\renamed_dir";
531 const char *dname1_long = BASEDIR "\\dir_for_rename_long";
532 const char *fname = BASEDIR "\\dir_for_rename\\file.txt";
533 const char *sname = BASEDIR "\\renamed_dir:a stream:$DATA";
534 bool ret = true;
535 int fnum = -1;
537 torture_comment(tctx, "Checking rename on a directory containing an open file.\n");
539 if (!torture_setup_dir(cli, BASEDIR)) {
540 return false;
543 /* create a directory */
544 smbcli_rmdir(cli->tree, dname1);
545 smbcli_rmdir(cli->tree, dname2);
546 smbcli_rmdir(cli->tree, dname1_long);
547 smbcli_unlink(cli->tree, dname1);
548 smbcli_unlink(cli->tree, dname2);
549 smbcli_unlink(cli->tree, dname1_long);
551 ZERO_STRUCT(io);
552 io.generic.level = RAW_OPEN_NTCREATEX;
553 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
554 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
555 io.ntcreatex.in.alloc_size = 0;
556 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
557 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
558 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
559 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
560 io.ntcreatex.in.fname = dname1;
561 status = smb_raw_open(cli->tree, tctx, &io);
562 CHECK_STATUS(status, NT_STATUS_OK);
564 fnum = io.ntcreatex.out.file.fnum;
565 smbcli_close(cli->tree, fnum);
567 /* create the longname directory */
568 io.ntcreatex.in.fname = dname1_long;
569 status = smb_raw_open(cli->tree, tctx, &io);
570 CHECK_STATUS(status, NT_STATUS_OK);
572 fnum = io.ntcreatex.out.file.fnum;
573 smbcli_close(cli->tree, fnum);
575 /* Now create and hold open a file. */
576 ZERO_STRUCT(io);
578 io.generic.level = RAW_OPEN_NTCREATEX;
579 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
580 io.ntcreatex.in.root_fid = 0;
581 io.ntcreatex.in.alloc_size = 0;
582 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
583 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
584 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
585 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
586 io.ntcreatex.in.create_options = 0;
587 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
588 io.ntcreatex.in.security_flags = 0;
589 io.ntcreatex.in.fname = fname;
591 /* Create the file. */
593 status = smb_raw_open(cli->tree, tctx, &io);
594 CHECK_STATUS(status, NT_STATUS_OK);
595 fnum = io.ntcreatex.out.file.fnum;
597 /* Now try and rename the directory. */
599 ZERO_STRUCT(ren_io);
600 ren_io.generic.level = RAW_RENAME_RENAME;
601 ren_io.rename.in.pattern1 = dname1;
602 ren_io.rename.in.pattern2 = dname2;
603 ren_io.rename.in.attrib = 0;
605 status = smb_raw_rename(cli->tree, &ren_io);
606 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
608 /* Close the file and try the rename. */
609 smbcli_close(cli->tree, fnum);
611 status = smb_raw_rename(cli->tree, &ren_io);
612 CHECK_STATUS(status, NT_STATUS_OK);
615 * Now try just holding a second handle on the directory and holding
616 * it open across a rename. This should be allowed.
618 io.ntcreatex.in.fname = dname2;
619 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
621 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
622 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
624 status = smb_raw_open(cli->tree, tctx, &io);
625 CHECK_STATUS(status, NT_STATUS_OK);
626 fnum = io.ntcreatex.out.file.fnum;
628 ren_io.generic.level = RAW_RENAME_RENAME;
629 ren_io.rename.in.pattern1 = dname2;
630 ren_io.rename.in.pattern2 = dname1;
631 ren_io.rename.in.attrib = 0;
633 status = smb_raw_rename(cli->tree, &ren_io);
634 CHECK_STATUS(status, NT_STATUS_OK);
636 /* close our handle to the directory. */
637 smbcli_close(cli->tree, fnum);
639 /* Open a handle on the long name, and then
640 * try a rename. This would catch a regression
641 * in bug #6781.
643 io.ntcreatex.in.fname = dname1_long;
644 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
646 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
647 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
649 status = smb_raw_open(cli->tree, tctx, &io);
650 CHECK_STATUS(status, NT_STATUS_OK);
651 fnum = io.ntcreatex.out.file.fnum;
653 ren_io.generic.level = RAW_RENAME_RENAME;
654 ren_io.rename.in.pattern1 = dname1;
655 ren_io.rename.in.pattern2 = dname2;
656 ren_io.rename.in.attrib = 0;
658 status = smb_raw_rename(cli->tree, &ren_io);
659 CHECK_STATUS(status, NT_STATUS_OK);
661 /* close our handle to the longname directory. */
662 smbcli_close(cli->tree, fnum);
665 * Now try opening a stream on the directory and holding it open
666 * across a rename. This should be allowed.
668 io.ntcreatex.in.fname = sname;
670 status = smb_raw_open(cli->tree, tctx, &io);
671 CHECK_STATUS(status, NT_STATUS_OK);
672 fnum = io.ntcreatex.out.file.fnum;
674 ren_io.generic.level = RAW_RENAME_RENAME;
675 ren_io.rename.in.pattern1 = dname2;
676 ren_io.rename.in.pattern2 = dname1;
677 ren_io.rename.in.attrib = 0;
679 status = smb_raw_rename(cli->tree, &ren_io);
680 CHECK_STATUS(status, NT_STATUS_OK);
682 done:
684 if (fnum != -1) {
685 smbcli_close(cli->tree, fnum);
687 smb_raw_exit(cli->session);
688 smbcli_deltree(cli->tree, BASEDIR);
689 return ret;
692 extern bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2);
693 extern bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1);
696 basic testing of rename calls
698 struct torture_suite *torture_raw_rename(TALLOC_CTX *mem_ctx)
700 struct torture_suite *suite = torture_suite_create(mem_ctx, "RENAME");
702 torture_suite_add_1smb_test(suite, "mv", test_mv);
703 /* test_trans2rename and test_nttransrename are actually in torture/raw/oplock.c to
704 use the handlers and macros there. */
705 torture_suite_add_2smb_test(suite, "trans2rename", test_trans2rename);
706 torture_suite_add_1smb_test(suite, "nttransrename", test_nttransrename);
707 torture_suite_add_1smb_test(suite, "ntrename", test_ntrename);
708 torture_suite_add_1smb_test(suite, "osxrename", test_osxrename);
709 torture_suite_add_1smb_test(suite, "directory rename", test_dir_rename);
711 return suite;