3b6de674ec1fd1e52985c5f66daebd5f0e188a36
[kamenim/samba.git] / source4 / torture / raw / setfileinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RAW_SFILEINFO_* individual test suite
4    Copyright (C) Andrew Tridgell 2003
5    
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.
10    
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.
15    
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/>.
18 */
19
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"
25
26 #define BASEDIR "\\testsfileinfo"
27
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. 
31 */
32 static bool
33 torture_raw_sfileinfo_base(struct torture_context *torture, struct smbcli_state *cli)
34 {
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;
48         
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);
53
54         if (!torture_setup_dir(cli, BASEDIR)) {
55                 return false;
56         }
57
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)
67
68 #define RECREATE_BOTH do { \
69                 RECREATE_FILE(path_fname); \
70                 smbcli_close(cli->tree, fnum); \
71                 RECREATE_FILE(fnum_fname); \
72         } while (0)
73
74         RECREATE_BOTH;
75         
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)
94
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); \
104         } \
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; \
109         } \
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); \
116         } \
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)
121
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); \
134                         } \
135                 } \
136                 if (!NT_STATUS_IS_OK(status2)) { \
137                         printf("%s - %s\n", #call, nt_errstr(status2)); \
138                         ret = false; \
139                 } \
140         }} while (0)
141
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                        (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
148                 dump_all_info(torture, &finfo1); \
149                 ret = false; \
150         }} while (0)
151
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                         (unsigned int)value, \
158                         (unsigned int)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)
164
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)
175
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)
183
184         
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);
191
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);
198
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);
205
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);
214
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);
222
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);
231
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);
245
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);
258
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);
272
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);
279
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);
292
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);
297
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);
301         */
302         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);
303
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);
309
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);
314
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);
320
321         /* this would delete the file! */
322         /*
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);
326         */
327
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);
332
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);
336
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);
342
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);
347
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);
353
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);
357
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);
362
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);
368
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);
373
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);
377
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);
381
382         CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
383         CHECK_VALUE(ALL_INFO, all_info, size, 37);
384
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);
388
389         CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
390         CHECK_VALUE(ALL_INFO, all_info, size, 7);
391
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);
396
397         CHECK_CALL_PATH(POSITION_INFORMATION, NT_STATUS_OK);
398         CHECK_VALUE(POSITION_INFORMATION, position_information, position, 0);
399
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);
404
405         CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
406         CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
407
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);
411
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);
415
416         CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
417         CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
418
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);
423
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
428
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));
434         }
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));
437         }
438
439         return ret;
440 }
441
442 /*
443  * basic testing of all RAW_SFILEINFO_RENAME call
444  */
445 static bool
446 torture_raw_sfileinfo_rename(struct torture_context *torture,
447     struct smbcli_state *cli)
448 {
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;
465         
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);
472
473         if (!torture_setup_dir(cli, BASEDIR)) {
474                 return false;
475         }
476
477         RECREATE_BOTH;
478
479         ZERO_STRUCT(sfinfo);
480
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));
483
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);
488
489         sfinfo.rename_information.in.new_name  = path_fname_new+strlen(BASEDIR)+1;
490         CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OBJECT_NAME_COLLISION);
491
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);
495
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);
500
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);
507
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;
513
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);
518
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);
522
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);
528
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);
535
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);
540
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);
545
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);
549
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);
553
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);
562
563         printf("Trying rename directory\n");
564         if (!torture_setup_dir(cli, path_dname)) {
565                 ret = false;
566                 goto done;
567         }
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;
579
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;
585         }
586
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;
604
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;
624
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;
663
664 done:
665         smb_raw_exit(cli->session);
666         smbcli_deltree(cli->tree, BASEDIR);
667         return ret;
668 }
669
670 /* 
671    look for the w2k3 setpathinfo STANDARD bug
672 */
673 static bool torture_raw_sfileinfo_bug(struct torture_context *torture,
674     struct smbcli_state *cli)
675 {
676         const char *fname = "\\bug3.txt";
677         union smb_setfileinfo sfinfo;
678         NTSTATUS status;
679         int fnum;
680
681         if (!torture_setting_bool(torture, "dangerous", false))
682                 torture_skip(torture, 
683                         "torture_raw_sfileinfo_bug disabled - enable dangerous tests to use\n");
684
685         fnum = create_complex_file(cli, torture, fname);
686         smbcli_close(cli->tree, fnum);
687
688         sfinfo.generic.level = RAW_SFILEINFO_STANDARD;
689         sfinfo.generic.in.file.path = fname;
690
691         sfinfo.standard.in.create_time = 0;
692         sfinfo.standard.in.access_time = 0;
693         sfinfo.standard.in.write_time  = 0;
694
695         status = smb_raw_setpathinfo(cli->tree, &sfinfo);
696         printf("%s - %s\n", fname, nt_errstr(status));
697
698         printf("now try and delete %s\n", fname);
699
700         return true;
701 }
702
703 /**
704  * Test both the snia cifs RAW_SFILEINFO_END_OF_FILE_INFO and the undocumented
705  * pass-through RAW_SFILEINFO_END_OF_FILE_INFORMATION in the context of
706  * trans2setpathinfo.
707  */
708 static bool
709 torture_raw_sfileinfo_eof(struct torture_context *tctx,
710     struct smbcli_state *cli1, struct smbcli_state *cli2)
711 {
712         const char *fname = BASEDIR "\\test_sfileinfo_end_of_file.dat";
713         NTSTATUS status;
714         bool ret = true;
715         union smb_open io;
716         union smb_setfileinfo sfi;
717         union smb_fileinfo qfi;
718         uint16_t fnum = 0;
719
720         if (!torture_setup_dir(cli1, BASEDIR)) {
721                 return false;
722         }
723
724         /* cleanup */
725         smbcli_unlink(cli1->tree, fname);
726
727         io.generic.level = RAW_OPEN_NTCREATEX;
728         io.ntcreatex.in.root_fid.fnum = 0;
729         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
730         io.ntcreatex.in.alloc_size = 0;
731         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
732         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
733         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
734         io.ntcreatex.in.create_options = 0;
735         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
736         io.ntcreatex.in.security_flags = 0;
737         io.ntcreatex.in.fname = fname;
738         io.ntcreatex.in.flags = 0;
739
740         /* Open the file sharing none. */
741         status = smb_raw_open(cli1->tree, tctx, &io);
742         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
743             done, "Status should be OK");
744         fnum = io.ntcreatex.out.file.fnum;
745
746         /* Try to sfileinfo to extend the file. */
747         ZERO_STRUCT(sfi);
748         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
749         sfi.generic.in.file.path = fname;
750         sfi.end_of_file_info.in.size = 100;
751         status = smb_raw_setpathinfo(cli2->tree, &sfi);
752
753         /* There should be share mode contention in this case. */
754         torture_assert_ntstatus_equal_goto(tctx, status,
755             NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be "
756             "SHARING_VIOLATION");
757
758         /* Make sure the size is still 0. */
759         ZERO_STRUCT(qfi);
760         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
761         qfi.generic.in.file.path = fname;
762         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
763         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
764             done, "Status should be OK");
765
766         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 0,
767             "alloc_size should be 0 since the setpathinfo failed.");
768
769         /* Try again with the pass through instead of documented version. */
770         ZERO_STRUCT(sfi);
771         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
772         sfi.generic.in.file.path = fname;
773         sfi.end_of_file_info.in.size = 100;
774         status = smb_raw_setpathinfo(cli2->tree, &sfi);
775
776         /*
777          * Looks like a windows bug:
778          * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html
779          */
780         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
781                 /* It succeeds! This is just weird! */
782                 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
783                     ret, done, "Status should be OK");
784
785                 /* Verify that the file was actually extended to 100. */
786                 ZERO_STRUCT(qfi);
787                 qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
788                 qfi.generic.in.file.path = fname;
789                 status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
790                 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
791                     ret, done, "Status should be OK");
792
793                 torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 100,
794                     "alloc_size should be 100 since the setpathinfo "
795                     "succeeded.");
796         } else {
797                 torture_assert_ntstatus_equal_goto(tctx, status,
798                     NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be "
799                     "SHARING_VIOLATION");
800         }
801
802         /* close the first file. */
803         smbcli_close(cli1->tree, fnum);
804         fnum = 0;
805
806         /* Try to sfileinfo to extend the file again (non-pass-through). */
807         ZERO_STRUCT(sfi);
808         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
809         sfi.generic.in.file.path = fname;
810         sfi.end_of_file_info.in.size = 200;
811         status = smb_raw_setpathinfo(cli2->tree, &sfi);
812
813         /* This should cause the client to retun invalid level. */
814         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
815                 /*
816                  * Windows sends back an invalid packet that smbclient sees
817                  * and returns INTERNAL_ERROR.
818                  */
819                 torture_assert_ntstatus_equal_goto(tctx, status,
820                     NT_STATUS_INTERNAL_ERROR, ret, done, "Status should be "
821                     "INTERNAL_ERROR");
822         } else {
823                 torture_assert_ntstatus_equal_goto(tctx, status,
824                     NT_STATUS_INVALID_LEVEL, ret, done, "Status should be "
825                     "INVALID_LEVEL");
826         }
827
828         /* Try to extend the file now with the passthrough level. */
829         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
830         status = smb_raw_setpathinfo(cli2->tree, &sfi);
831         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
832             done, "Status should be OK");
833
834         /* Verify that the file was actually extended to 200. */
835         ZERO_STRUCT(qfi);
836         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
837         qfi.generic.in.file.path = fname;
838         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
839
840         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
841             done, "Status should be OK");
842         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 200,
843             "alloc_size should be 200 since the setpathinfo succeeded.");
844
845         /* Open the file so end of file can be set by handle. */
846         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE;
847         status = smb_raw_open(cli1->tree, tctx, &io);
848         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
849             done, "Status should be OK");
850         fnum = io.ntcreatex.out.file.fnum;
851
852         /* Try sfileinfo to extend the file by handle (non-pass-through). */
853         ZERO_STRUCT(sfi);
854         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
855         sfi.generic.in.file.fnum = fnum;
856         sfi.end_of_file_info.in.size = 300;
857         status = smb_raw_setfileinfo(cli1->tree, &sfi);
858         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
859             done, "Status should be OK");
860
861         /* Verify that the file was actually extended to 300. */
862         ZERO_STRUCT(qfi);
863         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
864         qfi.generic.in.file.path = fname;
865         status = smb_raw_pathinfo(cli1->tree, tctx, &qfi);
866         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
867             done, "Status should be OK");
868         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 300,
869             "alloc_size should be 300 since the setpathinfo succeeded.");
870
871         /* Try sfileinfo to extend the file by handle (pass-through). */
872         ZERO_STRUCT(sfi);
873         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
874         sfi.generic.in.file.fnum = fnum;
875         sfi.end_of_file_info.in.size = 400;
876         status = smb_raw_setfileinfo(cli1->tree, &sfi);
877         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
878             done, "Status should be OK");
879
880         /* Verify that the file was actually extended to 300. */
881         ZERO_STRUCT(qfi);
882         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
883         qfi.generic.in.file.path = fname;
884         status = smb_raw_pathinfo(cli1->tree, tctx, &qfi);
885         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
886             done, "Status should be OK");
887         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 400,
888             "alloc_size should be 400 since the setpathinfo succeeded.");
889  done:
890         if (fnum > 0) {
891                 smbcli_close(cli1->tree, fnum);
892                 fnum = 0;
893         }
894
895         smb_raw_exit(cli1->session);
896         smb_raw_exit(cli2->session);
897         smbcli_deltree(cli1->tree, BASEDIR);
898         return ret;
899 }
900
901 static bool
902 torture_raw_sfileinfo_eof_access(struct torture_context *tctx,
903     struct smbcli_state *cli1, struct smbcli_state *cli2)
904 {
905         const char *fname = BASEDIR "\\test_exclusive3.dat";
906         NTSTATUS status, expected_status;
907         bool ret = true;
908         union smb_open io;
909         union smb_setfileinfo sfi;
910         uint16_t fnum=0;
911         uint32_t access_mask = 0;
912
913         if (!torture_setup_dir(cli1, BASEDIR)) {
914                 return false;
915         }
916
917         /* cleanup */
918         smbcli_unlink(cli1->tree, fname);
919
920         /*
921          * base ntcreatex parms
922          */
923         io.generic.level = RAW_OPEN_NTCREATEX;
924         io.ntcreatex.in.root_fid.fnum = 0;
925         io.ntcreatex.in.alloc_size = 0;
926         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
927         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
928         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
929         io.ntcreatex.in.create_options = 0;
930         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
931         io.ntcreatex.in.security_flags = 0;
932         io.ntcreatex.in.fname = fname;
933         io.ntcreatex.in.flags = 0;
934
935
936         for (access_mask = 1; access_mask <= 0x00001FF; access_mask++) {
937                 io.ntcreatex.in.access_mask = access_mask;
938
939                 status = smb_raw_open(cli1->tree, tctx, &io);
940                 if (!NT_STATUS_IS_OK(status)) {
941                         continue;
942                 }
943
944                 fnum = io.ntcreatex.out.file.fnum;
945
946                 ZERO_STRUCT(sfi);
947                 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
948                 sfi.generic.in.file.fnum = fnum;
949                 sfi.end_of_file_info.in.size = 100;
950
951                 status = smb_raw_setfileinfo(cli1->tree, &sfi);
952
953                 expected_status = (access_mask & SEC_FILE_WRITE_DATA) ?
954                     NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
955
956                 if (!NT_STATUS_EQUAL(expected_status, status)) {
957                         torture_comment(tctx, "0x%x wrong\n", access_mask);
958                 }
959
960                 torture_assert_ntstatus_equal_goto(tctx, status,
961                     expected_status, ret, done, "Status Wrong");
962
963                 smbcli_close(cli1->tree, fnum);
964         }
965
966 done:
967         smb_raw_exit(cli1->session);
968         smb_raw_exit(cli2->session);
969         smbcli_deltree(cli1->tree, BASEDIR);
970         return ret;
971 }
972
973 static bool
974 torture_raw_sfileinfo_archive(struct torture_context *tctx,
975     struct smbcli_state *cli)
976 {
977         const char *fname = BASEDIR "\\test_archive.dat";
978         NTSTATUS status;
979         bool ret = true;
980         union smb_open io;
981         union smb_setfileinfo sfinfo;
982         union smb_fileinfo finfo;
983         uint16_t fnum=0;
984
985         if (!torture_setup_dir(cli, BASEDIR)) {
986                 return false;
987         }
988
989         /* cleanup */
990         smbcli_unlink(cli->tree, fname);
991
992         /*
993          * create a normal file, verify archive bit
994          */
995         io.generic.level = RAW_OPEN_NTCREATEX;
996         io.ntcreatex.in.root_fid.fnum = 0;
997         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
998         io.ntcreatex.in.alloc_size = 0;
999         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1000         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1001         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1002         io.ntcreatex.in.create_options = 0;
1003         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1004         io.ntcreatex.in.security_flags = 0;
1005         io.ntcreatex.in.fname = fname;
1006         io.ntcreatex.in.flags = 0;
1007         status = smb_raw_open(cli->tree, tctx, &io);
1008         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1009             ret, done, "open failed");
1010         fnum = io.ntcreatex.out.file.fnum;
1011
1012         torture_assert_int_equal(tctx,
1013             io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1014             FILE_ATTRIBUTE_ARCHIVE,
1015             "archive bit not set");
1016
1017         /*
1018          * try to turn off archive bit
1019          */
1020         ZERO_STRUCT(sfinfo);
1021         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1022         sfinfo.generic.in.file.fnum = fnum;
1023         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
1024         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1025         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1026             ret, done, "setfileinfo failed");
1027
1028         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1029         finfo.generic.in.file.fnum = fnum;
1030         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1031         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1032             ret, done, "fileinfo failed");
1033
1034         torture_assert_int_equal(tctx,
1035             finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1036             FILE_ATTRIBUTE_NORMAL,
1037             "archive bit set");
1038
1039         status = smbcli_close(cli->tree, fnum);
1040         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1041             ret, done, "close failed");
1042
1043         status = smbcli_unlink(cli->tree, fname);
1044         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1045             ret, done, "unlink failed");
1046
1047         /*
1048          * create a directory, verify no archive bit
1049          */
1050         io.generic.level = RAW_OPEN_NTCREATEX;
1051         io.ntcreatex.in.root_fid.fnum = 0;
1052         io.ntcreatex.in.access_mask = SEC_RIGHTS_DIR_ALL;
1053         io.ntcreatex.in.alloc_size = 0;
1054         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1055         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1056         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1057         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1058         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1059         io.ntcreatex.in.security_flags = 0;
1060         io.ntcreatex.in.fname = fname;
1061         io.ntcreatex.in.flags = 0;
1062         status = smb_raw_open(cli->tree, tctx, &io);
1063         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1064             ret, done, "directory open failed");
1065         fnum = io.ntcreatex.out.file.fnum;
1066
1067         torture_assert_int_equal(tctx,
1068             io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1069             FILE_ATTRIBUTE_DIRECTORY,
1070             "archive bit set");
1071
1072         /*
1073          * verify you can turn on archive bit
1074          */
1075         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1076         sfinfo.generic.in.file.fnum = fnum;
1077         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE;
1078         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1079         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1080             ret, done, "setfileinfo failed");
1081
1082         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1083         finfo.generic.in.file.fnum = fnum;
1084         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1085         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1086             ret, done, "fileinfo failed");
1087
1088         torture_assert_int_equal(tctx,
1089             finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1090             FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE,
1091             "archive bit not set");
1092
1093         /*
1094          * and try to turn it back off
1095          */
1096         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1097         sfinfo.generic.in.file.fnum = fnum;
1098         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
1099         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1100         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1101             ret, done, "setfileinfo failed");
1102
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");
1108
1109         torture_assert_int_equal(tctx,
1110             finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1111             FILE_ATTRIBUTE_DIRECTORY,
1112             "archive bit set");
1113
1114         status = smbcli_close(cli->tree, fnum);
1115         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1116             ret, done, "close failed");
1117
1118 done:
1119         smbcli_close(cli->tree, fnum);
1120         smbcli_deltree(cli->tree, BASEDIR);
1121         return ret;
1122 }
1123
1124 struct torture_suite *torture_raw_sfileinfo(TALLOC_CTX *mem_ctx)
1125 {
1126         struct torture_suite *suite = torture_suite_create(mem_ctx,
1127             "SFILEINFO");
1128
1129         torture_suite_add_1smb_test(suite, "BASE", torture_raw_sfileinfo_base);
1130         torture_suite_add_1smb_test(suite, "RENAME",
1131                                       torture_raw_sfileinfo_rename);
1132         torture_suite_add_1smb_test(suite, "BUG", torture_raw_sfileinfo_bug);
1133         torture_suite_add_2smb_test(suite, "END-OF-FILE",
1134             torture_raw_sfileinfo_eof);
1135         torture_suite_add_2smb_test(suite, "END-OF-FILE-ACCESS",
1136             torture_raw_sfileinfo_eof_access);
1137         torture_suite_add_1smb_test(suite, "ARCHIVE", torture_raw_sfileinfo_archive);
1138
1139         return suite;
1140 }