Merge branch 'master' of ctdb into 'master' of samba
[nivanova/samba-autobuild/.git] / source4 / torture / basic / delete.c
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/util.h"
25 #include "system/filesys.h"
26 #include "libcli/raw/raw_proto.h"
27
28 #include "torture/raw/proto.h"
29 #include "torture/basic/proto.h"
30
31 static bool check_delete_on_close(struct torture_context *tctx,
32                                   struct smbcli_state *cli, int fnum,
33                                   const char *fname, bool expect_it,
34                                   const char *where)
35 {
36         union smb_search_data data;
37         NTSTATUS status;
38
39         time_t c_time, a_time, m_time;
40         size_t size;
41         uint16_t mode;
42
43         status = torture_single_search(cli, tctx,
44                                        fname,
45                                        RAW_SEARCH_TRANS2,
46                                        RAW_SEARCH_DATA_FULL_DIRECTORY_INFO,
47                                        FILE_ATTRIBUTE_DIRECTORY,
48                                        &data);
49         torture_assert_ntstatus_ok(tctx, status, 
50                 talloc_asprintf(tctx, "single_search failed (%s)", where));
51
52         if (fnum != -1) {
53                 union smb_fileinfo io;
54                 int nlink = expect_it ? 0 : 1;
55
56                 io.all_info.level = RAW_FILEINFO_ALL_INFO;
57                 io.all_info.in.file.fnum = fnum;
58
59                 status = smb_raw_fileinfo(cli->tree, tctx, &io);
60                 torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, 
61                                         "qfileinfo failed (%s)", where));
62
63                 torture_assert(tctx, expect_it == io.all_info.out.delete_pending, 
64                         talloc_asprintf(tctx, 
65                         "%s - Expected del_on_close flag %d, qfileinfo/all_info gave %d",
66                                where, expect_it, io.all_info.out.delete_pending));
67
68                 torture_assert(tctx, nlink == io.all_info.out.nlink, 
69                         talloc_asprintf(tctx, 
70                                 "%s - Expected nlink %d, qfileinfo/all_info gave %d",
71                                where, nlink, io.all_info.out.nlink));
72
73                 io.standard_info.level = RAW_FILEINFO_STANDARD_INFO;
74                 io.standard_info.in.file.fnum = fnum;
75
76                 status = smb_raw_fileinfo(cli->tree, tctx, &io);
77                 torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
78
79                 torture_assert(tctx, expect_it == io.standard_info.out.delete_pending,
80                         talloc_asprintf(tctx, "%s - Expected del_on_close flag %d, qfileinfo/standard_info gave %d\n",
81                                where, expect_it, io.standard_info.out.delete_pending));
82
83                 torture_assert(tctx, nlink == io.standard_info.out.nlink,
84                         talloc_asprintf(tctx, "%s - Expected nlink %d, qfileinfo/standard_info gave %d",
85                                where, nlink, io.all_info.out.nlink));
86         }
87
88         status = smbcli_qpathinfo(cli->tree, fname,
89                                   &c_time, &a_time, &m_time,
90                                   &size, &mode);
91
92         if (expect_it) {
93                 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DELETE_PENDING,
94                         "qpathinfo did not give correct error code");
95         } else {
96                 torture_assert_ntstatus_ok(tctx, status, 
97                         talloc_asprintf(tctx, "qpathinfo failed (%s)", where));
98         }
99
100         return true;
101 }
102
103 #define CHECK_STATUS(_cli, _expected) \
104         torture_assert_ntstatus_equal(tctx, _cli->tree->session->transport->error.e.nt_status, _expected, \
105                  "Incorrect status")
106
107 static const char *fname = "\\delete.file";
108 static const char *fname_new = "\\delete.new";
109 static const char *dname = "\\delete.dir";
110
111 static void del_clean_area(struct smbcli_state *cli1, struct smbcli_state *cli2)
112 {
113         smb_raw_exit(cli1->session);
114         smb_raw_exit(cli2->session);
115
116         smbcli_deltree(cli1->tree, dname);
117         smbcli_setatr(cli1->tree, fname, 0, 0);
118         smbcli_unlink(cli1->tree, fname);
119         smbcli_setatr(cli1->tree, fname_new, 0, 0);
120         smbcli_unlink(cli1->tree, fname_new);
121 }
122
123 /* Test 1 - this should delete the file on close. */
124
125 static bool deltest1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
126 {
127         int fnum1 = -1;
128
129         del_clean_area(cli1, cli2);
130
131         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
132                                       SEC_RIGHTS_FILE_ALL,
133                                       FILE_ATTRIBUTE_NORMAL,
134                                       NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
135                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
136         
137         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
138                        fname, smbcli_errstr(cli1->tree)));
139         
140         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
141                 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli1->tree)));
142
143         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
144         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)", 
145                        fname));
146
147         return true;
148 }
149
150 /* Test 2 - this should delete the file on close. */
151 static bool deltest2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
152 {
153         int fnum1 = -1;
154
155         del_clean_area(cli1, cli2);
156
157         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
158                                       SEC_RIGHTS_FILE_ALL,
159                                       FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
160                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
161         
162         torture_assert(tctx, fnum1 != -1, 
163                 talloc_asprintf(tctx, "open of %s failed (%s)", 
164                        fname, smbcli_errstr(cli1->tree)));
165         
166         torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, true), 
167                 talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
168                        smbcli_errstr(cli1->tree)));
169         
170         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
171                 talloc_asprintf(tctx, "close failed (%s)", 
172                        smbcli_errstr(cli1->tree)));
173         
174         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
175         if (fnum1 != -1) {
176                 printf("(%s) open of %s succeeded should have been deleted on close !\n", 
177                        __location__, fname);
178                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
179                         printf("(%s) close failed (%s)\n", 
180                                __location__, smbcli_errstr(cli1->tree));
181                         return false;
182                 }
183                 smbcli_unlink(cli1->tree, fname);
184         }
185         return true;
186 }
187
188 /* Test 3 - ... */
189 static bool deltest3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
190 {
191         int fnum1 = -1;
192         int fnum2 = -1;
193
194         del_clean_area(cli1, cli2);
195
196         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
197                                       SEC_RIGHTS_FILE_ALL,
198                                       FILE_ATTRIBUTE_NORMAL,
199                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
200                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
201
202         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
203                         fname, smbcli_errstr(cli1->tree)));
204
205         /* This should fail with a sharing violation - open for delete is only compatible
206            with SHARE_DELETE. */
207
208         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
209                                       SEC_RIGHTS_FILE_READ, 
210                                       FILE_ATTRIBUTE_NORMAL,
211                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
212                                       NTCREATEX_DISP_OPEN, 0, 0);
213
214         torture_assert(tctx, fnum2 == -1, 
215                 talloc_asprintf(tctx, "open  - 2 of %s succeeded - should have failed.", 
216                        fname));
217
218         /* This should succeed. */
219
220         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
221                                       SEC_RIGHTS_FILE_READ, 
222                                       FILE_ATTRIBUTE_NORMAL,
223                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, 
224                                       NTCREATEX_DISP_OPEN, 0, 0);
225
226         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open  - 2 of %s failed (%s)", 
227                        fname, smbcli_errstr(cli1->tree)));
228
229         torture_assert_ntstatus_ok(tctx, 
230                                                            smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
231                                                            talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
232                                                    smbcli_errstr(cli1->tree)));
233         
234         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
235                 talloc_asprintf(tctx, "close 1 failed (%s)", 
236                        smbcli_errstr(cli1->tree)));
237         
238         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum2),
239                 talloc_asprintf(tctx, "close 2 failed (%s)", 
240                        smbcli_errstr(cli1->tree)));
241         
242         /* This should fail - file should no longer be there. */
243
244         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
245         if (fnum1 != -1) {
246                 printf("(%s) open of %s succeeded should have been deleted on close !\n", 
247                        __location__, fname);
248                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
249                         printf("(%s) close failed (%s)\n", 
250                                __location__, smbcli_errstr(cli1->tree));
251                 }
252                 smbcli_unlink(cli1->tree, fname);
253                 return false;
254         }
255         return true;
256 }
257
258 /* Test 4 ... */
259 static bool deltest4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
260 {
261         int fnum1 = -1;
262         int fnum2 = -1;
263         bool correct = true;
264
265         del_clean_area(cli1, cli2);
266
267         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
268                                       SEC_FILE_READ_DATA  | 
269                                       SEC_FILE_WRITE_DATA |
270                                       SEC_STD_DELETE,
271                                       FILE_ATTRIBUTE_NORMAL, 
272                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
273                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
274                                                                 
275         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
276                        fname, smbcli_errstr(cli1->tree)));
277
278         /* This should succeed. */
279         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
280                                       SEC_RIGHTS_FILE_READ,
281                                       FILE_ATTRIBUTE_NORMAL, 
282                                       NTCREATEX_SHARE_ACCESS_READ  | 
283                                       NTCREATEX_SHARE_ACCESS_WRITE |
284                                       NTCREATEX_SHARE_ACCESS_DELETE, 
285                                       NTCREATEX_DISP_OPEN, 0, 0);
286         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open  - 2 of %s failed (%s)", 
287                        fname, smbcli_errstr(cli1->tree)));
288         
289         torture_assert_ntstatus_ok(tctx, 
290                                         smbcli_close(cli1->tree, fnum2),
291                                         talloc_asprintf(tctx, "close - 1 failed (%s)", 
292                                         smbcli_errstr(cli1->tree)));
293         
294         torture_assert_ntstatus_ok(tctx, 
295                                 smbcli_nt_delete_on_close(cli1->tree, fnum1, true), 
296                                 talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
297                         smbcli_errstr(cli1->tree)));
298
299         /* This should fail - no more opens once delete on close set. */
300         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
301                                       SEC_RIGHTS_FILE_READ,
302                                       FILE_ATTRIBUTE_NORMAL, 
303                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
304                                       NTCREATEX_DISP_OPEN, 0, 0);
305         torture_assert(tctx, fnum2 == -1, 
306                  talloc_asprintf(tctx, "open  - 3 of %s succeeded ! Should have failed.",
307                        fname ));
308
309         CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
310
311         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
312                  talloc_asprintf(tctx, "close - 2 failed (%s)", 
313                        smbcli_errstr(cli1->tree)));
314         
315         return correct;
316 }
317
318 /* Test 5 ... */
319 static bool deltest5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
320 {
321         int fnum1 = -1;
322
323         del_clean_area(cli1, cli2);
324
325         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
326         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
327                        fname, smbcli_errstr(cli1->tree)));
328         
329         /* This should fail - only allowed on NT opens with DELETE access. */
330
331         torture_assert(tctx, !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, true)),
332                  "setting delete_on_close on OpenX file succeeded - should fail !");
333
334         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
335                 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
336
337         return true;
338 }
339
340 /* Test 6 ... */
341 static bool deltest6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
342 {
343         int fnum1 = -1;
344
345         del_clean_area(cli1, cli2);
346
347         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
348                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
349                                    FILE_ATTRIBUTE_NORMAL, 
350                                    NTCREATEX_SHARE_ACCESS_READ  |
351                                    NTCREATEX_SHARE_ACCESS_WRITE |
352                                    NTCREATEX_SHARE_ACCESS_DELETE,
353                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
354         
355         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
356                        fname, smbcli_errstr(cli1->tree)));
357         
358         /* This should fail - only allowed on NT opens with DELETE access. */
359         
360         torture_assert(tctx, 
361                 !NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, true)),
362                 "setting delete_on_close on file with no delete access succeeded - should fail !");
363
364         torture_assert_ntstatus_ok(tctx, 
365                                    smbcli_close(cli1->tree, fnum1),
366                                    talloc_asprintf(tctx,
367                                                    "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         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
882
883         return correct;
884 }
885
886 /* Test 16 ... */
887 static bool deltest16a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
888 {
889         int fnum1 = -1;
890         int fnum2 = -1;
891         bool correct = true;
892
893         del_clean_area(cli1, cli2);
894
895         /* Test 16. */
896
897         /* Ensure the file doesn't already exist. */
898         smbcli_close(cli1->tree, fnum1);
899         smbcli_close(cli1->tree, fnum2);
900         smbcli_setatr(cli1->tree, fname, 0, 0);
901         smbcli_unlink(cli1->tree, fname);
902
903         /* Firstly open and create with all access */
904         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
905                                       SEC_RIGHTS_FILE_ALL,
906                                       FILE_ATTRIBUTE_NORMAL,
907                                       NTCREATEX_SHARE_ACCESS_READ|
908                                       NTCREATEX_SHARE_ACCESS_WRITE|
909                                       NTCREATEX_SHARE_ACCESS_DELETE,
910                                       NTCREATEX_DISP_CREATE,
911                                       0, 0);
912         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
913                        fname, smbcli_errstr(cli1->tree)));
914
915         /* And close - just to create the file. */
916         smbcli_close(cli1->tree, fnum1);
917
918         /* Firstly create with all access, but delete on close. */
919         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
920                                       SEC_RIGHTS_FILE_ALL,
921                                       FILE_ATTRIBUTE_NORMAL,
922                                       NTCREATEX_SHARE_ACCESS_READ|
923                                       NTCREATEX_SHARE_ACCESS_WRITE|
924                                       NTCREATEX_SHARE_ACCESS_DELETE,
925                                       NTCREATEX_DISP_OPEN,
926                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
927
928         torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
929
930         /* The delete on close bit is *not* reported as being set. */
931         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
932
933         /* The delete on close bit is *not* reported as being set. */
934         correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
935         correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
936
937         /* Now try opening again for read-only. */
938         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0,
939                                       SEC_RIGHTS_FILE_READ,
940                                       FILE_ATTRIBUTE_NORMAL,
941                                       NTCREATEX_SHARE_ACCESS_READ|
942                                       NTCREATEX_SHARE_ACCESS_WRITE|
943                                       NTCREATEX_SHARE_ACCESS_DELETE,
944                                       NTCREATEX_DISP_OPEN,
945                                       0, 0);
946
947         /* Should work. */
948         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
949                       fname, smbcli_errstr(cli1->tree)));
950
951         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
952         correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
953         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
954         correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
955
956         smbcli_close(cli1->tree, fnum1);
957
958         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
959         correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
960
961         smbcli_close(cli2->tree, fnum2);
962
963         /* And the file should be deleted ! */
964         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
965         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)",
966                        fname, smbcli_errstr(cli1->tree)));
967
968         smbcli_close(cli1->tree, fnum1);
969         smbcli_setatr(cli1->tree, fname, 0, 0);
970         smbcli_unlink(cli1->tree, fname);
971
972         return correct;
973 }
974
975 /* Test 17 ... */
976 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
977 {
978         int fnum1 = -1;
979         int fnum2 = -1;
980         bool correct = true;
981
982         del_clean_area(cli1, cli2);
983
984         /* Test 17. */
985
986         /* Ensure the file doesn't already exist. */
987         smbcli_close(cli1->tree, fnum1);
988         smbcli_close(cli1->tree, fnum2);
989         smbcli_setatr(cli1->tree, fname, 0, 0);
990         smbcli_unlink(cli1->tree, fname);
991
992         /* Firstly open and create with all access */
993         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
994                                       SEC_RIGHTS_FILE_ALL,
995                                       FILE_ATTRIBUTE_NORMAL,
996                                       NTCREATEX_SHARE_ACCESS_READ|
997                                       NTCREATEX_SHARE_ACCESS_WRITE|
998                                       NTCREATEX_SHARE_ACCESS_DELETE,
999                                       NTCREATEX_DISP_CREATE, 
1000                                       0, 0);
1001         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1002                        fname, smbcli_errstr(cli1->tree)));
1003
1004         /* And close - just to create the file. */
1005         smbcli_close(cli1->tree, fnum1);
1006         
1007         /* Next open with all access, but add delete on close. */
1008         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1009                                       SEC_RIGHTS_FILE_ALL,
1010                                       FILE_ATTRIBUTE_NORMAL,
1011                                       NTCREATEX_SHARE_ACCESS_READ|
1012                                       NTCREATEX_SHARE_ACCESS_WRITE|
1013                                       NTCREATEX_SHARE_ACCESS_DELETE,
1014                                       NTCREATEX_DISP_OPEN,
1015                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1016         
1017         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1018                        fname, smbcli_errstr(cli1->tree)));
1019
1020         /* The delete on close bit is *not* reported as being set. */
1021         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1022
1023         /* Now try opening again for read-only. */
1024         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1025                                       SEC_RIGHTS_FILE_READ|
1026                                       SEC_STD_DELETE,
1027                                       FILE_ATTRIBUTE_NORMAL,
1028                                       NTCREATEX_SHARE_ACCESS_READ|
1029                                       NTCREATEX_SHARE_ACCESS_WRITE|
1030                                       NTCREATEX_SHARE_ACCESS_DELETE,
1031                                       NTCREATEX_DISP_OPEN,
1032                                       0, 0);
1033         
1034         /* Should work. */
1035         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1036                        fname, smbcli_errstr(cli1->tree)));
1037
1038         /* still not reported as being set on either */
1039         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1040         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1041
1042         smbcli_close(cli1->tree, fnum1);
1043
1044         /* After the first close, the files has the delete on close bit set. */
1045         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1046
1047         smbcli_close(cli1->tree, fnum2);
1048
1049         /* Make sure the file has been deleted */
1050         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1051         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
1052                        fname, smbcli_errstr(cli1->tree)));
1053
1054         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1055
1056         return correct;
1057 }
1058
1059 /* Test 17a - like 17, but the delete on close handle is closed last */
1060 static bool deltest17a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1061 {
1062         int fnum1 = -1;
1063         int fnum2 = -1;
1064         bool correct = true;
1065
1066         del_clean_area(cli1, cli2);
1067
1068         /* Ensure the file doesn't already exist. */
1069         smbcli_close(cli1->tree, fnum1);
1070         smbcli_close(cli1->tree, fnum2);
1071         smbcli_setatr(cli1->tree, fname, 0, 0);
1072         smbcli_unlink(cli1->tree, fname);
1073
1074         /* Firstly open and create with all access */
1075         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1076                                       SEC_RIGHTS_FILE_ALL,
1077                                       FILE_ATTRIBUTE_NORMAL,
1078                                       NTCREATEX_SHARE_ACCESS_READ|
1079                                       NTCREATEX_SHARE_ACCESS_WRITE|
1080                                       NTCREATEX_SHARE_ACCESS_DELETE,
1081                                       NTCREATEX_DISP_CREATE,
1082                                       0, 0);
1083         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1084                        fname, smbcli_errstr(cli1->tree)));
1085
1086         /* And close - just to create the file. */
1087         smbcli_close(cli1->tree, fnum1);
1088
1089         /* Next open with all access, but add delete on close. */
1090         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1091                                       SEC_RIGHTS_FILE_ALL,
1092                                       FILE_ATTRIBUTE_NORMAL,
1093                                       NTCREATEX_SHARE_ACCESS_READ|
1094                                       NTCREATEX_SHARE_ACCESS_WRITE|
1095                                       NTCREATEX_SHARE_ACCESS_DELETE,
1096                                       NTCREATEX_DISP_OPEN,
1097                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1098
1099         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1100                        fname, smbcli_errstr(cli1->tree)));
1101
1102         /* The delete on close bit is *not* reported as being set. */
1103         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1104
1105         /* Now try opening again for read-only. */
1106         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1107                                       SEC_RIGHTS_FILE_READ|
1108                                       SEC_STD_DELETE,
1109                                       FILE_ATTRIBUTE_NORMAL,
1110                                       NTCREATEX_SHARE_ACCESS_READ|
1111                                       NTCREATEX_SHARE_ACCESS_WRITE|
1112                                       NTCREATEX_SHARE_ACCESS_DELETE,
1113                                       NTCREATEX_DISP_OPEN,
1114                                       0, 0);
1115
1116         /* Should work. */
1117         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1118                        fname, smbcli_errstr(cli1->tree)));
1119
1120         /* still not reported as being set on either */
1121         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1122         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1123
1124         smbcli_close(cli1->tree, fnum2);
1125
1126         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1127
1128         smbcli_close(cli1->tree, fnum1);
1129
1130         /*
1131          * The file is still there:
1132          * The second open seems to have removed the initial
1133          * delete on close flag from the first handle
1134          */
1135         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1136         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1137                        fname, smbcli_errstr(cli1->tree)));
1138
1139         smbcli_close(cli1->tree, fnum1);
1140         smbcli_setatr(cli1->tree, fname, 0, 0);
1141         smbcli_unlink(cli1->tree, fname);
1142
1143         return correct;
1144 }
1145
1146 /* Test 17b - like 17a, but the initial delete on close is set on the second handle */
1147 static bool deltest17b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1148 {
1149         int fnum1 = -1;
1150         int fnum2 = -1;
1151         bool correct = true;
1152
1153         del_clean_area(cli1, cli2);
1154
1155         /* Ensure the file doesn't already exist. */
1156         smbcli_close(cli1->tree, fnum1);
1157         smbcli_close(cli1->tree, fnum2);
1158         smbcli_setatr(cli1->tree, fname, 0, 0);
1159         smbcli_unlink(cli1->tree, fname);
1160
1161         /* Firstly open and create with all access */
1162         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1163                                       SEC_RIGHTS_FILE_ALL,
1164                                       FILE_ATTRIBUTE_NORMAL,
1165                                       NTCREATEX_SHARE_ACCESS_READ|
1166                                       NTCREATEX_SHARE_ACCESS_WRITE|
1167                                       NTCREATEX_SHARE_ACCESS_DELETE,
1168                                       NTCREATEX_DISP_CREATE,
1169                                       0, 0);
1170         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1171                        fname, smbcli_errstr(cli1->tree)));
1172
1173         /* And close - just to create the file. */
1174         smbcli_close(cli1->tree, fnum1);
1175
1176         /* Next open with all access, but add delete on close. */
1177         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1178                                       SEC_RIGHTS_FILE_ALL,
1179                                       FILE_ATTRIBUTE_NORMAL,
1180                                       NTCREATEX_SHARE_ACCESS_READ|
1181                                       NTCREATEX_SHARE_ACCESS_WRITE|
1182                                       NTCREATEX_SHARE_ACCESS_DELETE,
1183                                       NTCREATEX_DISP_OPEN,
1184                                       0, 0);
1185
1186         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1187                        fname, smbcli_errstr(cli1->tree)));
1188
1189         /* The delete on close bit is *not* reported as being set. */
1190         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1191
1192         /* Now try opening again for read-only. */
1193         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1194                                       SEC_RIGHTS_FILE_READ|
1195                                       SEC_STD_DELETE,
1196                                       FILE_ATTRIBUTE_NORMAL,
1197                                       NTCREATEX_SHARE_ACCESS_READ|
1198                                       NTCREATEX_SHARE_ACCESS_WRITE|
1199                                       NTCREATEX_SHARE_ACCESS_DELETE,
1200                                       NTCREATEX_DISP_OPEN,
1201                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1202
1203         /* Should work. */
1204         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1205                        fname, smbcli_errstr(cli1->tree)));
1206
1207         /* still not reported as being set on either */
1208         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1209         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1210
1211         smbcli_close(cli1->tree, fnum1);
1212
1213         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1214
1215         smbcli_close(cli1->tree, fnum2);
1216
1217         /* Make sure the file has been deleted */
1218         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1219         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1220                        fname));
1221
1222         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1223
1224         return correct;
1225 }
1226
1227 /* Test 17c - like 17, but the initial delete on close is set on the second handle */
1228 static bool deltest17c(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1229 {
1230         int fnum1 = -1;
1231         int fnum2 = -1;
1232         bool correct = true;
1233
1234         del_clean_area(cli1, cli2);
1235
1236         /* Ensure the file doesn't already exist. */
1237         smbcli_close(cli1->tree, fnum1);
1238         smbcli_close(cli1->tree, fnum2);
1239         smbcli_setatr(cli1->tree, fname, 0, 0);
1240         smbcli_unlink(cli1->tree, fname);
1241
1242         /* Firstly open and create with all access */
1243         fnum1 = smbcli_nt_create_full(cli1->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_CREATE,
1250                                       0, 0);
1251         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1252                        fname, smbcli_errstr(cli1->tree)));
1253
1254         /* And close - just to create the file. */
1255         smbcli_close(cli1->tree, fnum1);
1256
1257         /* Next open with all access, but add delete on close. */
1258         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1259                                       SEC_RIGHTS_FILE_ALL,
1260                                       FILE_ATTRIBUTE_NORMAL,
1261                                       NTCREATEX_SHARE_ACCESS_READ|
1262                                       NTCREATEX_SHARE_ACCESS_WRITE|
1263                                       NTCREATEX_SHARE_ACCESS_DELETE,
1264                                       NTCREATEX_DISP_OPEN,
1265                                       0, 0);
1266
1267         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1268                        fname, smbcli_errstr(cli1->tree)));
1269
1270         /* The delete on close bit is *not* reported as being set. */
1271         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1272
1273         /* Now try opening again for read-only. */
1274         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1275                                       SEC_RIGHTS_FILE_READ|
1276                                       SEC_STD_DELETE,
1277                                       FILE_ATTRIBUTE_NORMAL,
1278                                       NTCREATEX_SHARE_ACCESS_READ|
1279                                       NTCREATEX_SHARE_ACCESS_WRITE|
1280                                       NTCREATEX_SHARE_ACCESS_DELETE,
1281                                       NTCREATEX_DISP_OPEN,
1282                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1283
1284         /* Should work. */
1285         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1286                        fname, smbcli_errstr(cli1->tree)));
1287
1288         /* still not reported as being set on either */
1289         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1290         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1291
1292         smbcli_close(cli1->tree, fnum2);
1293
1294         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
1295
1296         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1297         torture_assert(tctx, fnum2 == -1, talloc_asprintf(tctx, "open - 3 of %s succeeded (should fail)",
1298                        fname));
1299
1300         CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1301
1302         smbcli_close(cli1->tree, fnum1);
1303
1304         /* Make sure the file has been deleted */
1305         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1306         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1307                        fname));
1308
1309         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1310
1311         return correct;
1312 }
1313
1314 /* Test 17d - like 17a, but the first delete-on-close opener creates the file */
1315 static bool deltest17d(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1316 {
1317         int fnum1 = -1;
1318         int fnum2 = -1;
1319         bool correct = true;
1320
1321         del_clean_area(cli1, cli2);
1322
1323         /* Ensure the file doesn't already exist. */
1324         smbcli_close(cli1->tree, fnum1);
1325         smbcli_close(cli1->tree, fnum2);
1326         smbcli_setatr(cli1->tree, fname, 0, 0);
1327         smbcli_unlink(cli1->tree, fname);
1328
1329
1330         /* Create the file with delete on close. */
1331         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1332                                       SEC_RIGHTS_FILE_ALL,
1333                                       FILE_ATTRIBUTE_NORMAL,
1334                                       NTCREATEX_SHARE_ACCESS_READ|
1335                                       NTCREATEX_SHARE_ACCESS_WRITE|
1336                                       NTCREATEX_SHARE_ACCESS_DELETE,
1337                                       NTCREATEX_DISP_CREATE,
1338                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1339
1340         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1341                        fname, smbcli_errstr(cli1->tree)));
1342
1343         /* The delete on close bit is *not* reported as being set. */
1344         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1345
1346         /* Now try opening again for read-only. */
1347         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1348                                       SEC_RIGHTS_FILE_READ|
1349                                       SEC_STD_DELETE,
1350                                       FILE_ATTRIBUTE_NORMAL,
1351                                       NTCREATEX_SHARE_ACCESS_READ|
1352                                       NTCREATEX_SHARE_ACCESS_WRITE|
1353                                       NTCREATEX_SHARE_ACCESS_DELETE,
1354                                       NTCREATEX_DISP_OPEN,
1355                                       0, 0);
1356
1357         /* Should work. */
1358         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1359                        fname, smbcli_errstr(cli1->tree)));
1360
1361         /* still not reported as being set on either */
1362         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1363         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1364
1365         smbcli_close(cli1->tree, fnum2);
1366
1367         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1368
1369         smbcli_close(cli1->tree, fnum1);
1370
1371         /*
1372          * The file is still there:
1373          * The second open seems to have removed the initial
1374          * delete on close flag from the first handle
1375          */
1376         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1377         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 3 of %s succeed (should fail)",
1378                        fname));
1379
1380         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1381
1382         return correct;
1383 }
1384
1385 static bool deltest17e(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1386 {
1387         int fnum1 = -1;
1388         int fnum2 = -1;
1389         int fnum3 = -1;
1390         bool correct = true;
1391
1392         del_clean_area(cli1, cli2);
1393
1394         /* Ensure the file doesn't already exist. */
1395         smbcli_close(cli1->tree, fnum1);
1396         smbcli_close(cli1->tree, fnum2);
1397         smbcli_setatr(cli1->tree, fname, 0, 0);
1398         smbcli_unlink(cli1->tree, fname);
1399
1400         /* Firstly open and create with all access */
1401         fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1402                                       SEC_RIGHTS_FILE_ALL,
1403                                       FILE_ATTRIBUTE_NORMAL,
1404                                       NTCREATEX_SHARE_ACCESS_READ|
1405                                       NTCREATEX_SHARE_ACCESS_WRITE|
1406                                       NTCREATEX_SHARE_ACCESS_DELETE,
1407                                       NTCREATEX_DISP_CREATE,
1408                                       0, 0);
1409         torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1410                        fname, smbcli_errstr(cli1->tree)));
1411
1412         /* Next open with all access, but add delete on close. */
1413         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1414                                       SEC_RIGHTS_FILE_ALL,
1415                                       FILE_ATTRIBUTE_NORMAL,
1416                                       NTCREATEX_SHARE_ACCESS_READ|
1417                                       NTCREATEX_SHARE_ACCESS_WRITE|
1418                                       NTCREATEX_SHARE_ACCESS_DELETE,
1419                                       NTCREATEX_DISP_OPEN,
1420                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1421
1422         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1423                        fname, smbcli_errstr(cli1->tree)));
1424
1425         /* The delete on close bit is *not* reported as being set. */
1426         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1427         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1428
1429         /* Now try opening again for read-only. */
1430         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1431                                       SEC_RIGHTS_FILE_READ|
1432                                       SEC_STD_DELETE,
1433                                       FILE_ATTRIBUTE_NORMAL,
1434                                       NTCREATEX_SHARE_ACCESS_READ|
1435                                       NTCREATEX_SHARE_ACCESS_WRITE|
1436                                       NTCREATEX_SHARE_ACCESS_DELETE,
1437                                       NTCREATEX_DISP_OPEN,
1438                                       0, 0);
1439
1440         /* Should work. */
1441         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1442                        fname, smbcli_errstr(cli1->tree)));
1443
1444         /* still not reported as being set on either */
1445         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1446         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1447         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1448
1449         smbcli_close(cli1->tree, fnum1);
1450
1451         /*
1452          * closing the handle that has delete_on_close set
1453          * inherits the flag to the global context
1454          */
1455         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1456         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1457
1458         smbcli_close(cli1->tree, fnum2);
1459
1460         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1461
1462         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1463         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1464                        fname));
1465
1466         CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1467
1468         smbcli_close(cli1->tree, fnum3);
1469
1470         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1471         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1472                        fname));
1473
1474         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1475
1476         return correct;
1477 }
1478
1479 static bool deltest17f(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1480 {
1481         int fnum1 = -1;
1482         int fnum2 = -1;
1483         int fnum3 = -1;
1484         bool correct = true;
1485         NTSTATUS status;
1486
1487         del_clean_area(cli1, cli2);
1488
1489         /* Ensure the file doesn't already exist. */
1490         smbcli_close(cli1->tree, fnum1);
1491         smbcli_close(cli1->tree, fnum2);
1492         smbcli_setatr(cli1->tree, fname, 0, 0);
1493         smbcli_unlink(cli1->tree, fname);
1494
1495         /* Firstly open and create with all access */
1496         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1497                                       SEC_RIGHTS_FILE_ALL,
1498                                       FILE_ATTRIBUTE_NORMAL,
1499                                       NTCREATEX_SHARE_ACCESS_READ|
1500                                       NTCREATEX_SHARE_ACCESS_WRITE|
1501                                       NTCREATEX_SHARE_ACCESS_DELETE,
1502                                       NTCREATEX_DISP_CREATE,
1503                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1504         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)",
1505                        fname, smbcli_errstr(cli1->tree)));
1506
1507         /* The delete on close bit is *not* reported as being set. */
1508         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1509
1510         /* Next open with all access, but add delete on close. */
1511         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1512                                       SEC_RIGHTS_FILE_ALL,
1513                                       FILE_ATTRIBUTE_NORMAL,
1514                                       NTCREATEX_SHARE_ACCESS_READ|
1515                                       NTCREATEX_SHARE_ACCESS_WRITE|
1516                                       NTCREATEX_SHARE_ACCESS_DELETE,
1517                                       NTCREATEX_DISP_OPEN,
1518                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1519
1520         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)",
1521                        fname, smbcli_errstr(cli1->tree)));
1522
1523         /* still not reported as being set on either */
1524         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1525         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1526
1527         /* Now try opening again for read-only. */
1528         fnum3 = smbcli_nt_create_full(cli1->tree, fname, 0,
1529                                       SEC_RIGHTS_FILE_READ|
1530                                       SEC_STD_DELETE,
1531                                       FILE_ATTRIBUTE_NORMAL,
1532                                       NTCREATEX_SHARE_ACCESS_READ|
1533                                       NTCREATEX_SHARE_ACCESS_WRITE|
1534                                       NTCREATEX_SHARE_ACCESS_DELETE,
1535                                       NTCREATEX_DISP_OPEN,
1536                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1537
1538         /* Should work. */
1539         torture_assert(tctx, fnum3 != -1, talloc_asprintf(tctx, "open - 3 of %s failed (%s)",
1540                        fname, smbcli_errstr(cli1->tree)));
1541
1542         /* still not reported as being set on either */
1543         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1544         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1545         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1546
1547         smbcli_close(cli1->tree, fnum1);
1548
1549         /*
1550          * closing the handle that has delete_on_close set
1551          * inherits the flag to the global context
1552          */
1553         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
1554         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1555
1556
1557         status = smbcli_nt_delete_on_close(cli1->tree, fnum2, false);
1558         torture_assert_ntstatus_ok(tctx, status,
1559                                         "clearing delete_on_close on file failed !");
1560
1561         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
1562         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, false, __location__);
1563
1564         smbcli_close(cli1->tree, fnum2);
1565
1566         correct &= check_delete_on_close(tctx, cli1, fnum3, fname, true, __location__);
1567
1568         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1569         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 4 of %s succeeded (should fail)",
1570                        fname));
1571
1572         CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1573
1574         smbcli_close(cli1->tree, fnum3);
1575
1576         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1577         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open - 5 of %s succeeded (should fail)",
1578                        fname));
1579
1580         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1581
1582         return correct;
1583 }
1584
1585 /* Test 18 ... */
1586 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1587 {
1588         int fnum1 = -1;
1589         int fnum2 = -1;
1590         bool correct = true;
1591
1592         del_clean_area(cli1, cli2);
1593
1594         /* Test 18. With directories. */
1595
1596         /* Ensure the file doesn't already exist. */
1597         smbcli_close(cli1->tree, fnum1);
1598         smbcli_close(cli1->tree, fnum2);
1599
1600         smbcli_deltree(cli1->tree, dname);
1601
1602         /* Firstly create with all access, but delete on close. */
1603         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1604                                       SEC_FILE_READ_DATA|
1605                                       SEC_FILE_WRITE_DATA|
1606                                       SEC_STD_DELETE,
1607                                       FILE_ATTRIBUTE_DIRECTORY,
1608                                       NTCREATEX_SHARE_ACCESS_READ|
1609                                       NTCREATEX_SHARE_ACCESS_WRITE|
1610                                       NTCREATEX_SHARE_ACCESS_DELETE,
1611                                       NTCREATEX_DISP_CREATE,
1612                                       NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1613         
1614         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1615                        dname, smbcli_errstr(cli1->tree)));
1616
1617         /*
1618          * The delete on close bit is *not* reported as being set.
1619          * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1620          * close as being set.  This causes the subsequent create to fail with
1621          * NT_STATUS_DELETE_PENDING.
1622          */
1623         correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1624
1625         /* Now try opening again for read-only. */
1626         fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1627                                       SEC_RIGHTS_FILE_READ,
1628                                       FILE_ATTRIBUTE_DIRECTORY,
1629                                       NTCREATEX_SHARE_ACCESS_READ|
1630                                       NTCREATEX_SHARE_ACCESS_WRITE|
1631                                       NTCREATEX_SHARE_ACCESS_DELETE,
1632                                       NTCREATEX_DISP_OPEN,
1633                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1634         
1635
1636         /* Should work. */
1637         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1638                        dname, smbcli_errstr(cli1->tree)));
1639
1640         correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1641         correct &= check_delete_on_close(tctx, cli1, fnum2, dname, false, __location__);
1642
1643         smbcli_close(cli1->tree, fnum1);
1644
1645         correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1646
1647         smbcli_close(cli1->tree, fnum2);
1648
1649         /* And the directory should be deleted ! */
1650         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1651                                       SEC_RIGHTS_FILE_READ,
1652                                       FILE_ATTRIBUTE_DIRECTORY,
1653                                       NTCREATEX_SHARE_ACCESS_READ|
1654                                       NTCREATEX_SHARE_ACCESS_WRITE|
1655                                       NTCREATEX_SHARE_ACCESS_DELETE,
1656                                       NTCREATEX_DISP_OPEN,
1657                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1658         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)", 
1659                        dname));
1660
1661         return correct;
1662 }
1663
1664 /* Test 19 ... */
1665 static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1666 {
1667         int fnum1 = -1;
1668         int fnum2 = -1;
1669         bool correct = true;
1670
1671         del_clean_area(cli1, cli2);
1672
1673         /* Test 19. */
1674
1675         smbcli_deltree(cli1->tree, dname);
1676
1677         /* Firstly open and create with all access */
1678         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1679                                       SEC_FILE_READ_DATA|
1680                                       SEC_FILE_WRITE_DATA|
1681                                       SEC_STD_DELETE,
1682                                       FILE_ATTRIBUTE_DIRECTORY,
1683                                       NTCREATEX_SHARE_ACCESS_READ|
1684                                       NTCREATEX_SHARE_ACCESS_WRITE|
1685                                       NTCREATEX_SHARE_ACCESS_DELETE,
1686                                       NTCREATEX_DISP_CREATE,
1687                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1688         
1689         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1690                        dname, smbcli_errstr(cli1->tree)));
1691
1692         /* And close - just to create the directory. */
1693         smbcli_close(cli1->tree, fnum1);
1694         
1695         /* Next open with all access, but add delete on close. */
1696         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1697                                       SEC_FILE_READ_DATA|
1698                                       SEC_FILE_WRITE_DATA|
1699                                       SEC_STD_DELETE,
1700                                       FILE_ATTRIBUTE_DIRECTORY,
1701                                       NTCREATEX_SHARE_ACCESS_READ|
1702                                       NTCREATEX_SHARE_ACCESS_WRITE|
1703                                       NTCREATEX_SHARE_ACCESS_DELETE,
1704                                       NTCREATEX_DISP_OPEN,
1705                                       NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1706         
1707         torture_assert(tctx, fnum1 != -1, 
1708                 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1709
1710         /*
1711          * The delete on close bit is *not* reported as being set.
1712          * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1713          * close as being set.  This causes the subsequent create to fail with
1714          * NT_STATUS_DELETE_PENDING.
1715          */
1716         correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1717
1718         /* Now try opening again for read-only. */
1719         fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1720                                       SEC_RIGHTS_FILE_READ,
1721                                       FILE_ATTRIBUTE_DIRECTORY,
1722                                       NTCREATEX_SHARE_ACCESS_READ|
1723                                       NTCREATEX_SHARE_ACCESS_WRITE|
1724                                       NTCREATEX_SHARE_ACCESS_DELETE,
1725                                       NTCREATEX_DISP_OPEN,
1726                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1727         
1728         /* Should work. */
1729         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1730                        dname, smbcli_errstr(cli1->tree)));
1731
1732         smbcli_close(cli1->tree, fnum1);
1733
1734         correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1735
1736         smbcli_close(cli1->tree, fnum2);
1737
1738         /* See if the file is deleted - for a directory this seems to be true ! */
1739         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1740                                       SEC_RIGHTS_FILE_READ,
1741                                       FILE_ATTRIBUTE_DIRECTORY,
1742                                       NTCREATEX_SHARE_ACCESS_READ|
1743                                       NTCREATEX_SHARE_ACCESS_WRITE|
1744                                       NTCREATEX_SHARE_ACCESS_DELETE,
1745                                       NTCREATEX_DISP_OPEN,
1746                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1747
1748         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1749
1750         torture_assert(tctx, fnum1 == -1, 
1751                 talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1752
1753         return correct;
1754 }
1755
1756 /* Test 20 ... */
1757 static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1758 {
1759         int fnum1 = -1;
1760         int dnum1 = -1;
1761         bool correct = true;
1762         NTSTATUS status;
1763
1764         del_clean_area(cli1, cli2);
1765
1766         /* Test 20 -- non-empty directory hardest to get right... */
1767
1768         if (torture_setting_bool(tctx, "samba3", false)) {
1769                 return true;
1770         }
1771
1772         smbcli_deltree(cli1->tree, dname);
1773
1774         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1775                                       SEC_FILE_READ_DATA|
1776                                       SEC_FILE_WRITE_DATA|
1777                                       SEC_STD_DELETE,
1778                                       FILE_ATTRIBUTE_DIRECTORY, 
1779                                       NTCREATEX_SHARE_ACCESS_READ|
1780                                       NTCREATEX_SHARE_ACCESS_WRITE|
1781                                       NTCREATEX_SHARE_ACCESS_DELETE,
1782                                       NTCREATEX_DISP_CREATE, 
1783                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1784         torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!", 
1785                        dname, smbcli_errstr(cli1->tree)));
1786
1787         correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
1788         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1789
1790         {
1791                 char *fullname;
1792                 asprintf(&fullname, "\\%s%s", dname, fname);
1793                 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1794                                     DENY_NONE);
1795                 torture_assert(tctx, fnum1 == -1, 
1796                                 "smbcli_open succeeded, should have "
1797                                "failed with NT_STATUS_DELETE_PENDING"
1798                                );
1799
1800                 torture_assert_ntstatus_equal(tctx, 
1801                                          smbcli_nt_error(cli1->tree),
1802                                      NT_STATUS_DELETE_PENDING, 
1803                                         "smbcli_open failed");
1804         }
1805
1806         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, false);
1807         torture_assert_ntstatus_ok(tctx, status, 
1808                                         "setting delete_on_close on file failed !");
1809                 
1810         {
1811                 char *fullname;
1812                 asprintf(&fullname, "\\%s%s", dname, fname);
1813                 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1814                                     DENY_NONE);
1815                 torture_assert(tctx, fnum1 != -1, 
1816                                 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1817                                smbcli_errstr(cli1->tree)));
1818                 smbcli_close(cli1->tree, fnum1);
1819         }
1820
1821         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1822
1823         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1824                  "setting delete_on_close failed");
1825         smbcli_close(cli1->tree, dnum1);
1826
1827         return correct;
1828 }
1829
1830 /* Test 20a ... */
1831 static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1832 {
1833         int fnum1 = -1;
1834         int fnum2 = -1;
1835         bool correct = true;
1836
1837         del_clean_area(cli1, cli2);
1838
1839         /* Test 20a. */
1840
1841         /* Ensure the file doesn't already exist. */
1842         smbcli_close(cli1->tree, fnum1);
1843         smbcli_close(cli1->tree, fnum2);
1844         smbcli_setatr(cli1->tree, fname, 0, 0);
1845         smbcli_unlink(cli1->tree, fname);
1846
1847         /* Firstly open and create with all access */
1848         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1849                                       SEC_RIGHTS_FILE_ALL,
1850                                       FILE_ATTRIBUTE_NORMAL,
1851                                       NTCREATEX_SHARE_ACCESS_READ|
1852                                       NTCREATEX_SHARE_ACCESS_WRITE|
1853                                       NTCREATEX_SHARE_ACCESS_DELETE,
1854                                       NTCREATEX_DISP_CREATE, 
1855                                       0, 0);
1856         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1857                        fname, smbcli_errstr(cli1->tree)));
1858
1859         /* Next open with all access, but add delete on close. */
1860         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
1861                                       SEC_RIGHTS_FILE_ALL,
1862                                       FILE_ATTRIBUTE_NORMAL,
1863                                       NTCREATEX_SHARE_ACCESS_READ|
1864                                       NTCREATEX_SHARE_ACCESS_WRITE|
1865                                       NTCREATEX_SHARE_ACCESS_DELETE,
1866                                       NTCREATEX_DISP_OPEN,
1867                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1868         
1869         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)", 
1870                        fname, smbcli_errstr(cli2->tree)));
1871
1872         /* The delete on close bit is *not* reported as being set. */
1873         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1874         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1875
1876         smbcli_close(cli1->tree, fnum1);
1877
1878         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1879
1880         smbcli_close(cli2->tree, fnum2);
1881
1882         /* See if the file is deleted - should be.... */
1883         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1884         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
1885                        fname, smbcli_errstr(cli1->tree)));
1886
1887         return correct;
1888 }
1889
1890 /* Test 20b ... */
1891 /* This is the delete semantics that the cifsfs client depends on when
1892  * trying to delete an open file on a Windows server. It
1893  * opens a file with initial delete on close set, renames it then closes
1894  * all open handles. The file goes away on Windows.
1895  */
1896
1897 static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1898 {
1899         int fnum1 = -1;
1900         int fnum2 = -1;
1901         bool correct = true;
1902
1903         del_clean_area(cli1, cli2);
1904
1905         /* Test 20b. */
1906
1907         /* Ensure the file doesn't already exist. */
1908         smbcli_close(cli1->tree, fnum1);
1909         smbcli_close(cli1->tree, fnum2);
1910         smbcli_setatr(cli1->tree, fname, 0, 0);
1911         smbcli_unlink(cli1->tree, fname);
1912         smbcli_setatr(cli1->tree, fname_new, 0, 0);
1913         smbcli_unlink(cli1->tree, fname_new);
1914
1915         /* Firstly open and create with all access */
1916         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1917                                       SEC_RIGHTS_FILE_ALL,
1918                                       FILE_ATTRIBUTE_NORMAL,
1919                                       NTCREATEX_SHARE_ACCESS_READ|
1920                                       NTCREATEX_SHARE_ACCESS_WRITE|
1921                                       NTCREATEX_SHARE_ACCESS_DELETE,
1922                                       NTCREATEX_DISP_CREATE, 
1923                                       0, 0);
1924         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1925                        fname, smbcli_errstr(cli1->tree)));
1926
1927         /* And close - just to create the file. */
1928         smbcli_close(cli1->tree, fnum1);
1929         
1930         /* Firstly open and create with all access */
1931         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1932                                       SEC_RIGHTS_FILE_ALL,
1933                                       FILE_ATTRIBUTE_NORMAL,
1934                                       NTCREATEX_SHARE_ACCESS_READ|
1935                                       NTCREATEX_SHARE_ACCESS_WRITE|
1936                                       NTCREATEX_SHARE_ACCESS_DELETE,
1937                                       NTCREATEX_DISP_OPEN, 
1938                                       0, 0);
1939         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1940                        fname, smbcli_errstr(cli1->tree)));
1941
1942         /* Next open with all access, but add delete on close. */
1943         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
1944                                       SEC_RIGHTS_FILE_ALL,
1945                                       FILE_ATTRIBUTE_NORMAL,
1946                                       NTCREATEX_SHARE_ACCESS_READ|
1947                                       NTCREATEX_SHARE_ACCESS_WRITE|
1948                                       NTCREATEX_SHARE_ACCESS_DELETE,
1949                                       NTCREATEX_DISP_OPEN,
1950                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1951         
1952         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)", 
1953                        fname, smbcli_errstr(cli2->tree)));
1954
1955         /* The delete on close bit is *not* reported as being set. */
1956         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1957         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1958
1959         smbcli_close(cli1->tree, fnum1);
1960
1961         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1962
1963         /* Rename the file by handle. */
1964
1965         {
1966                 union smb_setfileinfo sfinfo;
1967                 NTSTATUS status;
1968
1969                 memset(&sfinfo, '\0', sizeof(sfinfo));
1970                 sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
1971                 sfinfo.generic.in.file.fnum = fnum2;
1972                 sfinfo.rename_information.in.root_fid  = 0;
1973                 /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
1974                 sfinfo.rename_information.in.new_name  = fname_new + 1;
1975                 sfinfo.rename_information.in.overwrite = 1;
1976
1977                 status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
1978
1979                 torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
1980                         fname, fname_new, smbcli_errstr(cli2->tree)));
1981         }
1982
1983         correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, false, __location__);
1984
1985         smbcli_close(cli2->tree, fnum2);
1986
1987         /* See if the file is deleted - should be.... */
1988         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1989         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
1990                        fname, smbcli_errstr(cli1->tree)));
1991         fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
1992         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
1993                        fname_new, smbcli_errstr(cli1->tree)));
1994
1995         return correct;
1996 }
1997
1998
1999 /* Test 21 ... */
2000 static bool deltest21(struct torture_context *tctx)
2001 {
2002         int fnum1 = -1;
2003         struct smbcli_state *cli1;
2004         struct smbcli_state *cli2;
2005         bool correct = true;
2006
2007         if (!torture_open_connection(&cli1, tctx, 0))
2008                 return false;
2009
2010         if (!torture_open_connection(&cli2, tctx, 1))
2011                 return false;
2012
2013         del_clean_area(cli1, cli2);
2014
2015         /* Test 21 -- Test removal of file after socket close. */
2016
2017         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
2018                                       SEC_RIGHTS_FILE_ALL,
2019                                       FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
2020                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
2021         
2022         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
2023                        fname, smbcli_errstr(cli1->tree)));
2024         
2025         torture_assert_ntstatus_ok(tctx, 
2026                                 smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
2027                                 talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
2028                        smbcli_errstr(cli1->tree)));
2029         
2030         /* Ensure delete on close is set. */
2031         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
2032
2033         /* Now yank the rug from under cli1. */
2034         smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
2035
2036         fnum1 = -1;
2037
2038         if (!torture_open_connection(&cli1, tctx, 0)) {
2039                 return false;
2040         }
2041
2042         /* On slow build farm machines it might happen that they are not fast
2043          * enogh to delete the file for this test */
2044         smb_msleep(200);
2045
2046         /* File should not be there. */
2047         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
2048                                       SEC_RIGHTS_FILE_READ,
2049                                       FILE_ATTRIBUTE_NORMAL,
2050                                       NTCREATEX_SHARE_ACCESS_READ|
2051                                       NTCREATEX_SHARE_ACCESS_WRITE|
2052                                       NTCREATEX_SHARE_ACCESS_DELETE,
2053                                       NTCREATEX_DISP_OPEN,
2054                                       0, 0);
2055         
2056         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
2057
2058         return correct;
2059 }
2060
2061 /* Test 22 ... */
2062
2063 /*
2064  * Test whether a second *directory* handle inhibits delete if the first has
2065  * del-on-close set and is closed
2066  */
2067 static bool deltest22(struct torture_context *tctx)
2068 {
2069         int dnum1 = -1;
2070         int dnum2 = -1;
2071         struct smbcli_state *cli1;
2072         bool correct = true;
2073
2074         if (!torture_open_connection(&cli1, tctx, 0))
2075                 return false;
2076
2077         smbcli_deltree(cli1->tree, dname);
2078
2079         torture_assert_ntstatus_ok(
2080                 tctx, smbcli_mkdir(cli1->tree, dname),
2081                 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
2082                                 smbcli_errstr(cli1->tree)));
2083
2084         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2085                                       SEC_FILE_READ_DATA|
2086                                       SEC_FILE_WRITE_DATA|
2087                                       SEC_STD_DELETE,
2088                                       FILE_ATTRIBUTE_DIRECTORY, 
2089                                       NTCREATEX_SHARE_ACCESS_READ|
2090                                       NTCREATEX_SHARE_ACCESS_WRITE|
2091                                       NTCREATEX_SHARE_ACCESS_DELETE,
2092                                       NTCREATEX_DISP_OPEN, 
2093                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
2094
2095         torture_assert(tctx, dnum1 != -1,
2096                        talloc_asprintf(tctx, "open of %s failed: %s!", 
2097                                        dname, smbcli_errstr(cli1->tree)));
2098
2099         dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2100                                       SEC_FILE_READ_DATA|
2101                                       SEC_FILE_WRITE_DATA,
2102                                       FILE_ATTRIBUTE_DIRECTORY, 
2103                                       NTCREATEX_SHARE_ACCESS_READ|
2104                                       NTCREATEX_SHARE_ACCESS_WRITE|
2105                                       NTCREATEX_SHARE_ACCESS_DELETE,
2106                                       NTCREATEX_DISP_OPEN, 
2107                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
2108
2109         torture_assert(tctx, dnum2 != -1,
2110                        talloc_asprintf(tctx, "open of %s failed: %s!", 
2111                                        dname, smbcli_errstr(cli1->tree)));
2112
2113         torture_assert_ntstatus_ok(
2114                 tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true), 
2115                 talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
2116                                 smbcli_errstr(cli1->tree)));
2117
2118         smbcli_close(cli1->tree, dnum1);
2119
2120         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2121                                       SEC_FILE_READ_DATA|
2122                                       SEC_FILE_WRITE_DATA|
2123                                       SEC_STD_DELETE,
2124                                       FILE_ATTRIBUTE_DIRECTORY, 
2125                                       NTCREATEX_SHARE_ACCESS_READ|
2126                                       NTCREATEX_SHARE_ACCESS_WRITE|
2127                                       NTCREATEX_SHARE_ACCESS_DELETE,
2128                                       NTCREATEX_DISP_OPEN, 
2129                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
2130
2131         torture_assert(tctx, dnum1 == -1,
2132                        talloc_asprintf(tctx, "open of %s succeeded!\n",
2133                                        dname));
2134
2135         CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
2136
2137         smbcli_close(cli1->tree, dnum2);
2138         CHECK_STATUS(cli1, NT_STATUS_OK);
2139
2140         return correct;
2141 }
2142
2143 /* Test 23 - Second directory open fails when delete is pending. */
2144 static bool deltest23(struct torture_context *tctx,
2145                         struct smbcli_state *cli1,
2146                         struct smbcli_state *cli2)
2147 {
2148         int dnum1 = -1;
2149         int dnum2 = -1;
2150         bool correct = true;
2151
2152         del_clean_area(cli1, cli2);
2153
2154         /* Test 23 -- Basic delete on close for directories. */
2155
2156         /* Open a directory */
2157         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
2158                                       SEC_FILE_READ_DATA|
2159                                       SEC_FILE_WRITE_DATA|
2160                                       SEC_STD_DELETE,
2161                                       FILE_ATTRIBUTE_DIRECTORY,
2162                                       NTCREATEX_SHARE_ACCESS_READ|
2163                                       NTCREATEX_SHARE_ACCESS_WRITE|
2164                                       NTCREATEX_SHARE_ACCESS_DELETE,
2165                                       NTCREATEX_DISP_CREATE,
2166                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
2167
2168         torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx,
2169                            "open of %s failed: %s!",
2170                            dname, smbcli_errstr(cli1->tree)));
2171
2172         correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false,
2173             __location__);
2174
2175         /* Set delete on close */
2176         (void)smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
2177
2178         /* Attempt opening the directory again.  It should fail. */
2179         dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
2180                                       SEC_FILE_READ_DATA|
2181                                       SEC_FILE_WRITE_DATA|
2182                                       SEC_STD_DELETE,
2183                                       FILE_ATTRIBUTE_DIRECTORY,
2184                                       NTCREATEX_SHARE_ACCESS_READ|
2185                                       NTCREATEX_SHARE_ACCESS_WRITE|
2186                                       NTCREATEX_SHARE_ACCESS_DELETE,
2187                                       NTCREATEX_DISP_OPEN,
2188                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
2189
2190         torture_assert(tctx, dnum2 == -1, talloc_asprintf(tctx,
2191                            "open of %s succeeded: %s. It should have failed "
2192                            "with NT_STATUS_DELETE_PENDING",
2193                            dname, smbcli_errstr(cli1->tree)));
2194
2195         torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree),
2196             NT_STATUS_DELETE_PENDING, "smbcli_open failed");
2197
2198         return true;
2199 }
2200
2201 /*
2202   Test delete on close semantics.
2203  */
2204 struct torture_suite *torture_test_delete(void)
2205 {
2206         struct torture_suite *suite = torture_suite_create(
2207                 talloc_autofree_context(), "delete");
2208
2209         torture_suite_add_2smb_test(suite, "deltest1", deltest1);
2210         torture_suite_add_2smb_test(suite, "deltest2", deltest2);
2211         torture_suite_add_2smb_test(suite, "deltest3", deltest3);
2212         torture_suite_add_2smb_test(suite, "deltest4", deltest4);
2213         torture_suite_add_2smb_test(suite, "deltest5", deltest5);
2214         torture_suite_add_2smb_test(suite, "deltest6", deltest6);
2215         torture_suite_add_2smb_test(suite, "deltest7", deltest7);
2216         torture_suite_add_2smb_test(suite, "deltest8", deltest8);
2217         torture_suite_add_2smb_test(suite, "deltest9", deltest9);
2218         torture_suite_add_2smb_test(suite, "deltest10", deltest10);
2219         torture_suite_add_2smb_test(suite, "deltest11", deltest11);
2220         torture_suite_add_2smb_test(suite, "deltest12", deltest12);
2221         torture_suite_add_2smb_test(suite, "deltest13", deltest13);
2222         torture_suite_add_2smb_test(suite, "deltest14", deltest14);
2223         torture_suite_add_2smb_test(suite, "deltest15", deltest15);
2224         torture_suite_add_2smb_test(suite, "deltest16", deltest16);
2225         torture_suite_add_2smb_test(suite, "deltest16a", deltest16a);
2226         torture_suite_add_2smb_test(suite, "deltest17", deltest17);
2227         torture_suite_add_2smb_test(suite, "deltest17a", deltest17a);
2228         torture_suite_add_2smb_test(suite, "deltest17b", deltest17b);
2229         torture_suite_add_2smb_test(suite, "deltest17c", deltest17c);
2230         torture_suite_add_2smb_test(suite, "deltest17d", deltest17d);
2231         torture_suite_add_2smb_test(suite, "deltest17e", deltest17e);
2232         torture_suite_add_2smb_test(suite, "deltest17f", deltest17f);
2233         torture_suite_add_2smb_test(suite, "deltest18", deltest18);
2234         torture_suite_add_2smb_test(suite, "deltest19", deltest19);
2235         torture_suite_add_2smb_test(suite, "deltest20", deltest20);
2236         torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
2237         torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
2238         torture_suite_add_simple_test(suite, "deltest21", deltest21);
2239         torture_suite_add_simple_test(suite, "deltest22", deltest22);
2240         torture_suite_add_2smb_test(suite, "deltest23", deltest23);
2241
2242         return suite;
2243 }