2 Unix SMB/CIFS implementation.
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/>.
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)); \
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); \
42 #define BASEDIR "\\testrename"
47 static bool test_mv(struct torture_context
*tctx
,
48 struct smbcli_state
*cli
)
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
;
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
);
183 smbcli_close(cli
->tree
, fnum
);
184 smb_raw_exit(cli
->session
);
185 smbcli_deltree(cli
->tree
, BASEDIR
);
190 static bool test_osxrename(struct torture_context
*tctx
,
191 struct smbcli_state
*cli
)
194 union smb_unlink io_un
;
198 const char *fname1
= BASEDIR
"\\test1";
199 const char *FNAME1
= BASEDIR
"\\TEST1";
200 union smb_fileinfo finfo
;
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,
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
);
265 smbcli_close(cli
->tree
, fnum
);
266 smb_raw_exit(cli
->session
);
267 smbcli_deltree(cli
->tree
, BASEDIR
);
274 static bool test_ntrename(struct torture_context
*tctx
,
275 struct smbcli_state
*cli
)
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
);
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
);
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
);
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
);
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
));
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
) {
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
));
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
));
531 smb_raw_exit(cli
->session
);
532 smbcli_deltree(cli
->tree
, BASEDIR
);
539 static bool test_dir_rename(struct torture_context
*tctx
, struct smbcli_state
*cli
)
542 union smb_rename ren_io
;
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";
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
);
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. */
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. */
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
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
);
698 smbcli_close(cli
->tree
, fnum
);
700 smb_raw_exit(cli
->session
);
701 smbcli_deltree(cli
->tree
, BASEDIR
);
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
);