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