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