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 "system/filesys.h"
23 #include "librpc/gen_ndr/ndr_security.h"
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)); \
33 #define BASEDIR "\\testunlink"
38 static BOOL test_unlink(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
43 const char *fname = BASEDIR "\\test.txt";
45 if (!torture_setup_dir(cli, BASEDIR)) {
49 printf("Trying non-existant file\n");
50 io.in.pattern = fname;
52 status = smb_raw_unlink(cli->tree, &io);
53 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
55 smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
57 io.in.pattern = fname;
59 status = smb_raw_unlink(cli->tree, &io);
60 CHECK_STATUS(status, NT_STATUS_OK);
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);
66 io.in.pattern = fname;
68 status = smb_raw_unlink(cli->tree, &io);
69 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
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);
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);
81 printf("Trying a directory\n");
82 io.in.pattern = BASEDIR;
84 status = smb_raw_unlink(cli->tree, &io);
85 CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
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);
92 printf("Trying a bad path\n");
95 status = smb_raw_unlink(cli->tree, &io);
96 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
98 io.in.pattern = "\\..";
100 status = smb_raw_unlink(cli->tree, &io);
101 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
103 io.in.pattern = BASEDIR "\\..\\..";
105 status = smb_raw_unlink(cli->tree, &io);
106 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
108 io.in.pattern = BASEDIR "\\..";
110 status = smb_raw_unlink(cli->tree, &io);
111 CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
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";
117 status = smb_raw_unlink(cli->tree, &io);
118 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
120 io.in.pattern = BASEDIR "\\z*";
122 status = smb_raw_unlink(cli->tree, &io);
123 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
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);
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);
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);
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);
145 smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
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);
152 io.in.pattern = BASEDIR "\\*.tx?";
154 status = smb_raw_unlink(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_OK);
157 status = smb_raw_unlink(cli->tree, &io);
158 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
162 smb_raw_exit(cli->session);
163 smbcli_deltree(cli->tree, BASEDIR);
171 static BOOL test_delete_on_close(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
174 struct smb_unlink io;
175 struct smb_rmdir dio;
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;
184 if (!torture_setup_dir(cli, BASEDIR)) {
190 io.in.pattern = fname;
192 status = smb_raw_unlink(cli->tree, &io);
193 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
195 printf("Testing with delete_on_close 0\n");
196 fnum = create_complex_file(cli, mem_ctx, fname);
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);
204 smbcli_close(cli->tree, fnum);
206 status = smb_raw_unlink(cli->tree, &io);
207 CHECK_STATUS(status, NT_STATUS_OK);
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);
216 smbcli_close(cli->tree, fnum);
218 status = smb_raw_unlink(cli->tree, &io);
219 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
222 printf("Testing with directory and delete_on_close 0\n");
223 fnum = create_directory_handle(cli->tree, dname);
225 sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
226 sfinfo.disposition_info.file.fnum = fnum;
227 sfinfo.disposition_info.in.delete_on_close = 0;
228 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
229 CHECK_STATUS(status, NT_STATUS_OK);
231 smbcli_close(cli->tree, fnum);
233 status = smb_raw_rmdir(cli->tree, &dio);
234 CHECK_STATUS(status, NT_STATUS_OK);
236 printf("Testing with directory delete_on_close 1\n");
237 fnum = create_directory_handle(cli->tree, dname);
238 sfinfo.disposition_info.file.fnum = fnum;
239 sfinfo.disposition_info.in.delete_on_close = 1;
240 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
241 CHECK_STATUS(status, NT_STATUS_OK);
243 smbcli_close(cli->tree, fnum);
245 status = smb_raw_rmdir(cli->tree, &dio);
246 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
249 printf("Testing with non-empty directory delete_on_close\n");
250 fnum = create_directory_handle(cli->tree, dname);
251 fnum2 = create_complex_file(cli, mem_ctx, inside);
253 sfinfo.disposition_info.file.fnum = fnum;
254 sfinfo.disposition_info.in.delete_on_close = 1;
255 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
256 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
258 sfinfo.disposition_info.file.fnum = fnum2;
259 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
260 CHECK_STATUS(status, NT_STATUS_OK);
262 sfinfo.disposition_info.file.fnum = fnum;
263 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
264 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
266 smbcli_close(cli->tree, fnum2);
268 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
269 CHECK_STATUS(status, NT_STATUS_OK);
271 smbcli_close(cli->tree, fnum);
273 status = smb_raw_rmdir(cli->tree, &dio);
274 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
276 printf("Testing open dir with delete_on_close\n");
277 fnum = create_directory_handle(cli->tree, dname);
278 smbcli_close(cli->tree, fnum);
279 fnum2 = create_complex_file(cli, mem_ctx, inside);
280 smbcli_close(cli->tree, fnum2);
282 op.generic.level = RAW_OPEN_NTCREATEX;
283 op.ntcreatex.in.root_fid = 0;
284 op.ntcreatex.in.flags = 0;
285 op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
286 op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
287 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
288 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
289 op.ntcreatex.in.alloc_size = 0;
290 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
291 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
292 op.ntcreatex.in.security_flags = 0;
293 op.ntcreatex.in.fname = dname;
295 status = smb_raw_open(cli->tree, mem_ctx, &op);
296 CHECK_STATUS(status, NT_STATUS_OK);
297 fnum = op.ntcreatex.out.fnum;
299 smbcli_close(cli->tree, fnum);
301 status = smb_raw_rmdir(cli->tree, &dio);
302 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
305 printf("Testing double open dir with second delete_on_close\n");
306 fnum = create_directory_handle(cli->tree, dname);
307 fnum2 = create_complex_file(cli, mem_ctx, inside);
308 smbcli_close(cli->tree, fnum2);
310 op.generic.level = RAW_OPEN_NTCREATEX;
311 op.ntcreatex.in.root_fid = 0;
312 op.ntcreatex.in.flags = 0;
313 op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
314 op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
315 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
316 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
317 op.ntcreatex.in.alloc_size = 0;
318 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
319 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
320 op.ntcreatex.in.security_flags = 0;
321 op.ntcreatex.in.fname = dname;
323 status = smb_raw_open(cli->tree, mem_ctx, &op);
324 CHECK_STATUS(status, NT_STATUS_OK);
325 fnum2 = op.ntcreatex.out.fnum;
327 smbcli_close(cli->tree, fnum2);
328 smbcli_close(cli->tree, fnum);
330 status = smb_raw_rmdir(cli->tree, &dio);
331 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
334 printf("Testing pre-existing open dir with second delete_on_close\n");
335 fnum = create_directory_handle(cli->tree, dname);
336 smbcli_close(cli->tree, fnum);
338 fnum = create_complex_file(cli, mem_ctx, inside);
339 smbcli_close(cli->tree, fnum);
341 /* we have a dir with a file in it, no handles open */
343 op.generic.level = RAW_OPEN_NTCREATEX;
344 op.ntcreatex.in.root_fid = 0;
345 op.ntcreatex.in.flags = 0;
346 op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
347 op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
348 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
349 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
350 op.ntcreatex.in.alloc_size = 0;
351 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
352 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
353 op.ntcreatex.in.security_flags = 0;
354 op.ntcreatex.in.fname = dname;
356 status = smb_raw_open(cli->tree, mem_ctx, &op);
357 CHECK_STATUS(status, NT_STATUS_OK);
358 fnum = op.ntcreatex.out.fnum;
360 /* open without delete on close */
361 op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
362 status = smb_raw_open(cli->tree, mem_ctx, &op);
363 CHECK_STATUS(status, NT_STATUS_OK);
364 fnum2 = op.ntcreatex.out.fnum;
366 /* close 2nd file handle */
367 smbcli_close(cli->tree, fnum2);
369 status = smb_raw_rmdir(cli->tree, &dio);
370 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
373 smbcli_close(cli->tree, fnum);
375 status = smb_raw_rmdir(cli->tree, &dio);
376 CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
379 smb_raw_exit(cli->session);
380 smbcli_deltree(cli->tree, BASEDIR);
386 basic testing of unlink calls
388 BOOL torture_raw_unlink(void)
390 struct smbcli_state *cli;
394 if (!torture_open_connection(&cli)) {
398 mem_ctx = talloc_init("torture_raw_unlink");
400 ret &= test_unlink(cli, mem_ctx);
401 ret &= test_delete_on_close(cli, mem_ctx);
403 torture_close_connection(cli);
404 talloc_free(mem_ctx);