~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/basic/delete.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   delete on close testing
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2003
 
7
   
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include "includes.h"
 
23
#include "libcli/libcli.h"
 
24
#include "torture/torture.h"
 
25
#include "torture/util.h"
 
26
#include "system/filesys.h"
 
27
#include "libcli/raw/libcliraw.h"
 
28
#include "libcli/raw/raw_proto.h"
 
29
 
 
30
#include "torture/raw/proto.h"
 
31
 
 
32
static bool check_delete_on_close(struct torture_context *tctx, 
 
33
                                                                  struct smbcli_state *cli, int fnum,
 
34
                                                                  const char *fname, bool expect_it, 
 
35
                                                                  const char *where)
 
36
{
 
37
        union smb_search_data data;
 
38
        NTSTATUS status;
 
39
 
 
40
        time_t c_time, a_time, m_time;
 
41
        size_t size;
 
42
        uint16_t mode;
 
43
 
 
44
        status = torture_single_search(cli, tctx,
 
45
                                       fname,
 
46
                                       RAW_SEARCH_TRANS2,
 
47
                                       RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
 
48
                                       FILE_ATTRIBUTE_DIRECTORY,
 
49
                                       &data);
 
50
        torture_assert_ntstatus_ok(tctx, status, 
 
51
                talloc_asprintf(tctx, "single_search failed (%s)", where));
 
52
 
 
53
        if (fnum != -1) {
 
54
                union smb_fileinfo io;
 
55
                int nlink = expect_it ? 0 : 1;
 
56
 
 
57
                io.all_info.level = RAW_FILEINFO_ALL_INFO;
 
58
                io.all_info.in.file.fnum = fnum;
 
59
 
 
60
                status = smb_raw_fileinfo(cli->tree, tctx, &io);
 
61
                torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, 
 
62
                                        "qfileinfo failed (%s)", where));
 
63
 
 
64
                torture_assert(tctx, expect_it == io.all_info.out.delete_pending, 
 
65
                        talloc_asprintf(tctx, 
 
66
                        "%s - Expected del_on_close flag %d, qfileinfo/all_info gave %d",
 
67
                               where, expect_it, io.all_info.out.delete_pending));
 
68
 
 
69
                torture_assert(tctx, nlink == io.all_info.out.nlink, 
 
70
                        talloc_asprintf(tctx, 
 
71
                                "%s - Expected nlink %d, qfileinfo/all_info gave %d",
 
72
                               where, nlink, io.all_info.out.nlink));
 
73
 
 
74
                io.standard_info.level = RAW_FILEINFO_STANDARD_INFO;
 
75
                io.standard_info.in.file.fnum = fnum;
 
76
 
 
77
                status = smb_raw_fileinfo(cli->tree, tctx, &io);
 
78
                torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
 
79
 
 
80
                torture_assert(tctx, expect_it == io.standard_info.out.delete_pending,
 
81
                        talloc_asprintf(tctx, "%s - Expected del_on_close flag %d, qfileinfo/standard_info gave %d\n",
 
82
                               where, expect_it, io.standard_info.out.delete_pending));
 
83
 
 
84
                torture_assert(tctx, nlink == io.standard_info.out.nlink,
 
85
                        talloc_asprintf(tctx, "%s - Expected nlink %d, qfileinfo/standard_info gave %d",
 
86
                               where, nlink, io.all_info.out.nlink));
 
87
        }
 
88
 
 
89
        status = smbcli_qpathinfo(cli->tree, fname,
 
90
                                  &c_time, &a_time, &m_time,
 
91
                                  &size, &mode);
 
92
 
 
93
        if (expect_it) {
 
94
                torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
 
95
                        "qpathinfo did not give correct error code");
 
96
        } else {
 
97
                torture_assert_ntstatus_ok(tctx, status, 
 
98
                        talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
 
99
        }
 
100
 
 
101
        return true;
 
102
}
 
103
 
 
104
#define CHECK_STATUS(_cli, _expected) \
 
105
        torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
 
106
                 "Incorrect status")
 
107
 
 
108
static const char *fname = "\\delete.file";
 
109
static const char *fname_new = "\\delete.new";
 
110
static const char *dname = "\\delete.dir";
 
111
 
 
112
static void del_clean_area(struct smbcli_state *cli1, struct smbcli_state *cli2)
 
113
{
 
114
        smb_raw_exit(cli1->session);
 
115
        smb_raw_exit(cli2->session);
 
116
 
 
117
        smbcli_deltree(cli1->tree, dname);
 
118
        smbcli_setatr(cli1->tree, fname, 0, 0);
 
119
        smbcli_unlink(cli1->tree, fname);
 
120
        smbcli_setatr(cli1->tree, fname_new, 0, 0);
 
121
        smbcli_unlink(cli1->tree, fname_new);
 
122
}
 
123
 
 
124
/* Test 1 - this should delete the file on close. */
 
125
 
 
126
static bool deltest1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
127
{
 
128
        int fnum1 = -1;
 
129
 
 
130
        del_clean_area(cli1, cli2);
 
131
 
 
132
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
133
                                      SEC_RIGHTS_FILE_ALL,
 
134
                                      FILE_ATTRIBUTE_NORMAL,
 
135
                                      NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
 
136
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
137
        
 
138
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
139
                       fname, smbcli_errstr(cli1->tree)));
 
140
        
 
141
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
 
142
                talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli1->tree)));
 
143
 
 
144
        fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
 
145
        torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)", 
 
146
                       fname));
 
147
 
 
148
        return true;
 
149
}
 
150
 
 
151
/* Test 2 - this should delete the file on close. */
 
152
static bool deltest2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
153
{
 
154
        int fnum1 = -1;
 
155
 
 
156
        del_clean_area(cli1, cli2);
 
157
 
 
158
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
159
                                      SEC_RIGHTS_FILE_ALL,
 
160
                                      FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
 
161
                                      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
162
        
 
163
        torture_assert(tctx, fnum1 != -1, 
 
164
                talloc_asprintf(tctx, "open of %s failed (%s)", 
 
165
                       fname, smbcli_errstr(cli1->tree)));
 
166
        
 
167
        torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, true), 
 
168
                talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
 
169
                       smbcli_errstr(cli1->tree)));
 
170
        
 
171
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
 
172
                talloc_asprintf(tctx, "close failed (%s)", 
 
173
                       smbcli_errstr(cli1->tree)));
 
174
        
 
175
        fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
 
176
        if (fnum1 != -1) {
 
177
                printf("(%s) open of %s succeeded should have been deleted on close !\n", 
 
178
                       __location__, fname);
 
179
                if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
 
180
                        printf("(%s) close failed (%s)\n", 
 
181
                               __location__, smbcli_errstr(cli1->tree));
 
182
                        return false;
 
183
                }
 
184
                smbcli_unlink(cli1->tree, fname);
 
185
        }
 
186
        return true;
 
187
}
 
188
 
 
189
/* Test 3 - ... */
 
190
static bool deltest3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
191
{
 
192
        int fnum1 = -1;
 
193
        int fnum2 = -1;
 
194
 
 
195
        del_clean_area(cli1, cli2);
 
196
 
 
197
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
198
                                      SEC_RIGHTS_FILE_ALL,
 
199
                                      FILE_ATTRIBUTE_NORMAL,
 
200
                                      NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
 
201
                                      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
202
 
 
203
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
204
                        fname, smbcli_errstr(cli1->tree)));
 
205
 
 
206
        /* This should fail with a sharing violation - open for delete is only compatible
 
207
           with SHARE_DELETE. */
 
208
 
 
209
        fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
210
                                      SEC_RIGHTS_FILE_READ, 
 
211
                                      FILE_ATTRIBUTE_NORMAL,
 
212
                                      NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
 
213
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
214
 
 
215
        torture_assert(tctx, fnum2 == -1, 
 
216
                talloc_asprintf(tctx, "open  - 2 of %s succeeded - should have failed.", 
 
217
                       fname));
 
218
 
 
219
        /* This should succeed. */
 
220
 
 
221
        fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
222
                                      SEC_RIGHTS_FILE_READ, 
 
223
                                      FILE_ATTRIBUTE_NORMAL,
 
224
                                      NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, 
 
225
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
226
 
 
227
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open  - 2 of %s failed (%s)", 
 
228
                       fname, smbcli_errstr(cli1->tree)));
 
229
 
 
230
        torture_assert_ntstatus_ok(tctx, 
 
231
                                                           smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
 
232
                                                           talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
 
233
                                                   smbcli_errstr(cli1->tree)));
 
234
        
 
235
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
 
236
                talloc_asprintf(tctx, "close 1 failed (%s)", 
 
237
                       smbcli_errstr(cli1->tree)));
 
238
        
 
239
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum2),
 
240
                talloc_asprintf(tctx, "close 2 failed (%s)", 
 
241
                       smbcli_errstr(cli1->tree)));
 
242
        
 
243
        /* This should fail - file should no longer be there. */
 
244
 
 
245
        fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
 
246
        if (fnum1 != -1) {
 
247
                printf("(%s) open of %s succeeded should have been deleted on close !\n", 
 
248
                       __location__, fname);
 
249
                if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
 
250
                        printf("(%s) close failed (%s)\n", 
 
251
                               __location__, smbcli_errstr(cli1->tree));
 
252
                }
 
253
                smbcli_unlink(cli1->tree, fname);
 
254
                return false;
 
255
        }
 
256
        return true;
 
257
}
 
258
 
 
259
/* Test 4 ... */
 
260
static bool deltest4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
261
{
 
262
        int fnum1 = -1;
 
263
        int fnum2 = -1;
 
264
        bool correct = true;
 
265
 
 
266
        del_clean_area(cli1, cli2);
 
267
 
 
268
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
269
                                      SEC_FILE_READ_DATA  | 
 
270
                                      SEC_FILE_WRITE_DATA |
 
271
                                      SEC_STD_DELETE,
 
272
                                      FILE_ATTRIBUTE_NORMAL, 
 
273
                                      NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
 
274
                                      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
275
                                                                
 
276
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
277
                       fname, smbcli_errstr(cli1->tree)));
 
278
 
 
279
        /* This should succeed. */
 
280
        fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
281
                                      SEC_RIGHTS_FILE_READ,
 
282
                                      FILE_ATTRIBUTE_NORMAL, 
 
283
                                      NTCREATEX_SHARE_ACCESS_READ  | 
 
284
                                      NTCREATEX_SHARE_ACCESS_WRITE |
 
285
                                      NTCREATEX_SHARE_ACCESS_DELETE, 
 
286
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
287
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open  - 2 of %s failed (%s)", 
 
288
                       fname, smbcli_errstr(cli1->tree)));
 
289
        
 
290
        torture_assert_ntstatus_ok(tctx, 
 
291
                                        smbcli_close(cli1->tree, fnum2),
 
292
                                        talloc_asprintf(tctx, "close - 1 failed (%s)", 
 
293
                                        smbcli_errstr(cli1->tree)));
 
294
        
 
295
        torture_assert_ntstatus_ok(tctx, 
 
296
                                smbcli_nt_delete_on_close(cli1->tree, fnum1, true), 
 
297
                                talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
 
298
                        smbcli_errstr(cli1->tree)));
 
299
 
 
300
        /* This should fail - no more opens once delete on close set. */
 
301
        fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
302
                                      SEC_RIGHTS_FILE_READ,
 
303
                                      FILE_ATTRIBUTE_NORMAL, 
 
304
                                      NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
 
305
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
306
        torture_assert(tctx, fnum2 == -1, 
 
307
                 talloc_asprintf(tctx, "open  - 3 of %s succeeded ! Should have failed.",
 
308
                       fname ));
 
309
 
 
310
        CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
 
311
 
 
312
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
 
313
                 talloc_asprintf(tctx, "close - 2 failed (%s)", 
 
314
                       smbcli_errstr(cli1->tree)));
 
315
        
 
316
        return correct;
 
317
}
 
318
 
 
319
/* Test 5 ... */
 
320
static bool deltest5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
321
{
 
322
        int fnum1 = -1;
 
323
 
 
324
        del_clean_area(cli1, cli2);
 
325
 
 
326
        fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
 
327
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
328
                       fname, smbcli_errstr(cli1->tree)));
 
329
        
 
330
        /* This should fail - only allowed on NT opens with DELETE access. */
 
331
 
 
332
        torture_assert(tctx, !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, true)),
 
333
                 "setting delete_on_close on OpenX file succeeded - should fail !");
 
334
 
 
335
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
 
336
                talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
 
337
 
 
338
        return true;
 
339
}
 
340
 
 
341
/* Test 6 ... */
 
342
static bool deltest6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
343
{
 
344
        int fnum1 = -1;
 
345
 
 
346
        del_clean_area(cli1, cli2);
 
347
 
 
348
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
349
                                   SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
 
350
                                   FILE_ATTRIBUTE_NORMAL, 
 
351
                                   NTCREATEX_SHARE_ACCESS_READ  |
 
352
                                   NTCREATEX_SHARE_ACCESS_WRITE |
 
353
                                   NTCREATEX_SHARE_ACCESS_DELETE,
 
354
                                   NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
355
        
 
356
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
357
                       fname, smbcli_errstr(cli1->tree)));
 
358
        
 
359
        /* This should fail - only allowed on NT opens with DELETE access. */
 
360
        
 
361
        torture_assert(tctx, 
 
362
                !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, true)),
 
363
                "setting delete_on_close on file with no delete access succeeded - should fail !");
 
364
 
 
365
        torture_assert_ntstatus_ok(tctx, 
 
366
                                                           smbcli_close(cli1->tree, fnum1),
 
367
                talloc_asprintf(tctx, "close - 2 failed (%s)", 
 
368
                       smbcli_errstr(cli1->tree)));
 
369
 
 
370
        return true;
 
371
}
 
372
 
 
373
/* Test 7 ... */
 
374
static bool deltest7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
375
{
 
376
        int fnum1 = -1;
 
377
        bool correct = true;
 
378
 
 
379
        del_clean_area(cli1, cli2);
 
380
 
 
381
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
382
                                      SEC_FILE_READ_DATA  | 
 
383
                                      SEC_FILE_WRITE_DATA |
 
384
                                      SEC_STD_DELETE,
 
385
                                      FILE_ATTRIBUTE_NORMAL, 0, 
 
386
                                      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
387
                                                                
 
388
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
389
                       fname, smbcli_errstr(cli1->tree)));
 
390
 
 
391
        torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
 
392
                        "setting delete_on_close on file failed !");
 
393
 
 
394
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
 
395
        
 
396
        torture_assert_ntstatus_ok(tctx, 
 
397
                                        smbcli_nt_delete_on_close(cli1->tree, fnum1, false), 
 
398
                                        "unsetting delete_on_close on file failed !");
 
399
 
 
400
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
401
        
 
402
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
 
403
                talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
 
404
        
 
405
        /* This next open should succeed - we reset the flag. */
 
406
        
 
407
        fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
 
408
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
409
                       fname, smbcli_errstr(cli1->tree)));
 
410
 
 
411
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
 
412
                                                       talloc_asprintf(tctx, "close - 2 failed (%s)", 
 
413
                                                   smbcli_errstr(cli1->tree)));
 
414
 
 
415
        return correct;
 
416
}
 
417
 
 
418
/* Test 8 ... */
 
419
static bool deltest8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
420
{
 
421
        int fnum1 = -1;
 
422
        int fnum2 = -1;
 
423
        bool correct = true;
 
424
 
 
425
        del_clean_area(cli1, cli2);
 
426
 
 
427
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
428
                                      SEC_FILE_READ_DATA|
 
429
                                      SEC_FILE_WRITE_DATA|
 
430
                                      SEC_STD_DELETE,
 
431
                                      FILE_ATTRIBUTE_NORMAL, 
 
432
                                      NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
 
433
                                      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
434
        
 
435
        torture_assert(tctx, fnum1 != -1,
 
436
                talloc_asprintf(tctx, "open of %s failed (%s)", 
 
437
                       fname, smbcli_errstr(cli1->tree)));
 
438
 
 
439
        fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
 
440
                                      SEC_FILE_READ_DATA|
 
441
                                      SEC_FILE_WRITE_DATA|
 
442
                                      SEC_STD_DELETE,
 
443
                                      FILE_ATTRIBUTE_NORMAL, 
 
444
                                      NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
 
445
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
446
        
 
447
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
448
                       fname, smbcli_errstr(cli1->tree)));
 
449
 
 
450
        torture_assert_ntstatus_ok(tctx, 
 
451
                                        smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
 
452
                "setting delete_on_close on file failed !");
 
453
 
 
454
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
 
455
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
 
456
 
 
457
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
 
458
                talloc_asprintf(tctx, "close - 1 failed (%s)", 
 
459
                       smbcli_errstr(cli1->tree)));
 
460
 
 
461
        correct &= check_delete_on_close(tctx, cli1, -1, fname, true, __location__);
 
462
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
 
463
        
 
464
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
 
465
                talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli2->tree)));
 
466
 
 
467
        /* This should fail.. */
 
468
        fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
 
469
        torture_assert(tctx, fnum1 == -1,
 
470
                talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !\n", fname));
 
471
 
 
472
        return correct;
 
473
}
 
474
 
 
475
/* Test 9 ... */
 
476
static bool deltest9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
477
{
 
478
        int fnum1 = -1;
 
479
 
 
480
        del_clean_area(cli1, cli2);
 
481
 
 
482
        /* This should fail - we need to set DELETE_ACCESS. */
 
483
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
 
484
                                      SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
 
485
                                      FILE_ATTRIBUTE_NORMAL, 
 
486
                                      NTCREATEX_SHARE_ACCESS_NONE, 
 
487
                                      NTCREATEX_DISP_OVERWRITE_IF, 
 
488
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
489
        
 
490
        torture_assert(tctx, fnum1 == -1, 
 
491
                                   talloc_asprintf(tctx, "open of %s succeeded should have failed!", 
 
492
                       fname));
 
493
 
 
494
        return true;
 
495
}
 
496
 
 
497
/* Test 10 ... */
 
498
static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
499
{
 
500
        int fnum1 = -1;
 
501
 
 
502
        del_clean_area(cli1, cli2);
 
503
 
 
504
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
505
                                      SEC_FILE_READ_DATA|
 
506
                                      SEC_FILE_WRITE_DATA|
 
507
                                      SEC_STD_DELETE,
 
508
                                      FILE_ATTRIBUTE_NORMAL, 
 
509
                                      NTCREATEX_SHARE_ACCESS_NONE, 
 
510
                                      NTCREATEX_DISP_OVERWRITE_IF, 
 
511
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
512
        torture_assert(tctx, fnum1 != -1, 
 
513
                talloc_asprintf(tctx, "open of %s failed (%s)", 
 
514
                       fname, smbcli_errstr(cli1->tree)));
 
515
 
 
516
        /* This should delete the file. */
 
517
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
 
518
                talloc_asprintf(tctx, "close failed (%s)", 
 
519
                       smbcli_errstr(cli1->tree)));
 
520
 
 
521
        /* This should fail.. */
 
522
        fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
 
523
        torture_assert(tctx, fnum1 == -1, 
 
524
                                talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
 
525
                       fname));
 
526
        return true;
 
527
}
 
528
 
 
529
/* Test 11 ... */
 
530
static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
531
{
 
532
        int fnum1 = -1;
 
533
        NTSTATUS status;
 
534
 
 
535
        del_clean_area(cli1, cli2);
 
536
 
 
537
        /* test 11 - does having read only attribute still allow delete on close. */
 
538
 
 
539
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
540
                                      SEC_RIGHTS_FILE_ALL,
 
541
                                      FILE_ATTRIBUTE_READONLY, 
 
542
                                      NTCREATEX_SHARE_ACCESS_NONE, 
 
543
                                      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
544
        
 
545
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
546
                       fname, smbcli_errstr(cli1->tree)));
 
547
 
 
548
        status = smbcli_nt_delete_on_close(cli1->tree, fnum1, true);
 
549
 
 
550
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE, 
 
551
                talloc_asprintf(tctx, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1->tree)));
 
552
 
 
553
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
 
554
                talloc_asprintf(tctx, "close failed (%s)", 
 
555
                       smbcli_errstr(cli1->tree)));
 
556
 
 
557
        return true;
 
558
}
 
559
 
 
560
/* Test 12 ... */
 
561
static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
562
{
 
563
        int fnum1 = -1;
 
564
        NTSTATUS status;
 
565
 
 
566
        del_clean_area(cli1, cli2);
 
567
 
 
568
        /* test 12 - does having read only attribute still allow delete on
 
569
         * close at time of open. */
 
570
 
 
571
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
572
                                      SEC_RIGHTS_FILE_ALL,
 
573
                                      FILE_ATTRIBUTE_READONLY,
 
574
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
575
                                      NTCREATEX_DISP_OVERWRITE_IF, 
 
576
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
577
        
 
578
        torture_assert(tctx, fnum1 == -1, 
 
579
                 talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
 
580
                       "NT_STATUS_CANNOT_DELETE.\n", fname));
 
581
 
 
582
        status = smbcli_nt_error(cli1->tree);
 
583
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE, 
 
584
                         talloc_asprintf(tctx, "setting delete_on_close on open should "
 
585
                               "fail with NT_STATUS_CANNOT_DELETE. Got %s "
 
586
                               "instead)", 
 
587
                               smbcli_errstr(cli1->tree)));
 
588
        
 
589
        return true;
 
590
}
 
591
 
 
592
/* Test 13 ... */
 
593
static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
594
{
 
595
        int fnum1 = -1;
 
596
        int fnum2 = -1;
 
597
        bool correct = true;
 
598
 
 
599
        del_clean_area(cli1, cli2);
 
600
 
 
601
        /* Test 13: Does resetting the delete on close flag affect a second
 
602
         * fd? */
 
603
 
 
604
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
605
                                      SEC_FILE_READ_DATA|
 
606
                                      SEC_FILE_WRITE_DATA|
 
607
                                      SEC_STD_DELETE,
 
608
                                      FILE_ATTRIBUTE_NORMAL, 
 
609
                                      NTCREATEX_SHARE_ACCESS_READ|
 
610
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
611
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
612
                                      NTCREATEX_DISP_OVERWRITE_IF,
 
613
                                      0, 0);
 
614
        
 
615
        torture_assert(tctx, fnum1 != -1, 
 
616
                talloc_asprintf(tctx, "open of %s failed (%s)", 
 
617
                       fname, smbcli_errstr(cli1->tree)));
 
618
 
 
619
        fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
 
620
                                      SEC_FILE_READ_DATA|
 
621
                                      SEC_FILE_WRITE_DATA|
 
622
                                      SEC_STD_DELETE,
 
623
                                      FILE_ATTRIBUTE_NORMAL, 
 
624
                                      NTCREATEX_SHARE_ACCESS_READ|
 
625
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
626
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
627
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
628
        
 
629
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, 
 
630
                                "open of %s failed (%s)", 
 
631
                       fname, smbcli_errstr(cli2->tree)));
 
632
 
 
633
        torture_assert_ntstatus_ok(tctx, 
 
634
                                                smbcli_nt_delete_on_close(cli1->tree, fnum1,
 
635
                                                       true), 
 
636
                 "setting delete_on_close on file failed !");
 
637
 
 
638
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
 
639
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
 
640
 
 
641
        torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
 
642
                                                       false), 
 
643
                 "setting delete_on_close on file failed !");
 
644
 
 
645
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
646
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
 
647
        
 
648
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
 
649
                talloc_asprintf(tctx, "close - 1 failed (%s)", 
 
650
                       smbcli_errstr(cli1->tree)));
 
651
 
 
652
        torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
 
653
                        talloc_asprintf(tctx, "close - 2 failed (%s)", 
 
654
                       smbcli_errstr(cli2->tree)));
 
655
 
 
656
        fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
 
657
 
 
658
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!", 
 
659
                       fname));
 
660
 
 
661
        smbcli_close(cli1->tree, fnum1);
 
662
 
 
663
        return correct;
 
664
}
 
665
 
 
666
/* Test 14 ... */
 
667
static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
668
{
 
669
        int dnum1 = -1;
 
670
        bool correct = true;
 
671
 
 
672
        del_clean_area(cli1, cli2);
 
673
 
 
674
        /* Test 14 -- directory */
 
675
 
 
676
        dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
 
677
                                      SEC_FILE_READ_DATA|
 
678
                                      SEC_FILE_WRITE_DATA|
 
679
                                      SEC_STD_DELETE,
 
680
                                      FILE_ATTRIBUTE_DIRECTORY, 
 
681
                                      NTCREATEX_SHARE_ACCESS_READ|
 
682
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
683
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
684
                                      NTCREATEX_DISP_CREATE, 0, 0);
 
685
        torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!", 
 
686
                       dname, smbcli_errstr(cli1->tree)));
 
687
 
 
688
        correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
 
689
        torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
 
690
                        "setting delete_on_close on file failed !");
 
691
        correct &= check_delete_on_close(tctx, cli1, dnum1, dname, true, __location__);
 
692
        smbcli_close(cli1->tree, dnum1);
 
693
 
 
694
        /* Now it should be gone... */
 
695
 
 
696
        dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
 
697
                                      SEC_FILE_READ_DATA|
 
698
                                      SEC_FILE_WRITE_DATA|
 
699
                                      SEC_STD_DELETE,
 
700
                                      FILE_ATTRIBUTE_DIRECTORY, 
 
701
                                      NTCREATEX_SHARE_ACCESS_READ|
 
702
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
703
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
704
                                      NTCREATEX_DISP_OPEN, 0, 0);
 
705
        torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
 
706
 
 
707
        return correct;
 
708
}
 
709
 
 
710
/* Test 15 ... */
 
711
static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
712
{
 
713
        int fnum1 = -1;
 
714
        bool correct = true;
 
715
        int fnum2 = -1;
 
716
        NTSTATUS status;
 
717
 
 
718
        del_clean_area(cli1, cli2);
 
719
 
 
720
        /* Test 15: delete on close under rename */
 
721
 
 
722
        smbcli_setatr(cli1->tree, fname, 0, 0);
 
723
        smbcli_unlink(cli1->tree, fname);
 
724
        smbcli_unlink(cli1->tree, fname_new);
 
725
        
 
726
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
727
                                      SEC_FILE_READ_DATA,
 
728
                                      FILE_ATTRIBUTE_NORMAL, 
 
729
                                      NTCREATEX_SHARE_ACCESS_READ|
 
730
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
731
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
732
                                      NTCREATEX_DISP_OVERWRITE_IF,
 
733
                                      0, 0);
 
734
 
 
735
        torture_assert(tctx, fnum1 != -1, 
 
736
                talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
 
737
 
 
738
        status = smbcli_rename(cli2->tree, fname, fname_new);
 
739
 
 
740
        torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
 
741
 
 
742
        fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0, 
 
743
                                      SEC_GENERIC_ALL,
 
744
                                      FILE_ATTRIBUTE_NORMAL, 
 
745
                                      NTCREATEX_SHARE_ACCESS_READ|
 
746
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
747
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
748
                                      NTCREATEX_DISP_OVERWRITE_IF,
 
749
                                      0, 0);
 
750
 
 
751
        torture_assert(tctx, fnum2 != -1, 
 
752
                talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
753
                       fname_new, smbcli_errstr(cli1->tree)));
 
754
 
 
755
        status = smbcli_nt_delete_on_close(cli2->tree, fnum2, true);
 
756
 
 
757
        torture_assert_ntstatus_ok(tctx, status, 
 
758
                "setting delete_on_close on file failed !");
 
759
 
 
760
        smbcli_close(cli2->tree, fnum2);
 
761
 
 
762
        /* The file should be around under the new name, there's a second
 
763
         * handle open */
 
764
 
 
765
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, true, __location__);
 
766
 
 
767
        fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
 
768
                                      SEC_GENERIC_ALL,
 
769
                                      FILE_ATTRIBUTE_NORMAL, 
 
770
                                      NTCREATEX_SHARE_ACCESS_READ|
 
771
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
772
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
773
                                      NTCREATEX_DISP_OVERWRITE_IF,
 
774
                                      0, 0);
 
775
 
 
776
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
777
                       fname, smbcli_errstr(cli1->tree)));
 
778
 
 
779
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
 
780
 
 
781
        smbcli_close(cli2->tree, fnum2);
 
782
        smbcli_close(cli1->tree, fnum1);
 
783
 
 
784
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
785
                                      SEC_FILE_READ_EA,
 
786
                                      FILE_ATTRIBUTE_NORMAL, 
 
787
                                      NTCREATEX_SHARE_ACCESS_READ|
 
788
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
789
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
790
                                      NTCREATEX_DISP_OPEN,
 
791
                                      0, 0);
 
792
 
 
793
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
794
                       fname, smbcli_errstr(cli1->tree)));
 
795
 
 
796
        smbcli_close(cli1->tree, fnum1);
 
797
 
 
798
        fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0, 
 
799
                                      SEC_FILE_READ_EA,
 
800
                                      FILE_ATTRIBUTE_NORMAL, 
 
801
                                      NTCREATEX_SHARE_ACCESS_READ|
 
802
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
803
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
804
                                      NTCREATEX_DISP_OPEN,
 
805
                                      0, 0);
 
806
 
 
807
        torture_assert(tctx, fnum1 == -1, 
 
808
                "smbcli_open succeeded, should have "
 
809
                       "failed");
 
810
 
 
811
        return correct;
 
812
}
 
813
 
 
814
/* Test 16 ... */
 
815
static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
816
{
 
817
        int fnum1 = -1;
 
818
        int fnum2 = -1;
 
819
        bool correct = true;
 
820
 
 
821
        del_clean_area(cli1, cli2);
 
822
 
 
823
        /* Test 16. */
 
824
 
 
825
        /* Ensure the file doesn't already exist. */
 
826
        smbcli_close(cli1->tree, fnum1);
 
827
        smbcli_close(cli1->tree, fnum2);
 
828
        smbcli_setatr(cli1->tree, fname, 0, 0);
 
829
        smbcli_unlink(cli1->tree, fname);
 
830
 
 
831
        /* Firstly create with all access, but delete on close. */
 
832
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
833
                                      SEC_RIGHTS_FILE_ALL,
 
834
                                      FILE_ATTRIBUTE_NORMAL,
 
835
                                      NTCREATEX_SHARE_ACCESS_READ|
 
836
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
837
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
838
                                      NTCREATEX_DISP_CREATE,
 
839
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
840
        
 
841
        torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
 
842
 
 
843
        /* The delete on close bit is *not* reported as being set. */
 
844
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
845
 
 
846
        /* The delete on close bit is *not* reported as being set. */
 
847
        correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
 
848
        correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
 
849
 
 
850
        /* Now try opening again for read-only. */
 
851
        fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
 
852
                                      SEC_RIGHTS_FILE_READ,
 
853
                                      FILE_ATTRIBUTE_NORMAL,
 
854
                                      NTCREATEX_SHARE_ACCESS_READ|
 
855
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
856
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
857
                                      NTCREATEX_DISP_OPEN,
 
858
                                      0, 0);
 
859
        
 
860
        /* Should work. */
 
861
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
862
                      fname, smbcli_errstr(cli1->tree)));
 
863
 
 
864
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
865
        correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
 
866
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
 
867
        correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
 
868
 
 
869
        smbcli_close(cli1->tree, fnum1);
 
870
 
 
871
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
 
872
        correct &= check_delete_on_close(tctx, cli2, -1, fname, true, __location__);
 
873
 
 
874
        smbcli_close(cli2->tree, fnum2);
 
875
 
 
876
        /* And the file should be deleted ! */
 
877
        fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
 
878
        torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)", 
 
879
                       fname));
 
880
 
 
881
        return correct;
 
882
}
 
883
 
 
884
/* Test 17 ... */
 
885
static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
886
{
 
887
        int fnum1 = -1;
 
888
        int fnum2 = -1;
 
889
        bool correct = true;
 
890
 
 
891
        del_clean_area(cli1, cli2);
 
892
 
 
893
        /* Test 17. */
 
894
 
 
895
        /* Ensure the file doesn't already exist. */
 
896
        smbcli_close(cli1->tree, fnum1);
 
897
        smbcli_close(cli1->tree, fnum2);
 
898
        smbcli_setatr(cli1->tree, fname, 0, 0);
 
899
        smbcli_unlink(cli1->tree, fname);
 
900
 
 
901
        /* Firstly open and create with all access */
 
902
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
903
                                      SEC_RIGHTS_FILE_ALL,
 
904
                                      FILE_ATTRIBUTE_NORMAL,
 
905
                                      NTCREATEX_SHARE_ACCESS_READ|
 
906
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
907
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
908
                                      NTCREATEX_DISP_CREATE, 
 
909
                                      0, 0);
 
910
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
911
                       fname, smbcli_errstr(cli1->tree)));
 
912
 
 
913
        /* And close - just to create the file. */
 
914
        smbcli_close(cli1->tree, fnum1);
 
915
        
 
916
        /* Next open with all access, but add delete on close. */
 
917
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
918
                                      SEC_RIGHTS_FILE_ALL,
 
919
                                      FILE_ATTRIBUTE_NORMAL,
 
920
                                      NTCREATEX_SHARE_ACCESS_READ|
 
921
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
922
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
923
                                      NTCREATEX_DISP_OPEN,
 
924
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
925
        
 
926
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
927
                       fname, smbcli_errstr(cli1->tree)));
 
928
 
 
929
        /* The delete on close bit is *not* reported as being set. */
 
930
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
931
 
 
932
        /* Now try opening again for read-only. */
 
933
        fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
934
                                      SEC_RIGHTS_FILE_READ|
 
935
                                      SEC_STD_DELETE,
 
936
                                      FILE_ATTRIBUTE_NORMAL,
 
937
                                      NTCREATEX_SHARE_ACCESS_READ|
 
938
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
939
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
940
                                      NTCREATEX_DISP_OPEN,
 
941
                                      0, 0);
 
942
        
 
943
        /* Should work. */
 
944
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
945
                       fname, smbcli_errstr(cli1->tree)));
 
946
 
 
947
        /* still not reported as being set on either */
 
948
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
949
        correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
 
950
 
 
951
        smbcli_close(cli1->tree, fnum1);
 
952
 
 
953
        /* After the first close, the files has the delete on close bit set. */
 
954
        correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
 
955
 
 
956
        smbcli_close(cli1->tree, fnum2);
 
957
 
 
958
        /* Make sure the file has been deleted */
 
959
        fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
 
960
        torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
 
961
                       fname, smbcli_errstr(cli1->tree)));
 
962
 
 
963
        CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 
964
 
 
965
        return correct;
 
966
}
 
967
 
 
968
/* Test 18 ... */
 
969
static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
970
{
 
971
        int fnum1 = -1;
 
972
        int fnum2 = -1;
 
973
        bool correct = true;
 
974
 
 
975
        del_clean_area(cli1, cli2);
 
976
 
 
977
        /* Test 18. With directories. */
 
978
 
 
979
        /* Ensure the file doesn't already exist. */
 
980
        smbcli_close(cli1->tree, fnum1);
 
981
        smbcli_close(cli1->tree, fnum2);
 
982
 
 
983
        smbcli_deltree(cli1->tree, dname);
 
984
 
 
985
        /* Firstly create with all access, but delete on close. */
 
986
        fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
 
987
                                      SEC_FILE_READ_DATA|
 
988
                                      SEC_FILE_WRITE_DATA|
 
989
                                      SEC_STD_DELETE,
 
990
                                      FILE_ATTRIBUTE_DIRECTORY,
 
991
                                      NTCREATEX_SHARE_ACCESS_READ|
 
992
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
993
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
994
                                      NTCREATEX_DISP_CREATE,
 
995
                                      NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
996
        
 
997
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
998
                       dname, smbcli_errstr(cli1->tree)));
 
999
 
 
1000
        /*
 
1001
         * The delete on close bit is *not* reported as being set.
 
1002
         * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
 
1003
         * close as being set.  This causes the subsequent create to fail with
 
1004
         * NT_STATUS_DELETE_PENDING.
 
1005
         */
 
1006
        correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
 
1007
 
 
1008
        /* Now try opening again for read-only. */
 
1009
        fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0, 
 
1010
                                      SEC_RIGHTS_FILE_READ,
 
1011
                                      FILE_ATTRIBUTE_DIRECTORY,
 
1012
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1013
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1014
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1015
                                      NTCREATEX_DISP_OPEN,
 
1016
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1017
        
 
1018
 
 
1019
        /* Should work. */
 
1020
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
1021
                       dname, smbcli_errstr(cli1->tree)));
 
1022
 
 
1023
        correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
 
1024
        correct &= check_delete_on_close(tctx, cli1, fnum2, dname, false, __location__);
 
1025
 
 
1026
        smbcli_close(cli1->tree, fnum1);
 
1027
 
 
1028
        correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
 
1029
 
 
1030
        smbcli_close(cli1->tree, fnum2);
 
1031
 
 
1032
        /* And the directory should be deleted ! */
 
1033
        fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
 
1034
                                      SEC_RIGHTS_FILE_READ,
 
1035
                                      FILE_ATTRIBUTE_DIRECTORY,
 
1036
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1037
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1038
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1039
                                      NTCREATEX_DISP_OPEN,
 
1040
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1041
        torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)", 
 
1042
                       dname));
 
1043
 
 
1044
        return correct;
 
1045
}
 
1046
 
 
1047
/* Test 19 ... */
 
1048
static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
1049
{
 
1050
        int fnum1 = -1;
 
1051
        int fnum2 = -1;
 
1052
        bool correct = true;
 
1053
 
 
1054
        del_clean_area(cli1, cli2);
 
1055
 
 
1056
        /* Test 19. */
 
1057
 
 
1058
        smbcli_deltree(cli1->tree, dname);
 
1059
 
 
1060
        /* Firstly open and create with all access */
 
1061
        fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
 
1062
                                      SEC_FILE_READ_DATA|
 
1063
                                      SEC_FILE_WRITE_DATA|
 
1064
                                      SEC_STD_DELETE,
 
1065
                                      FILE_ATTRIBUTE_DIRECTORY,
 
1066
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1067
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1068
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1069
                                      NTCREATEX_DISP_CREATE,
 
1070
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1071
        
 
1072
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
1073
                       dname, smbcli_errstr(cli1->tree)));
 
1074
 
 
1075
        /* And close - just to create the directory. */
 
1076
        smbcli_close(cli1->tree, fnum1);
 
1077
        
 
1078
        /* Next open with all access, but add delete on close. */
 
1079
        fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
 
1080
                                      SEC_FILE_READ_DATA|
 
1081
                                      SEC_FILE_WRITE_DATA|
 
1082
                                      SEC_STD_DELETE,
 
1083
                                      FILE_ATTRIBUTE_DIRECTORY,
 
1084
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1085
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1086
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1087
                                      NTCREATEX_DISP_OPEN,
 
1088
                                      NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
1089
        
 
1090
        torture_assert(tctx, fnum1 != -1, 
 
1091
                talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
 
1092
 
 
1093
        /*
 
1094
         * The delete on close bit is *not* reported as being set.
 
1095
         * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
 
1096
         * close as being set.  This causes the subsequent create to fail with
 
1097
         * NT_STATUS_DELETE_PENDING.
 
1098
         */
 
1099
        correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
 
1100
 
 
1101
        /* Now try opening again for read-only. */
 
1102
        fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0, 
 
1103
                                      SEC_RIGHTS_FILE_READ,
 
1104
                                      FILE_ATTRIBUTE_DIRECTORY,
 
1105
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1106
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1107
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1108
                                      NTCREATEX_DISP_OPEN,
 
1109
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1110
        
 
1111
        /* Should work. */
 
1112
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
1113
                       dname, smbcli_errstr(cli1->tree)));
 
1114
 
 
1115
        smbcli_close(cli1->tree, fnum1);
 
1116
 
 
1117
        correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
 
1118
 
 
1119
        smbcli_close(cli1->tree, fnum2);
 
1120
 
 
1121
        /* See if the file is deleted - for a directory this seems to be true ! */
 
1122
        fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
 
1123
                                      SEC_RIGHTS_FILE_READ,
 
1124
                                      FILE_ATTRIBUTE_DIRECTORY,
 
1125
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1126
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1127
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1128
                                      NTCREATEX_DISP_OPEN,
 
1129
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1130
 
 
1131
        CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 
1132
 
 
1133
        torture_assert(tctx, fnum1 == -1, 
 
1134
                talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
 
1135
 
 
1136
        return correct;
 
1137
}
 
1138
 
 
1139
/* Test 20 ... */
 
1140
static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
1141
{
 
1142
        int fnum1 = -1;
 
1143
        int dnum1 = -1;
 
1144
        bool correct = true;
 
1145
        NTSTATUS status;
 
1146
 
 
1147
        del_clean_area(cli1, cli2);
 
1148
 
 
1149
        /* Test 20 -- non-empty directory hardest to get right... */
 
1150
 
 
1151
        if (torture_setting_bool(tctx, "samba3", false)) {
 
1152
                return true;
 
1153
        }
 
1154
 
 
1155
        smbcli_deltree(cli1->tree, dname);
 
1156
 
 
1157
        dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
 
1158
                                      SEC_FILE_READ_DATA|
 
1159
                                      SEC_FILE_WRITE_DATA|
 
1160
                                      SEC_STD_DELETE,
 
1161
                                      FILE_ATTRIBUTE_DIRECTORY, 
 
1162
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1163
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1164
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1165
                                      NTCREATEX_DISP_CREATE, 
 
1166
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1167
        torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!", 
 
1168
                       dname, smbcli_errstr(cli1->tree)));
 
1169
 
 
1170
        correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
 
1171
        status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
 
1172
 
 
1173
        {
 
1174
                char *fullname;
 
1175
                asprintf(&fullname, "\\%s%s", dname, fname);
 
1176
                fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
 
1177
                                    DENY_NONE);
 
1178
                torture_assert(tctx, fnum1 == -1, 
 
1179
                                "smbcli_open succeeded, should have "
 
1180
                               "failed with NT_STATUS_DELETE_PENDING"
 
1181
                               );
 
1182
 
 
1183
                torture_assert_ntstatus_equal(tctx, 
 
1184
                                         smbcli_nt_error(cli1->tree),
 
1185
                                     NT_STATUS_DELETE_PENDING, 
 
1186
                                        "smbcli_open failed");
 
1187
        }
 
1188
 
 
1189
        status = smbcli_nt_delete_on_close(cli1->tree, dnum1, false);
 
1190
        torture_assert_ntstatus_ok(tctx, status, 
 
1191
                                        "setting delete_on_close on file failed !");
 
1192
                
 
1193
        {
 
1194
                char *fullname;
 
1195
                asprintf(&fullname, "\\%s%s", dname, fname);
 
1196
                fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
 
1197
                                    DENY_NONE);
 
1198
                torture_assert(tctx, fnum1 != -1, 
 
1199
                                talloc_asprintf(tctx, "smbcli_open failed: %s\n",
 
1200
                               smbcli_errstr(cli1->tree)));
 
1201
                smbcli_close(cli1->tree, fnum1);
 
1202
        }
 
1203
 
 
1204
        status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
 
1205
 
 
1206
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
 
1207
                 "setting delete_on_close failed");
 
1208
        smbcli_close(cli1->tree, dnum1);
 
1209
 
 
1210
        return correct;
 
1211
}
 
1212
 
 
1213
/* Test 20a ... */
 
1214
static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
1215
{
 
1216
        int fnum1 = -1;
 
1217
        int fnum2 = -1;
 
1218
        bool correct = true;
 
1219
 
 
1220
        del_clean_area(cli1, cli2);
 
1221
 
 
1222
        /* Test 20a. */
 
1223
 
 
1224
        /* Ensure the file doesn't already exist. */
 
1225
        smbcli_close(cli1->tree, fnum1);
 
1226
        smbcli_close(cli1->tree, fnum2);
 
1227
        smbcli_setatr(cli1->tree, fname, 0, 0);
 
1228
        smbcli_unlink(cli1->tree, fname);
 
1229
 
 
1230
        /* Firstly open and create with all access */
 
1231
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
1232
                                      SEC_RIGHTS_FILE_ALL,
 
1233
                                      FILE_ATTRIBUTE_NORMAL,
 
1234
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1235
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1236
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1237
                                      NTCREATEX_DISP_CREATE, 
 
1238
                                      0, 0);
 
1239
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
1240
                       fname, smbcli_errstr(cli1->tree)));
 
1241
 
 
1242
        /* Next open with all access, but add delete on close. */
 
1243
        fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
 
1244
                                      SEC_RIGHTS_FILE_ALL,
 
1245
                                      FILE_ATTRIBUTE_NORMAL,
 
1246
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1247
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1248
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1249
                                      NTCREATEX_DISP_OPEN,
 
1250
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
1251
        
 
1252
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)", 
 
1253
                       fname, smbcli_errstr(cli2->tree)));
 
1254
 
 
1255
        /* The delete on close bit is *not* reported as being set. */
 
1256
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
1257
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
 
1258
 
 
1259
        smbcli_close(cli1->tree, fnum1);
 
1260
 
 
1261
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
 
1262
 
 
1263
        smbcli_close(cli2->tree, fnum2);
 
1264
 
 
1265
        /* See if the file is deleted - should be.... */
 
1266
        fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
 
1267
        torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
 
1268
                       fname, smbcli_errstr(cli1->tree)));
 
1269
 
 
1270
        return correct;
 
1271
}
 
1272
 
 
1273
/* Test 20b ... */
 
1274
/* This is the delete semantics that the cifsfs client depends on when
 
1275
 * trying to delete an open file on a Windows server. It
 
1276
 * opens a file with initial delete on close set, renames it then closes
 
1277
 * all open handles. The file goes away on Windows.
 
1278
 */
 
1279
 
 
1280
static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 
1281
{
 
1282
        int fnum1 = -1;
 
1283
        int fnum2 = -1;
 
1284
        bool correct = true;
 
1285
 
 
1286
        del_clean_area(cli1, cli2);
 
1287
 
 
1288
        /* Test 20b. */
 
1289
 
 
1290
        /* Ensure the file doesn't already exist. */
 
1291
        smbcli_close(cli1->tree, fnum1);
 
1292
        smbcli_close(cli1->tree, fnum2);
 
1293
        smbcli_setatr(cli1->tree, fname, 0, 0);
 
1294
        smbcli_unlink(cli1->tree, fname);
 
1295
        smbcli_setatr(cli1->tree, fname_new, 0, 0);
 
1296
        smbcli_unlink(cli1->tree, fname_new);
 
1297
 
 
1298
        /* Firstly open and create with all access */
 
1299
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
1300
                                      SEC_RIGHTS_FILE_ALL,
 
1301
                                      FILE_ATTRIBUTE_NORMAL,
 
1302
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1303
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1304
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1305
                                      NTCREATEX_DISP_CREATE, 
 
1306
                                      0, 0);
 
1307
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
1308
                       fname, smbcli_errstr(cli1->tree)));
 
1309
 
 
1310
        /* And close - just to create the file. */
 
1311
        smbcli_close(cli1->tree, fnum1);
 
1312
        
 
1313
        /* Firstly open and create with all access */
 
1314
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
1315
                                      SEC_RIGHTS_FILE_ALL,
 
1316
                                      FILE_ATTRIBUTE_NORMAL,
 
1317
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1318
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1319
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1320
                                      NTCREATEX_DISP_OPEN, 
 
1321
                                      0, 0);
 
1322
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
 
1323
                       fname, smbcli_errstr(cli1->tree)));
 
1324
 
 
1325
        /* Next open with all access, but add delete on close. */
 
1326
        fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
 
1327
                                      SEC_RIGHTS_FILE_ALL,
 
1328
                                      FILE_ATTRIBUTE_NORMAL,
 
1329
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1330
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1331
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1332
                                      NTCREATEX_DISP_OPEN,
 
1333
                                      NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
 
1334
        
 
1335
        torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)", 
 
1336
                       fname, smbcli_errstr(cli2->tree)));
 
1337
 
 
1338
        /* The delete on close bit is *not* reported as being set. */
 
1339
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
 
1340
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
 
1341
 
 
1342
        smbcli_close(cli1->tree, fnum1);
 
1343
 
 
1344
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
 
1345
 
 
1346
        /* Rename the file by handle. */
 
1347
 
 
1348
        {
 
1349
                union smb_setfileinfo sfinfo;
 
1350
                NTSTATUS status;
 
1351
 
 
1352
                memset(&sfinfo, '\0', sizeof(sfinfo));
 
1353
                sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
 
1354
                sfinfo.generic.in.file.fnum = fnum2;
 
1355
                sfinfo.rename_information.in.root_fid  = 0;
 
1356
                /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
 
1357
                sfinfo.rename_information.in.new_name  = fname_new + 1;
 
1358
                sfinfo.rename_information.in.overwrite = 1;
 
1359
 
 
1360
                status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
 
1361
 
 
1362
                torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
 
1363
                        fname, fname_new, smbcli_errstr(cli2->tree)));
 
1364
        }
 
1365
 
 
1366
        correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, false, __location__);
 
1367
 
 
1368
        smbcli_close(cli2->tree, fnum2);
 
1369
 
 
1370
        /* See if the file is deleted - should be.... */
 
1371
        fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
 
1372
        torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
 
1373
                       fname, smbcli_errstr(cli1->tree)));
 
1374
        fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
 
1375
        torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
 
1376
                       fname_new, smbcli_errstr(cli1->tree)));
 
1377
 
 
1378
        return correct;
 
1379
}
 
1380
 
 
1381
 
 
1382
/* Test 21 ... */
 
1383
static bool deltest21(struct torture_context *tctx)
 
1384
{
 
1385
        int fnum1 = -1;
 
1386
        struct smbcli_state *cli1;
 
1387
        struct smbcli_state *cli2;
 
1388
        bool correct = true;
 
1389
 
 
1390
        if (!torture_open_connection(&cli1, tctx, 0))
 
1391
                return false;
 
1392
 
 
1393
        if (!torture_open_connection(&cli2, tctx, 1))
 
1394
                return false;
 
1395
 
 
1396
        del_clean_area(cli1, cli2);
 
1397
 
 
1398
        /* Test 21 -- Test removal of file after socket close. */
 
1399
 
 
1400
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
1401
                                      SEC_RIGHTS_FILE_ALL,
 
1402
                                      FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
 
1403
                                      NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
 
1404
        
 
1405
        torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
 
1406
                       fname, smbcli_errstr(cli1->tree)));
 
1407
        
 
1408
        torture_assert_ntstatus_ok(tctx, 
 
1409
                                smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
 
1410
                                talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
 
1411
                       smbcli_errstr(cli1->tree)));
 
1412
        
 
1413
        /* Ensure delete on close is set. */
 
1414
        correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
 
1415
 
 
1416
        /* Now yank the rug from under cli1. */
 
1417
        smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
 
1418
 
 
1419
        fnum1 = -1;
 
1420
 
 
1421
        if (!torture_open_connection(&cli1, tctx, 0)) {
 
1422
                return false;
 
1423
        }
 
1424
 
 
1425
        /* On slow build farm machines it might happen that they are not fast
 
1426
         * enogh to delete the file for this test */
 
1427
        msleep(200);
 
1428
 
 
1429
        /* File should not be there. */
 
1430
        fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
 
1431
                                      SEC_RIGHTS_FILE_READ,
 
1432
                                      FILE_ATTRIBUTE_NORMAL,
 
1433
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1434
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1435
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1436
                                      NTCREATEX_DISP_OPEN,
 
1437
                                      0, 0);
 
1438
        
 
1439
        CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
 
1440
 
 
1441
        return correct;
 
1442
}
 
1443
 
 
1444
/* Test 22 ... */
 
1445
 
 
1446
/*
 
1447
 * Test whether a second *directory* handle inhibits delete if the first has
 
1448
 * del-on-close set and is closed
 
1449
 */
 
1450
static bool deltest22(struct torture_context *tctx)
 
1451
{
 
1452
        int dnum1 = -1;
 
1453
        int dnum2 = -1;
 
1454
        struct smbcli_state *cli1;
 
1455
        bool correct = true;
 
1456
 
 
1457
        if (!torture_open_connection(&cli1, tctx, 0))
 
1458
                return false;
 
1459
 
 
1460
        smbcli_deltree(cli1->tree, dname);
 
1461
 
 
1462
        torture_assert_ntstatus_ok(
 
1463
                tctx, smbcli_mkdir(cli1->tree, dname),
 
1464
                talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
 
1465
                                smbcli_errstr(cli1->tree)));
 
1466
 
 
1467
        dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
 
1468
                                      SEC_FILE_READ_DATA|
 
1469
                                      SEC_FILE_WRITE_DATA|
 
1470
                                      SEC_STD_DELETE,
 
1471
                                      FILE_ATTRIBUTE_DIRECTORY, 
 
1472
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1473
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1474
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1475
                                      NTCREATEX_DISP_OPEN, 
 
1476
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1477
 
 
1478
        torture_assert(tctx, dnum1 != -1,
 
1479
                       talloc_asprintf(tctx, "open of %s failed: %s!", 
 
1480
                                       dname, smbcli_errstr(cli1->tree)));
 
1481
 
 
1482
        dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
 
1483
                                      SEC_FILE_READ_DATA|
 
1484
                                      SEC_FILE_WRITE_DATA,
 
1485
                                      FILE_ATTRIBUTE_DIRECTORY, 
 
1486
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1487
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1488
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1489
                                      NTCREATEX_DISP_OPEN, 
 
1490
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1491
 
 
1492
        torture_assert(tctx, dnum2 != -1,
 
1493
                       talloc_asprintf(tctx, "open of %s failed: %s!", 
 
1494
                                       dname, smbcli_errstr(cli1->tree)));
 
1495
 
 
1496
        torture_assert_ntstatus_ok(
 
1497
                tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true), 
 
1498
                talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
 
1499
                                smbcli_errstr(cli1->tree)));
 
1500
 
 
1501
        smbcli_close(cli1->tree, dnum1);
 
1502
 
 
1503
        dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
 
1504
                                      SEC_FILE_READ_DATA|
 
1505
                                      SEC_FILE_WRITE_DATA|
 
1506
                                      SEC_STD_DELETE,
 
1507
                                      FILE_ATTRIBUTE_DIRECTORY, 
 
1508
                                      NTCREATEX_SHARE_ACCESS_READ|
 
1509
                                      NTCREATEX_SHARE_ACCESS_WRITE|
 
1510
                                      NTCREATEX_SHARE_ACCESS_DELETE,
 
1511
                                      NTCREATEX_DISP_OPEN, 
 
1512
                                      NTCREATEX_OPTIONS_DIRECTORY, 0);
 
1513
 
 
1514
        torture_assert(tctx, dnum1 == -1,
 
1515
                       talloc_asprintf(tctx, "open of %s succeeded!\n",
 
1516
                                       dname));
 
1517
 
 
1518
        CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
 
1519
 
 
1520
        return correct;
 
1521
}
 
1522
 
 
1523
/*
 
1524
  Test delete on close semantics.
 
1525
 */
 
1526
struct torture_suite *torture_test_delete(void)
 
1527
{
 
1528
        struct torture_suite *suite = torture_suite_create(
 
1529
                talloc_autofree_context(),
 
1530
                "DELETE");
 
1531
 
 
1532
        torture_suite_add_2smb_test(suite, "deltest1", deltest1);
 
1533
        torture_suite_add_2smb_test(suite, "deltest2", deltest2);
 
1534
        torture_suite_add_2smb_test(suite, "deltest3", deltest3);
 
1535
        torture_suite_add_2smb_test(suite, "deltest4", deltest4);
 
1536
        torture_suite_add_2smb_test(suite, "deltest5", deltest5);
 
1537
        torture_suite_add_2smb_test(suite, "deltest6", deltest6);
 
1538
        torture_suite_add_2smb_test(suite, "deltest7", deltest7);
 
1539
        torture_suite_add_2smb_test(suite, "deltest8", deltest8);
 
1540
        torture_suite_add_2smb_test(suite, "deltest9", deltest9);
 
1541
        torture_suite_add_2smb_test(suite, "deltest10", deltest10);
 
1542
        torture_suite_add_2smb_test(suite, "deltest11", deltest11);
 
1543
        torture_suite_add_2smb_test(suite, "deltest12", deltest12);
 
1544
        torture_suite_add_2smb_test(suite, "deltest13", deltest13);
 
1545
        torture_suite_add_2smb_test(suite, "deltest14", deltest14);
 
1546
        torture_suite_add_2smb_test(suite, "deltest15", deltest15);
 
1547
        torture_suite_add_2smb_test(suite, "deltest16", deltest16);
 
1548
        torture_suite_add_2smb_test(suite, "deltest17", deltest17);
 
1549
        torture_suite_add_2smb_test(suite, "deltest18", deltest18);
 
1550
        torture_suite_add_2smb_test(suite, "deltest19", deltest19);
 
1551
        torture_suite_add_2smb_test(suite, "deltest20", deltest20);
 
1552
        torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
 
1553
        torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
 
1554
        torture_suite_add_simple_test(suite, "deltest21", deltest21);
 
1555
        torture_suite_add_simple_test(suite, "deltest22", deltest22);
 
1556
 
 
1557
        return suite;
 
1558
}