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 "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)); \
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); \
43 #define BASEDIR "\\testrename"
48 static bool test_mv(struct torture_context
*tctx
,
49 struct smbcli_state
*cli
)
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
;
61 torture_comment(tctx
, "Testing SMBmv\n");
63 if (!torture_setup_dir(cli
, BASEDIR
)) {
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
);
186 smbcli_close(cli
->tree
, fnum
);
187 smb_raw_exit(cli
->session
);
188 smbcli_deltree(cli
->tree
, BASEDIR
);
193 static bool test_osxrename(struct torture_context
*tctx
,
194 struct smbcli_state
*cli
)
197 union smb_unlink io_un
;
201 const char *fname1
= BASEDIR
"\\test1";
202 const char *FNAME1
= BASEDIR
"\\TEST1";
203 union smb_fileinfo finfo
;
206 torture_comment(tctx
, "\nTesting OSX Rename\n");
207 if (!torture_setup_dir(cli
, BASEDIR
)) {
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,
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
);
270 smbcli_close(cli
->tree
, fnum
);
271 smb_raw_exit(cli
->session
);
272 smbcli_deltree(cli
->tree
, BASEDIR
);
279 static bool test_ntrename(struct torture_context
*tctx
,
280 struct smbcli_state
*cli
)
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
)) {
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
);
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
));
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
) {
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
));
516 smb_raw_exit(cli
->session
);
517 smbcli_deltree(cli
->tree
, BASEDIR
);
524 static bool test_dir_rename(struct torture_context
*tctx
, struct smbcli_state
*cli
)
527 union smb_rename ren_io
;
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";
537 torture_comment(tctx
, "Checking rename on a directory containing an open file.\n");
539 if (!torture_setup_dir(cli
, BASEDIR
)) {
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
);
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. */
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. */
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
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
);
685 smbcli_close(cli
->tree
, fnum
);
687 smb_raw_exit(cli
->session
);
688 smbcli_deltree(cli
->tree
, BASEDIR
);
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
);