s4-smbtorture: Make test names lowercase and dot-separated.
[kai/samba-autobuild/.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, NT_STATUS_NOT_SUPPORTED)) { \
83                 torture_warning(torture, \
84                         "(%s) %s - %s", __location__, #call, \
85                         nt_errstr(status)); \
86         } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
87                 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
88                         nt_errstr(status), nt_errstr(rightstatus)); \
89                 ret = false; \
90         } \
91         finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
92         finfo1.generic.in.file.fnum = fnum; \
93         status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
94         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
95                 torture_warning(torture, \
96                         "(%s) %s - %s", __location__, #call, \
97                         nt_errstr(status)); \
98         } else if (!NT_STATUS_IS_OK(status2)) { \
99                 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
100                 ret = false; \
101         }} while (0)
102
103 #define CHECK_CALL_PATH(call, rightstatus) do { \
104         check_fnum = false; \
105         call_name = #call; \
106         sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
107         sfinfo.generic.in.file.path = path_fname; \
108         status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
109         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
110                 sfinfo.generic.in.file.path = path_fname_new; \
111                 status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
112         } \
113         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
114                 torture_warning(torture, \
115                         "(%s) %s - %s", __location__, #call, \
116                         nt_errstr(status)); \
117         } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
118                 printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
119                         nt_errstr(status), nt_errstr(rightstatus)); \
120                 ret = false; \
121         } \
122         finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
123         finfo1.generic.in.file.path = path_fname; \
124         status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
125         if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
126                 finfo1.generic.in.file.path = path_fname_new; \
127                 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
128         } \
129         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
130                 torture_warning(torture, \
131                         "(%s) %s - %s", __location__, #call, \
132                         nt_errstr(status)); \
133         } else if (!NT_STATUS_IS_OK(status2)) { \
134                 printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \
135                 ret = false; \
136         }} while (0)
137
138 #define CHECK1(call) \
139         do { if (NT_STATUS_IS_OK(status)) { \
140                 finfo2.generic.level = RAW_FILEINFO_ ## call; \
141                 if (check_fnum) { \
142                         finfo2.generic.in.file.fnum = fnum; \
143                         status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
144                 } else { \
145                         finfo2.generic.in.file.path = path_fname; \
146                         status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
147                         if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
148                                 finfo2.generic.in.file.path = path_fname_new; \
149                                 status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
150                         } \
151                 } \
152                 if (!NT_STATUS_IS_OK(status2)) { \
153                         printf("%s - %s\n", #call, nt_errstr(status2)); \
154                         ret = false; \
155                 } \
156         }} while (0)
157
158 #define CHECK_VALUE(call, stype, field, value) do { \
159         CHECK1(call); \
160         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
161                 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
162                        call_name, #stype, #field, \
163                        (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
164                 dump_all_info(torture, &finfo1); \
165                 ret = false; \
166         }} while (0)
167
168 #define CHECK_TIME(call, stype, field, value) do { \
169         CHECK1(call); \
170         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
171                 printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
172                         call_name, #stype, #field, \
173                         (unsigned int)value, \
174                         (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
175                 printf("\t%s", timestring(torture, value)); \
176                 printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
177                 dump_all_info(torture, &finfo1); \
178                 ret = false; \
179         }} while (0)
180
181 #define CHECK_STR(call, stype, field, value) do { \
182         CHECK1(call); \
183         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
184                 printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
185                         call_name, #stype, #field, \
186                         value, \
187                         finfo2.stype.out.field); \
188                 dump_all_info(torture, &finfo1); \
189                 ret = false; \
190         }} while (0)
191
192 #define CHECK_STATUS(status, correct) do { \
193         if (!NT_STATUS_EQUAL(status, correct)) { \
194                 printf("(%s) Incorrect status %s - should be %s\n", \
195                        __location__, nt_errstr(status), nt_errstr(correct)); \
196                 ret = false; \
197                 goto done; \
198         }} while (0)
199
200         
201         printf("Test setattr\n");
202         sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_READONLY;
203         sfinfo.setattr.in.write_time = basetime;
204         CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
205         CHECK_VALUE  (ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);
206         CHECK_TIME   (ALL_INFO, all_info, write_time, basetime);
207
208         printf("setting to NORMAL doesn't do anything\n");
209         sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_NORMAL;
210         sfinfo.setattr.in.write_time = 0;
211         CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
212         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);
213         CHECK_TIME (ALL_INFO, all_info, write_time, basetime);
214
215         printf("a zero write_time means don't change\n");
216         sfinfo.setattr.in.attrib = 0;
217         sfinfo.setattr.in.write_time = 0;
218         CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
219         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);
220         CHECK_TIME (ALL_INFO, all_info, write_time, basetime);
221
222         printf("Test setattre\n");
223         sfinfo.setattre.in.create_time = basetime + 20;
224         sfinfo.setattre.in.access_time = basetime + 30;
225         sfinfo.setattre.in.write_time  = basetime + 40;
226         CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
227         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
228         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
229         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 40);
230
231         sfinfo.setattre.in.create_time = 0;
232         sfinfo.setattre.in.access_time = 0;
233         sfinfo.setattre.in.write_time  = 0;
234         CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
235         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
236         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
237         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 40);
238
239         printf("Test standard level\n");
240         sfinfo.standard.in.create_time = basetime + 100;
241         sfinfo.standard.in.access_time = basetime + 200;
242         sfinfo.standard.in.write_time  = basetime + 300;
243         CHECK_CALL_FNUM(STANDARD, NT_STATUS_OK);
244         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
245         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
246         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
247
248         printf("Test basic_info level\n");
249         basetime += 86400;
250         unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
251         unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
252         unix_to_nt_time(&sfinfo.basic_info.in.write_time,  basetime + 300);
253         unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
254         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
255         CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
256         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
257         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
258         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
259         CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
260         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);
261
262         printf("a zero time means don't change\n");
263         unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
264         unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
265         unix_to_nt_time(&sfinfo.basic_info.in.write_time,  0);
266         unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
267         sfinfo.basic_info.in.attrib = 0;
268         CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
269         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
270         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
271         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
272         CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
273         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);
274
275         printf("Test basic_information level\n");
276         basetime += 86400;
277         unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
278         unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
279         unix_to_nt_time(&sfinfo.basic_info.in.write_time,  basetime + 300);
280         unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
281         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
282         CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
283         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
284         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
285         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
286         CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
287         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);
288
289         CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
290         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
291         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
292         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
293         CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
294         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);
295
296         torture_comment(torture, "try to change a file to a directory\n");
297         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
298         CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_INVALID_PARAMETER);
299
300         printf("a zero time means don't change\n");
301         unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
302         unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
303         unix_to_nt_time(&sfinfo.basic_info.in.write_time,  0);
304         unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
305         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
306         CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
307         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
308         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
309         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
310         CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
311         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);
312
313         CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
314         CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
315         CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
316         CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
317
318         /* interesting - w2k3 leaves change_time as current time for 0 change time
319            in setpathinfo
320           CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
321         */
322         CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);
323
324         printf("Test disposition_info level\n");
325         sfinfo.disposition_info.in.delete_on_close = 1;
326         CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
327         CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
328         CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
329
330         sfinfo.disposition_info.in.delete_on_close = 0;
331         CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
332         CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
333         CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
334
335         printf("Test disposition_information level\n");
336         sfinfo.disposition_info.in.delete_on_close = 1;
337         CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
338         CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
339         CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
340
341         /* this would delete the file! */
342         /*
343           CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
344           CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
345           CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
346         */
347
348         sfinfo.disposition_info.in.delete_on_close = 0;
349         CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
350         CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
351         CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
352
353         CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
354         CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
355         CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
356
357         printf("Test allocation_info level\n");
358         sfinfo.allocation_info.in.alloc_size = 0;
359         CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
360         CHECK_VALUE(ALL_INFO, all_info, size, 0);
361         CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
362
363         sfinfo.allocation_info.in.alloc_size = 4096;
364         CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
365         CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
366         CHECK_VALUE(ALL_INFO, all_info, size, 0);
367
368         RECREATE_BOTH;
369         sfinfo.allocation_info.in.alloc_size = 0;
370         CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
371         CHECK_VALUE(ALL_INFO, all_info, size, 0);
372         CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
373
374         CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
375         CHECK_VALUE(ALL_INFO, all_info, size, 0);
376         CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
377
378         sfinfo.allocation_info.in.alloc_size = 4096;
379         CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
380         CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
381         CHECK_VALUE(ALL_INFO, all_info, size, 0);
382
383         /* setting the allocation size up via setpathinfo seems
384            to be broken in w2k3 */
385         CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
386         CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
387         CHECK_VALUE(ALL_INFO, all_info, size, 0);
388
389         printf("Test end_of_file_info level\n");
390         sfinfo.end_of_file_info.in.size = 37;
391         CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
392         CHECK_VALUE(ALL_INFO, all_info, size, 37);
393
394         sfinfo.end_of_file_info.in.size = 7;
395         CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
396         CHECK_VALUE(ALL_INFO, all_info, size, 7);
397
398         sfinfo.end_of_file_info.in.size = 37;
399         CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
400         CHECK_VALUE(ALL_INFO, all_info, size, 37);
401
402         CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
403         CHECK_VALUE(ALL_INFO, all_info, size, 37);
404
405         sfinfo.end_of_file_info.in.size = 7;
406         CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
407         CHECK_VALUE(ALL_INFO, all_info, size, 7);
408
409         CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
410         CHECK_VALUE(ALL_INFO, all_info, size, 7);
411
412         printf("Test position_information level\n");
413         sfinfo.position_information.in.position = 123456;
414         CHECK_CALL_FNUM(POSITION_INFORMATION, NT_STATUS_OK);
415         CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
416
417         CHECK_CALL_PATH(POSITION_INFORMATION, NT_STATUS_OK);
418         CHECK_VALUE(POSITION_INFORMATION, position_information, position, 0);
419
420         printf("Test mode_information level\n");
421         sfinfo.mode_information.in.mode = 2;
422         CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
423         CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
424
425         CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
426         CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
427
428         sfinfo.mode_information.in.mode = 1;
429         CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
430         CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
431
432         sfinfo.mode_information.in.mode = 0;
433         CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
434         CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
435
436         CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
437         CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
438
439 #if 0
440         printf("Test unix_basic level\n");
441         CHECK_CALL_FNUM(UNIX_BASIC, NT_STATUS_OK);
442         CHECK_CALL_PATH(UNIX_BASIC, NT_STATUS_OK);
443
444         printf("Test unix_link level\n");
445         CHECK_CALL_FNUM(UNIX_LINK, NT_STATUS_OK);
446         CHECK_CALL_PATH(UNIX_LINK, NT_STATUS_OK);
447 #endif
448
449 done:
450         smb_raw_exit(cli->session);
451         smbcli_close(cli->tree, fnum);
452         if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) {
453                 printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree));
454         }
455         if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
456                 printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
457         }
458
459         return ret;
460 }
461
462 /*
463  * basic testing of all RAW_SFILEINFO_RENAME call
464  */
465 static bool
466 torture_raw_sfileinfo_rename(struct torture_context *torture,
467     struct smbcli_state *cli)
468 {
469         bool ret = true;
470         int fnum_saved, d_fnum, fnum2, fnum = -1;
471         char *fnum_fname;
472         char *fnum_fname_new;
473         char *path_fname;
474         char *path_fname_new;
475         char *path_dname;
476         char *path_dname_new;
477         char *saved_name;
478         char *saved_name_new;
479         union smb_fileinfo finfo1, finfo2;
480         union smb_setfileinfo sfinfo;
481         NTSTATUS status, status2;
482         const char *call_name;
483         bool check_fnum;
484         int n = time(NULL) % 100;
485         
486         asprintf(&path_fname, BASEDIR "\\fname_test_%d.txt", n);
487         asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n);
488         asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n);
489         asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n);
490         asprintf(&path_dname, BASEDIR "\\dname_test_%d", n);
491         asprintf(&path_dname_new, BASEDIR "\\dname_test_new_%d", n);
492
493         if (!torture_setup_dir(cli, BASEDIR)) {
494                 return false;
495         }
496
497         RECREATE_BOTH;
498
499         ZERO_STRUCT(sfinfo);
500
501         smbcli_close(cli->tree, create_complex_file(cli, torture, fnum_fname_new));
502         smbcli_close(cli->tree, create_complex_file(cli, torture, path_fname_new));
503
504         sfinfo.rename_information.in.overwrite = 0;
505         sfinfo.rename_information.in.root_fid  = 0;
506         sfinfo.rename_information.in.new_name  = fnum_fname_new+strlen(BASEDIR)+1;
507         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OBJECT_NAME_COLLISION);
508
509         sfinfo.rename_information.in.new_name  = path_fname_new+strlen(BASEDIR)+1;
510         CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OBJECT_NAME_COLLISION);
511
512         sfinfo.rename_information.in.new_name  = fnum_fname_new;
513         sfinfo.rename_information.in.overwrite = 1;
514         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_NOT_SUPPORTED);
515
516         sfinfo.rename_information.in.new_name  = fnum_fname_new+strlen(BASEDIR)+1;
517         sfinfo.rename_information.in.overwrite = 1;
518         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
519         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname_new);
520
521         printf("Trying rename with dest file open\n");
522         fnum2 = create_complex_file(cli, torture, fnum_fname);
523         sfinfo.rename_information.in.new_name  = fnum_fname+strlen(BASEDIR)+1;
524         sfinfo.rename_information.in.overwrite = 1;
525         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_ACCESS_DENIED);
526         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname_new);
527
528         fnum_saved = fnum;
529         fnum = fnum2;
530         sfinfo.disposition_info.in.delete_on_close = 1;
531         CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
532         fnum = fnum_saved;
533
534         printf("Trying rename with dest file open and delete_on_close\n");
535         sfinfo.rename_information.in.new_name  = fnum_fname+strlen(BASEDIR)+1;
536         sfinfo.rename_information.in.overwrite = 1;
537         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_ACCESS_DENIED);
538
539         smbcli_close(cli->tree, fnum2);
540         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
541         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
542
543         printf("Trying rename with source file open twice\n");
544         sfinfo.rename_information.in.new_name  = fnum_fname+strlen(BASEDIR)+1;
545         sfinfo.rename_information.in.overwrite = 1;
546         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
547         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
548
549         fnum2 = create_complex_file(cli, torture, fnum_fname);
550         sfinfo.rename_information.in.new_name  = fnum_fname_new+strlen(BASEDIR)+1;
551         sfinfo.rename_information.in.overwrite = 0;
552         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
553         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname_new);
554         smbcli_close(cli->tree, fnum2);
555
556         sfinfo.rename_information.in.new_name  = fnum_fname+strlen(BASEDIR)+1;
557         sfinfo.rename_information.in.overwrite = 0;
558         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
559         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
560
561         sfinfo.rename_information.in.new_name  = path_fname_new+strlen(BASEDIR)+1;
562         sfinfo.rename_information.in.overwrite = 1;
563         CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
564         CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
565
566         sfinfo.rename_information.in.new_name  = fnum_fname+strlen(BASEDIR)+1;
567         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
568         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
569
570         sfinfo.rename_information.in.new_name  = path_fname+strlen(BASEDIR)+1;
571         CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
572         CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
573
574         printf("Trying rename with a root fid\n");
575         status = create_directory_handle(cli->tree, BASEDIR, &d_fnum);
576         CHECK_STATUS(status, NT_STATUS_OK);
577         sfinfo.rename_information.in.new_name  = fnum_fname_new+strlen(BASEDIR)+1;
578         sfinfo.rename_information.in.root_fid = d_fnum;
579         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_INVALID_PARAMETER);
580         CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
581         smbcli_close(cli->tree, d_fnum);
582
583         printf("Trying rename directory\n");
584         if (!torture_setup_dir(cli, path_dname)) {
585                 ret = false;
586                 goto done;
587         }
588         saved_name = path_fname;
589         saved_name_new = path_fname_new;
590         path_fname = path_dname;
591         path_fname_new = path_dname_new;
592         sfinfo.rename_information.in.new_name  = path_dname_new+strlen(BASEDIR)+1;
593         sfinfo.rename_information.in.overwrite = 0;
594         sfinfo.rename_information.in.root_fid  = 0;
595         CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
596         CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
597         path_fname = saved_name;
598         path_fname_new = saved_name_new;
599
600         if (torture_setting_bool(torture, "samba3", false)) {
601                 printf("SKIP: Trying rename directory with a handle\n");
602                 printf("SKIP: Trying rename by path while a handle is open\n");
603                 printf("SKIP: Trying rename directory by path while a handle is open\n");
604                 goto done;
605         }
606
607         printf("Trying rename directory with a handle\n");
608         status = create_directory_handle(cli->tree, path_dname_new, &d_fnum);
609         fnum_saved = fnum;
610         fnum = d_fnum;
611         saved_name = fnum_fname;
612         saved_name_new = fnum_fname_new;
613         fnum_fname = path_dname;
614         fnum_fname_new = path_dname_new;
615         sfinfo.rename_information.in.new_name  = path_dname+strlen(BASEDIR)+1;
616         sfinfo.rename_information.in.overwrite = 0;
617         sfinfo.rename_information.in.root_fid  = 0;
618         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
619         CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
620         smbcli_close(cli->tree, d_fnum);
621         fnum = fnum_saved;
622         fnum_fname = saved_name;
623         fnum_fname_new = saved_name_new;
624
625         printf("Trying rename by path while a handle is open\n");
626         fnum_saved = fnum;
627         fnum = create_complex_file(cli, torture, path_fname);
628         sfinfo.rename_information.in.new_name  = path_fname_new+strlen(BASEDIR)+1;
629         sfinfo.rename_information.in.overwrite = 0;
630         sfinfo.rename_information.in.root_fid  = 0;
631         CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
632         CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
633         /* check that the handle returns the same name */
634         check_fnum = true;
635         CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
636         /* rename it back on the handle */
637         sfinfo.rename_information.in.new_name  = path_fname+strlen(BASEDIR)+1;
638         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
639         CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
640         check_fnum = false;
641         CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
642         smbcli_close(cli->tree, fnum);
643         fnum = fnum_saved;
644
645         printf("Trying rename directory by path while a handle is open\n");
646         status = create_directory_handle(cli->tree, path_dname, &d_fnum);
647         fnum_saved = fnum;
648         fnum = d_fnum;
649         saved_name = path_fname;
650         saved_name_new = path_fname_new;
651         path_fname = path_dname;
652         path_fname_new = path_dname_new;
653         sfinfo.rename_information.in.new_name  = path_dname_new+strlen(BASEDIR)+1;
654         sfinfo.rename_information.in.overwrite = 0;
655         sfinfo.rename_information.in.root_fid  = 0;
656         CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
657         CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
658         path_fname = saved_name;
659         path_fname_new = saved_name_new;
660         saved_name = fnum_fname;
661         saved_name_new = fnum_fname_new;
662         fnum_fname = path_dname;
663         fnum_fname_new = path_dname_new;
664         /* check that the handle returns the same name */
665         check_fnum = true;
666         CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
667         /* rename it back on the handle */
668         sfinfo.rename_information.in.new_name  = path_dname+strlen(BASEDIR)+1;
669         CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
670         CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
671         fnum_fname = saved_name;
672         fnum_fname_new = saved_name_new;
673         saved_name = path_fname;
674         saved_name_new = path_fname_new;
675         path_fname = path_dname;
676         path_fname_new = path_dname_new;
677         check_fnum = false;
678         CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
679         smbcli_close(cli->tree, d_fnum);
680         fnum = fnum_saved;
681         path_fname = saved_name;
682         path_fname_new = saved_name_new;
683
684 done:
685         smb_raw_exit(cli->session);
686         smbcli_deltree(cli->tree, BASEDIR);
687         return ret;
688 }
689
690 /* 
691    look for the w2k3 setpathinfo STANDARD bug
692 */
693 static bool torture_raw_sfileinfo_bug(struct torture_context *torture,
694     struct smbcli_state *cli)
695 {
696         const char *fname = "\\bug3.txt";
697         union smb_setfileinfo sfinfo;
698         NTSTATUS status;
699         int fnum;
700
701         if (!torture_setting_bool(torture, "dangerous", false))
702                 torture_skip(torture, 
703                         "torture_raw_sfileinfo_bug disabled - enable dangerous tests to use\n");
704
705         fnum = create_complex_file(cli, torture, fname);
706         smbcli_close(cli->tree, fnum);
707
708         sfinfo.generic.level = RAW_SFILEINFO_STANDARD;
709         sfinfo.generic.in.file.path = fname;
710
711         sfinfo.standard.in.create_time = 0;
712         sfinfo.standard.in.access_time = 0;
713         sfinfo.standard.in.write_time  = 0;
714
715         status = smb_raw_setpathinfo(cli->tree, &sfinfo);
716         printf("%s - %s\n", fname, nt_errstr(status));
717
718         printf("now try and delete %s\n", fname);
719
720         return true;
721 }
722
723 /**
724  * Test both the snia cifs RAW_SFILEINFO_END_OF_FILE_INFO and the undocumented
725  * pass-through RAW_SFILEINFO_END_OF_FILE_INFORMATION in the context of
726  * trans2setpathinfo.
727  */
728 static bool
729 torture_raw_sfileinfo_eof(struct torture_context *tctx,
730     struct smbcli_state *cli1, struct smbcli_state *cli2)
731 {
732         const char *fname = BASEDIR "\\test_sfileinfo_end_of_file.dat";
733         NTSTATUS status;
734         bool ret = true;
735         union smb_open io;
736         union smb_setfileinfo sfi;
737         union smb_fileinfo qfi;
738         uint16_t fnum = 0;
739
740         if (!torture_setup_dir(cli1, BASEDIR)) {
741                 return false;
742         }
743
744         /* cleanup */
745         smbcli_unlink(cli1->tree, fname);
746
747         io.generic.level = RAW_OPEN_NTCREATEX;
748         io.ntcreatex.in.root_fid.fnum = 0;
749         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
750         io.ntcreatex.in.alloc_size = 0;
751         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
752         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
753         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
754         io.ntcreatex.in.create_options = 0;
755         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
756         io.ntcreatex.in.security_flags = 0;
757         io.ntcreatex.in.fname = fname;
758         io.ntcreatex.in.flags = 0;
759
760         /* Open the file sharing none. */
761         status = smb_raw_open(cli1->tree, tctx, &io);
762         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
763             done, "Status should be OK");
764         fnum = io.ntcreatex.out.file.fnum;
765
766         /* Try to sfileinfo to extend the file. */
767         ZERO_STRUCT(sfi);
768         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
769         sfi.generic.in.file.path = fname;
770         sfi.end_of_file_info.in.size = 100;
771         status = smb_raw_setpathinfo(cli2->tree, &sfi);
772
773         /* There should be share mode contention in this case. */
774         torture_assert_ntstatus_equal_goto(tctx, status,
775             NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be "
776             "SHARING_VIOLATION");
777
778         /* Make sure the size is still 0. */
779         ZERO_STRUCT(qfi);
780         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
781         qfi.generic.in.file.path = fname;
782         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
783         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
784             done, "Status should be OK");
785
786         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 0,
787             "alloc_size should be 0 since the setpathinfo failed.");
788
789         /* Try again with the pass through instead of documented version. */
790         ZERO_STRUCT(sfi);
791         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
792         sfi.generic.in.file.path = fname;
793         sfi.end_of_file_info.in.size = 100;
794         status = smb_raw_setpathinfo(cli2->tree, &sfi);
795
796         /*
797          * Looks like a windows bug:
798          * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html
799          */
800         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
801                 /* It succeeds! This is just weird! */
802                 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
803                     ret, done, "Status should be OK");
804
805                 /* Verify that the file was actually extended to 100. */
806                 ZERO_STRUCT(qfi);
807                 qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
808                 qfi.generic.in.file.path = fname;
809                 status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
810                 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
811                     ret, done, "Status should be OK");
812
813                 torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 100,
814                     "alloc_size should be 100 since the setpathinfo "
815                     "succeeded.");
816         } else {
817                 torture_assert_ntstatus_equal_goto(tctx, status,
818                     NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be "
819                     "SHARING_VIOLATION");
820         }
821
822         /* close the first file. */
823         smbcli_close(cli1->tree, fnum);
824         fnum = 0;
825
826         /* Try to sfileinfo to extend the file again (non-pass-through). */
827         ZERO_STRUCT(sfi);
828         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
829         sfi.generic.in.file.path = fname;
830         sfi.end_of_file_info.in.size = 200;
831         status = smb_raw_setpathinfo(cli2->tree, &sfi);
832
833         /* This should cause the client to retun invalid level. */
834         if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
835                 /*
836                  * Windows sends back an invalid packet that smbclient sees
837                  * and returns INTERNAL_ERROR.
838                  */
839                 torture_assert_ntstatus_equal_goto(tctx, status,
840                     NT_STATUS_INTERNAL_ERROR, ret, done, "Status should be "
841                     "INTERNAL_ERROR");
842         } else {
843                 torture_assert_ntstatus_equal_goto(tctx, status,
844                     NT_STATUS_INVALID_LEVEL, ret, done, "Status should be "
845                     "INVALID_LEVEL");
846         }
847
848         /* Try to extend the file now with the passthrough level. */
849         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
850         status = smb_raw_setpathinfo(cli2->tree, &sfi);
851         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
852             done, "Status should be OK");
853
854         /* Verify that the file was actually extended to 200. */
855         ZERO_STRUCT(qfi);
856         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
857         qfi.generic.in.file.path = fname;
858         status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
859
860         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
861             done, "Status should be OK");
862         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 200,
863             "alloc_size should be 200 since the setpathinfo succeeded.");
864
865         /* Open the file so end of file can be set by handle. */
866         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE;
867         status = smb_raw_open(cli1->tree, tctx, &io);
868         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
869             done, "Status should be OK");
870         fnum = io.ntcreatex.out.file.fnum;
871
872         /* Try sfileinfo to extend the file by handle (non-pass-through). */
873         ZERO_STRUCT(sfi);
874         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
875         sfi.generic.in.file.fnum = fnum;
876         sfi.end_of_file_info.in.size = 300;
877         status = smb_raw_setfileinfo(cli1->tree, &sfi);
878         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
879             done, "Status should be OK");
880
881         /* Verify that the file was actually extended to 300. */
882         ZERO_STRUCT(qfi);
883         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
884         qfi.generic.in.file.path = fname;
885         status = smb_raw_pathinfo(cli1->tree, tctx, &qfi);
886         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
887             done, "Status should be OK");
888         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 300,
889             "alloc_size should be 300 since the setpathinfo succeeded.");
890
891         /* Try sfileinfo to extend the file by handle (pass-through). */
892         ZERO_STRUCT(sfi);
893         sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
894         sfi.generic.in.file.fnum = fnum;
895         sfi.end_of_file_info.in.size = 400;
896         status = smb_raw_setfileinfo(cli1->tree, &sfi);
897         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
898             done, "Status should be OK");
899
900         /* Verify that the file was actually extended to 300. */
901         ZERO_STRUCT(qfi);
902         qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
903         qfi.generic.in.file.path = fname;
904         status = smb_raw_pathinfo(cli1->tree, tctx, &qfi);
905         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
906             done, "Status should be OK");
907         torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 400,
908             "alloc_size should be 400 since the setpathinfo succeeded.");
909  done:
910         if (fnum > 0) {
911                 smbcli_close(cli1->tree, fnum);
912                 fnum = 0;
913         }
914
915         smb_raw_exit(cli1->session);
916         smb_raw_exit(cli2->session);
917         smbcli_deltree(cli1->tree, BASEDIR);
918         return ret;
919 }
920
921 static bool
922 torture_raw_sfileinfo_eof_access(struct torture_context *tctx,
923     struct smbcli_state *cli1, struct smbcli_state *cli2)
924 {
925         const char *fname = BASEDIR "\\test_exclusive3.dat";
926         NTSTATUS status, expected_status;
927         bool ret = true;
928         union smb_open io;
929         union smb_setfileinfo sfi;
930         uint16_t fnum=0;
931         uint32_t access_mask = 0;
932
933         if (!torture_setup_dir(cli1, BASEDIR)) {
934                 return false;
935         }
936
937         /* cleanup */
938         smbcli_unlink(cli1->tree, fname);
939
940         /*
941          * base ntcreatex parms
942          */
943         io.generic.level = RAW_OPEN_NTCREATEX;
944         io.ntcreatex.in.root_fid.fnum = 0;
945         io.ntcreatex.in.alloc_size = 0;
946         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
947         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
948         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
949         io.ntcreatex.in.create_options = 0;
950         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
951         io.ntcreatex.in.security_flags = 0;
952         io.ntcreatex.in.fname = fname;
953         io.ntcreatex.in.flags = 0;
954
955
956         for (access_mask = 1; access_mask <= 0x00001FF; access_mask++) {
957                 io.ntcreatex.in.access_mask = access_mask;
958
959                 status = smb_raw_open(cli1->tree, tctx, &io);
960                 if (!NT_STATUS_IS_OK(status)) {
961                         continue;
962                 }
963
964                 fnum = io.ntcreatex.out.file.fnum;
965
966                 ZERO_STRUCT(sfi);
967                 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
968                 sfi.generic.in.file.fnum = fnum;
969                 sfi.end_of_file_info.in.size = 100;
970
971                 status = smb_raw_setfileinfo(cli1->tree, &sfi);
972
973                 expected_status = (access_mask & SEC_FILE_WRITE_DATA) ?
974                     NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
975
976                 if (!NT_STATUS_EQUAL(expected_status, status)) {
977                         torture_comment(tctx, "0x%x wrong\n", access_mask);
978                 }
979
980                 torture_assert_ntstatus_equal_goto(tctx, status,
981                     expected_status, ret, done, "Status Wrong");
982
983                 smbcli_close(cli1->tree, fnum);
984         }
985
986 done:
987         smb_raw_exit(cli1->session);
988         smb_raw_exit(cli2->session);
989         smbcli_deltree(cli1->tree, BASEDIR);
990         return ret;
991 }
992
993 static bool
994 torture_raw_sfileinfo_archive(struct torture_context *tctx,
995     struct smbcli_state *cli)
996 {
997         const char *fname = BASEDIR "\\test_archive.dat";
998         NTSTATUS status;
999         bool ret = true;
1000         union smb_open io;
1001         union smb_setfileinfo sfinfo;
1002         union smb_fileinfo finfo;
1003         uint16_t fnum=0;
1004
1005         if (!torture_setup_dir(cli, BASEDIR)) {
1006                 return false;
1007         }
1008
1009         /* cleanup */
1010         smbcli_unlink(cli->tree, fname);
1011
1012         /*
1013          * create a normal file, verify archive bit
1014          */
1015         io.generic.level = RAW_OPEN_NTCREATEX;
1016         io.ntcreatex.in.root_fid.fnum = 0;
1017         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1018         io.ntcreatex.in.alloc_size = 0;
1019         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1020         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1021         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1022         io.ntcreatex.in.create_options = 0;
1023         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1024         io.ntcreatex.in.security_flags = 0;
1025         io.ntcreatex.in.fname = fname;
1026         io.ntcreatex.in.flags = 0;
1027         status = smb_raw_open(cli->tree, tctx, &io);
1028         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1029             ret, done, "open failed");
1030         fnum = io.ntcreatex.out.file.fnum;
1031
1032         torture_assert_int_equal(tctx,
1033             io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1034             FILE_ATTRIBUTE_ARCHIVE,
1035             "archive bit not set");
1036
1037         /*
1038          * try to turn off archive bit
1039          */
1040         ZERO_STRUCT(sfinfo);
1041         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1042         sfinfo.generic.in.file.fnum = fnum;
1043         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
1044         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1045         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1046             ret, done, "setfileinfo failed");
1047
1048         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1049         finfo.generic.in.file.fnum = fnum;
1050         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1051         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1052             ret, done, "fileinfo failed");
1053
1054         torture_assert_int_equal(tctx,
1055             finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1056             FILE_ATTRIBUTE_NORMAL,
1057             "archive bit set");
1058
1059         status = smbcli_close(cli->tree, fnum);
1060         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1061             ret, done, "close failed");
1062
1063         status = smbcli_unlink(cli->tree, fname);
1064         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1065             ret, done, "unlink failed");
1066
1067         /*
1068          * create a directory, verify no archive bit
1069          */
1070         io.generic.level = RAW_OPEN_NTCREATEX;
1071         io.ntcreatex.in.root_fid.fnum = 0;
1072         io.ntcreatex.in.access_mask = SEC_RIGHTS_DIR_ALL;
1073         io.ntcreatex.in.alloc_size = 0;
1074         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1075         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1076         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1077         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1078         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1079         io.ntcreatex.in.security_flags = 0;
1080         io.ntcreatex.in.fname = fname;
1081         io.ntcreatex.in.flags = 0;
1082         status = smb_raw_open(cli->tree, tctx, &io);
1083         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1084             ret, done, "directory open failed");
1085         fnum = io.ntcreatex.out.file.fnum;
1086
1087         torture_assert_int_equal(tctx,
1088             io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1089             FILE_ATTRIBUTE_DIRECTORY,
1090             "archive bit set");
1091
1092         /*
1093          * verify you can turn on archive bit
1094          */
1095         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1096         sfinfo.generic.in.file.fnum = fnum;
1097         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE;
1098         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1099         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1100             ret, done, "setfileinfo failed");
1101
1102         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1103         finfo.generic.in.file.fnum = fnum;
1104         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1105         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1106             ret, done, "fileinfo failed");
1107
1108         torture_assert_int_equal(tctx,
1109             finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1110             FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE,
1111             "archive bit not set");
1112
1113         /*
1114          * and try to turn it back off
1115          */
1116         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1117         sfinfo.generic.in.file.fnum = fnum;
1118         sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
1119         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1120         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1121             ret, done, "setfileinfo failed");
1122
1123         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1124         finfo.generic.in.file.fnum = fnum;
1125         status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1126         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1127             ret, done, "fileinfo failed");
1128
1129         torture_assert_int_equal(tctx,
1130             finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1131             FILE_ATTRIBUTE_DIRECTORY,
1132             "archive bit set");
1133
1134         status = smbcli_close(cli->tree, fnum);
1135         torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1136             ret, done, "close failed");
1137
1138 done:
1139         smbcli_close(cli->tree, fnum);
1140         smbcli_deltree(cli->tree, BASEDIR);
1141         return ret;
1142 }
1143
1144 struct torture_suite *torture_raw_sfileinfo(TALLOC_CTX *mem_ctx)
1145 {
1146         struct torture_suite *suite = torture_suite_create(mem_ctx, "sfileinfo");
1147
1148         torture_suite_add_1smb_test(suite, "base", torture_raw_sfileinfo_base);
1149         torture_suite_add_1smb_test(suite, "rename", torture_raw_sfileinfo_rename);
1150         torture_suite_add_1smb_test(suite, "bug", torture_raw_sfileinfo_bug);
1151         torture_suite_add_2smb_test(suite, "end-of-file",
1152             torture_raw_sfileinfo_eof);
1153         torture_suite_add_2smb_test(suite, "end-of-file-access",
1154             torture_raw_sfileinfo_eof_access);
1155         torture_suite_add_1smb_test(suite, "archive",
1156                                                                 torture_raw_sfileinfo_archive);
1157
1158         return suite;
1159 }