2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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.
22 #include "torture/torture.h"
23 #include "system/filesys.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/libcli.h"
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)); \
35 #define BASEDIR "\\testunlink"
40 static BOOL test_unlink(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
45 const char *fname = BASEDIR "\\test.txt";
47 if (!torture_setup_dir(cli, BASEDIR)) {
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);
57 smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
147 smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
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);
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);
159 status = smb_raw_unlink(cli->tree, &io);
160 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
164 smb_raw_exit(cli->session);
165 smbcli_deltree(cli->tree, BASEDIR);
173 static BOOL test_delete_on_close(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
177 struct smb_rmdir dio;
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;
186 if (!torture_setup_dir(cli, BASEDIR)) {
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);
197 printf("Testing with delete_on_close 0\n");
198 fnum = create_complex_file(cli, mem_ctx, fname);
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);
206 smbcli_close(cli->tree, fnum);
208 status = smb_raw_unlink(cli->tree, &io);
209 CHECK_STATUS(status, NT_STATUS_OK);
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);
218 smbcli_close(cli->tree, fnum);
220 status = smb_raw_unlink(cli->tree, &io);
221 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
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);
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);
234 smbcli_close(cli->tree, fnum);
236 status = smb_raw_rmdir(cli->tree, &dio);
237 CHECK_STATUS(status, NT_STATUS_OK);
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);
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);
248 smbcli_close(cli->tree, fnum);
250 status = smb_raw_rmdir(cli->tree, &dio);
251 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
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);
258 fnum2 = create_complex_file(cli, mem_ctx, inside);
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);
265 sfinfo.disposition_info.file.fnum = fnum2;
266 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
267 CHECK_STATUS(status, NT_STATUS_OK);
269 sfinfo.disposition_info.file.fnum = fnum;
270 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
271 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
273 smbcli_close(cli->tree, fnum2);
275 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
276 CHECK_STATUS(status, NT_STATUS_OK);
278 smbcli_close(cli->tree, fnum);
280 status = smb_raw_rmdir(cli->tree, &dio);
281 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
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);
287 smbcli_close(cli->tree, fnum);
288 fnum2 = create_complex_file(cli, mem_ctx, inside);
289 smbcli_close(cli->tree, fnum2);
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;
304 status = smb_raw_open(cli->tree, mem_ctx, &op);
305 CHECK_STATUS(status, NT_STATUS_OK);
306 fnum = op.ntcreatex.file.fnum;
308 smbcli_close(cli->tree, fnum);
310 status = smb_raw_rmdir(cli->tree, &dio);
311 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
313 smbcli_deltree(cli->tree, dname);
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);
320 fnum2 = create_complex_file(cli, mem_ctx, inside);
321 smbcli_close(cli->tree, fnum2);
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;
336 status = smb_raw_open(cli->tree, mem_ctx, &op);
337 CHECK_STATUS(status, NT_STATUS_OK);
338 fnum2 = op.ntcreatex.file.fnum;
340 smbcli_close(cli->tree, fnum2);
342 status = smb_raw_rmdir(cli->tree, &dio);
343 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
345 smbcli_deltree(cli->tree, dname);
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);
351 smbcli_close(cli->tree, fnum);
353 fnum = create_complex_file(cli, mem_ctx, inside);
354 smbcli_close(cli->tree, fnum);
356 /* we have a dir with a file in it, no handles open */
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;
371 status = smb_raw_open(cli->tree, mem_ctx, &op);
372 CHECK_STATUS(status, NT_STATUS_OK);
373 fnum = op.ntcreatex.file.fnum;
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;
381 /* close 2nd file handle */
382 smbcli_close(cli->tree, fnum2);
384 status = smb_raw_rmdir(cli->tree, &dio);
385 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
388 smbcli_close(cli->tree, fnum);
390 status = smb_raw_rmdir(cli->tree, &dio);
391 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
394 smb_raw_exit(cli->session);
395 smbcli_deltree(cli->tree, BASEDIR);
401 basic testing of unlink calls
403 BOOL torture_raw_unlink(void)
405 struct smbcli_state *cli;
409 if (!torture_open_connection(&cli)) {
413 mem_ctx = talloc_init("torture_raw_unlink");
415 ret &= test_unlink(cli, mem_ctx);
416 ret &= test_delete_on_close(cli, mem_ctx);
418 torture_close_connection(cli);
419 talloc_free(mem_ctx);