2 Unix SMB/CIFS implementation.
3 RAW_SFILEINFO_* individual 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/>.
21 #include "system/time.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
26 #define BASEDIR "\\testsfileinfo"
28 /* basic testing of all RAW_SFILEINFO_* calls
29 for each call we test that it succeeds, and where possible test
30 for consistency between the calls.
33 torture_raw_sfileinfo_base(struct torture_context
*torture
, struct smbcli_state
*cli
)
41 union smb_fileinfo finfo1
, finfo2
;
42 union smb_setfileinfo sfinfo
;
43 NTSTATUS status
, status2
;
44 const char *call_name
;
45 time_t basetime
= (time(NULL
) - 86400) & ~1;
47 int n
= time(NULL
) % 100;
49 asprintf(&path_fname
, BASEDIR
"\\fname_test_%d.txt", n
);
50 asprintf(&path_fname_new
, BASEDIR
"\\fname_test_new_%d.txt", n
);
51 asprintf(&fnum_fname
, BASEDIR
"\\fnum_test_%d.txt", n
);
52 asprintf(&fnum_fname_new
, BASEDIR
"\\fnum_test_new_%d.txt", n
);
54 if (!torture_setup_dir(cli
, BASEDIR
)) {
58 #define RECREATE_FILE(fname) do { \
59 if (fnum != -1) smbcli_close(cli->tree, fnum); \
60 fnum = create_complex_file(cli, torture, fname); \
62 printf("(%s) ERROR: open of %s failed (%s)\n", \
63 __location__, fname, smbcli_errstr(cli->tree)); \
68 #define RECREATE_BOTH do { \
69 RECREATE_FILE(path_fname); \
70 smbcli_close(cli->tree, fnum); \
71 RECREATE_FILE(fnum_fname); \
76 #define CHECK_CALL_FNUM(call, rightstatus) do { \
79 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
80 sfinfo.generic.in.file.fnum = fnum; \
81 status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
82 if (!NT_STATUS_EQUAL(status, rightstatus)) { \
83 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
84 nt_errstr(status), nt_errstr(rightstatus)); \
87 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
88 finfo1.generic.in.file.fnum = fnum; \
89 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
90 if (!NT_STATUS_IS_OK(status2)) { \
91 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
95 #define CHECK_CALL_PATH(call, rightstatus) do { \
98 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
99 sfinfo.generic.in.file.path = path_fname; \
100 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
101 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
102 sfinfo.generic.in.file.path = path_fname_new; \
103 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
105 if (!NT_STATUS_EQUAL(status, rightstatus)) { \
106 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
107 nt_errstr(status), nt_errstr(rightstatus)); \
110 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
111 finfo1.generic.in.file.path = path_fname; \
112 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
113 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
114 finfo1.generic.in.file.path = path_fname_new; \
115 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
117 if (!NT_STATUS_IS_OK(status2)) { \
118 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \
122 #define CHECK1(call) \
123 do { if (NT_STATUS_IS_OK(status)) { \
124 finfo2.generic.level = RAW_FILEINFO_ ## call; \
126 finfo2.generic.in.file.fnum = fnum; \
127 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
129 finfo2.generic.in.file.path = path_fname; \
130 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
131 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
132 finfo2.generic.in.file.path = path_fname_new; \
133 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
136 if (!NT_STATUS_IS_OK(status2)) { \
137 printf("%s - %s\n", #call, nt_errstr(status2)); \
142 #define CHECK_VALUE(call, stype, field, value) do { \
144 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
145 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
146 call_name, #stype, #field, \
147 (uint_t)value, (uint_t)finfo2.stype.out.field); \
148 dump_all_info(torture, &finfo1); \
152 #define CHECK_TIME(call, stype, field, value) do { \
154 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
155 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
156 call_name, #stype, #field, \
158 (uint_t)nt_time_to_unix(finfo2.stype.out.field)); \
159 printf("\t%s", timestring(torture, value)); \
160 printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
161 dump_all_info(torture, &finfo1); \
165 #define CHECK_STR(call, stype, field, value) do { \
167 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
168 printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
169 call_name, #stype, #field, \
171 finfo2.stype.out.field); \
172 dump_all_info(torture, &finfo1); \
176 #define CHECK_STATUS(status, correct) do { \
177 if (!NT_STATUS_EQUAL(status, correct)) { \
178 printf("(%s) Incorrect status %s - should be %s\n", \
179 __location__, nt_errstr(status), nt_errstr(correct)); \
185 printf("test setattr\n");
186 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
187 sfinfo
.setattr
.in
.write_time
= basetime
;
188 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
189 CHECK_VALUE (ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
190 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
192 printf("setting to NORMAL doesn't do anything\n");
193 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
194 sfinfo
.setattr
.in
.write_time
= 0;
195 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
196 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
197 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
199 printf("a zero write_time means don't change\n");
200 sfinfo
.setattr
.in
.attrib
= 0;
201 sfinfo
.setattr
.in
.write_time
= 0;
202 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
203 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
204 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
206 printf("test setattre\n");
207 sfinfo
.setattre
.in
.create_time
= basetime
+ 20;
208 sfinfo
.setattre
.in
.access_time
= basetime
+ 30;
209 sfinfo
.setattre
.in
.write_time
= basetime
+ 40;
210 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
211 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
212 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
213 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
215 sfinfo
.setattre
.in
.create_time
= 0;
216 sfinfo
.setattre
.in
.access_time
= 0;
217 sfinfo
.setattre
.in
.write_time
= 0;
218 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
219 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
220 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
221 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
223 printf("test standard level\n");
224 sfinfo
.standard
.in
.create_time
= basetime
+ 100;
225 sfinfo
.standard
.in
.access_time
= basetime
+ 200;
226 sfinfo
.standard
.in
.write_time
= basetime
+ 300;
227 CHECK_CALL_FNUM(STANDARD
, NT_STATUS_OK
);
228 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
229 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
230 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
232 printf("test basic_info level\n");
234 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
235 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
236 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
237 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
238 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
239 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_OK
);
240 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
241 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
242 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
243 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
244 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
246 printf("a zero time means don't change\n");
247 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
248 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
249 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
250 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
251 sfinfo
.basic_info
.in
.attrib
= 0;
252 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_OK
);
253 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
254 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
255 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
256 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
257 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
259 printf("test basic_information level\n");
261 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
262 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
263 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
264 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
265 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
266 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
267 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
268 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
269 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
270 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
271 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
273 CHECK_CALL_PATH(BASIC_INFORMATION
, NT_STATUS_OK
);
274 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
275 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
276 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
277 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
278 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
280 printf("a zero time means don't change\n");
281 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
282 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
283 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
284 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
285 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
286 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
287 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
288 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
289 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
290 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
291 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
293 CHECK_CALL_PATH(BASIC_INFORMATION
, NT_STATUS_OK
);
294 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
295 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
296 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
298 /* interesting - w2k3 leaves change_time as current time for 0 change time
300 CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
302 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
304 printf("test disposition_info level\n");
305 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
306 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
307 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
308 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
310 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
311 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
312 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
313 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
315 printf("test disposition_information level\n");
316 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
317 CHECK_CALL_FNUM(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
318 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
319 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
321 /* this would delete the file! */
323 CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
324 CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
325 CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
328 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
329 CHECK_CALL_FNUM(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
330 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
331 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
333 CHECK_CALL_PATH(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
334 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
335 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
337 printf("test allocation_info level\n");
338 sfinfo
.allocation_info
.in
.alloc_size
= 0;
339 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
340 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
341 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
343 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
344 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
345 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
346 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
349 sfinfo
.allocation_info
.in
.alloc_size
= 0;
350 CHECK_CALL_FNUM(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
351 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
352 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
354 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
355 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
356 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
358 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
359 CHECK_CALL_FNUM(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
360 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
361 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
363 /* setting the allocation size up via setpathinfo seems
364 to be broken in w2k3 */
365 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
366 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
367 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
369 printf("test end_of_file_info level\n");
370 sfinfo
.end_of_file_info
.in
.size
= 37;
371 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
372 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
374 sfinfo
.end_of_file_info
.in
.size
= 7;
375 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
376 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
378 sfinfo
.end_of_file_info
.in
.size
= 37;
379 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
380 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
382 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
383 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
385 sfinfo
.end_of_file_info
.in
.size
= 7;
386 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
387 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
389 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
390 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
392 printf("test position_information level\n");
393 sfinfo
.position_information
.in
.position
= 123456;
394 CHECK_CALL_FNUM(POSITION_INFORMATION
, NT_STATUS_OK
);
395 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 123456);
397 CHECK_CALL_PATH(POSITION_INFORMATION
, NT_STATUS_OK
);
398 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 0);
400 printf("test mode_information level\n");
401 sfinfo
.mode_information
.in
.mode
= 2;
402 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
403 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 2);
405 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
406 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
408 sfinfo
.mode_information
.in
.mode
= 1;
409 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
410 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
412 sfinfo
.mode_information
.in
.mode
= 0;
413 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
414 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
416 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
417 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
420 printf("test unix_basic level\n");
421 CHECK_CALL_FNUM(UNIX_BASIC
, NT_STATUS_OK
);
422 CHECK_CALL_PATH(UNIX_BASIC
, NT_STATUS_OK
);
424 printf("test unix_link level\n");
425 CHECK_CALL_FNUM(UNIX_LINK
, NT_STATUS_OK
);
426 CHECK_CALL_PATH(UNIX_LINK
, NT_STATUS_OK
);
430 smb_raw_exit(cli
->session
);
431 smbcli_close(cli
->tree
, fnum
);
432 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, fnum_fname
))) {
433 printf("Failed to delete %s - %s\n", fnum_fname
, smbcli_errstr(cli
->tree
));
435 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, path_fname
))) {
436 printf("Failed to delete %s - %s\n", path_fname
, smbcli_errstr(cli
->tree
));
443 * basic testing of all RAW_SFILEINFO_RENAME call
446 torture_raw_sfileinfo_rename(struct torture_context
*torture
,
447 struct smbcli_state
*cli
)
450 int fnum_saved
, d_fnum
, fnum2
, fnum
= -1;
452 char *fnum_fname_new
;
454 char *path_fname_new
;
456 char *path_dname_new
;
458 char *saved_name_new
;
459 union smb_fileinfo finfo1
, finfo2
;
460 union smb_setfileinfo sfinfo
;
461 NTSTATUS status
, status2
;
462 const char *call_name
;
464 int n
= time(NULL
) % 100;
466 asprintf(&path_fname
, BASEDIR
"\\fname_test_%d.txt", n
);
467 asprintf(&path_fname_new
, BASEDIR
"\\fname_test_new_%d.txt", n
);
468 asprintf(&fnum_fname
, BASEDIR
"\\fnum_test_%d.txt", n
);
469 asprintf(&fnum_fname_new
, BASEDIR
"\\fnum_test_new_%d.txt", n
);
470 asprintf(&path_dname
, BASEDIR
"\\dname_test_%d", n
);
471 asprintf(&path_dname_new
, BASEDIR
"\\dname_test_new_%d", n
);
473 if (!torture_setup_dir(cli
, BASEDIR
)) {
481 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, fnum_fname_new
));
482 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, path_fname_new
));
484 sfinfo
.rename_information
.in
.overwrite
= 0;
485 sfinfo
.rename_information
.in
.root_fid
= 0;
486 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
487 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
489 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
490 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
492 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
;
493 sfinfo
.rename_information
.in
.overwrite
= 1;
494 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_NOT_SUPPORTED
);
496 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
497 sfinfo
.rename_information
.in
.overwrite
= 1;
498 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
499 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
501 printf("Trying rename with dest file open\n");
502 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
503 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
504 sfinfo
.rename_information
.in
.overwrite
= 1;
505 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_ACCESS_DENIED
);
506 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
510 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
511 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
514 printf("Trying rename with dest file open and delete_on_close\n");
515 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
516 sfinfo
.rename_information
.in
.overwrite
= 1;
517 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_ACCESS_DENIED
);
519 smbcli_close(cli
->tree
, fnum2
);
520 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
521 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
523 printf("Trying rename with source file open twice\n");
524 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
525 sfinfo
.rename_information
.in
.overwrite
= 1;
526 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
527 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
529 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
530 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
531 sfinfo
.rename_information
.in
.overwrite
= 0;
532 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
533 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
534 smbcli_close(cli
->tree
, fnum2
);
536 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
537 sfinfo
.rename_information
.in
.overwrite
= 0;
538 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
539 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
541 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
542 sfinfo
.rename_information
.in
.overwrite
= 1;
543 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
544 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
546 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
547 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
548 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
550 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
551 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
552 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
554 printf("Trying rename with a root fid\n");
555 status
= create_directory_handle(cli
->tree
, BASEDIR
, &d_fnum
);
556 CHECK_STATUS(status
, NT_STATUS_OK
);
557 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
558 sfinfo
.rename_information
.in
.root_fid
= d_fnum
;
559 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
560 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
561 smbcli_close(cli
->tree
, d_fnum
);
563 printf("Trying rename directory\n");
564 if (!torture_setup_dir(cli
, path_dname
)) {
568 saved_name
= path_fname
;
569 saved_name_new
= path_fname_new
;
570 path_fname
= path_dname
;
571 path_fname_new
= path_dname_new
;
572 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
573 sfinfo
.rename_information
.in
.overwrite
= 0;
574 sfinfo
.rename_information
.in
.root_fid
= 0;
575 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
576 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
577 path_fname
= saved_name
;
578 path_fname_new
= saved_name_new
;
580 if (torture_setting_bool(torture
, "samba3", false)) {
581 printf("SKIP: Trying rename directory with a handle\n");
582 printf("SKIP: Trying rename by path while a handle is open\n");
583 printf("SKIP: Trying rename directory by path while a handle is open\n");
587 printf("Trying rename directory with a handle\n");
588 status
= create_directory_handle(cli
->tree
, path_dname_new
, &d_fnum
);
591 saved_name
= fnum_fname
;
592 saved_name_new
= fnum_fname_new
;
593 fnum_fname
= path_dname
;
594 fnum_fname_new
= path_dname_new
;
595 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
596 sfinfo
.rename_information
.in
.overwrite
= 0;
597 sfinfo
.rename_information
.in
.root_fid
= 0;
598 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
599 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
600 smbcli_close(cli
->tree
, d_fnum
);
602 fnum_fname
= saved_name
;
603 fnum_fname_new
= saved_name_new
;
605 printf("Trying rename by path while a handle is open\n");
607 fnum
= create_complex_file(cli
, torture
, path_fname
);
608 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
609 sfinfo
.rename_information
.in
.overwrite
= 0;
610 sfinfo
.rename_information
.in
.root_fid
= 0;
611 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
612 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
613 /* check that the handle returns the same name */
615 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
616 /* rename it back on the handle */
617 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
618 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
619 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
621 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
622 smbcli_close(cli
->tree
, fnum
);
625 printf("Trying rename directory by path while a handle is open\n");
626 status
= create_directory_handle(cli
->tree
, path_dname
, &d_fnum
);
629 saved_name
= path_fname
;
630 saved_name_new
= path_fname_new
;
631 path_fname
= path_dname
;
632 path_fname_new
= path_dname_new
;
633 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
634 sfinfo
.rename_information
.in
.overwrite
= 0;
635 sfinfo
.rename_information
.in
.root_fid
= 0;
636 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
637 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
638 path_fname
= saved_name
;
639 path_fname_new
= saved_name_new
;
640 saved_name
= fnum_fname
;
641 saved_name_new
= fnum_fname_new
;
642 fnum_fname
= path_dname
;
643 fnum_fname_new
= path_dname_new
;
644 /* check that the handle returns the same name */
646 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
647 /* rename it back on the handle */
648 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
649 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
650 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
651 fnum_fname
= saved_name
;
652 fnum_fname_new
= saved_name_new
;
653 saved_name
= path_fname
;
654 saved_name_new
= path_fname_new
;
655 path_fname
= path_dname
;
656 path_fname_new
= path_dname_new
;
658 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
659 smbcli_close(cli
->tree
, d_fnum
);
661 path_fname
= saved_name
;
662 path_fname_new
= saved_name_new
;
665 smb_raw_exit(cli
->session
);
666 smbcli_deltree(cli
->tree
, BASEDIR
);
671 look for the w2k3 setpathinfo STANDARD bug
673 static bool torture_raw_sfileinfo_bug(struct torture_context
*torture
,
674 struct smbcli_state
*cli
)
676 const char *fname
= "\\bug3.txt";
677 union smb_setfileinfo sfinfo
;
681 if (!torture_setting_bool(torture
, "dangerous", false))
682 torture_skip(torture
,
683 "torture_raw_sfileinfo_bug disabled - enable dangerous tests to use\n");
685 fnum
= create_complex_file(cli
, torture
, fname
);
686 smbcli_close(cli
->tree
, fnum
);
688 sfinfo
.generic
.level
= RAW_SFILEINFO_STANDARD
;
689 sfinfo
.generic
.in
.file
.path
= fname
;
691 sfinfo
.standard
.in
.create_time
= 0;
692 sfinfo
.standard
.in
.access_time
= 0;
693 sfinfo
.standard
.in
.write_time
= 0;
695 status
= smb_raw_setpathinfo(cli
->tree
, &sfinfo
);
696 printf("%s - %s\n", fname
, nt_errstr(status
));
698 printf("now try and delete %s\n", fname
);
704 torture_raw_sfileinfo_eof(struct torture_context
*tctx
, struct smbcli_state
*cli1
,
705 struct smbcli_state
*cli2
)
707 const char *fname
= BASEDIR
"\\test_sfileinfo_end_of_file.dat";
711 union smb_setfileinfo sfi
;
712 union smb_fileinfo qfi
;
715 if (!torture_setup_dir(cli1
, BASEDIR
)) {
720 smbcli_unlink(cli1
->tree
, fname
);
722 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
723 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
724 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
725 io
.ntcreatex
.in
.alloc_size
= 0;
726 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
727 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
728 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
729 io
.ntcreatex
.in
.create_options
= 0;
730 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
731 io
.ntcreatex
.in
.security_flags
= 0;
732 io
.ntcreatex
.in
.fname
= fname
;
733 io
.ntcreatex
.in
.flags
= 0;
735 /* Open the file sharing none. */
736 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
737 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
738 done
, "Status should be OK");
739 fnum
= io
.ntcreatex
.out
.file
.fnum
;
741 /* Try to sfileinfo to extend the file. */
743 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
744 sfi
.generic
.in
.file
.path
= fname
;
745 sfi
.end_of_file_info
.in
.size
= 100;
746 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
748 /* There should be share mode contention in this case. */
749 torture_assert_ntstatus_equal_goto(tctx
, status
,
750 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
751 "SHARING_VIOLATION");
753 /* Make sure the size is still 0. */
755 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
756 qfi
.generic
.in
.file
.path
= fname
;
757 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
758 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
759 done
, "Status should be OK");
761 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 0,
762 "alloc_size should be 0 since the setpathinfo failed.");
764 /* Try again with the pass through instead of documented version. */
766 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
767 sfi
.generic
.in
.file
.path
= fname
;
768 sfi
.end_of_file_info
.in
.size
= 100;
769 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
772 * Looks like a windows bug:
773 * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html
775 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
776 /* It succeeds! This is just weird! */
777 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
778 done
, "Status should be OK");
780 torture_assert_ntstatus_equal_goto(tctx
, status
,
781 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
782 "SHARING_VIOLATION");
786 /* Verify that the file was actually extended to 100. */
788 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
789 qfi
.generic
.in
.file
.path
= fname
;
790 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
791 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
792 done
, "Status should be OK");
794 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 100,
795 "alloc_size should be 100 since the setpathinfo succeeded.");
798 * Try another open with just write to mimic what setpathinfo should
799 * be doing under the covers.
801 io
.ntcreatex
.in
.access_mask
= SEC_FILE_WRITE_DATA
;
802 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
803 torture_assert_ntstatus_equal_goto(tctx
, status
,
804 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
805 "SHARING_VIOLATION");
807 smbcli_close(cli1
->tree
, fnum
);
810 smb_raw_exit(cli1
->session
);
811 smb_raw_exit(cli2
->session
);
812 smbcli_deltree(cli1
->tree
, BASEDIR
);
817 torture_raw_sfileinfo_eof_access(struct torture_context
*tctx
,
818 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
820 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
821 NTSTATUS status
, expected_status
;
824 union smb_setfileinfo sfi
;
826 uint32_t access_mask
= 0;
828 if (!torture_setup_dir(cli1
, BASEDIR
)) {
833 smbcli_unlink(cli1
->tree
, fname
);
836 * base ntcreatex parms
838 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
839 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
840 io
.ntcreatex
.in
.alloc_size
= 0;
841 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
842 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
843 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
844 io
.ntcreatex
.in
.create_options
= 0;
845 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
846 io
.ntcreatex
.in
.security_flags
= 0;
847 io
.ntcreatex
.in
.fname
= fname
;
848 io
.ntcreatex
.in
.flags
= 0;
851 for (access_mask
= 1; access_mask
<= 0x00001FF; access_mask
++) {
852 io
.ntcreatex
.in
.access_mask
= access_mask
;
854 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
855 if (!NT_STATUS_IS_OK(status
)) {
859 fnum
= io
.ntcreatex
.out
.file
.fnum
;
862 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
863 sfi
.generic
.in
.file
.fnum
= fnum
;
864 sfi
.end_of_file_info
.in
.size
= 100;
866 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
868 expected_status
= (access_mask
& SEC_FILE_WRITE_DATA
) ?
869 NT_STATUS_OK
: NT_STATUS_ACCESS_DENIED
;
871 if (!NT_STATUS_EQUAL(expected_status
, status
)) {
872 torture_comment(tctx
, "0x%x wrong\n", access_mask
);
875 torture_assert_ntstatus_equal_goto(tctx
, status
,
876 expected_status
, ret
, done
, "Status Wrong");
878 smbcli_close(cli1
->tree
, fnum
);
882 smb_raw_exit(cli1
->session
);
883 smb_raw_exit(cli2
->session
);
884 smbcli_deltree(cli1
->tree
, BASEDIR
);
888 struct torture_suite
*torture_raw_sfileinfo(TALLOC_CTX
*mem_ctx
)
890 struct torture_suite
*suite
= torture_suite_create(mem_ctx
,
893 torture_suite_add_1smb_test(suite
, "BASE", torture_raw_sfileinfo_base
);
894 torture_suite_add_1smb_test(suite
, "RENAME",
895 torture_raw_sfileinfo_rename
);
896 torture_suite_add_1smb_test(suite
, "BUG", torture_raw_sfileinfo_bug
);
897 torture_suite_add_2smb_test(suite
, "END-OF-FILE",
898 torture_raw_sfileinfo_eof
);
899 torture_suite_add_2smb_test(suite
, "END-OF-FILE-ACCESS",
900 torture_raw_sfileinfo_eof_access
);