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