r9008: check the return status for the directory handle creations
[sfrench/samba-autobuild/.git] / source4 / torture / raw / unlink.c
1 /* 
2    Unix SMB/CIFS implementation.
3    unlink 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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "librpc/gen_ndr/ndr_security.h"
24
25 #define CHECK_STATUS(status, correct) do { \
26         if (!NT_STATUS_EQUAL(status, correct)) { \
27                 printf("(%s) Incorrect status %s - should be %s\n", \
28                        __location__, nt_errstr(status), nt_errstr(correct)); \
29                 ret = False; \
30                 goto done; \
31         }} while (0)
32
33 #define BASEDIR "\\testunlink"
34
35 /*
36   test unlink ops
37 */
38 static BOOL test_unlink(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
39 {
40         struct smb_unlink io;
41         NTSTATUS status;
42         BOOL ret = True;
43         const char *fname = BASEDIR "\\test.txt";
44
45         if (!torture_setup_dir(cli, BASEDIR)) {
46                 return False;
47         }
48
49         printf("Trying non-existant file\n");
50         io.in.pattern = fname;
51         io.in.attrib = 0;
52         status = smb_raw_unlink(cli->tree, &io);
53         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
54
55         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
56
57         io.in.pattern = fname;
58         io.in.attrib = 0;
59         status = smb_raw_unlink(cli->tree, &io);
60         CHECK_STATUS(status, NT_STATUS_OK);
61
62         printf("Trying a hidden file\n");
63         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
64         torture_set_file_attribute(cli->tree, fname, FILE_ATTRIBUTE_HIDDEN);
65
66         io.in.pattern = fname;
67         io.in.attrib = 0;
68         status = smb_raw_unlink(cli->tree, &io);
69         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
70
71         io.in.pattern = fname;
72         io.in.attrib = FILE_ATTRIBUTE_HIDDEN;
73         status = smb_raw_unlink(cli->tree, &io);
74         CHECK_STATUS(status, NT_STATUS_OK);
75
76         io.in.pattern = fname;
77         io.in.attrib = FILE_ATTRIBUTE_HIDDEN;
78         status = smb_raw_unlink(cli->tree, &io);
79         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
80
81         printf("Trying a directory\n");
82         io.in.pattern = BASEDIR;
83         io.in.attrib = 0;
84         status = smb_raw_unlink(cli->tree, &io);
85         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
86
87         io.in.pattern = BASEDIR;
88         io.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
89         status = smb_raw_unlink(cli->tree, &io);
90         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
91
92         printf("Trying a bad path\n");
93         io.in.pattern = "..";
94         io.in.attrib = 0;
95         status = smb_raw_unlink(cli->tree, &io);
96         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
97
98         io.in.pattern = "\\..";
99         io.in.attrib = 0;
100         status = smb_raw_unlink(cli->tree, &io);
101         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
102
103         io.in.pattern = BASEDIR "\\..\\..";
104         io.in.attrib = 0;
105         status = smb_raw_unlink(cli->tree, &io);
106         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
107
108         io.in.pattern = BASEDIR "\\..";
109         io.in.attrib = 0;
110         status = smb_raw_unlink(cli->tree, &io);
111         CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
112
113         printf("Trying wildcards\n");
114         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
115         io.in.pattern = BASEDIR "\\t*.t";
116         io.in.attrib = 0;
117         status = smb_raw_unlink(cli->tree, &io);
118         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
119
120         io.in.pattern = BASEDIR "\\z*";
121         io.in.attrib = 0;
122         status = smb_raw_unlink(cli->tree, &io);
123         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
124
125         io.in.pattern = BASEDIR "\\z*";
126         io.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
127         status = smb_raw_unlink(cli->tree, &io);
128         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
129
130         io.in.pattern = BASEDIR "\\*";
131         io.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
132         status = smb_raw_unlink(cli->tree, &io);
133         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
134
135         io.in.pattern = BASEDIR "\\?";
136         io.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
137         status = smb_raw_unlink(cli->tree, &io);
138         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
139
140         io.in.pattern = BASEDIR "\\t*";
141         io.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
142         status = smb_raw_unlink(cli->tree, &io);
143         CHECK_STATUS(status, NT_STATUS_OK);
144
145         smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
146
147         io.in.pattern = BASEDIR "\\*.dat";
148         io.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
149         status = smb_raw_unlink(cli->tree, &io);
150         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
151
152         io.in.pattern = BASEDIR "\\*.tx?";
153         io.in.attrib = 0;
154         status = smb_raw_unlink(cli->tree, &io);
155         CHECK_STATUS(status, NT_STATUS_OK);
156
157         status = smb_raw_unlink(cli->tree, &io);
158         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
159
160
161 done:
162         smb_raw_exit(cli->session);
163         smbcli_deltree(cli->tree, BASEDIR);
164         return ret;
165 }
166
167
168 /*
169   test delete on close 
170 */
171 static BOOL test_delete_on_close(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
172 {
173         union smb_open op;
174         struct smb_unlink io;
175         struct smb_rmdir dio;
176         NTSTATUS status;
177         BOOL ret = True;
178         int fnum, fnum2;
179         const char *fname = BASEDIR "\\test.txt";
180         const char *dname = BASEDIR "\\test.dir";
181         const char *inside = BASEDIR "\\test.dir\\test.txt";
182         union smb_setfileinfo sfinfo;
183
184         if (!torture_setup_dir(cli, BASEDIR)) {
185                 return False;
186         }
187
188         dio.in.path = dname;
189
190         io.in.pattern = fname;
191         io.in.attrib = 0;
192         status = smb_raw_unlink(cli->tree, &io);
193         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
194
195         printf("Testing with delete_on_close 0\n");
196         fnum = create_complex_file(cli, mem_ctx, fname);
197
198         sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
199         sfinfo.disposition_info.file.fnum = fnum;
200         sfinfo.disposition_info.in.delete_on_close = 0;
201         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
202         CHECK_STATUS(status, NT_STATUS_OK);
203
204         smbcli_close(cli->tree, fnum);
205
206         status = smb_raw_unlink(cli->tree, &io);
207         CHECK_STATUS(status, NT_STATUS_OK);
208
209         printf("Testing with delete_on_close 1\n");
210         fnum = create_complex_file(cli, mem_ctx, fname);
211         sfinfo.disposition_info.file.fnum = fnum;
212         sfinfo.disposition_info.in.delete_on_close = 1;
213         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
214         CHECK_STATUS(status, NT_STATUS_OK);
215
216         smbcli_close(cli->tree, fnum);
217
218         status = smb_raw_unlink(cli->tree, &io);
219         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
220
221
222         printf("Testing with directory and delete_on_close 0\n");
223         status = create_directory_handle(cli->tree, dname, &fnum);
224         CHECK_STATUS(status, NT_STATUS_OK);
225
226         sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
227         sfinfo.disposition_info.file.fnum = fnum;
228         sfinfo.disposition_info.in.delete_on_close = 0;
229         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
230         CHECK_STATUS(status, NT_STATUS_OK);
231
232         smbcli_close(cli->tree, fnum);
233
234         status = smb_raw_rmdir(cli->tree, &dio);
235         CHECK_STATUS(status, NT_STATUS_OK);
236
237         printf("Testing with directory delete_on_close 1\n");
238         status = create_directory_handle(cli->tree, dname, &fnum);
239         CHECK_STATUS(status, NT_STATUS_OK);
240         
241         sfinfo.disposition_info.file.fnum = fnum;
242         sfinfo.disposition_info.in.delete_on_close = 1;
243         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
244         CHECK_STATUS(status, NT_STATUS_OK);
245
246         smbcli_close(cli->tree, fnum);
247
248         status = smb_raw_rmdir(cli->tree, &dio);
249         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
250
251
252         printf("Testing with non-empty directory delete_on_close\n");
253         status = create_directory_handle(cli->tree, dname, &fnum);
254         CHECK_STATUS(status, NT_STATUS_OK);
255         
256         fnum2 = create_complex_file(cli, mem_ctx, inside);
257
258         sfinfo.disposition_info.file.fnum = fnum;
259         sfinfo.disposition_info.in.delete_on_close = 1;
260         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
261         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
262
263         sfinfo.disposition_info.file.fnum = fnum2;
264         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
265         CHECK_STATUS(status, NT_STATUS_OK);
266
267         sfinfo.disposition_info.file.fnum = fnum;
268         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
269         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
270
271         smbcli_close(cli->tree, fnum2);
272
273         status = smb_raw_setfileinfo(cli->tree, &sfinfo);
274         CHECK_STATUS(status, NT_STATUS_OK);
275
276         smbcli_close(cli->tree, fnum);
277
278         status = smb_raw_rmdir(cli->tree, &dio);
279         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
280
281         printf("Testing open dir with delete_on_close\n");
282         status = create_directory_handle(cli->tree, dname, &fnum);
283         CHECK_STATUS(status, NT_STATUS_OK);
284         
285         smbcli_close(cli->tree, fnum);
286         fnum2 = create_complex_file(cli, mem_ctx, inside);
287         smbcli_close(cli->tree, fnum2);
288
289         op.generic.level = RAW_OPEN_NTCREATEX;
290         op.ntcreatex.in.root_fid = 0;
291         op.ntcreatex.in.flags = 0;
292         op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
293         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
294         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
295         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
296         op.ntcreatex.in.alloc_size = 0;
297         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
298         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
299         op.ntcreatex.in.security_flags = 0;
300         op.ntcreatex.in.fname = dname;
301
302         status = smb_raw_open(cli->tree, mem_ctx, &op);
303         CHECK_STATUS(status, NT_STATUS_OK);
304         fnum = op.ntcreatex.out.fnum;
305
306         smbcli_close(cli->tree, fnum);
307
308         status = smb_raw_rmdir(cli->tree, &dio);
309         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
310
311         smbcli_deltree(cli->tree, dname);
312
313         printf("Testing double open dir with second delete_on_close\n");
314         status = create_directory_handle(cli->tree, dname, &fnum);
315         CHECK_STATUS(status, NT_STATUS_OK);
316         smbcli_close(cli->tree, fnum);
317         
318         fnum2 = create_complex_file(cli, mem_ctx, inside);
319         smbcli_close(cli->tree, fnum2);
320
321         op.generic.level = RAW_OPEN_NTCREATEX;
322         op.ntcreatex.in.root_fid = 0;
323         op.ntcreatex.in.flags = 0;
324         op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
325         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
326         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
327         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
328         op.ntcreatex.in.alloc_size = 0;
329         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
330         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
331         op.ntcreatex.in.security_flags = 0;
332         op.ntcreatex.in.fname = dname;
333
334         status = smb_raw_open(cli->tree, mem_ctx, &op);
335         CHECK_STATUS(status, NT_STATUS_OK);
336         fnum2 = op.ntcreatex.out.fnum;
337
338         smbcli_close(cli->tree, fnum2);
339
340         status = smb_raw_rmdir(cli->tree, &dio);
341         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
342
343         smbcli_deltree(cli->tree, dname);
344
345         printf("Testing pre-existing open dir with second delete_on_close\n");
346         status = create_directory_handle(cli->tree, dname, &fnum);
347         CHECK_STATUS(status, NT_STATUS_OK);
348         
349         smbcli_close(cli->tree, fnum);
350
351         fnum = create_complex_file(cli, mem_ctx, inside);
352         smbcli_close(cli->tree, fnum);
353
354         /* we have a dir with a file in it, no handles open */
355
356         op.generic.level = RAW_OPEN_NTCREATEX;
357         op.ntcreatex.in.root_fid = 0;
358         op.ntcreatex.in.flags = 0;
359         op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
360         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
361         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
362         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
363         op.ntcreatex.in.alloc_size = 0;
364         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
365         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
366         op.ntcreatex.in.security_flags = 0;
367         op.ntcreatex.in.fname = dname;
368
369         status = smb_raw_open(cli->tree, mem_ctx, &op);
370         CHECK_STATUS(status, NT_STATUS_OK);
371         fnum = op.ntcreatex.out.fnum;
372
373         /* open without delete on close */
374         op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
375         status = smb_raw_open(cli->tree, mem_ctx, &op);
376         CHECK_STATUS(status, NT_STATUS_OK);
377         fnum2 = op.ntcreatex.out.fnum;
378
379         /* close 2nd file handle */
380         smbcli_close(cli->tree, fnum2);
381
382         status = smb_raw_rmdir(cli->tree, &dio);
383         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
384         
385
386         smbcli_close(cli->tree, fnum);
387
388         status = smb_raw_rmdir(cli->tree, &dio);
389         CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
390         
391 done:
392         smb_raw_exit(cli->session);
393         smbcli_deltree(cli->tree, BASEDIR);
394         return ret;
395 }
396
397
398 /* 
399    basic testing of unlink calls
400 */
401 BOOL torture_raw_unlink(void)
402 {
403         struct smbcli_state *cli;
404         BOOL ret = True;
405         TALLOC_CTX *mem_ctx;
406
407         if (!torture_open_connection(&cli)) {
408                 return False;
409         }
410
411         mem_ctx = talloc_init("torture_raw_unlink");
412
413         ret &= test_unlink(cli, mem_ctx);
414         ret &= test_delete_on_close(cli, mem_ctx);
415
416         torture_close_connection(cli);
417         talloc_free(mem_ctx);
418         return ret;
419 }