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
)
42 union smb_fileinfo finfo1
, finfo2
;
43 union smb_setfileinfo sfinfo
;
44 NTSTATUS status
, status2
;
45 const char *call_name
;
46 time_t basetime
= (time(NULL
) - 86400) & ~1;
48 int n
= time(NULL
) % 100;
50 asprintf(&path_fname
, BASEDIR
"\\fname_test_%d.txt", n
);
51 asprintf(&path_fname_new
, BASEDIR
"\\fname_test_new_%d.txt", n
);
52 asprintf(&fnum_fname
, BASEDIR
"\\fnum_test_%d.txt", n
);
53 asprintf(&fnum_fname_new
, BASEDIR
"\\fnum_test_new_%d.txt", n
);
55 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
57 #define RECREATE_FILE(fname) do { \
58 if (fnum != -1) smbcli_close(cli->tree, fnum); \
59 fnum = create_complex_file(cli, torture, fname); \
61 printf("(%s) ERROR: open of %s failed (%s)\n", \
62 __location__, fname, smbcli_errstr(cli->tree)); \
67 #define RECREATE_BOTH do { \
68 RECREATE_FILE(path_fname); \
69 smbcli_close(cli->tree, fnum); \
70 RECREATE_FILE(fnum_fname); \
75 #define CHECK_CALL_FNUM(call, rightstatus) do { \
78 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
79 sfinfo.generic.in.file.fnum = fnum; \
80 status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
81 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
82 torture_warning(torture, \
83 "(%s) %s - %s", __location__, #call, \
85 } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
86 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
87 nt_errstr(status), nt_errstr(rightstatus)); \
90 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
91 finfo1.generic.in.file.fnum = fnum; \
92 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
93 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
94 torture_warning(torture, \
95 "(%s) %s - %s", __location__, #call, \
97 } else if (!NT_STATUS_IS_OK(status2)) { \
98 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
102 #define CHECK_CALL_PATH(call, rightstatus) do { \
103 check_fnum = false; \
105 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
106 sfinfo.generic.in.file.path = path_fname; \
107 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
108 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
109 sfinfo.generic.in.file.path = path_fname_new; \
110 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
112 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
113 torture_warning(torture, \
114 "(%s) %s - %s", __location__, #call, \
115 nt_errstr(status)); \
116 } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
117 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
118 nt_errstr(status), nt_errstr(rightstatus)); \
121 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
122 finfo1.generic.in.file.path = path_fname; \
123 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
124 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
125 finfo1.generic.in.file.path = path_fname_new; \
126 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
128 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
129 torture_warning(torture, \
130 "(%s) %s - %s", __location__, #call, \
131 nt_errstr(status)); \
132 } else if (!NT_STATUS_IS_OK(status2)) { \
133 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \
137 #define CHECK1(call) \
138 do { if (NT_STATUS_IS_OK(status)) { \
139 finfo2.generic.level = RAW_FILEINFO_ ## call; \
141 finfo2.generic.in.file.fnum = fnum; \
142 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
144 finfo2.generic.in.file.path = path_fname; \
145 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
146 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
147 finfo2.generic.in.file.path = path_fname_new; \
148 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
151 if (!NT_STATUS_IS_OK(status2)) { \
152 printf("%s - %s\n", #call, nt_errstr(status2)); \
157 #define CHECK_VALUE(call, stype, field, value) do { \
159 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
160 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
161 call_name, #stype, #field, \
162 (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
163 dump_all_info(torture, &finfo1); \
167 #define CHECK_TIME(call, stype, field, value) do { \
169 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
170 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
171 call_name, #stype, #field, \
172 (unsigned int)value, \
173 (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
174 printf("\t%s", timestring(torture, value)); \
175 printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
176 dump_all_info(torture, &finfo1); \
180 #define CHECK_STR(call, stype, field, value) do { \
182 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
183 printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
184 call_name, #stype, #field, \
186 finfo2.stype.out.field); \
187 dump_all_info(torture, &finfo1); \
191 #define CHECK_STATUS(status, correct) do { \
192 if (!NT_STATUS_EQUAL(status, correct)) { \
193 printf("(%s) Incorrect status %s - should be %s\n", \
194 __location__, nt_errstr(status), nt_errstr(correct)); \
200 printf("Test setattr\n");
201 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
202 sfinfo
.setattr
.in
.write_time
= basetime
;
203 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
204 CHECK_VALUE (ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
205 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
207 printf("setting to NORMAL doesn't do anything\n");
208 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
209 sfinfo
.setattr
.in
.write_time
= 0;
210 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
211 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
212 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
214 printf("a zero write_time means don't change\n");
215 sfinfo
.setattr
.in
.attrib
= 0;
216 sfinfo
.setattr
.in
.write_time
= 0;
217 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
218 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
219 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
221 printf("Test setattre\n");
222 sfinfo
.setattre
.in
.create_time
= basetime
+ 20;
223 sfinfo
.setattre
.in
.access_time
= basetime
+ 30;
224 sfinfo
.setattre
.in
.write_time
= basetime
+ 40;
225 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
226 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
227 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
228 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
230 sfinfo
.setattre
.in
.create_time
= 0;
231 sfinfo
.setattre
.in
.access_time
= 0;
232 sfinfo
.setattre
.in
.write_time
= 0;
233 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
234 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
235 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
236 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
238 printf("Test standard level\n");
239 sfinfo
.standard
.in
.create_time
= basetime
+ 100;
240 sfinfo
.standard
.in
.access_time
= basetime
+ 200;
241 sfinfo
.standard
.in
.write_time
= basetime
+ 300;
242 CHECK_CALL_FNUM(STANDARD
, NT_STATUS_OK
);
243 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
244 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
245 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
247 printf("Test basic_info level\n");
249 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
250 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
251 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
252 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
253 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
254 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_OK
);
255 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
256 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
257 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
258 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
259 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
261 printf("a zero time means don't change\n");
262 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
263 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
264 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
265 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
266 sfinfo
.basic_info
.in
.attrib
= 0;
267 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_OK
);
268 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
269 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
270 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
271 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
272 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
274 printf("Test basic_information level\n");
276 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
277 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
278 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
279 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
280 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
281 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
282 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
283 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
284 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
285 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
286 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
288 CHECK_CALL_PATH(BASIC_INFORMATION
, NT_STATUS_OK
);
289 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
290 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
291 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
292 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
293 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
295 torture_comment(torture
, "try to change a file to a directory\n");
296 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
;
297 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_INVALID_PARAMETER
);
299 printf("a zero time means don't change\n");
300 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
301 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
302 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
303 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
304 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
305 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
306 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
307 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
308 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
309 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
310 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
312 CHECK_CALL_PATH(BASIC_INFORMATION
, NT_STATUS_OK
);
313 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
314 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
315 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
317 /* interesting - w2k3 leaves change_time as current time for 0 change time
319 CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
321 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
323 printf("Test disposition_info level\n");
324 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
325 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
326 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
327 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
329 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
330 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
331 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
332 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
334 printf("Test disposition_information level\n");
335 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
336 CHECK_CALL_FNUM(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
337 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
338 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
340 /* this would delete the file! */
342 CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
343 CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
344 CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
347 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
348 CHECK_CALL_FNUM(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
349 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
350 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
352 CHECK_CALL_PATH(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
353 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
354 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
356 printf("Test allocation_info level\n");
357 sfinfo
.allocation_info
.in
.alloc_size
= 0;
358 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
359 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
360 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
362 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
363 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
364 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
365 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
368 sfinfo
.allocation_info
.in
.alloc_size
= 0;
369 CHECK_CALL_FNUM(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
370 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
371 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
373 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
374 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
375 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
377 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
378 CHECK_CALL_FNUM(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
379 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
380 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
382 /* setting the allocation size up via setpathinfo seems
383 to be broken in w2k3 */
384 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
385 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
386 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
388 printf("Test end_of_file_info level\n");
389 sfinfo
.end_of_file_info
.in
.size
= 37;
390 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
391 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
393 sfinfo
.end_of_file_info
.in
.size
= 7;
394 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
395 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
397 sfinfo
.end_of_file_info
.in
.size
= 37;
398 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
399 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
401 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
402 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
404 sfinfo
.end_of_file_info
.in
.size
= 7;
405 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
406 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
408 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
409 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
411 printf("Test position_information level\n");
412 sfinfo
.position_information
.in
.position
= 123456;
413 CHECK_CALL_FNUM(POSITION_INFORMATION
, NT_STATUS_OK
);
414 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 123456);
416 CHECK_CALL_PATH(POSITION_INFORMATION
, NT_STATUS_OK
);
417 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 0);
419 printf("Test mode_information level\n");
420 sfinfo
.mode_information
.in
.mode
= 2;
421 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
422 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 2);
424 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
425 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
427 sfinfo
.mode_information
.in
.mode
= 1;
428 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
429 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
431 sfinfo
.mode_information
.in
.mode
= 0;
432 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
433 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
435 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
436 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
439 printf("Test unix_basic level\n");
440 CHECK_CALL_FNUM(UNIX_BASIC
, NT_STATUS_OK
);
441 CHECK_CALL_PATH(UNIX_BASIC
, NT_STATUS_OK
);
443 printf("Test unix_link level\n");
444 CHECK_CALL_FNUM(UNIX_LINK
, NT_STATUS_OK
);
445 CHECK_CALL_PATH(UNIX_LINK
, NT_STATUS_OK
);
449 smb_raw_exit(cli
->session
);
450 smbcli_close(cli
->tree
, fnum
);
451 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, fnum_fname
))) {
452 printf("Failed to delete %s - %s\n", fnum_fname
, smbcli_errstr(cli
->tree
));
454 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, path_fname
))) {
455 printf("Failed to delete %s - %s\n", path_fname
, smbcli_errstr(cli
->tree
));
462 * basic testing of all RAW_SFILEINFO_RENAME call
465 torture_raw_sfileinfo_rename(struct torture_context
*torture
,
466 struct smbcli_state
*cli
)
469 int fnum_saved
, d_fnum
, fnum2
, fnum
= -1;
471 char *fnum_fname_new
;
473 char *path_fname_new
;
475 char *path_dname_new
;
477 char *saved_name_new
;
478 union smb_fileinfo finfo1
, finfo2
;
479 union smb_setfileinfo sfinfo
;
480 NTSTATUS status
, status2
;
481 const char *call_name
;
483 int n
= time(NULL
) % 100;
485 asprintf(&path_fname
, BASEDIR
"\\fname_test_%d.txt", n
);
486 asprintf(&path_fname_new
, BASEDIR
"\\fname_test_new_%d.txt", n
);
487 asprintf(&fnum_fname
, BASEDIR
"\\fnum_test_%d.txt", n
);
488 asprintf(&fnum_fname_new
, BASEDIR
"\\fnum_test_new_%d.txt", n
);
489 asprintf(&path_dname
, BASEDIR
"\\dname_test_%d", n
);
490 asprintf(&path_dname_new
, BASEDIR
"\\dname_test_new_%d", n
);
492 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
498 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, fnum_fname_new
));
499 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, path_fname_new
));
501 sfinfo
.rename_information
.in
.overwrite
= 0;
502 sfinfo
.rename_information
.in
.root_fid
= 0;
503 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
504 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
506 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
507 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
509 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
;
510 sfinfo
.rename_information
.in
.overwrite
= 1;
511 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_NOT_SUPPORTED
);
513 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
514 sfinfo
.rename_information
.in
.overwrite
= 1;
515 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
516 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
518 printf("Trying rename with dest file open\n");
519 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
520 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
521 sfinfo
.rename_information
.in
.overwrite
= 1;
522 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_ACCESS_DENIED
);
523 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
527 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
528 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
531 printf("Trying rename with dest file open and delete_on_close\n");
532 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
533 sfinfo
.rename_information
.in
.overwrite
= 1;
534 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_ACCESS_DENIED
);
536 smbcli_close(cli
->tree
, fnum2
);
537 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
538 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
540 printf("Trying rename with source file open twice\n");
541 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
542 sfinfo
.rename_information
.in
.overwrite
= 1;
543 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
544 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
546 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
547 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
548 sfinfo
.rename_information
.in
.overwrite
= 0;
549 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
550 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
551 smbcli_close(cli
->tree
, fnum2
);
553 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
554 sfinfo
.rename_information
.in
.overwrite
= 0;
555 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
556 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
558 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
559 sfinfo
.rename_information
.in
.overwrite
= 1;
560 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
561 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
563 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
564 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
565 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
567 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
568 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
569 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
571 printf("Trying rename with a root fid\n");
572 status
= create_directory_handle(cli
->tree
, BASEDIR
, &d_fnum
);
573 CHECK_STATUS(status
, NT_STATUS_OK
);
574 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
575 sfinfo
.rename_information
.in
.root_fid
= d_fnum
;
576 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
577 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
578 smbcli_close(cli
->tree
, d_fnum
);
580 printf("Trying rename directory\n");
581 if (!torture_setup_dir(cli
, path_dname
)) {
585 saved_name
= path_fname
;
586 saved_name_new
= path_fname_new
;
587 path_fname
= path_dname
;
588 path_fname_new
= path_dname_new
;
589 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
590 sfinfo
.rename_information
.in
.overwrite
= 0;
591 sfinfo
.rename_information
.in
.root_fid
= 0;
592 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
593 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
594 path_fname
= saved_name
;
595 path_fname_new
= saved_name_new
;
597 if (torture_setting_bool(torture
, "samba3", false)) {
598 printf("SKIP: Trying rename directory with a handle\n");
599 printf("SKIP: Trying rename by path while a handle is open\n");
600 printf("SKIP: Trying rename directory by path while a handle is open\n");
604 printf("Trying rename directory with a handle\n");
605 status
= create_directory_handle(cli
->tree
, path_dname_new
, &d_fnum
);
608 saved_name
= fnum_fname
;
609 saved_name_new
= fnum_fname_new
;
610 fnum_fname
= path_dname
;
611 fnum_fname_new
= path_dname_new
;
612 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
613 sfinfo
.rename_information
.in
.overwrite
= 0;
614 sfinfo
.rename_information
.in
.root_fid
= 0;
615 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
616 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
617 smbcli_close(cli
->tree
, d_fnum
);
619 fnum_fname
= saved_name
;
620 fnum_fname_new
= saved_name_new
;
622 printf("Trying rename by path while a handle is open\n");
624 fnum
= create_complex_file(cli
, torture
, path_fname
);
625 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
626 sfinfo
.rename_information
.in
.overwrite
= 0;
627 sfinfo
.rename_information
.in
.root_fid
= 0;
628 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
629 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
630 /* check that the handle returns the same name */
632 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
633 /* rename it back on the handle */
634 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
635 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
636 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
638 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
639 smbcli_close(cli
->tree
, fnum
);
642 printf("Trying rename directory by path while a handle is open\n");
643 status
= create_directory_handle(cli
->tree
, path_dname
, &d_fnum
);
646 saved_name
= path_fname
;
647 saved_name_new
= path_fname_new
;
648 path_fname
= path_dname
;
649 path_fname_new
= path_dname_new
;
650 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
651 sfinfo
.rename_information
.in
.overwrite
= 0;
652 sfinfo
.rename_information
.in
.root_fid
= 0;
653 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
654 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
655 path_fname
= saved_name
;
656 path_fname_new
= saved_name_new
;
657 saved_name
= fnum_fname
;
658 saved_name_new
= fnum_fname_new
;
659 fnum_fname
= path_dname
;
660 fnum_fname_new
= path_dname_new
;
661 /* check that the handle returns the same name */
663 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
664 /* rename it back on the handle */
665 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
666 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
667 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
668 fnum_fname
= saved_name
;
669 fnum_fname_new
= saved_name_new
;
670 saved_name
= path_fname
;
671 saved_name_new
= path_fname_new
;
672 path_fname
= path_dname
;
673 path_fname_new
= path_dname_new
;
675 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
676 smbcli_close(cli
->tree
, d_fnum
);
678 path_fname
= saved_name
;
679 path_fname_new
= saved_name_new
;
682 smb_raw_exit(cli
->session
);
683 smbcli_deltree(cli
->tree
, BASEDIR
);
688 look for the w2k3 setpathinfo STANDARD bug
690 static bool torture_raw_sfileinfo_bug(struct torture_context
*torture
,
691 struct smbcli_state
*cli
)
693 const char *fname
= "\\bug3.txt";
694 union smb_setfileinfo sfinfo
;
698 if (!torture_setting_bool(torture
, "dangerous", false))
699 torture_skip(torture
,
700 "torture_raw_sfileinfo_bug disabled - enable dangerous tests to use\n");
702 fnum
= create_complex_file(cli
, torture
, fname
);
703 smbcli_close(cli
->tree
, fnum
);
705 sfinfo
.generic
.level
= RAW_SFILEINFO_STANDARD
;
706 sfinfo
.generic
.in
.file
.path
= fname
;
708 sfinfo
.standard
.in
.create_time
= 0;
709 sfinfo
.standard
.in
.access_time
= 0;
710 sfinfo
.standard
.in
.write_time
= 0;
712 status
= smb_raw_setpathinfo(cli
->tree
, &sfinfo
);
713 printf("%s - %s\n", fname
, nt_errstr(status
));
715 printf("now try and delete %s\n", fname
);
721 * Test both the snia cifs RAW_SFILEINFO_END_OF_FILE_INFO and the undocumented
722 * pass-through RAW_SFILEINFO_END_OF_FILE_INFORMATION in the context of
726 torture_raw_sfileinfo_eof(struct torture_context
*tctx
,
727 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
729 const char *fname
= BASEDIR
"\\test_sfileinfo_end_of_file.dat";
733 union smb_setfileinfo sfi
;
734 union smb_fileinfo qfi
;
737 if (!torture_setup_dir(cli1
, BASEDIR
)) {
742 smbcli_unlink(cli1
->tree
, fname
);
744 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
745 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
746 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
747 io
.ntcreatex
.in
.alloc_size
= 0;
748 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
749 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
750 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
751 io
.ntcreatex
.in
.create_options
= 0;
752 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
753 io
.ntcreatex
.in
.security_flags
= 0;
754 io
.ntcreatex
.in
.fname
= fname
;
755 io
.ntcreatex
.in
.flags
= 0;
757 /* Open the file sharing none. */
758 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
759 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
760 done
, "Status should be OK");
761 fnum
= io
.ntcreatex
.out
.file
.fnum
;
763 /* Try to sfileinfo to extend the file. */
765 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
766 sfi
.generic
.in
.file
.path
= fname
;
767 sfi
.end_of_file_info
.in
.size
= 100;
768 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
770 /* There should be share mode contention in this case. */
771 torture_assert_ntstatus_equal_goto(tctx
, status
,
772 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
773 "SHARING_VIOLATION");
775 /* Make sure the size is still 0. */
777 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
778 qfi
.generic
.in
.file
.path
= fname
;
779 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
780 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
781 done
, "Status should be OK");
783 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 0,
784 "alloc_size should be 0 since the setpathinfo failed.");
786 /* Try again with the pass through instead of documented version. */
788 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
789 sfi
.generic
.in
.file
.path
= fname
;
790 sfi
.end_of_file_info
.in
.size
= 100;
791 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
794 * Looks like a windows bug:
795 * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html
797 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
798 /* It succeeds! This is just weird! */
799 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
800 ret
, done
, "Status should be OK");
802 /* Verify that the file was actually extended to 100. */
804 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
805 qfi
.generic
.in
.file
.path
= fname
;
806 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
807 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
808 ret
, done
, "Status should be OK");
810 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 100,
811 "alloc_size should be 100 since the setpathinfo "
814 torture_assert_ntstatus_equal_goto(tctx
, status
,
815 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
816 "SHARING_VIOLATION");
819 /* close the first file. */
820 smbcli_close(cli1
->tree
, fnum
);
823 /* Try to sfileinfo to extend the file again (non-pass-through). */
825 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
826 sfi
.generic
.in
.file
.path
= fname
;
827 sfi
.end_of_file_info
.in
.size
= 200;
828 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
830 /* This should cause the client to retun invalid level. */
831 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
833 * Windows sends back an invalid packet that smbclient sees
834 * and returns INTERNAL_ERROR.
836 torture_assert_ntstatus_equal_goto(tctx
, status
,
837 NT_STATUS_INTERNAL_ERROR
, ret
, done
, "Status should be "
840 torture_assert_ntstatus_equal_goto(tctx
, status
,
841 NT_STATUS_INVALID_LEVEL
, ret
, done
, "Status should be "
845 /* Try to extend the file now with the passthrough level. */
846 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
847 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
848 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
849 done
, "Status should be OK");
851 /* Verify that the file was actually extended to 200. */
853 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
854 qfi
.generic
.in
.file
.path
= fname
;
855 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
857 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
858 done
, "Status should be OK");
859 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 200,
860 "alloc_size should be 200 since the setpathinfo succeeded.");
862 /* Open the file so end of file can be set by handle. */
863 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_WRITE
;
864 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
865 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
866 done
, "Status should be OK");
867 fnum
= io
.ntcreatex
.out
.file
.fnum
;
869 /* Try sfileinfo to extend the file by handle (non-pass-through). */
871 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
872 sfi
.generic
.in
.file
.fnum
= fnum
;
873 sfi
.end_of_file_info
.in
.size
= 300;
874 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
875 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
876 done
, "Status should be OK");
878 /* Verify that the file was actually extended to 300. */
880 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
881 qfi
.generic
.in
.file
.path
= fname
;
882 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qfi
);
883 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
884 done
, "Status should be OK");
885 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 300,
886 "alloc_size should be 300 since the setpathinfo succeeded.");
888 /* Try sfileinfo to extend the file by handle (pass-through). */
890 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
891 sfi
.generic
.in
.file
.fnum
= fnum
;
892 sfi
.end_of_file_info
.in
.size
= 400;
893 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
894 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
895 done
, "Status should be OK");
897 /* Verify that the file was actually extended to 300. */
899 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
900 qfi
.generic
.in
.file
.path
= fname
;
901 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qfi
);
902 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
903 done
, "Status should be OK");
904 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 400,
905 "alloc_size should be 400 since the setpathinfo succeeded.");
908 smbcli_close(cli1
->tree
, fnum
);
912 smb_raw_exit(cli1
->session
);
913 smb_raw_exit(cli2
->session
);
914 smbcli_deltree(cli1
->tree
, BASEDIR
);
919 torture_raw_sfileinfo_eof_access(struct torture_context
*tctx
,
920 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
922 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
923 NTSTATUS status
, expected_status
;
926 union smb_setfileinfo sfi
;
928 uint32_t access_mask
= 0;
930 if (!torture_setup_dir(cli1
, BASEDIR
)) {
935 smbcli_unlink(cli1
->tree
, fname
);
938 * base ntcreatex parms
940 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
941 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
942 io
.ntcreatex
.in
.alloc_size
= 0;
943 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
944 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
945 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
946 io
.ntcreatex
.in
.create_options
= 0;
947 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
948 io
.ntcreatex
.in
.security_flags
= 0;
949 io
.ntcreatex
.in
.fname
= fname
;
950 io
.ntcreatex
.in
.flags
= 0;
953 for (access_mask
= 1; access_mask
<= 0x00001FF; access_mask
++) {
954 io
.ntcreatex
.in
.access_mask
= access_mask
;
956 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
957 if (!NT_STATUS_IS_OK(status
)) {
961 fnum
= io
.ntcreatex
.out
.file
.fnum
;
964 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
965 sfi
.generic
.in
.file
.fnum
= fnum
;
966 sfi
.end_of_file_info
.in
.size
= 100;
968 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
970 expected_status
= (access_mask
& SEC_FILE_WRITE_DATA
) ?
971 NT_STATUS_OK
: NT_STATUS_ACCESS_DENIED
;
973 if (!NT_STATUS_EQUAL(expected_status
, status
)) {
974 torture_comment(tctx
, "0x%x wrong\n", access_mask
);
977 torture_assert_ntstatus_equal_goto(tctx
, status
,
978 expected_status
, ret
, done
, "Status Wrong");
980 smbcli_close(cli1
->tree
, fnum
);
984 smb_raw_exit(cli1
->session
);
985 smb_raw_exit(cli2
->session
);
986 smbcli_deltree(cli1
->tree
, BASEDIR
);
991 torture_raw_sfileinfo_archive(struct torture_context
*tctx
,
992 struct smbcli_state
*cli
)
994 const char *fname
= BASEDIR
"\\test_archive.dat";
998 union smb_setfileinfo sfinfo
;
999 union smb_fileinfo finfo
;
1002 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
1005 smbcli_unlink(cli
->tree
, fname
);
1008 * create a normal file, verify archive bit
1010 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1011 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1012 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1013 io
.ntcreatex
.in
.alloc_size
= 0;
1014 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1015 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1016 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1017 io
.ntcreatex
.in
.create_options
= 0;
1018 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1019 io
.ntcreatex
.in
.security_flags
= 0;
1020 io
.ntcreatex
.in
.fname
= fname
;
1021 io
.ntcreatex
.in
.flags
= 0;
1022 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1023 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1024 ret
, done
, "open failed");
1025 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1027 torture_assert_int_equal(tctx
,
1028 io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1029 FILE_ATTRIBUTE_ARCHIVE
,
1030 "archive bit not set");
1033 * try to turn off archive bit
1035 ZERO_STRUCT(sfinfo
);
1036 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1037 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1038 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
1039 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1040 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1041 ret
, done
, "setfileinfo failed");
1043 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1044 finfo
.generic
.in
.file
.fnum
= fnum
;
1045 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1046 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1047 ret
, done
, "fileinfo failed");
1049 torture_assert_int_equal(tctx
,
1050 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1051 FILE_ATTRIBUTE_NORMAL
,
1054 status
= smbcli_close(cli
->tree
, fnum
);
1055 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1056 ret
, done
, "close failed");
1058 status
= smbcli_unlink(cli
->tree
, fname
);
1059 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1060 ret
, done
, "unlink failed");
1063 * create a directory, verify no archive bit
1065 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1066 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1067 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_DIR_ALL
;
1068 io
.ntcreatex
.in
.alloc_size
= 0;
1069 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1070 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1071 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1072 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1073 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1074 io
.ntcreatex
.in
.security_flags
= 0;
1075 io
.ntcreatex
.in
.fname
= fname
;
1076 io
.ntcreatex
.in
.flags
= 0;
1077 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1078 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1079 ret
, done
, "directory open failed");
1080 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1082 torture_assert_int_equal(tctx
,
1083 io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1084 FILE_ATTRIBUTE_DIRECTORY
,
1088 * verify you can turn on archive bit
1090 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1091 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1092 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
;
1093 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1094 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1095 ret
, done
, "setfileinfo failed");
1097 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1098 finfo
.generic
.in
.file
.fnum
= fnum
;
1099 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1100 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1101 ret
, done
, "fileinfo failed");
1103 torture_assert_int_equal(tctx
,
1104 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1105 FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
,
1106 "archive bit not set");
1109 * and try to turn it back off
1111 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1112 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1113 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
;
1114 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1115 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1116 ret
, done
, "setfileinfo failed");
1118 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1119 finfo
.generic
.in
.file
.fnum
= fnum
;
1120 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1121 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1122 ret
, done
, "fileinfo failed");
1124 torture_assert_int_equal(tctx
,
1125 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1126 FILE_ATTRIBUTE_DIRECTORY
,
1129 status
= smbcli_close(cli
->tree
, fnum
);
1130 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1131 ret
, done
, "close failed");
1134 smbcli_close(cli
->tree
, fnum
);
1135 smbcli_deltree(cli
->tree
, BASEDIR
);
1139 struct torture_suite
*torture_raw_sfileinfo(TALLOC_CTX
*mem_ctx
)
1141 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "sfileinfo");
1143 torture_suite_add_1smb_test(suite
, "base", torture_raw_sfileinfo_base
);
1144 torture_suite_add_1smb_test(suite
, "rename", torture_raw_sfileinfo_rename
);
1145 torture_suite_add_1smb_test(suite
, "bug", torture_raw_sfileinfo_bug
);
1146 torture_suite_add_2smb_test(suite
, "end-of-file",
1147 torture_raw_sfileinfo_eof
);
1148 torture_suite_add_2smb_test(suite
, "end-of-file-access",
1149 torture_raw_sfileinfo_eof_access
);
1150 torture_suite_add_1smb_test(suite
, "archive",
1151 torture_raw_sfileinfo_archive
);