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_INFO
;
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 status
= create_directory_handle(cli
->tree
, dname
, &fnum
);
224 CHECK_STATUS(status
, NT_STATUS_OK
);
226 sfinfo
.disposition_info
.level
= RAW_SFILEINFO_DISPOSITION_INFO
;
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
);
232 smbcli_close(cli
->tree
, fnum
);
234 status
= smb_raw_rmdir(cli
->tree
, &dio
);
235 CHECK_STATUS(status
, NT_STATUS_OK
);
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
);
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
);
246 smbcli_close(cli
->tree
, fnum
);
248 status
= smb_raw_rmdir(cli
->tree
, &dio
);
249 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
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
);
256 fnum2
= create_complex_file(cli
, mem_ctx
, inside
);
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
);
263 sfinfo
.disposition_info
.file
.fnum
= fnum2
;
264 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
265 CHECK_STATUS(status
, NT_STATUS_OK
);
267 sfinfo
.disposition_info
.file
.fnum
= fnum
;
268 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
269 CHECK_STATUS(status
, NT_STATUS_DIRECTORY_NOT_EMPTY
);
271 smbcli_close(cli
->tree
, fnum2
);
273 status
= smb_raw_setfileinfo(cli
->tree
, &sfinfo
);
274 CHECK_STATUS(status
, NT_STATUS_OK
);
276 smbcli_close(cli
->tree
, fnum
);
278 status
= smb_raw_rmdir(cli
->tree
, &dio
);
279 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
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
);
285 smbcli_close(cli
->tree
, fnum
);
286 fnum2
= create_complex_file(cli
, mem_ctx
, inside
);
287 smbcli_close(cli
->tree
, fnum2
);
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
;
302 status
= smb_raw_open(cli
->tree
, mem_ctx
, &op
);
303 CHECK_STATUS(status
, NT_STATUS_OK
);
304 fnum
= op
.ntcreatex
.out
.fnum
;
306 smbcli_close(cli
->tree
, fnum
);
308 status
= smb_raw_rmdir(cli
->tree
, &dio
);
309 CHECK_STATUS(status
, NT_STATUS_DIRECTORY_NOT_EMPTY
);
311 smbcli_deltree(cli
->tree
, dname
);
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
);
318 fnum2
= create_complex_file(cli
, mem_ctx
, inside
);
319 smbcli_close(cli
->tree
, fnum2
);
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
;
334 status
= smb_raw_open(cli
->tree
, mem_ctx
, &op
);
335 CHECK_STATUS(status
, NT_STATUS_OK
);
336 fnum2
= op
.ntcreatex
.out
.fnum
;
338 smbcli_close(cli
->tree
, fnum2
);
340 status
= smb_raw_rmdir(cli
->tree
, &dio
);
341 CHECK_STATUS(status
, NT_STATUS_DIRECTORY_NOT_EMPTY
);
343 smbcli_deltree(cli
->tree
, dname
);
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
);
349 smbcli_close(cli
->tree
, fnum
);
351 fnum
= create_complex_file(cli
, mem_ctx
, inside
);
352 smbcli_close(cli
->tree
, fnum
);
354 /* we have a dir with a file in it, no handles open */
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
;
369 status
= smb_raw_open(cli
->tree
, mem_ctx
, &op
);
370 CHECK_STATUS(status
, NT_STATUS_OK
);
371 fnum
= op
.ntcreatex
.out
.fnum
;
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
;
379 /* close 2nd file handle */
380 smbcli_close(cli
->tree
, fnum2
);
382 status
= smb_raw_rmdir(cli
->tree
, &dio
);
383 CHECK_STATUS(status
, NT_STATUS_DIRECTORY_NOT_EMPTY
);
386 smbcli_close(cli
->tree
, fnum
);
388 status
= smb_raw_rmdir(cli
->tree
, &dio
);
389 CHECK_STATUS(status
, NT_STATUS_DIRECTORY_NOT_EMPTY
);
392 smb_raw_exit(cli
->session
);
393 smbcli_deltree(cli
->tree
, BASEDIR
);
399 basic testing of unlink calls
401 BOOL
torture_raw_unlink(void)
403 struct smbcli_state
*cli
;
407 if (!torture_open_connection(&cli
)) {
411 mem_ctx
= talloc_init("torture_raw_unlink");
413 ret
&= test_unlink(cli
, mem_ctx
);
414 ret
&= test_delete_on_close(cli
, mem_ctx
);
416 torture_close_connection(cli
);
417 talloc_free(mem_ctx
);