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 if (!torture_setup_dir(cli
, BASEDIR
)) {
59 #define RECREATE_FILE(fname) do { \
60 if (fnum != -1) smbcli_close(cli->tree, fnum); \
61 fnum = create_complex_file(cli, torture, fname); \
63 printf("(%s) ERROR: open of %s failed (%s)\n", \
64 __location__, fname, smbcli_errstr(cli->tree)); \
69 #define RECREATE_BOTH do { \
70 RECREATE_FILE(path_fname); \
71 smbcli_close(cli->tree, fnum); \
72 RECREATE_FILE(fnum_fname); \
77 #define CHECK_CALL_FNUM(call, rightstatus) do { \
80 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
81 sfinfo.generic.in.file.fnum = fnum; \
82 status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
83 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
84 torture_warning(torture, \
85 "(%s) %s - %s", __location__, #call, \
87 } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
88 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
89 nt_errstr(status), nt_errstr(rightstatus)); \
92 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
93 finfo1.generic.in.file.fnum = fnum; \
94 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
95 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
96 torture_warning(torture, \
97 "(%s) %s - %s", __location__, #call, \
99 } else if (!NT_STATUS_IS_OK(status2)) { \
100 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
104 #define CHECK_CALL_PATH(call, rightstatus) do { \
105 check_fnum = false; \
107 sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
108 sfinfo.generic.in.file.path = path_fname; \
109 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
110 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
111 sfinfo.generic.in.file.path = path_fname_new; \
112 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
114 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
115 torture_warning(torture, \
116 "(%s) %s - %s", __location__, #call, \
117 nt_errstr(status)); \
118 } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
119 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
120 nt_errstr(status), nt_errstr(rightstatus)); \
123 finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
124 finfo1.generic.in.file.path = path_fname; \
125 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
126 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
127 finfo1.generic.in.file.path = path_fname_new; \
128 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
130 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
131 torture_warning(torture, \
132 "(%s) %s - %s", __location__, #call, \
133 nt_errstr(status)); \
134 } else if (!NT_STATUS_IS_OK(status2)) { \
135 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \
139 #define CHECK1(call) \
140 do { if (NT_STATUS_IS_OK(status)) { \
141 finfo2.generic.level = RAW_FILEINFO_ ## call; \
143 finfo2.generic.in.file.fnum = fnum; \
144 status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
146 finfo2.generic.in.file.path = path_fname; \
147 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
148 if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
149 finfo2.generic.in.file.path = path_fname_new; \
150 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
153 if (!NT_STATUS_IS_OK(status2)) { \
154 printf("%s - %s\n", #call, nt_errstr(status2)); \
159 #define CHECK_VALUE(call, stype, field, value) do { \
161 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
162 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
163 call_name, #stype, #field, \
164 (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
165 dump_all_info(torture, &finfo1); \
169 #define CHECK_TIME(call, stype, field, value) do { \
171 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
172 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
173 call_name, #stype, #field, \
174 (unsigned int)value, \
175 (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
176 printf("\t%s", timestring(torture, value)); \
177 printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
178 dump_all_info(torture, &finfo1); \
182 #define CHECK_STR(call, stype, field, value) do { \
184 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
185 printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
186 call_name, #stype, #field, \
188 finfo2.stype.out.field); \
189 dump_all_info(torture, &finfo1); \
193 #define CHECK_STATUS(status, correct) do { \
194 if (!NT_STATUS_EQUAL(status, correct)) { \
195 printf("(%s) Incorrect status %s - should be %s\n", \
196 __location__, nt_errstr(status), nt_errstr(correct)); \
202 printf("Test setattr\n");
203 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
204 sfinfo
.setattr
.in
.write_time
= basetime
;
205 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
206 CHECK_VALUE (ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
207 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
209 printf("setting to NORMAL doesn't do anything\n");
210 sfinfo
.setattr
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
211 sfinfo
.setattr
.in
.write_time
= 0;
212 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
213 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
214 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
216 printf("a zero write_time means don't change\n");
217 sfinfo
.setattr
.in
.attrib
= 0;
218 sfinfo
.setattr
.in
.write_time
= 0;
219 CHECK_CALL_PATH(SETATTR
, NT_STATUS_OK
);
220 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
221 CHECK_TIME (ALL_INFO
, all_info
, write_time
, basetime
);
223 printf("Test setattre\n");
224 sfinfo
.setattre
.in
.create_time
= basetime
+ 20;
225 sfinfo
.setattre
.in
.access_time
= basetime
+ 30;
226 sfinfo
.setattre
.in
.write_time
= basetime
+ 40;
227 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
228 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
229 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
230 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
232 sfinfo
.setattre
.in
.create_time
= 0;
233 sfinfo
.setattre
.in
.access_time
= 0;
234 sfinfo
.setattre
.in
.write_time
= 0;
235 CHECK_CALL_FNUM(SETATTRE
, NT_STATUS_OK
);
236 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 20);
237 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 30);
238 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 40);
240 printf("Test standard level\n");
241 sfinfo
.standard
.in
.create_time
= basetime
+ 100;
242 sfinfo
.standard
.in
.access_time
= basetime
+ 200;
243 sfinfo
.standard
.in
.write_time
= basetime
+ 300;
244 CHECK_CALL_FNUM(STANDARD
, NT_STATUS_OK
);
245 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
246 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
247 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
249 printf("Test basic_info level\n");
251 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
252 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
253 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
254 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
255 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_READONLY
;
256 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_OK
);
257 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
258 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
259 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
260 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
261 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
263 printf("a zero time means don't change\n");
264 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
265 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
266 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
267 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
268 sfinfo
.basic_info
.in
.attrib
= 0;
269 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_OK
);
270 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
271 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
272 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
273 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
274 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_READONLY
);
276 printf("Test basic_information level\n");
278 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, basetime
+ 100);
279 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, basetime
+ 200);
280 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, basetime
+ 300);
281 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, basetime
+ 400);
282 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
283 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
284 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
285 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
286 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
287 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
288 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
290 CHECK_CALL_PATH(BASIC_INFORMATION
, NT_STATUS_OK
);
291 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
292 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
293 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
294 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
295 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
297 torture_comment(torture
, "try to change a file to a directory\n");
298 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
;
299 CHECK_CALL_FNUM(BASIC_INFO
, NT_STATUS_INVALID_PARAMETER
);
301 printf("a zero time means don't change\n");
302 unix_to_nt_time(&sfinfo
.basic_info
.in
.create_time
, 0);
303 unix_to_nt_time(&sfinfo
.basic_info
.in
.access_time
, 0);
304 unix_to_nt_time(&sfinfo
.basic_info
.in
.write_time
, 0);
305 unix_to_nt_time(&sfinfo
.basic_info
.in
.change_time
, 0);
306 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
307 CHECK_CALL_FNUM(BASIC_INFORMATION
, NT_STATUS_OK
);
308 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
309 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
310 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
311 CHECK_TIME(ALL_INFO
, all_info
, change_time
, basetime
+ 400);
312 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
314 CHECK_CALL_PATH(BASIC_INFORMATION
, NT_STATUS_OK
);
315 CHECK_TIME(ALL_INFO
, all_info
, create_time
, basetime
+ 100);
316 CHECK_TIME(ALL_INFO
, all_info
, access_time
, basetime
+ 200);
317 CHECK_TIME(ALL_INFO
, all_info
, write_time
, basetime
+ 300);
319 /* interesting - w2k3 leaves change_time as current time for 0 change time
321 CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
323 CHECK_VALUE(ALL_INFO
, all_info
, attrib
, FILE_ATTRIBUTE_NORMAL
);
325 printf("Test disposition_info level\n");
326 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
327 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
328 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
329 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
331 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
332 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
333 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
334 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
336 printf("Test disposition_information level\n");
337 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
338 CHECK_CALL_FNUM(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
339 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 1);
340 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 0);
342 /* this would delete the file! */
344 CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
345 CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
346 CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
349 sfinfo
.disposition_info
.in
.delete_on_close
= 0;
350 CHECK_CALL_FNUM(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 CHECK_CALL_PATH(DISPOSITION_INFORMATION
, NT_STATUS_OK
);
355 CHECK_VALUE(ALL_INFO
, all_info
, delete_pending
, 0);
356 CHECK_VALUE(ALL_INFO
, all_info
, nlink
, 1);
358 printf("Test allocation_info level\n");
359 sfinfo
.allocation_info
.in
.alloc_size
= 0;
360 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
361 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
362 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
364 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
365 CHECK_CALL_FNUM(ALLOCATION_INFO
, NT_STATUS_OK
);
366 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
367 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
370 sfinfo
.allocation_info
.in
.alloc_size
= 0;
371 CHECK_CALL_FNUM(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 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
376 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
377 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
379 sfinfo
.allocation_info
.in
.alloc_size
= 4096;
380 CHECK_CALL_FNUM(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
381 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 4096);
382 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
384 /* setting the allocation size up via setpathinfo seems
385 to be broken in w2k3 */
386 CHECK_CALL_PATH(ALLOCATION_INFORMATION
, NT_STATUS_OK
);
387 CHECK_VALUE(ALL_INFO
, all_info
, alloc_size
, 0);
388 CHECK_VALUE(ALL_INFO
, all_info
, size
, 0);
390 printf("Test end_of_file_info level\n");
391 sfinfo
.end_of_file_info
.in
.size
= 37;
392 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
393 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
395 sfinfo
.end_of_file_info
.in
.size
= 7;
396 CHECK_CALL_FNUM(END_OF_FILE_INFO
, NT_STATUS_OK
);
397 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
399 sfinfo
.end_of_file_info
.in
.size
= 37;
400 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
401 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
403 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
404 CHECK_VALUE(ALL_INFO
, all_info
, size
, 37);
406 sfinfo
.end_of_file_info
.in
.size
= 7;
407 CHECK_CALL_FNUM(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
408 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
410 CHECK_CALL_PATH(END_OF_FILE_INFORMATION
, NT_STATUS_OK
);
411 CHECK_VALUE(ALL_INFO
, all_info
, size
, 7);
413 printf("Test position_information level\n");
414 sfinfo
.position_information
.in
.position
= 123456;
415 CHECK_CALL_FNUM(POSITION_INFORMATION
, NT_STATUS_OK
);
416 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 123456);
418 CHECK_CALL_PATH(POSITION_INFORMATION
, NT_STATUS_OK
);
419 CHECK_VALUE(POSITION_INFORMATION
, position_information
, position
, 0);
421 printf("Test mode_information level\n");
422 sfinfo
.mode_information
.in
.mode
= 2;
423 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
424 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 2);
426 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
427 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
429 sfinfo
.mode_information
.in
.mode
= 1;
430 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
431 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
433 sfinfo
.mode_information
.in
.mode
= 0;
434 CHECK_CALL_FNUM(MODE_INFORMATION
, NT_STATUS_OK
);
435 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
437 CHECK_CALL_PATH(MODE_INFORMATION
, NT_STATUS_OK
);
438 CHECK_VALUE(MODE_INFORMATION
, mode_information
, mode
, 0);
441 printf("Test unix_basic level\n");
442 CHECK_CALL_FNUM(UNIX_BASIC
, NT_STATUS_OK
);
443 CHECK_CALL_PATH(UNIX_BASIC
, NT_STATUS_OK
);
445 printf("Test unix_link level\n");
446 CHECK_CALL_FNUM(UNIX_LINK
, NT_STATUS_OK
);
447 CHECK_CALL_PATH(UNIX_LINK
, NT_STATUS_OK
);
451 smb_raw_exit(cli
->session
);
452 smbcli_close(cli
->tree
, fnum
);
453 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, fnum_fname
))) {
454 printf("Failed to delete %s - %s\n", fnum_fname
, smbcli_errstr(cli
->tree
));
456 if (NT_STATUS_IS_ERR(smbcli_unlink(cli
->tree
, path_fname
))) {
457 printf("Failed to delete %s - %s\n", path_fname
, smbcli_errstr(cli
->tree
));
464 * basic testing of all RAW_SFILEINFO_RENAME call
467 torture_raw_sfileinfo_rename(struct torture_context
*torture
,
468 struct smbcli_state
*cli
)
471 int fnum_saved
, d_fnum
, fnum2
, fnum
= -1;
473 char *fnum_fname_new
;
475 char *path_fname_new
;
477 char *path_dname_new
;
479 char *saved_name_new
;
480 union smb_fileinfo finfo1
, finfo2
;
481 union smb_setfileinfo sfinfo
;
482 NTSTATUS status
, status2
;
483 const char *call_name
;
485 int n
= time(NULL
) % 100;
487 asprintf(&path_fname
, BASEDIR
"\\fname_test_%d.txt", n
);
488 asprintf(&path_fname_new
, BASEDIR
"\\fname_test_new_%d.txt", n
);
489 asprintf(&fnum_fname
, BASEDIR
"\\fnum_test_%d.txt", n
);
490 asprintf(&fnum_fname_new
, BASEDIR
"\\fnum_test_new_%d.txt", n
);
491 asprintf(&path_dname
, BASEDIR
"\\dname_test_%d", n
);
492 asprintf(&path_dname_new
, BASEDIR
"\\dname_test_new_%d", n
);
494 if (!torture_setup_dir(cli
, BASEDIR
)) {
502 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, fnum_fname_new
));
503 smbcli_close(cli
->tree
, create_complex_file(cli
, torture
, path_fname_new
));
505 sfinfo
.rename_information
.in
.overwrite
= 0;
506 sfinfo
.rename_information
.in
.root_fid
= 0;
507 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
508 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
510 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
511 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OBJECT_NAME_COLLISION
);
513 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
;
514 sfinfo
.rename_information
.in
.overwrite
= 1;
515 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_NOT_SUPPORTED
);
517 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
518 sfinfo
.rename_information
.in
.overwrite
= 1;
519 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
520 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
522 printf("Trying rename with dest file open\n");
523 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
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_ACCESS_DENIED
);
527 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname_new
);
531 sfinfo
.disposition_info
.in
.delete_on_close
= 1;
532 CHECK_CALL_FNUM(DISPOSITION_INFO
, NT_STATUS_OK
);
535 printf("Trying rename with dest file open and delete_on_close\n");
536 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
537 sfinfo
.rename_information
.in
.overwrite
= 1;
538 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_ACCESS_DENIED
);
540 smbcli_close(cli
->tree
, fnum2
);
541 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
542 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
544 printf("Trying rename with source file open twice\n");
545 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
546 sfinfo
.rename_information
.in
.overwrite
= 1;
547 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
548 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
550 fnum2
= create_complex_file(cli
, torture
, fnum_fname
);
551 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+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_new
);
555 smbcli_close(cli
->tree
, fnum2
);
557 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
558 sfinfo
.rename_information
.in
.overwrite
= 0;
559 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
560 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
562 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
563 sfinfo
.rename_information
.in
.overwrite
= 1;
564 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
565 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
567 sfinfo
.rename_information
.in
.new_name
= fnum_fname
+strlen(BASEDIR
)+1;
568 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
569 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
571 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
572 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
573 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
575 printf("Trying rename with a root fid\n");
576 status
= create_directory_handle(cli
->tree
, BASEDIR
, &d_fnum
);
577 CHECK_STATUS(status
, NT_STATUS_OK
);
578 sfinfo
.rename_information
.in
.new_name
= fnum_fname_new
+strlen(BASEDIR
)+1;
579 sfinfo
.rename_information
.in
.root_fid
= d_fnum
;
580 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_INVALID_PARAMETER
);
581 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, fnum_fname
);
582 smbcli_close(cli
->tree
, d_fnum
);
584 printf("Trying rename directory\n");
585 if (!torture_setup_dir(cli
, path_dname
)) {
589 saved_name
= path_fname
;
590 saved_name_new
= path_fname_new
;
591 path_fname
= path_dname
;
592 path_fname_new
= path_dname_new
;
593 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
594 sfinfo
.rename_information
.in
.overwrite
= 0;
595 sfinfo
.rename_information
.in
.root_fid
= 0;
596 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
597 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
598 path_fname
= saved_name
;
599 path_fname_new
= saved_name_new
;
601 if (torture_setting_bool(torture
, "samba3", false)) {
602 printf("SKIP: Trying rename directory with a handle\n");
603 printf("SKIP: Trying rename by path while a handle is open\n");
604 printf("SKIP: Trying rename directory by path while a handle is open\n");
608 printf("Trying rename directory with a handle\n");
609 status
= create_directory_handle(cli
->tree
, path_dname_new
, &d_fnum
);
612 saved_name
= fnum_fname
;
613 saved_name_new
= fnum_fname_new
;
614 fnum_fname
= path_dname
;
615 fnum_fname_new
= path_dname_new
;
616 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
617 sfinfo
.rename_information
.in
.overwrite
= 0;
618 sfinfo
.rename_information
.in
.root_fid
= 0;
619 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
620 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
621 smbcli_close(cli
->tree
, d_fnum
);
623 fnum_fname
= saved_name
;
624 fnum_fname_new
= saved_name_new
;
626 printf("Trying rename by path while a handle is open\n");
628 fnum
= create_complex_file(cli
, torture
, path_fname
);
629 sfinfo
.rename_information
.in
.new_name
= path_fname_new
+strlen(BASEDIR
)+1;
630 sfinfo
.rename_information
.in
.overwrite
= 0;
631 sfinfo
.rename_information
.in
.root_fid
= 0;
632 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
633 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
634 /* check that the handle returns the same name */
636 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname_new
);
637 /* rename it back on the handle */
638 sfinfo
.rename_information
.in
.new_name
= path_fname
+strlen(BASEDIR
)+1;
639 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
640 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
642 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_fname
);
643 smbcli_close(cli
->tree
, fnum
);
646 printf("Trying rename directory by path while a handle is open\n");
647 status
= create_directory_handle(cli
->tree
, path_dname
, &d_fnum
);
650 saved_name
= path_fname
;
651 saved_name_new
= path_fname_new
;
652 path_fname
= path_dname
;
653 path_fname_new
= path_dname_new
;
654 sfinfo
.rename_information
.in
.new_name
= path_dname_new
+strlen(BASEDIR
)+1;
655 sfinfo
.rename_information
.in
.overwrite
= 0;
656 sfinfo
.rename_information
.in
.root_fid
= 0;
657 CHECK_CALL_PATH(RENAME_INFORMATION
, NT_STATUS_OK
);
658 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
659 path_fname
= saved_name
;
660 path_fname_new
= saved_name_new
;
661 saved_name
= fnum_fname
;
662 saved_name_new
= fnum_fname_new
;
663 fnum_fname
= path_dname
;
664 fnum_fname_new
= path_dname_new
;
665 /* check that the handle returns the same name */
667 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname_new
);
668 /* rename it back on the handle */
669 sfinfo
.rename_information
.in
.new_name
= path_dname
+strlen(BASEDIR
)+1;
670 CHECK_CALL_FNUM(RENAME_INFORMATION
, NT_STATUS_OK
);
671 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
672 fnum_fname
= saved_name
;
673 fnum_fname_new
= saved_name_new
;
674 saved_name
= path_fname
;
675 saved_name_new
= path_fname_new
;
676 path_fname
= path_dname
;
677 path_fname_new
= path_dname_new
;
679 CHECK_STR(NAME_INFO
, name_info
, fname
.s
, path_dname
);
680 smbcli_close(cli
->tree
, d_fnum
);
682 path_fname
= saved_name
;
683 path_fname_new
= saved_name_new
;
686 smb_raw_exit(cli
->session
);
687 smbcli_deltree(cli
->tree
, BASEDIR
);
692 look for the w2k3 setpathinfo STANDARD bug
694 static bool torture_raw_sfileinfo_bug(struct torture_context
*torture
,
695 struct smbcli_state
*cli
)
697 const char *fname
= "\\bug3.txt";
698 union smb_setfileinfo sfinfo
;
702 if (!torture_setting_bool(torture
, "dangerous", false))
703 torture_skip(torture
,
704 "torture_raw_sfileinfo_bug disabled - enable dangerous tests to use\n");
706 fnum
= create_complex_file(cli
, torture
, fname
);
707 smbcli_close(cli
->tree
, fnum
);
709 sfinfo
.generic
.level
= RAW_SFILEINFO_STANDARD
;
710 sfinfo
.generic
.in
.file
.path
= fname
;
712 sfinfo
.standard
.in
.create_time
= 0;
713 sfinfo
.standard
.in
.access_time
= 0;
714 sfinfo
.standard
.in
.write_time
= 0;
716 status
= smb_raw_setpathinfo(cli
->tree
, &sfinfo
);
717 printf("%s - %s\n", fname
, nt_errstr(status
));
719 printf("now try and delete %s\n", fname
);
725 * Test both the snia cifs RAW_SFILEINFO_END_OF_FILE_INFO and the undocumented
726 * pass-through RAW_SFILEINFO_END_OF_FILE_INFORMATION in the context of
730 torture_raw_sfileinfo_eof(struct torture_context
*tctx
,
731 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
733 const char *fname
= BASEDIR
"\\test_sfileinfo_end_of_file.dat";
737 union smb_setfileinfo sfi
;
738 union smb_fileinfo qfi
;
741 if (!torture_setup_dir(cli1
, BASEDIR
)) {
746 smbcli_unlink(cli1
->tree
, fname
);
748 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
749 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
750 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
751 io
.ntcreatex
.in
.alloc_size
= 0;
752 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
753 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
754 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
755 io
.ntcreatex
.in
.create_options
= 0;
756 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
757 io
.ntcreatex
.in
.security_flags
= 0;
758 io
.ntcreatex
.in
.fname
= fname
;
759 io
.ntcreatex
.in
.flags
= 0;
761 /* Open the file sharing none. */
762 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
763 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
764 done
, "Status should be OK");
765 fnum
= io
.ntcreatex
.out
.file
.fnum
;
767 /* Try to sfileinfo to extend the file. */
769 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
770 sfi
.generic
.in
.file
.path
= fname
;
771 sfi
.end_of_file_info
.in
.size
= 100;
772 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
774 /* There should be share mode contention in this case. */
775 torture_assert_ntstatus_equal_goto(tctx
, status
,
776 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
777 "SHARING_VIOLATION");
779 /* Make sure the size is still 0. */
781 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
782 qfi
.generic
.in
.file
.path
= fname
;
783 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
784 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
785 done
, "Status should be OK");
787 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 0,
788 "alloc_size should be 0 since the setpathinfo failed.");
790 /* Try again with the pass through instead of documented version. */
792 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
793 sfi
.generic
.in
.file
.path
= fname
;
794 sfi
.end_of_file_info
.in
.size
= 100;
795 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
798 * Looks like a windows bug:
799 * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html
801 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
802 /* It succeeds! This is just weird! */
803 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
804 ret
, done
, "Status should be OK");
806 /* Verify that the file was actually extended to 100. */
808 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
809 qfi
.generic
.in
.file
.path
= fname
;
810 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
811 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
812 ret
, done
, "Status should be OK");
814 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 100,
815 "alloc_size should be 100 since the setpathinfo "
818 torture_assert_ntstatus_equal_goto(tctx
, status
,
819 NT_STATUS_SHARING_VIOLATION
, ret
, done
, "Status should be "
820 "SHARING_VIOLATION");
823 /* close the first file. */
824 smbcli_close(cli1
->tree
, fnum
);
827 /* Try to sfileinfo to extend the file again (non-pass-through). */
829 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
830 sfi
.generic
.in
.file
.path
= fname
;
831 sfi
.end_of_file_info
.in
.size
= 200;
832 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
834 /* This should cause the client to retun invalid level. */
835 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
837 * Windows sends back an invalid packet that smbclient sees
838 * and returns INTERNAL_ERROR.
840 torture_assert_ntstatus_equal_goto(tctx
, status
,
841 NT_STATUS_INTERNAL_ERROR
, ret
, done
, "Status should be "
844 torture_assert_ntstatus_equal_goto(tctx
, status
,
845 NT_STATUS_INVALID_LEVEL
, ret
, done
, "Status should be "
849 /* Try to extend the file now with the passthrough level. */
850 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
851 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
852 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
853 done
, "Status should be OK");
855 /* Verify that the file was actually extended to 200. */
857 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
858 qfi
.generic
.in
.file
.path
= fname
;
859 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
861 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
862 done
, "Status should be OK");
863 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 200,
864 "alloc_size should be 200 since the setpathinfo succeeded.");
866 /* Open the file so end of file can be set by handle. */
867 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_WRITE
;
868 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
869 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
870 done
, "Status should be OK");
871 fnum
= io
.ntcreatex
.out
.file
.fnum
;
873 /* Try sfileinfo to extend the file by handle (non-pass-through). */
875 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
876 sfi
.generic
.in
.file
.fnum
= fnum
;
877 sfi
.end_of_file_info
.in
.size
= 300;
878 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
879 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
880 done
, "Status should be OK");
882 /* Verify that the file was actually extended to 300. */
884 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
885 qfi
.generic
.in
.file
.path
= fname
;
886 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qfi
);
887 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
888 done
, "Status should be OK");
889 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 300,
890 "alloc_size should be 300 since the setpathinfo succeeded.");
892 /* Try sfileinfo to extend the file by handle (pass-through). */
894 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
895 sfi
.generic
.in
.file
.fnum
= fnum
;
896 sfi
.end_of_file_info
.in
.size
= 400;
897 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
898 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
899 done
, "Status should be OK");
901 /* Verify that the file was actually extended to 300. */
903 qfi
.generic
.level
= RAW_FILEINFO_STANDARD_INFO
;
904 qfi
.generic
.in
.file
.path
= fname
;
905 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qfi
);
906 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
, ret
,
907 done
, "Status should be OK");
908 torture_assert_u64_equal(tctx
, qfi
.standard_info
.out
.size
, 400,
909 "alloc_size should be 400 since the setpathinfo succeeded.");
912 smbcli_close(cli1
->tree
, fnum
);
916 smb_raw_exit(cli1
->session
);
917 smb_raw_exit(cli2
->session
);
918 smbcli_deltree(cli1
->tree
, BASEDIR
);
923 torture_raw_sfileinfo_eof_access(struct torture_context
*tctx
,
924 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
926 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
927 NTSTATUS status
, expected_status
;
930 union smb_setfileinfo sfi
;
932 uint32_t access_mask
= 0;
934 if (!torture_setup_dir(cli1
, BASEDIR
)) {
939 smbcli_unlink(cli1
->tree
, fname
);
942 * base ntcreatex parms
944 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
945 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
946 io
.ntcreatex
.in
.alloc_size
= 0;
947 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
948 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
949 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
950 io
.ntcreatex
.in
.create_options
= 0;
951 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
952 io
.ntcreatex
.in
.security_flags
= 0;
953 io
.ntcreatex
.in
.fname
= fname
;
954 io
.ntcreatex
.in
.flags
= 0;
957 for (access_mask
= 1; access_mask
<= 0x00001FF; access_mask
++) {
958 io
.ntcreatex
.in
.access_mask
= access_mask
;
960 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
961 if (!NT_STATUS_IS_OK(status
)) {
965 fnum
= io
.ntcreatex
.out
.file
.fnum
;
968 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
969 sfi
.generic
.in
.file
.fnum
= fnum
;
970 sfi
.end_of_file_info
.in
.size
= 100;
972 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
974 expected_status
= (access_mask
& SEC_FILE_WRITE_DATA
) ?
975 NT_STATUS_OK
: NT_STATUS_ACCESS_DENIED
;
977 if (!NT_STATUS_EQUAL(expected_status
, status
)) {
978 torture_comment(tctx
, "0x%x wrong\n", access_mask
);
981 torture_assert_ntstatus_equal_goto(tctx
, status
,
982 expected_status
, ret
, done
, "Status Wrong");
984 smbcli_close(cli1
->tree
, fnum
);
988 smb_raw_exit(cli1
->session
);
989 smb_raw_exit(cli2
->session
);
990 smbcli_deltree(cli1
->tree
, BASEDIR
);
995 torture_raw_sfileinfo_archive(struct torture_context
*tctx
,
996 struct smbcli_state
*cli
)
998 const char *fname
= BASEDIR
"\\test_archive.dat";
1002 union smb_setfileinfo sfinfo
;
1003 union smb_fileinfo finfo
;
1006 if (!torture_setup_dir(cli
, BASEDIR
)) {
1011 smbcli_unlink(cli
->tree
, fname
);
1014 * create a normal file, verify archive bit
1016 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1017 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1018 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1019 io
.ntcreatex
.in
.alloc_size
= 0;
1020 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1021 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1022 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1023 io
.ntcreatex
.in
.create_options
= 0;
1024 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1025 io
.ntcreatex
.in
.security_flags
= 0;
1026 io
.ntcreatex
.in
.fname
= fname
;
1027 io
.ntcreatex
.in
.flags
= 0;
1028 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1029 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1030 ret
, done
, "open failed");
1031 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1033 torture_assert_int_equal(tctx
,
1034 io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1035 FILE_ATTRIBUTE_ARCHIVE
,
1036 "archive bit not set");
1039 * try to turn off archive bit
1041 ZERO_STRUCT(sfinfo
);
1042 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1043 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1044 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_NORMAL
;
1045 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1046 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1047 ret
, done
, "setfileinfo failed");
1049 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1050 finfo
.generic
.in
.file
.fnum
= fnum
;
1051 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1052 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1053 ret
, done
, "fileinfo failed");
1055 torture_assert_int_equal(tctx
,
1056 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1057 FILE_ATTRIBUTE_NORMAL
,
1060 status
= smbcli_close(cli
->tree
, fnum
);
1061 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1062 ret
, done
, "close failed");
1064 status
= smbcli_unlink(cli
->tree
, fname
);
1065 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1066 ret
, done
, "unlink failed");
1069 * create a directory, verify no archive bit
1071 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1072 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1073 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_DIR_ALL
;
1074 io
.ntcreatex
.in
.alloc_size
= 0;
1075 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
1076 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1077 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1078 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
1079 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1080 io
.ntcreatex
.in
.security_flags
= 0;
1081 io
.ntcreatex
.in
.fname
= fname
;
1082 io
.ntcreatex
.in
.flags
= 0;
1083 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
1084 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1085 ret
, done
, "directory open failed");
1086 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1088 torture_assert_int_equal(tctx
,
1089 io
.ntcreatex
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1090 FILE_ATTRIBUTE_DIRECTORY
,
1094 * verify you can turn on archive bit
1096 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1097 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1098 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
;
1099 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1100 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1101 ret
, done
, "setfileinfo failed");
1103 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1104 finfo
.generic
.in
.file
.fnum
= fnum
;
1105 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1106 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1107 ret
, done
, "fileinfo failed");
1109 torture_assert_int_equal(tctx
,
1110 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1111 FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_ARCHIVE
,
1112 "archive bit not set");
1115 * and try to turn it back off
1117 sfinfo
.generic
.level
= RAW_SFILEINFO_BASIC_INFO
;
1118 sfinfo
.generic
.in
.file
.fnum
= fnum
;
1119 sfinfo
.basic_info
.in
.attrib
= FILE_ATTRIBUTE_DIRECTORY
;
1120 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
1121 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1122 ret
, done
, "setfileinfo failed");
1124 finfo
.generic
.level
= RAW_FILEINFO_ALL_INFO
;
1125 finfo
.generic
.in
.file
.fnum
= fnum
;
1126 status
= smb_raw_fileinfo(cli
->tree
, tctx
, &finfo
);
1127 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1128 ret
, done
, "fileinfo failed");
1130 torture_assert_int_equal(tctx
,
1131 finfo
.all_info
.out
.attrib
& ~FILE_ATTRIBUTE_NONINDEXED
,
1132 FILE_ATTRIBUTE_DIRECTORY
,
1135 status
= smbcli_close(cli
->tree
, fnum
);
1136 torture_assert_ntstatus_equal_goto(tctx
, status
, NT_STATUS_OK
,
1137 ret
, done
, "close failed");
1140 smbcli_close(cli
->tree
, fnum
);
1141 smbcli_deltree(cli
->tree
, BASEDIR
);
1145 struct torture_suite
*torture_raw_sfileinfo(TALLOC_CTX
*mem_ctx
)
1147 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "sfileinfo");
1149 torture_suite_add_1smb_test(suite
, "base", torture_raw_sfileinfo_base
);
1150 torture_suite_add_1smb_test(suite
, "rename", torture_raw_sfileinfo_rename
);
1151 torture_suite_add_1smb_test(suite
, "bug", torture_raw_sfileinfo_bug
);
1152 torture_suite_add_2smb_test(suite
, "end-of-file",
1153 torture_raw_sfileinfo_eof
);
1154 torture_suite_add_2smb_test(suite
, "end-of-file-access",
1155 torture_raw_sfileinfo_eof_access
);
1156 torture_suite_add_1smb_test(suite
, "archive",
1157 torture_raw_sfileinfo_archive
);