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 3 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, see <http://www.gnu.org/licenses/>.
21
#include "torture/torture.h"
22
#include "system/filesys.h"
23
#include "libcli/raw/libcliraw.h"
24
#include "libcli/raw/raw_proto.h"
25
#include "libcli/libcli.h"
26
#include "torture/util.h"
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)); \
36
#define BASEDIR "\\testunlink"
41
static bool test_unlink(struct torture_context *tctx, struct smbcli_state *cli)
46
const char *fname = BASEDIR "\\test.txt";
48
if (!torture_setup_dir(cli, BASEDIR)) {
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);
58
smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
128
io.unlink.in.pattern = BASEDIR "\\z*";
129
io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
130
status = smb_raw_unlink(cli->tree, &io);
132
if (torture_setting_bool(tctx, "samba3", false)) {
134
* In Samba3 we gave up upon getting the error codes in
135
* wildcard unlink correct. Trying gentest showed that this is
136
* irregular beyond our capabilities. So for
137
* FILE_ATTRIBUTE_DIRECTORY we always return NAME_INVALID.
138
* Tried by jra and vl. If others feel like solving this
139
* puzzle, please tell us :-)
141
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
144
CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
147
io.unlink.in.pattern = BASEDIR "\\*";
148
io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
149
status = smb_raw_unlink(cli->tree, &io);
150
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
152
io.unlink.in.pattern = BASEDIR "\\?";
153
io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
154
status = smb_raw_unlink(cli->tree, &io);
155
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
157
io.unlink.in.pattern = BASEDIR "\\t*";
158
io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
159
status = smb_raw_unlink(cli->tree, &io);
160
if (torture_setting_bool(tctx, "samba3", false)) {
161
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
164
CHECK_STATUS(status, NT_STATUS_OK);
167
smbcli_close(cli->tree, smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE));
169
io.unlink.in.pattern = BASEDIR "\\*.dat";
170
io.unlink.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
171
status = smb_raw_unlink(cli->tree, &io);
172
if (torture_setting_bool(tctx, "samba3", false)) {
173
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
176
CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
179
io.unlink.in.pattern = BASEDIR "\\*.tx?";
180
io.unlink.in.attrib = 0;
181
status = smb_raw_unlink(cli->tree, &io);
182
if (torture_setting_bool(tctx, "samba3", false)) {
183
CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
186
CHECK_STATUS(status, NT_STATUS_OK);
189
status = smb_raw_unlink(cli->tree, &io);
190
CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
194
smb_raw_exit(cli->session);
195
smbcli_deltree(cli->tree, BASEDIR);
203
static bool test_delete_on_close(struct torture_context *tctx,
204
struct smbcli_state *cli)
208
struct smb_rmdir dio;
212
const char *fname = BASEDIR "\\test.txt";
213
const char *dname = BASEDIR "\\test.dir";
214
const char *inside = BASEDIR "\\test.dir\\test.txt";
215
union smb_setfileinfo sfinfo;
217
if (!torture_setup_dir(cli, BASEDIR)) {
223
io.unlink.in.pattern = fname;
224
io.unlink.in.attrib = 0;
225
status = smb_raw_unlink(cli->tree, &io);
226
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
228
printf("Testing with delete_on_close 0\n");
229
fnum = create_complex_file(cli, tctx, fname);
231
sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
232
sfinfo.disposition_info.in.file.fnum = fnum;
233
sfinfo.disposition_info.in.delete_on_close = 0;
234
status = smb_raw_setfileinfo(cli->tree, &sfinfo);
235
CHECK_STATUS(status, NT_STATUS_OK);
237
smbcli_close(cli->tree, fnum);
239
status = smb_raw_unlink(cli->tree, &io);
240
CHECK_STATUS(status, NT_STATUS_OK);
242
printf("Testing with delete_on_close 1\n");
243
fnum = create_complex_file(cli, tctx, fname);
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);
249
smbcli_close(cli->tree, fnum);
251
status = smb_raw_unlink(cli->tree, &io);
252
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
255
printf("Testing with directory and delete_on_close 0\n");
256
status = create_directory_handle(cli->tree, dname, &fnum);
257
CHECK_STATUS(status, NT_STATUS_OK);
259
sfinfo.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
260
sfinfo.disposition_info.in.file.fnum = fnum;
261
sfinfo.disposition_info.in.delete_on_close = 0;
262
status = smb_raw_setfileinfo(cli->tree, &sfinfo);
263
CHECK_STATUS(status, NT_STATUS_OK);
265
smbcli_close(cli->tree, fnum);
267
status = smb_raw_rmdir(cli->tree, &dio);
268
CHECK_STATUS(status, NT_STATUS_OK);
270
printf("Testing with directory delete_on_close 1\n");
271
status = create_directory_handle(cli->tree, dname, &fnum);
272
CHECK_STATUS(status, NT_STATUS_OK);
274
sfinfo.disposition_info.in.file.fnum = fnum;
275
sfinfo.disposition_info.in.delete_on_close = 1;
276
status = smb_raw_setfileinfo(cli->tree, &sfinfo);
277
CHECK_STATUS(status, NT_STATUS_OK);
279
smbcli_close(cli->tree, fnum);
281
status = smb_raw_rmdir(cli->tree, &dio);
282
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
285
if (!torture_setting_bool(tctx, "samba3", false)) {
288
* Known deficiency, also skipped in base-delete.
291
printf("Testing with non-empty directory delete_on_close\n");
292
status = create_directory_handle(cli->tree, dname, &fnum);
293
CHECK_STATUS(status, NT_STATUS_OK);
295
fnum2 = create_complex_file(cli, tctx, inside);
297
sfinfo.disposition_info.in.file.fnum = fnum;
298
sfinfo.disposition_info.in.delete_on_close = 1;
299
status = smb_raw_setfileinfo(cli->tree, &sfinfo);
300
CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
302
sfinfo.disposition_info.in.file.fnum = fnum2;
303
status = smb_raw_setfileinfo(cli->tree, &sfinfo);
304
CHECK_STATUS(status, NT_STATUS_OK);
306
sfinfo.disposition_info.in.file.fnum = fnum;
307
status = smb_raw_setfileinfo(cli->tree, &sfinfo);
308
CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
310
smbcli_close(cli->tree, fnum2);
312
status = smb_raw_setfileinfo(cli->tree, &sfinfo);
313
CHECK_STATUS(status, NT_STATUS_OK);
315
smbcli_close(cli->tree, fnum);
317
status = smb_raw_rmdir(cli->tree, &dio);
318
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
321
printf("Testing open dir with delete_on_close\n");
322
status = create_directory_handle(cli->tree, dname, &fnum);
323
CHECK_STATUS(status, NT_STATUS_OK);
325
smbcli_close(cli->tree, fnum);
326
fnum2 = create_complex_file(cli, tctx, inside);
327
smbcli_close(cli->tree, fnum2);
329
op.generic.level = RAW_OPEN_NTCREATEX;
330
op.ntcreatex.in.root_fid = 0;
331
op.ntcreatex.in.flags = 0;
332
op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
333
op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
334
op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
335
op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
336
op.ntcreatex.in.alloc_size = 0;
337
op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
338
op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
339
op.ntcreatex.in.security_flags = 0;
340
op.ntcreatex.in.fname = dname;
342
status = smb_raw_open(cli->tree, tctx, &op);
343
CHECK_STATUS(status, NT_STATUS_OK);
344
fnum = op.ntcreatex.out.file.fnum;
346
smbcli_close(cli->tree, fnum);
348
status = smb_raw_rmdir(cli->tree, &dio);
349
CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
351
smbcli_deltree(cli->tree, dname);
353
printf("Testing double open dir with second delete_on_close\n");
354
status = create_directory_handle(cli->tree, dname, &fnum);
355
CHECK_STATUS(status, NT_STATUS_OK);
356
smbcli_close(cli->tree, fnum);
358
fnum2 = create_complex_file(cli, tctx, inside);
359
smbcli_close(cli->tree, fnum2);
361
op.generic.level = RAW_OPEN_NTCREATEX;
362
op.ntcreatex.in.root_fid = 0;
363
op.ntcreatex.in.flags = 0;
364
op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
365
op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
366
op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
367
op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
368
op.ntcreatex.in.alloc_size = 0;
369
op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
370
op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
371
op.ntcreatex.in.security_flags = 0;
372
op.ntcreatex.in.fname = dname;
374
status = smb_raw_open(cli->tree, tctx, &op);
375
CHECK_STATUS(status, NT_STATUS_OK);
376
fnum2 = op.ntcreatex.out.file.fnum;
378
smbcli_close(cli->tree, fnum2);
380
status = smb_raw_rmdir(cli->tree, &dio);
381
CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
383
smbcli_deltree(cli->tree, dname);
385
printf("Testing pre-existing open dir with second delete_on_close\n");
386
status = create_directory_handle(cli->tree, dname, &fnum);
387
CHECK_STATUS(status, NT_STATUS_OK);
389
smbcli_close(cli->tree, fnum);
391
fnum = create_complex_file(cli, tctx, inside);
392
smbcli_close(cli->tree, fnum);
394
/* we have a dir with a file in it, no handles open */
396
op.generic.level = RAW_OPEN_NTCREATEX;
397
op.ntcreatex.in.root_fid = 0;
398
op.ntcreatex.in.flags = 0;
399
op.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
400
op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY |NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
401
op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
402
op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
403
op.ntcreatex.in.alloc_size = 0;
404
op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
405
op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
406
op.ntcreatex.in.security_flags = 0;
407
op.ntcreatex.in.fname = dname;
409
status = smb_raw_open(cli->tree, tctx, &op);
410
CHECK_STATUS(status, NT_STATUS_OK);
411
fnum = op.ntcreatex.out.file.fnum;
413
/* open without delete on close */
414
op.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
415
status = smb_raw_open(cli->tree, tctx, &op);
416
CHECK_STATUS(status, NT_STATUS_OK);
417
fnum2 = op.ntcreatex.out.file.fnum;
419
/* close 2nd file handle */
420
smbcli_close(cli->tree, fnum2);
422
status = smb_raw_rmdir(cli->tree, &dio);
423
CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
426
smbcli_close(cli->tree, fnum);
428
status = smb_raw_rmdir(cli->tree, &dio);
429
CHECK_STATUS(status, NT_STATUS_DIRECTORY_NOT_EMPTY);
432
smb_raw_exit(cli->session);
433
smbcli_deltree(cli->tree, BASEDIR);
439
basic testing of unlink calls
441
struct torture_suite *torture_raw_unlink(TALLOC_CTX *mem_ctx)
443
struct torture_suite *suite = torture_suite_create(mem_ctx, "UNLINK");
445
torture_suite_add_1smb_test(suite, "unlink", test_unlink);
446
torture_suite_add_1smb_test(suite, "delete_on_close", test_delete_on_close);