docs: man smbtorture: Add missing meta data.
[Samba/gebeck_regimport.git] / source4 / torture / raw / rename.c
blob63e13c0546f31c87b6446caa49ab1050303fc063
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 "libcli/libcli.h"
22 #include "torture/util.h"
23 #include "torture/raw/proto.h"
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)
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)
42 #define BASEDIR "\\testrename"
45 test SMBmv ops
47 static bool test_mv(struct torture_context *tctx,
48 struct smbcli_state *cli)
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;
60 torture_comment(tctx, "Testing SMBmv\n");
62 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
64 torture_comment(tctx, "Trying simple rename\n");
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;
81 status = smb_raw_open(cli->tree, tctx, &op);
82 CHECK_STATUS(status, NT_STATUS_OK);
83 fnum = op.ntcreatex.out.file.fnum;
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;
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);
94 smbcli_close(cli->tree, fnum);
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;
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);
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);
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);
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);
130 io.rename.in.pattern1 = fname1;
131 io.rename.in.pattern2 = fname2;
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);
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);
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);
150 torture_comment(tctx, "trying wildcard rename\n");
151 io.rename.in.pattern1 = BASEDIR "\\*.txt";
152 io.rename.in.pattern2 = fname1;
154 status = smb_raw_rename(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_OK);
157 torture_comment(tctx, "and again\n");
158 status = smb_raw_rename(cli->tree, &io);
159 CHECK_STATUS(status, NT_STATUS_OK);
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);
167 status = smb_raw_rename(cli->tree, &io);
168 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
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);
178 io.rename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
179 status = smb_raw_rename(cli->tree, &io);
180 CHECK_STATUS(status, NT_STATUS_OK);
182 done:
183 smbcli_close(cli->tree, fnum);
184 smb_raw_exit(cli->session);
185 smbcli_deltree(cli->tree, BASEDIR);
186 return ret;
190 static bool test_osxrename(struct torture_context *tctx,
191 struct smbcli_state *cli)
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;
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;
220 status = smb_raw_open(cli->tree, tctx, &op);
221 CHECK_STATUS(status, NT_STATUS_OK);
222 fnum = op.ntcreatex.out.file.fnum;
224 io.generic.level = RAW_RENAME_RENAME;
225 io.rename.in.attrib = 0;
227 smbcli_close(cli->tree, fnum);
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. */
234 torture_comment(tctx, "Checking os X rename (case changing)\n");
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);
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);
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);
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);
264 done:
265 smbcli_close(cli->tree, fnum);
266 smb_raw_exit(cli->session);
267 smbcli_deltree(cli->tree, BASEDIR);
268 return ret;
272 test SMBntrename ops
274 static bool test_ntrename(struct torture_context *tctx,
275 struct smbcli_state *cli)
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;
285 torture_comment(tctx, "Testing SMBntrename\n");
287 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
289 torture_comment(tctx, "Trying simple rename\n");
291 fnum = create_complex_file(cli, tctx, fname1);
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;
300 status = smb_raw_rename(cli->tree, &io);
301 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
303 smbcli_close(cli->tree, fnum);
304 status = smb_raw_rename(cli->tree, &io);
305 CHECK_STATUS(status, NT_STATUS_OK);
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);
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);
318 torture_comment(tctx, "trying wildcard rename\n");
319 io.ntrename.in.old_name = BASEDIR "\\*.txt";
320 io.ntrename.in.new_name = fname1;
322 status = smb_raw_rename(cli->tree, &io);
323 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
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);
333 io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
334 status = smb_raw_rename(cli->tree, &io);
335 CHECK_STATUS(status, NT_STATUS_OK);
337 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
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);
347 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
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);
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);
362 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
364 smbcli_unlink(cli->tree, fname2);
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);
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);
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);
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);
394 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
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);
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);
409 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
411 smbcli_unlink(cli->tree, fname2);
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);
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);
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);
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);
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);
455 torture_comment(tctx, "Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n");
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);
465 io.ntrename.in.flags = RENAME_FLAG_COPY;
466 status = smb_raw_rename(cli->tree, &io);
467 CHECK_STATUS(status, NT_STATUS_OK);
469 #if 0
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);
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);
482 torture_all_info(cli->tree, fname1);
483 torture_all_info(cli->tree, fname2);
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);
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));
498 #endif
500 torture_comment(tctx, "Checking other flags\n");
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;
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));
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));
530 done:
531 smb_raw_exit(cli->session);
532 smbcli_deltree(cli->tree, BASEDIR);
533 return ret;
537 test dir rename.
539 static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli)
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;
552 torture_comment(tctx, "Checking rename on a directory containing an open file.\n");
554 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
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);
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);
577 fnum = io.ntcreatex.out.file.fnum;
578 smbcli_close(cli->tree, fnum);
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);
585 fnum = io.ntcreatex.out.file.fnum;
586 smbcli_close(cli->tree, fnum);
588 /* Now create and hold open a file. */
589 ZERO_STRUCT(io);
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;
604 /* Create the file. */
606 status = smb_raw_open(cli->tree, tctx, &io);
607 CHECK_STATUS(status, NT_STATUS_OK);
608 fnum = io.ntcreatex.out.file.fnum;
610 /* Now try and rename the directory. */
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;
618 status = smb_raw_rename(cli->tree, &ren_io);
619 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
621 /* Close the file and try the rename. */
622 smbcli_close(cli->tree, fnum);
624 status = smb_raw_rename(cli->tree, &ren_io);
625 CHECK_STATUS(status, NT_STATUS_OK);
628 * Now try just holding a second handle on the directory and holding
629 * it open across a rename. This should be allowed.
631 io.ntcreatex.in.fname = dname2;
632 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
634 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
635 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
637 status = smb_raw_open(cli->tree, tctx, &io);
638 CHECK_STATUS(status, NT_STATUS_OK);
639 fnum = io.ntcreatex.out.file.fnum;
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;
646 status = smb_raw_rename(cli->tree, &ren_io);
647 CHECK_STATUS(status, NT_STATUS_OK);
649 /* close our handle to the directory. */
650 smbcli_close(cli->tree, fnum);
652 /* Open a handle on the long name, and then
653 * try a rename. This would catch a regression
654 * in bug #6781.
656 io.ntcreatex.in.fname = dname1_long;
657 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
659 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
660 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
662 status = smb_raw_open(cli->tree, tctx, &io);
663 CHECK_STATUS(status, NT_STATUS_OK);
664 fnum = io.ntcreatex.out.file.fnum;
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;
671 status = smb_raw_rename(cli->tree, &ren_io);
672 CHECK_STATUS(status, NT_STATUS_OK);
674 /* close our handle to the longname directory. */
675 smbcli_close(cli->tree, fnum);
678 * Now try opening a stream on the directory and holding it open
679 * across a rename. This should be allowed.
681 io.ntcreatex.in.fname = sname;
683 status = smb_raw_open(cli->tree, tctx, &io);
684 CHECK_STATUS(status, NT_STATUS_OK);
685 fnum = io.ntcreatex.out.file.fnum;
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;
692 status = smb_raw_rename(cli->tree, &ren_io);
693 CHECK_STATUS(status, NT_STATUS_OK);
695 done:
697 if (fnum != -1) {
698 smbcli_close(cli->tree, fnum);
700 smb_raw_exit(cli->session);
701 smbcli_deltree(cli->tree, BASEDIR);
702 return ret;
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);
709 basic testing of rename calls
711 struct torture_suite *torture_raw_rename(TALLOC_CTX *mem_ctx)
713 struct torture_suite *suite = torture_suite_create(mem_ctx, "rename");
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);
724 return suite;