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"
25 #include "torture/raw/proto.h"
27 #define BASEDIR "\\testsfileinfo"
29 /* basic testing of all RAW_SFILEINFO_* calls
30 for each call we test that it succeeds, and where possible test
31 for consistency between the calls.
34 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 path_fname
= talloc_asprintf(torture
, BASEDIR
"\\fname_test_%d.txt", n
);
50 path_fname_new
= talloc_asprintf(torture
, BASEDIR
"\\fname_test_new_%d.txt", n
);
51 fnum_fname
= talloc_asprintf(torture
, BASEDIR
"\\fnum_test_%d.txt", n
);
53 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
55 #define RECREATE_FILE(fname) do { \
56 if (fnum != -1) smbcli_close(cli->tree, fnum); \
57 fnum = create_complex_file(cli, torture, fname); \
59 printf("(%s) ERROR: open of %s failed (%s)\n", \
60 __location__, fname, smbcli_errstr(cli->tree)); \
65 #define RECREATE_BOTH do { \
66 RECREATE_FILE(path_fname); \
67 smbcli_close(cli->tree, fnum); \
68 RECREATE_FILE(fnum_fname); \
73 #define CHECK_CALL_FNUM(call, rightstatus) do { \
76 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
77 sfinfo.generic.in.file.fnum = fnum; \
78 status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
79 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
80 torture_warning(torture, \
81 "(%s) %s - %s", __location__, #call, \
83 } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
84 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
85 nt_errstr(status), nt_errstr(rightstatus)); \
88 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
89 finfo1.generic.in.file.fnum = fnum; \
90 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
91 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
92 torture_warning(torture, \
93 "(%s) %s - %s", __location__, #call, \
95 } else if (!NT_STATUS_IS_OK(status2)) { \
96 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
100 #define CHECK_CALL_PATH(call, rightstatus) do { \
101 check_fnum = false; \
103 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
104 sfinfo.generic.in.file.path = path_fname; \
105 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
106 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
107 sfinfo.generic.in.file.path = path_fname_new; \
108 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
110 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
111 torture_warning(torture, \
112 "(%s) %s - %s", __location__, #call, \
113 nt_errstr(status)); \
114 } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
115 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
116 nt_errstr(status), nt_errstr(rightstatus)); \
119 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
120 finfo1.generic.in.file.path = path_fname; \
121 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
122 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
123 finfo1.generic.in.file.path = path_fname_new; \
124 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
126 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
127 torture_warning(torture, \
128 "(%s) %s - %s", __location__, #call, \
129 nt_errstr(status)); \
130 } else if (!NT_STATUS_IS_OK(status2)) { \
131 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \
135 #define CHECK1(call) \
136 do { if (NT_STATUS_IS_OK(status)) { \
137 finfo2.generic.level = RAW_FILEINFO_ ## call; \
139 finfo2.generic.in.file.fnum = fnum; \
140 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
142 finfo2.generic.in.file.path = path_fname; \
143 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
144 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
145 finfo2.generic.in.file.path = path_fname_new; \
146 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
149 if (!NT_STATUS_IS_OK(status2)) { \
150 printf("%s - %s\n", #call, nt_errstr(status2)); \
155 #define CHECK_VALUE(call, stype, field, value) do { \
157 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
158 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
159 call_name, #stype, #field, \
160 (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
161 dump_all_info(torture, &finfo1); \
165 #define CHECK_TIME(call, stype, field, value) do { \
167 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
168 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
169 call_name, #stype, #field, \
170 (unsigned int)value, \
171 (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
172 printf("\t%s", timestring(torture, value)); \
173 printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
174 dump_all_info(torture, &finfo1); \
178 #define CHECK_STR(call, stype, field, value) do { \
180 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
181 printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
182 call_name, #stype, #field, \
184 finfo2.stype.out.field); \
185 dump_all_info(torture, &finfo1); \
189 #define CHECK_STATUS(status, correct) do { \
190 if (!NT_STATUS_EQUAL(status, correct)) { \
191 printf("(%s) Incorrect status %s - should be %s\n", \
192 __location__, nt_errstr(status), nt_errstr(correct)); \
198 printf("Test setattr\n");
199 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
200 sfinfo
.setattr
.in
.write_time
= basetime
;
201 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
202 CHECK_VALUE (ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
203 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
205 printf("setting to NORMAL doesn't do anything\n");
206 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
207 sfinfo
.setattr
.in
.write_time
= 0;
208 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
209 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
210 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
212 printf("a zero write_time means don't change\n");
213 sfinfo
.setattr
.in
.attrib
= 0;
214 sfinfo
.setattr
.in
.write_time
= 0;
215 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
216 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
217 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
219 printf("Test setattre\n");
220 sfinfo
.setattre
.in
.create_time
= basetime
+ 20;
221 sfinfo
.setattre
.in
.access_time
= basetime
+ 30;
222 sfinfo
.setattre
.in
.write_time
= basetime
+ 40;
223 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
224 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
225 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
226 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
228 sfinfo
.setattre
.in
.create_time
= 0;
229 sfinfo
.setattre
.in
.access_time
= 0;
230 sfinfo
.setattre
.in
.write_time
= 0;
231 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
232 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
233 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
234 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
236 printf("Test standard level\n");
237 sfinfo
.standard
.in
.create_time
= basetime
+ 100;
238 sfinfo
.standard
.in
.access_time
= basetime
+ 200;
239 sfinfo
.standard
.in
.write_time
= basetime
+ 300;
240 CHECK_CALL_FNUM(STANDARD
, NT_STATUS_OK
);
241 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
242 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
243 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
245 printf("Test basic_info level\n");
247 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
248 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
249 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
250 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
251 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
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("a zero time means don't change\n");
260 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
261 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
262 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
263 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
264 sfinfo
.basic_info
.in
.attrib
= 0;
265 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_OK
);
266 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
267 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
268 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
269 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
270 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
272 printf("Test basic_information level\n");
274 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
275 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
276 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
277 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
278 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
279 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
280 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
281 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
282 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
283 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
284 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
286 CHECK_CALL_PATH(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 torture_comment(torture
, "try to change a file to a directory\n");
294 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
;
295 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_INVALID_PARAMETER
);
297 printf("a zero time means don't change\n");
298 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
299 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
300 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
301 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
302 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
303 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
304 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
305 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
306 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
307 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
308 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
310 CHECK_CALL_PATH(BASIC_INFORMATION
, NT_STATUS_OK
);
311 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
312 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
313 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
315 /* interesting - w2k3 leaves change_time as current time for 0 change time
317 CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
319 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
321 printf("Test disposition_info level\n");
322 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
323 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
324 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
325 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
327 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
328 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
329 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
330 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
332 printf("Test disposition_information level\n");
333 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
334 CHECK_CALL_FNUM(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
335 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
336 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
338 /* this would delete the file! */
340 CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
341 CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
342 CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
345 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
346 CHECK_CALL_FNUM(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
347 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
348 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
350 CHECK_CALL_PATH(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
351 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
352 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
354 printf("Test allocation_info level\n");
355 sfinfo
.allocation_info
.in
.alloc_size
= 0;
356 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
357 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
358 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
360 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
361 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
362 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
363 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
366 sfinfo
.allocation_info
.in
.alloc_size
= 0;
367 CHECK_CALL_FNUM(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
368 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
369 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
371 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
372 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
373 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
375 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
376 CHECK_CALL_FNUM(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
377 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
378 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
380 /* setting the allocation size up via setpathinfo seems
381 to be broken in w2k3 */
382 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
383 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
384 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
386 printf("Test end_of_file_info level\n");
387 sfinfo
.end_of_file_info
.in
.size
= 37;
388 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
389 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
391 sfinfo
.end_of_file_info
.in
.size
= 7;
392 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
393 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
395 sfinfo
.end_of_file_info
.in
.size
= 37;
396 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
397 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
399 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
400 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
402 sfinfo
.end_of_file_info
.in
.size
= 7;
403 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
404 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
406 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
407 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
409 printf("Test position_information level\n");
410 sfinfo
.position_information
.in
.position
= 123456;
411 CHECK_CALL_FNUM(POSITION_INFORMATION
, NT_STATUS_OK
);
412 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 123456);
414 CHECK_CALL_PATH(POSITION_INFORMATION
, NT_STATUS_OK
);
415 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 0);
417 printf("Test mode_information level\n");
418 sfinfo
.mode_information
.in
.mode
= 2;
419 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
420 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 2);
422 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
423 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
425 sfinfo
.mode_information
.in
.mode
= 1;
426 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
427 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
429 sfinfo
.mode_information
.in
.mode
= 0;
430 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
431 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
433 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
434 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
437 printf("Test unix_basic level\n");
438 CHECK_CALL_FNUM(UNIX_BASIC
, NT_STATUS_OK
);
439 CHECK_CALL_PATH(UNIX_BASIC
, NT_STATUS_OK
);
441 printf("Test unix_link level\n");
442 CHECK_CALL_FNUM(UNIX_LINK
, NT_STATUS_OK
);
443 CHECK_CALL_PATH(UNIX_LINK
, NT_STATUS_OK
);
447 smb_raw_exit(cli
->session
);
448 smbcli_close(cli
->tree
, fnum
);
449 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, fnum_fname
))) {
450 printf("Failed to delete %s - %s\n", fnum_fname
, smbcli_errstr(cli
->tree
));
452 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, path_fname
))) {
453 printf("Failed to delete %s - %s\n", path_fname
, smbcli_errstr(cli
->tree
));
460 * basic testing of all RAW_SFILEINFO_RENAME call
463 torture_raw_sfileinfo_rename(struct torture_context
*torture
,
464 struct smbcli_state
*cli
)
467 int fnum_saved
, d_fnum
, fnum2
, fnum
= -1;
469 char *fnum_fname_new
;
471 char *path_fname_new
;
473 char *path_dname_new
;
475 char *saved_name_new
;
476 union smb_fileinfo finfo1
, finfo2
;
477 union smb_setfileinfo sfinfo
;
478 NTSTATUS status
, status2
;
479 const char *call_name
;
481 int n
= time(NULL
) % 100;
483 path_fname
= talloc_asprintf(torture
, BASEDIR
"\\fname_test_%d.txt", n
);
484 path_fname_new
= talloc_asprintf(torture
, BASEDIR
"\\fname_test_new_%d.txt", n
);
485 fnum_fname
= talloc_asprintf(torture
, BASEDIR
"\\fnum_test_%d.txt", n
);
486 fnum_fname_new
= talloc_asprintf(torture
, BASEDIR
"\\fnum_test_new_%d.txt", n
);
487 path_dname
= talloc_asprintf(torture
, BASEDIR
"\\dname_test_%d", n
);
488 path_dname_new
= talloc_asprintf(torture
, BASEDIR
"\\dname_test_new_%d", n
);
490 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
496 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, fnum_fname_new
));
497 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, path_fname_new
));
499 sfinfo
.rename_information
.in
.overwrite
= 0;
500 sfinfo
.rename_information
.in
.root_fid
= 0;
501 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
502 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
504 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
505 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
507 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
;
508 sfinfo
.rename_information
.in
.overwrite
= 1;
509 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_NOT_SUPPORTED
);
511 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
512 sfinfo
.rename_information
.in
.overwrite
= 1;
513 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
514 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
516 printf("Trying rename with dest file open\n");
517 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
518 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
519 sfinfo
.rename_information
.in
.overwrite
= 1;
520 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_ACCESS_DENIED
);
521 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
525 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
526 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
529 printf("Trying rename with dest file open and delete_on_close\n");
530 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
531 sfinfo
.rename_information
.in
.overwrite
= 1;
532 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_ACCESS_DENIED
);
534 smbcli_close(cli
->tree
, fnum2
);
535 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
536 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
538 printf("Trying rename with source file open twice\n");
539 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
540 sfinfo
.rename_information
.in
.overwrite
= 1;
541 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
542 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
544 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
545 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
546 sfinfo
.rename_information
.in
.overwrite
= 0;
547 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
548 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
549 smbcli_close(cli
->tree
, fnum2
);
551 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
552 sfinfo
.rename_information
.in
.overwrite
= 0;
553 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
554 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
556 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
557 sfinfo
.rename_information
.in
.overwrite
= 1;
558 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
559 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
561 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
562 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
563 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
565 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
566 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
567 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
569 printf("Trying rename with a root fid\n");
570 status
= create_directory_handle(cli
->tree
, BASEDIR
, &d_fnum
);
571 CHECK_STATUS(status
, NT_STATUS_OK
);
572 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
573 sfinfo
.rename_information
.in
.root_fid
= d_fnum
;
574 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
575 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
576 smbcli_close(cli
->tree
, d_fnum
);
578 printf("Trying rename directory\n");
579 if (!torture_setup_dir(cli
, path_dname
)) {
583 saved_name
= path_fname
;
584 saved_name_new
= path_fname_new
;
585 path_fname
= path_dname
;
586 path_fname_new
= path_dname_new
;
587 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
588 sfinfo
.rename_information
.in
.overwrite
= 0;
589 sfinfo
.rename_information
.in
.root_fid
= 0;
590 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
591 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
592 path_fname
= saved_name
;
593 path_fname_new
= saved_name_new
;
595 if (torture_setting_bool(torture
, "samba3", false)) {
596 printf("SKIP: Trying rename directory with a handle\n");
597 printf("SKIP: Trying rename by path while a handle is open\n");
598 printf("SKIP: Trying rename directory by path while a handle is open\n");
602 printf("Trying rename directory with a handle\n");
603 status
= create_directory_handle(cli
->tree
, path_dname_new
, &d_fnum
);
606 saved_name
= fnum_fname
;
607 saved_name_new
= fnum_fname_new
;
608 fnum_fname
= path_dname
;
609 fnum_fname_new
= path_dname_new
;
610 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
611 sfinfo
.rename_information
.in
.overwrite
= 0;
612 sfinfo
.rename_information
.in
.root_fid
= 0;
613 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
614 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
615 smbcli_close(cli
->tree
, d_fnum
);
617 fnum_fname
= saved_name
;
618 fnum_fname_new
= saved_name_new
;
620 printf("Trying rename by path while a handle is open\n");
622 fnum
= create_complex_file(cli
, torture
, path_fname
);
623 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
624 sfinfo
.rename_information
.in
.overwrite
= 0;
625 sfinfo
.rename_information
.in
.root_fid
= 0;
626 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
627 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
628 /* check that the handle returns the same name */
630 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
631 /* rename it back on the handle */
632 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
633 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
634 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
636 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
637 smbcli_close(cli
->tree
, fnum
);
640 printf("Trying rename directory by path while a handle is open\n");
641 status
= create_directory_handle(cli
->tree
, path_dname
, &d_fnum
);
644 saved_name
= path_fname
;
645 saved_name_new
= path_fname_new
;
646 path_fname
= path_dname
;
647 path_fname_new
= path_dname_new
;
648 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
649 sfinfo
.rename_information
.in
.overwrite
= 0;
650 sfinfo
.rename_information
.in
.root_fid
= 0;
651 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
652 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
653 path_fname
= saved_name
;
654 path_fname_new
= saved_name_new
;
655 saved_name
= fnum_fname
;
656 saved_name_new
= fnum_fname_new
;
657 fnum_fname
= path_dname
;
658 fnum_fname_new
= path_dname_new
;
659 /* check that the handle returns the same name */
661 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
662 /* rename it back on the handle */
663 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
664 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
665 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
666 fnum_fname
= saved_name
;
667 fnum_fname_new
= saved_name_new
;
668 saved_name
= path_fname
;
669 saved_name_new
= path_fname_new
;
670 path_fname
= path_dname
;
671 path_fname_new
= path_dname_new
;
673 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
674 smbcli_close(cli
->tree
, d_fnum
);
676 path_fname
= saved_name
;
677 path_fname_new
= saved_name_new
;
680 smb_raw_exit(cli
->session
);
681 smbcli_deltree(cli
->tree
, BASEDIR
);
686 look for the w2k3 setpathinfo STANDARD bug
688 static bool torture_raw_sfileinfo_bug(struct torture_context
*torture
,
689 struct smbcli_state
*cli
)
691 const char *fname
= "\\bug3.txt";
692 union smb_setfileinfo sfinfo
;
696 if (!torture_setting_bool(torture
, "dangerous", false))
697 torture_skip(torture
,
698 "torture_raw_sfileinfo_bug disabled - enable dangerous tests to use\n");
700 fnum
= create_complex_file(cli
, torture
, fname
);
701 smbcli_close(cli
->tree
, fnum
);
703 sfinfo
.generic
.level
= RAW_SFILEINFO_STANDARD
;
704 sfinfo
.generic
.in
.file
.path
= fname
;
706 sfinfo
.standard
.in
.create_time
= 0;
707 sfinfo
.standard
.in
.access_time
= 0;
708 sfinfo
.standard
.in
.write_time
= 0;
710 status
= smb_raw_setpathinfo(cli
->tree
, &sfinfo
);
711 printf("%s - %s\n", fname
, nt_errstr(status
));
713 printf("now try and delete %s\n", fname
);
719 * Test both the snia cifs RAW_SFILEINFO_END_OF_FILE_INFO and the undocumented
720 * pass-through RAW_SFILEINFO_END_OF_FILE_INFORMATION in the context of
724 torture_raw_sfileinfo_eof(struct torture_context
*tctx
,
725 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
727 const char *fname
= BASEDIR
"\\test_sfileinfo_end_of_file.dat";
731 union smb_setfileinfo sfi
;
732 union smb_fileinfo qfi
;
735 if (!torture_setup_dir(cli1
, BASEDIR
)) {
740 smbcli_unlink(cli1
->tree
, fname
);
742 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
743 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
744 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
745 io
.ntcreatex
.in
.alloc_size
= 0;
746 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
747 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
748 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
749 io
.ntcreatex
.in
.create_options
= 0;
750 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
751 io
.ntcreatex
.in
.security_flags
= 0;
752 io
.ntcreatex
.in
.fname
= fname
;
753 io
.ntcreatex
.in
.flags
= 0;
755 /* Open the file sharing none. */
756 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
757 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
758 done
, "Status should be OK");
759 fnum
= io
.ntcreatex
.out
.file
.fnum
;
761 /* Try to sfileinfo to extend the file. */
763 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
764 sfi
.generic
.in
.file
.path
= fname
;
765 sfi
.end_of_file_info
.in
.size
= 100;
766 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
768 /* There should be share mode contention in this case. */
769 torture_assert_ntstatus_equal_goto(tctx
, status
,
770 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
771 "SHARING_VIOLATION");
773 /* Make sure the size is still 0. */
775 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
776 qfi
.generic
.in
.file
.path
= fname
;
777 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
778 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
779 done
, "Status should be OK");
781 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 0,
782 "alloc_size should be 0 since the setpathinfo failed.");
784 /* Try again with the pass through instead of documented version. */
786 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
787 sfi
.generic
.in
.file
.path
= fname
;
788 sfi
.end_of_file_info
.in
.size
= 100;
789 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
792 * Looks like a windows bug:
793 * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html
795 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
796 /* It succeeds! This is just weird! */
797 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
798 ret
, done
, "Status should be OK");
800 /* Verify that the file was actually extended to 100. */
802 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
803 qfi
.generic
.in
.file
.path
= fname
;
804 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
805 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
806 ret
, done
, "Status should be OK");
808 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 100,
809 "alloc_size should be 100 since the setpathinfo "
812 torture_assert_ntstatus_equal_goto(tctx
, status
,
813 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
814 "SHARING_VIOLATION");
817 /* close the first file. */
818 smbcli_close(cli1
->tree
, fnum
);
821 /* Try to sfileinfo to extend the file again (non-pass-through). */
823 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
824 sfi
.generic
.in
.file
.path
= fname
;
825 sfi
.end_of_file_info
.in
.size
= 200;
826 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
828 /* This should cause the client to retun invalid level. */
829 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
831 * Windows sends back an invalid packet that smbclient sees
832 * and returns INTERNAL_ERROR.
834 torture_assert_ntstatus_equal_goto(tctx
, status
,
835 NT_STATUS_INTERNAL_ERROR
, ret
, done
, "Status should be "
838 torture_assert_ntstatus_equal_goto(tctx
, status
,
839 NT_STATUS_INVALID_LEVEL
, ret
, done
, "Status should be "
843 /* Try to extend the file now with the passthrough level. */
844 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
845 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
846 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
847 done
, "Status should be OK");
849 /* Verify that the file was actually extended to 200. */
851 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
852 qfi
.generic
.in
.file
.path
= fname
;
853 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
855 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
856 done
, "Status should be OK");
857 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 200,
858 "alloc_size should be 200 since the setpathinfo succeeded.");
860 /* Open the file so end of file can be set by handle. */
861 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_WRITE
;
862 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
863 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
864 done
, "Status should be OK");
865 fnum
= io
.ntcreatex
.out
.file
.fnum
;
867 /* Try sfileinfo to extend the file by handle (non-pass-through). */
869 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
870 sfi
.generic
.in
.file
.fnum
= fnum
;
871 sfi
.end_of_file_info
.in
.size
= 300;
872 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
873 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
874 done
, "Status should be OK");
876 /* Verify that the file was actually extended to 300. */
878 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
879 qfi
.generic
.in
.file
.path
= fname
;
880 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qfi
);
881 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
882 done
, "Status should be OK");
883 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 300,
884 "alloc_size should be 300 since the setpathinfo succeeded.");
886 /* Try sfileinfo to extend the file by handle (pass-through). */
888 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
889 sfi
.generic
.in
.file
.fnum
= fnum
;
890 sfi
.end_of_file_info
.in
.size
= 400;
891 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
892 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
893 done
, "Status should be OK");
895 /* Verify that the file was actually extended to 300. */
897 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
898 qfi
.generic
.in
.file
.path
= fname
;
899 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qfi
);
900 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
901 done
, "Status should be OK");
902 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 400,
903 "alloc_size should be 400 since the setpathinfo succeeded.");
906 smbcli_close(cli1
->tree
, fnum
);
910 smb_raw_exit(cli1
->session
);
911 smb_raw_exit(cli2
->session
);
912 smbcli_deltree(cli1
->tree
, BASEDIR
);
917 torture_raw_sfileinfo_eof_access(struct torture_context
*tctx
,
918 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
920 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
921 NTSTATUS status
, expected_status
;
924 union smb_setfileinfo sfi
;
926 uint32_t access_mask
= 0;
928 if (!torture_setup_dir(cli1
, BASEDIR
)) {
933 smbcli_unlink(cli1
->tree
, fname
);
936 * base ntcreatex parms
938 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
939 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
940 io
.ntcreatex
.in
.alloc_size
= 0;
941 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
942 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
943 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
944 io
.ntcreatex
.in
.create_options
= 0;
945 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
946 io
.ntcreatex
.in
.security_flags
= 0;
947 io
.ntcreatex
.in
.fname
= fname
;
948 io
.ntcreatex
.in
.flags
= 0;
951 for (access_mask
= 1; access_mask
<= 0x00001FF; access_mask
++) {
952 io
.ntcreatex
.in
.access_mask
= access_mask
;
954 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
955 if (!NT_STATUS_IS_OK(status
)) {
959 fnum
= io
.ntcreatex
.out
.file
.fnum
;
962 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
963 sfi
.generic
.in
.file
.fnum
= fnum
;
964 sfi
.end_of_file_info
.in
.size
= 100;
966 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
968 expected_status
= (access_mask
& SEC_FILE_WRITE_DATA
) ?
969 NT_STATUS_OK
: NT_STATUS_ACCESS_DENIED
;
971 if (!NT_STATUS_EQUAL(expected_status
, status
)) {
972 torture_comment(tctx
, "0x%x wrong\n", access_mask
);
975 torture_assert_ntstatus_equal_goto(tctx
, status
,
976 expected_status
, ret
, done
, "Status Wrong");
978 smbcli_close(cli1
->tree
, fnum
);
982 smb_raw_exit(cli1
->session
);
983 smb_raw_exit(cli2
->session
);
984 smbcli_deltree(cli1
->tree
, BASEDIR
);
989 torture_raw_sfileinfo_archive(struct torture_context
*tctx
,
990 struct smbcli_state
*cli
)
992 const char *fname
= BASEDIR
"\\test_archive.dat";
996 union smb_setfileinfo sfinfo
;
997 union smb_fileinfo finfo
;
1000 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
1003 smbcli_unlink(cli
->tree
, fname
);
1006 * create a normal file, verify archive bit
1008 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1009 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1010 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1011 io
.ntcreatex
.in
.alloc_size
= 0;
1012 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1013 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1014 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1015 io
.ntcreatex
.in
.create_options
= 0;
1016 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1017 io
.ntcreatex
.in
.security_flags
= 0;
1018 io
.ntcreatex
.in
.fname
= fname
;
1019 io
.ntcreatex
.in
.flags
= 0;
1020 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1021 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1022 ret
, done
, "open failed");
1023 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1025 torture_assert_int_equal(tctx
,
1026 io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1027 FILE_ATTRIBUTE_ARCHIVE
,
1028 "archive bit not set");
1031 * try to turn off archive bit
1033 ZERO_STRUCT(sfinfo
);
1034 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1035 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1036 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
1037 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1038 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1039 ret
, done
, "setfileinfo failed");
1041 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1042 finfo
.generic
.in
.file
.fnum
= fnum
;
1043 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1044 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1045 ret
, done
, "fileinfo failed");
1047 torture_assert_int_equal(tctx
,
1048 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1049 FILE_ATTRIBUTE_NORMAL
,
1052 status
= smbcli_close(cli
->tree
, fnum
);
1053 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1054 ret
, done
, "close failed");
1056 status
= smbcli_unlink(cli
->tree
, fname
);
1057 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1058 ret
, done
, "unlink failed");
1061 * create a directory, verify no archive bit
1063 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1064 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1065 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_DIR_ALL
;
1066 io
.ntcreatex
.in
.alloc_size
= 0;
1067 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1068 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1069 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1070 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1071 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1072 io
.ntcreatex
.in
.security_flags
= 0;
1073 io
.ntcreatex
.in
.fname
= fname
;
1074 io
.ntcreatex
.in
.flags
= 0;
1075 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1076 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1077 ret
, done
, "directory open failed");
1078 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1080 torture_assert_int_equal(tctx
,
1081 io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1082 FILE_ATTRIBUTE_DIRECTORY
,
1086 * verify you can turn on archive bit
1088 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1089 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1090 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
;
1091 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1092 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1093 ret
, done
, "setfileinfo failed");
1095 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1096 finfo
.generic
.in
.file
.fnum
= fnum
;
1097 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1098 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1099 ret
, done
, "fileinfo failed");
1101 torture_assert_int_equal(tctx
,
1102 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1103 FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
,
1104 "archive bit not set");
1107 * and try to turn it back off
1109 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1110 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1111 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
;
1112 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1113 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1114 ret
, done
, "setfileinfo failed");
1116 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1117 finfo
.generic
.in
.file
.fnum
= fnum
;
1118 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1119 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1120 ret
, done
, "fileinfo failed");
1122 torture_assert_int_equal(tctx
,
1123 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1124 FILE_ATTRIBUTE_DIRECTORY
,
1127 status
= smbcli_close(cli
->tree
, fnum
);
1128 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1129 ret
, done
, "close failed");
1132 smbcli_close(cli
->tree
, fnum
);
1133 smbcli_deltree(cli
->tree
, BASEDIR
);
1137 struct torture_suite
*torture_raw_sfileinfo(TALLOC_CTX
*mem_ctx
)
1139 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "sfileinfo");
1141 torture_suite_add_1smb_test(suite
, "base", torture_raw_sfileinfo_base
);
1142 torture_suite_add_1smb_test(suite
, "rename", torture_raw_sfileinfo_rename
);
1143 torture_suite_add_1smb_test(suite
, "bug", torture_raw_sfileinfo_bug
);
1144 torture_suite_add_2smb_test(suite
, "end-of-file",
1145 torture_raw_sfileinfo_eof
);
1146 torture_suite_add_2smb_test(suite
, "end-of-file-access",
1147 torture_raw_sfileinfo_eof_access
);
1148 torture_suite_add_1smb_test(suite
, "archive",
1149 torture_raw_sfileinfo_archive
);