s3-winbind: Add an update function for winbind cache.
[Samba/gebeck_regimport.git] / source4 / torture / raw / rename.c
blobb9f2039ff2a3a45a9a79c1cc0992a2197b83c199
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 if (!torture_setup_dir(cli, BASEDIR)) {
63 return false;
66 torture_comment(tctx, "Trying simple rename\n");
68 op.generic.level = RAW_OPEN_NTCREATEX;
69 op.ntcreatex.in.root_fid.fnum = 0;
70 op.ntcreatex.in.flags = 0;
71 op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
72 op.ntcreatex.in.create_options = 0;
73 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
74 op.ntcreatex.in.share_access =
75 NTCREATEX_SHARE_ACCESS_READ |
76 NTCREATEX_SHARE_ACCESS_WRITE;
77 op.ntcreatex.in.alloc_size = 0;
78 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
79 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
80 op.ntcreatex.in.security_flags = 0;
81 op.ntcreatex.in.fname = fname1;
83 status = smb_raw_open(cli->tree, tctx, &op);
84 CHECK_STATUS(status, NT_STATUS_OK);
85 fnum = op.ntcreatex.out.file.fnum;
87 io.generic.level = RAW_RENAME_RENAME;
88 io.rename.in.pattern1 = fname1;
89 io.rename.in.pattern2 = fname2;
90 io.rename.in.attrib = 0;
92 torture_comment(tctx, "trying rename while first file open\n");
93 status = smb_raw_rename(cli->tree, &io);
94 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
96 smbcli_close(cli->tree, fnum);
98 op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
99 op.ntcreatex.in.share_access =
100 NTCREATEX_SHARE_ACCESS_DELETE |
101 NTCREATEX_SHARE_ACCESS_READ |
102 NTCREATEX_SHARE_ACCESS_WRITE;
103 status = smb_raw_open(cli->tree, tctx, &op);
104 CHECK_STATUS(status, NT_STATUS_OK);
105 fnum = op.ntcreatex.out.file.fnum;
107 torture_comment(tctx, "trying rename while first file open with SHARE_ACCESS_DELETE\n");
108 status = smb_raw_rename(cli->tree, &io);
109 CHECK_STATUS(status, NT_STATUS_OK);
111 io.rename.in.pattern1 = fname2;
112 io.rename.in.pattern2 = fname1;
113 status = smb_raw_rename(cli->tree, &io);
114 CHECK_STATUS(status, NT_STATUS_OK);
116 torture_comment(tctx, "Trying case-changing rename\n");
117 io.rename.in.pattern1 = fname1;
118 io.rename.in.pattern2 = Fname1;
119 status = smb_raw_rename(cli->tree, &io);
120 CHECK_STATUS(status, NT_STATUS_OK);
122 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
123 finfo.all_info.in.file.path = fname1;
124 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
125 CHECK_STATUS(status, NT_STATUS_OK);
126 if (strcmp(finfo.all_info.out.fname.s, Fname1) != 0) {
127 torture_warning(tctx, "(%s) Incorrect filename [%s] after case-changing "
128 "rename, should be [%s]\n", __location__,
129 finfo.all_info.out.fname.s, Fname1);
132 io.rename.in.pattern1 = fname1;
133 io.rename.in.pattern2 = fname2;
135 torture_comment(tctx, "trying rename while not open\n");
136 smb_raw_exit(cli->session);
137 status = smb_raw_rename(cli->tree, &io);
138 CHECK_STATUS(status, NT_STATUS_OK);
140 torture_comment(tctx, "Trying self rename\n");
141 io.rename.in.pattern1 = fname2;
142 io.rename.in.pattern2 = fname2;
143 status = smb_raw_rename(cli->tree, &io);
144 CHECK_STATUS(status, NT_STATUS_OK);
146 io.rename.in.pattern1 = fname1;
147 io.rename.in.pattern2 = fname1;
148 status = smb_raw_rename(cli->tree, &io);
149 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
152 torture_comment(tctx, "trying wildcard rename\n");
153 io.rename.in.pattern1 = BASEDIR "\\*.txt";
154 io.rename.in.pattern2 = fname1;
156 status = smb_raw_rename(cli->tree, &io);
157 CHECK_STATUS(status, NT_STATUS_OK);
159 torture_comment(tctx, "and again\n");
160 status = smb_raw_rename(cli->tree, &io);
161 CHECK_STATUS(status, NT_STATUS_OK);
163 torture_comment(tctx, "Trying extension change\n");
164 io.rename.in.pattern1 = BASEDIR "\\*.txt";
165 io.rename.in.pattern2 = BASEDIR "\\*.bak";
166 status = smb_raw_rename(cli->tree, &io);
167 CHECK_STATUS(status, NT_STATUS_OK);
169 status = smb_raw_rename(cli->tree, &io);
170 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
172 torture_comment(tctx, "Checking attrib handling\n");
173 torture_set_file_attribute(cli->tree, BASEDIR "\\test1.bak", FILE_ATTRIBUTE_HIDDEN);
174 io.rename.in.pattern1 = BASEDIR "\\test1.bak";
175 io.rename.in.pattern2 = BASEDIR "\\*.txt";
176 io.rename.in.attrib = 0;
177 status = smb_raw_rename(cli->tree, &io);
178 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
180 io.rename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
181 status = smb_raw_rename(cli->tree, &io);
182 CHECK_STATUS(status, NT_STATUS_OK);
184 done:
185 smbcli_close(cli->tree, fnum);
186 smb_raw_exit(cli->session);
187 smbcli_deltree(cli->tree, BASEDIR);
188 return ret;
192 static bool test_osxrename(struct torture_context *tctx,
193 struct smbcli_state *cli)
195 union smb_rename io;
196 union smb_unlink io_un;
197 NTSTATUS status;
198 bool ret = true;
199 int fnum = -1;
200 const char *fname1 = BASEDIR "\\test1";
201 const char *FNAME1 = BASEDIR "\\TEST1";
202 union smb_fileinfo finfo;
203 union smb_open op;
205 torture_comment(tctx, "\nTesting OSX Rename\n");
206 if (!torture_setup_dir(cli, BASEDIR)) {
207 return false;
209 op.generic.level = RAW_OPEN_NTCREATEX;
210 op.ntcreatex.in.root_fid.fnum = 0;
211 op.ntcreatex.in.flags = 0;
212 op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
213 op.ntcreatex.in.create_options = 0;
214 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
215 op.ntcreatex.in.share_access =
216 NTCREATEX_SHARE_ACCESS_READ |
217 NTCREATEX_SHARE_ACCESS_WRITE;
218 op.ntcreatex.in.alloc_size = 0;
219 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
220 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
221 op.ntcreatex.in.security_flags = 0;
222 op.ntcreatex.in.fname = fname1;
224 status = smb_raw_open(cli->tree, tctx, &op);
225 CHECK_STATUS(status, NT_STATUS_OK);
226 fnum = op.ntcreatex.out.file.fnum;
228 io.generic.level = RAW_RENAME_RENAME;
229 io.rename.in.attrib = 0;
231 smbcli_close(cli->tree, fnum);
233 /* Rename by changing case. First check for the
234 * existence of the file with the "newname".
235 * If we find one and both the output and input are same case,
236 * delete it. */
238 torture_comment(tctx, "Checking os X rename (case changing)\n");
240 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
241 finfo.all_info.in.file.path = FNAME1;
242 torture_comment(tctx, "Looking for file %s \n",FNAME1);
243 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
245 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
246 torture_comment(tctx, "Name of the file found %s \n", finfo.all_info.out.fname.s);
247 if (strcmp(finfo.all_info.out.fname.s, finfo.all_info.in.file.path) == 0) {
248 /* If file is found with the same case delete it */
249 torture_comment(tctx, "Deleting File %s \n", finfo.all_info.out.fname.s);
250 io_un.unlink.in.pattern = finfo.all_info.out.fname.s;
251 io_un.unlink.in.attrib = 0;
252 status = smb_raw_unlink(cli->tree, &io_un);
253 CHECK_STATUS(status, NT_STATUS_OK);
257 io.rename.in.pattern1 = fname1;
258 io.rename.in.pattern2 = FNAME1;
259 status = smb_raw_rename(cli->tree, &io);
260 CHECK_STATUS(status, NT_STATUS_OK);
262 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
263 finfo.all_info.in.file.path = fname1;
264 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
265 CHECK_STATUS(status, NT_STATUS_OK);
266 torture_comment(tctx, "File name after rename %s \n",finfo.all_info.out.fname.s);
268 done:
269 smbcli_close(cli->tree, fnum);
270 smb_raw_exit(cli->session);
271 smbcli_deltree(cli->tree, BASEDIR);
272 return ret;
276 test SMBntrename ops
278 static bool test_ntrename(struct torture_context *tctx,
279 struct smbcli_state *cli)
281 union smb_rename io;
282 NTSTATUS status;
283 bool ret = true;
284 int fnum, i;
285 const char *fname1 = BASEDIR "\\test1.txt";
286 const char *fname2 = BASEDIR "\\test2.txt";
287 union smb_fileinfo finfo;
289 torture_comment(tctx, "Testing SMBntrename\n");
291 if (!torture_setup_dir(cli, BASEDIR)) {
292 return false;
295 torture_comment(tctx, "Trying simple rename\n");
297 fnum = create_complex_file(cli, tctx, fname1);
299 io.generic.level = RAW_RENAME_NTRENAME;
300 io.ntrename.in.old_name = fname1;
301 io.ntrename.in.new_name = fname2;
302 io.ntrename.in.attrib = 0;
303 io.ntrename.in.cluster_size = 0;
304 io.ntrename.in.flags = RENAME_FLAG_RENAME;
306 status = smb_raw_rename(cli->tree, &io);
307 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
309 smbcli_close(cli->tree, fnum);
310 status = smb_raw_rename(cli->tree, &io);
311 CHECK_STATUS(status, NT_STATUS_OK);
313 torture_comment(tctx, "Trying self rename\n");
314 io.ntrename.in.old_name = fname2;
315 io.ntrename.in.new_name = fname2;
316 status = smb_raw_rename(cli->tree, &io);
317 CHECK_STATUS(status, NT_STATUS_OK);
319 io.ntrename.in.old_name = fname1;
320 io.ntrename.in.new_name = fname1;
321 status = smb_raw_rename(cli->tree, &io);
322 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
324 torture_comment(tctx, "trying wildcard rename\n");
325 io.ntrename.in.old_name = BASEDIR "\\*.txt";
326 io.ntrename.in.new_name = fname1;
328 status = smb_raw_rename(cli->tree, &io);
329 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
331 torture_comment(tctx, "Checking attrib handling\n");
332 torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN);
333 io.ntrename.in.old_name = fname2;
334 io.ntrename.in.new_name = fname1;
335 io.ntrename.in.attrib = 0;
336 status = smb_raw_rename(cli->tree, &io);
337 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
339 io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
340 status = smb_raw_rename(cli->tree, &io);
341 CHECK_STATUS(status, NT_STATUS_OK);
343 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
345 torture_comment(tctx, "Checking hard link\n");
346 io.ntrename.in.old_name = fname1;
347 io.ntrename.in.new_name = fname2;
348 io.ntrename.in.attrib = 0;
349 io.ntrename.in.flags = RENAME_FLAG_HARD_LINK;
350 status = smb_raw_rename(cli->tree, &io);
351 CHECK_STATUS(status, NT_STATUS_OK);
353 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
355 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
356 finfo.generic.in.file.path = fname2;
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 finfo.generic.in.file.path = fname1;
363 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
364 CHECK_STATUS(status, NT_STATUS_OK);
365 CHECK_VALUE(finfo.all_info.out.nlink, 2);
366 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
368 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
370 smbcli_unlink(cli->tree, fname2);
372 finfo.generic.in.file.path = fname1;
373 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
374 CHECK_STATUS(status, NT_STATUS_OK);
375 CHECK_VALUE(finfo.all_info.out.nlink, 1);
376 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
378 torture_comment(tctx, "Checking copy\n");
379 io.ntrename.in.old_name = fname1;
380 io.ntrename.in.new_name = fname2;
381 io.ntrename.in.attrib = 0;
382 io.ntrename.in.flags = RENAME_FLAG_COPY;
383 status = smb_raw_rename(cli->tree, &io);
384 CHECK_STATUS(status, NT_STATUS_OK);
386 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
387 finfo.generic.in.file.path = fname1;
388 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
389 CHECK_STATUS(status, NT_STATUS_OK);
390 CHECK_VALUE(finfo.all_info.out.nlink, 1);
391 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
393 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
394 finfo.generic.in.file.path = fname2;
395 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
396 CHECK_STATUS(status, NT_STATUS_OK);
397 CHECK_VALUE(finfo.all_info.out.nlink, 1);
398 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
400 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
402 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
403 finfo.generic.in.file.path = fname2;
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_NORMAL);
409 finfo.generic.in.file.path = fname1;
410 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
411 CHECK_STATUS(status, NT_STATUS_OK);
412 CHECK_VALUE(finfo.all_info.out.nlink, 1);
413 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
415 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
417 smbcli_unlink(cli->tree, fname2);
419 finfo.generic.in.file.path = fname1;
420 status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
421 CHECK_STATUS(status, NT_STATUS_OK);
422 CHECK_VALUE(finfo.all_info.out.nlink, 1);
424 torture_comment(tctx, "Checking invalid flags\n");
425 io.ntrename.in.old_name = fname1;
426 io.ntrename.in.new_name = fname2;
427 io.ntrename.in.attrib = 0;
428 io.ntrename.in.flags = 0;
429 status = smb_raw_rename(cli->tree, &io);
430 if (TARGET_IS_WIN7(tctx)) {
431 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
432 } else {
433 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
436 io.ntrename.in.flags = 300;
437 status = smb_raw_rename(cli->tree, &io);
438 if (TARGET_IS_WIN7(tctx)) {
439 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
440 } else {
441 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
444 io.ntrename.in.flags = 0x106;
445 status = smb_raw_rename(cli->tree, &io);
446 if (TARGET_IS_WIN7(tctx)) {
447 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
448 } else {
449 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
452 torture_comment(tctx, "Checking unknown field\n");
453 io.ntrename.in.old_name = fname1;
454 io.ntrename.in.new_name = fname2;
455 io.ntrename.in.attrib = 0;
456 io.ntrename.in.flags = RENAME_FLAG_RENAME;
457 io.ntrename.in.cluster_size = 0xff;
458 status = smb_raw_rename(cli->tree, &io);
459 CHECK_STATUS(status, NT_STATUS_OK);
461 torture_comment(tctx, "Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n");
463 io.ntrename.in.old_name = fname2;
464 io.ntrename.in.new_name = fname1;
465 io.ntrename.in.attrib = 0;
466 io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
467 io.ntrename.in.cluster_size = 1;
468 status = smb_raw_rename(cli->tree, &io);
469 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
471 io.ntrename.in.flags = RENAME_FLAG_COPY;
472 status = smb_raw_rename(cli->tree, &io);
473 CHECK_STATUS(status, NT_STATUS_OK);
475 #if 0
477 char buf[16384];
478 fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE);
479 memset(buf, 1, sizeof(buf));
480 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
481 smbcli_close(cli->tree, fnum);
483 fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE);
484 memset(buf, 1, sizeof(buf));
485 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1);
486 smbcli_close(cli->tree, fnum);
488 torture_all_info(cli->tree, fname1);
489 torture_all_info(cli->tree, fname2);
493 io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
494 status = smb_raw_rename(cli->tree, &io);
495 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
497 for (i=0;i<20000;i++) {
498 io.ntrename.in.cluster_size = i;
499 status = smb_raw_rename(cli->tree, &io);
500 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
501 torture_warning(tctx, "i=%d status=%s\n", i, nt_errstr(status));
504 #endif
506 torture_comment(tctx, "Checking other flags\n");
508 for (i=0;i<0xFFF;i++) {
509 if (i == RENAME_FLAG_RENAME ||
510 i == RENAME_FLAG_HARD_LINK ||
511 i == RENAME_FLAG_COPY) {
512 continue;
515 io.ntrename.in.old_name = fname2;
516 io.ntrename.in.new_name = fname1;
517 io.ntrename.in.flags = i;
518 io.ntrename.in.attrib = 0;
519 io.ntrename.in.cluster_size = 0;
520 status = smb_raw_rename(cli->tree, &io);
521 if (TARGET_IS_WIN7(tctx)){
522 if (!NT_STATUS_EQUAL(status,
523 NT_STATUS_INVALID_PARAMETER)) {
524 torture_warning(tctx, "flags=0x%x status=%s\n",
525 i, nt_errstr(status));
527 } else {
528 if (!NT_STATUS_EQUAL(status,
529 NT_STATUS_ACCESS_DENIED)) {
530 torture_warning(tctx, "flags=0x%x status=%s\n",
531 i, nt_errstr(status));
536 done:
537 smb_raw_exit(cli->session);
538 smbcli_deltree(cli->tree, BASEDIR);
539 return ret;
543 test dir rename.
545 static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli)
547 union smb_open io;
548 union smb_rename ren_io;
549 NTSTATUS status;
550 const char *dname1 = BASEDIR "\\dir_for_rename";
551 const char *dname2 = BASEDIR "\\renamed_dir";
552 const char *dname1_long = BASEDIR "\\dir_for_rename_long";
553 const char *fname = BASEDIR "\\dir_for_rename\\file.txt";
554 const char *sname = BASEDIR "\\renamed_dir:a stream:$DATA";
555 bool ret = true;
556 int fnum = -1;
558 torture_comment(tctx, "Checking rename on a directory containing an open file.\n");
560 if (!torture_setup_dir(cli, BASEDIR)) {
561 return false;
564 /* create a directory */
565 smbcli_rmdir(cli->tree, dname1);
566 smbcli_rmdir(cli->tree, dname2);
567 smbcli_rmdir(cli->tree, dname1_long);
568 smbcli_unlink(cli->tree, dname1);
569 smbcli_unlink(cli->tree, dname2);
570 smbcli_unlink(cli->tree, dname1_long);
572 ZERO_STRUCT(io);
573 io.generic.level = RAW_OPEN_NTCREATEX;
574 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
575 io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
576 io.ntcreatex.in.alloc_size = 0;
577 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
578 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
579 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
580 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
581 io.ntcreatex.in.fname = dname1;
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 /* create the longname directory */
589 io.ntcreatex.in.fname = dname1_long;
590 status = smb_raw_open(cli->tree, tctx, &io);
591 CHECK_STATUS(status, NT_STATUS_OK);
593 fnum = io.ntcreatex.out.file.fnum;
594 smbcli_close(cli->tree, fnum);
596 /* Now create and hold open a file. */
597 ZERO_STRUCT(io);
599 io.generic.level = RAW_OPEN_NTCREATEX;
600 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
601 io.ntcreatex.in.root_fid.fnum = 0;
602 io.ntcreatex.in.alloc_size = 0;
603 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
604 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
605 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
606 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
607 io.ntcreatex.in.create_options = 0;
608 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
609 io.ntcreatex.in.security_flags = 0;
610 io.ntcreatex.in.fname = fname;
612 /* Create the file. */
614 status = smb_raw_open(cli->tree, tctx, &io);
615 CHECK_STATUS(status, NT_STATUS_OK);
616 fnum = io.ntcreatex.out.file.fnum;
618 /* Now try and rename the directory. */
620 ZERO_STRUCT(ren_io);
621 ren_io.generic.level = RAW_RENAME_RENAME;
622 ren_io.rename.in.pattern1 = dname1;
623 ren_io.rename.in.pattern2 = dname2;
624 ren_io.rename.in.attrib = 0;
626 status = smb_raw_rename(cli->tree, &ren_io);
627 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
629 /* Close the file and try the rename. */
630 smbcli_close(cli->tree, fnum);
632 status = smb_raw_rename(cli->tree, &ren_io);
633 CHECK_STATUS(status, NT_STATUS_OK);
636 * Now try just holding a second handle on the directory and holding
637 * it open across a rename. This should be allowed.
639 io.ntcreatex.in.fname = dname2;
640 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
642 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
643 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
645 status = smb_raw_open(cli->tree, tctx, &io);
646 CHECK_STATUS(status, NT_STATUS_OK);
647 fnum = io.ntcreatex.out.file.fnum;
649 ren_io.generic.level = RAW_RENAME_RENAME;
650 ren_io.rename.in.pattern1 = dname2;
651 ren_io.rename.in.pattern2 = dname1;
652 ren_io.rename.in.attrib = 0;
654 status = smb_raw_rename(cli->tree, &ren_io);
655 CHECK_STATUS(status, NT_STATUS_OK);
657 /* close our handle to the directory. */
658 smbcli_close(cli->tree, fnum);
660 /* Open a handle on the long name, and then
661 * try a rename. This would catch a regression
662 * in bug #6781.
664 io.ntcreatex.in.fname = dname1_long;
665 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
667 io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
668 SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
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 = dname1;
676 ren_io.rename.in.pattern2 = dname2;
677 ren_io.rename.in.attrib = 0;
679 status = smb_raw_rename(cli->tree, &ren_io);
680 CHECK_STATUS(status, NT_STATUS_OK);
682 /* close our handle to the longname directory. */
683 smbcli_close(cli->tree, fnum);
686 * Now try opening a stream on the directory and holding it open
687 * across a rename. This should be allowed.
689 io.ntcreatex.in.fname = sname;
691 status = smb_raw_open(cli->tree, tctx, &io);
692 CHECK_STATUS(status, NT_STATUS_OK);
693 fnum = io.ntcreatex.out.file.fnum;
695 ren_io.generic.level = RAW_RENAME_RENAME;
696 ren_io.rename.in.pattern1 = dname2;
697 ren_io.rename.in.pattern2 = dname1;
698 ren_io.rename.in.attrib = 0;
700 status = smb_raw_rename(cli->tree, &ren_io);
701 CHECK_STATUS(status, NT_STATUS_OK);
703 done:
705 if (fnum != -1) {
706 smbcli_close(cli->tree, fnum);
708 smb_raw_exit(cli->session);
709 smbcli_deltree(cli->tree, BASEDIR);
710 return ret;
713 extern bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2);
714 extern bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1);
717 basic testing of rename calls
719 struct torture_suite *torture_raw_rename(TALLOC_CTX *mem_ctx)
721 struct torture_suite *suite = torture_suite_create(mem_ctx, "rename");
723 torture_suite_add_1smb_test(suite, "mv", test_mv);
724 /* test_trans2rename and test_nttransrename are actually in torture/raw/oplock.c to
725 use the handlers and macros there. */
726 torture_suite_add_2smb_test(suite, "trans2rename", test_trans2rename);
727 torture_suite_add_1smb_test(suite, "nttransrename", test_nttransrename);
728 torture_suite_add_1smb_test(suite, "ntrename", test_ntrename);
729 torture_suite_add_1smb_test(suite, "osxrename", test_osxrename);
730 torture_suite_add_1smb_test(suite, "directory rename", test_dir_rename);
732 return suite;