Fix a bunch of "warning: variable ‘XXXX’ set but not used [-Wunused-but-set-variable...
[mat/samba.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, "close - 2 failed (%s)", 
367                        smbcli_errstr(cli1->tree)));
368
369         return true;
370 }
371
372 /* Test 7 ... */
373 static bool deltest7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
374 {
375         int fnum1 = -1;
376         bool correct = true;
377
378         del_clean_area(cli1, cli2);
379
380         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
381                                       SEC_FILE_READ_DATA  | 
382                                       SEC_FILE_WRITE_DATA |
383                                       SEC_STD_DELETE,
384                                       FILE_ATTRIBUTE_NORMAL, 0, 
385                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
386                                                                 
387         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
388                        fname, smbcli_errstr(cli1->tree)));
389
390         torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
391                         "setting delete_on_close on file failed !");
392
393         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
394         
395         torture_assert_ntstatus_ok(tctx, 
396                                         smbcli_nt_delete_on_close(cli1->tree, fnum1, false), 
397                                         "unsetting delete_on_close on file failed !");
398
399         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
400         
401         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
402                 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli1->tree)));
403         
404         /* This next open should succeed - we reset the flag. */
405         
406         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
407         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
408                        fname, smbcli_errstr(cli1->tree)));
409
410         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
411                                                        talloc_asprintf(tctx, "close - 2 failed (%s)", 
412                                                    smbcli_errstr(cli1->tree)));
413
414         return correct;
415 }
416
417 /* Test 8 ... */
418 static bool deltest8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
419 {
420         int fnum1 = -1;
421         int fnum2 = -1;
422         bool correct = true;
423
424         del_clean_area(cli1, cli2);
425
426         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
427                                       SEC_FILE_READ_DATA|
428                                       SEC_FILE_WRITE_DATA|
429                                       SEC_STD_DELETE,
430                                       FILE_ATTRIBUTE_NORMAL, 
431                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
432                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
433         
434         torture_assert(tctx, fnum1 != -1,
435                 talloc_asprintf(tctx, "open of %s failed (%s)", 
436                        fname, smbcli_errstr(cli1->tree)));
437
438         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
439                                       SEC_FILE_READ_DATA|
440                                       SEC_FILE_WRITE_DATA|
441                                       SEC_STD_DELETE,
442                                       FILE_ATTRIBUTE_NORMAL, 
443                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
444                                       NTCREATEX_DISP_OPEN, 0, 0);
445         
446         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
447                        fname, smbcli_errstr(cli1->tree)));
448
449         torture_assert_ntstatus_ok(tctx, 
450                                         smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
451                 "setting delete_on_close on file failed !");
452
453         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
454         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
455
456         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
457                 talloc_asprintf(tctx, "close - 1 failed (%s)", 
458                        smbcli_errstr(cli1->tree)));
459
460         correct &= check_delete_on_close(tctx, cli1, -1, fname, true, __location__);
461         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
462         
463         torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
464                 talloc_asprintf(tctx, "close - 2 failed (%s)", smbcli_errstr(cli2->tree)));
465
466         /* This should fail.. */
467         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
468         torture_assert(tctx, fnum1 == -1,
469                 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !\n", fname));
470
471         return correct;
472 }
473
474 /* Test 9 ... */
475 static bool deltest9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
476 {
477         int fnum1 = -1;
478
479         del_clean_area(cli1, cli2);
480
481         /* This should fail - we need to set DELETE_ACCESS. */
482         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
483                                       SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
484                                       FILE_ATTRIBUTE_NORMAL, 
485                                       NTCREATEX_SHARE_ACCESS_NONE, 
486                                       NTCREATEX_DISP_OVERWRITE_IF, 
487                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
488         
489         torture_assert(tctx, fnum1 == -1, 
490                                    talloc_asprintf(tctx, "open of %s succeeded should have failed!", 
491                        fname));
492
493         return true;
494 }
495
496 /* Test 10 ... */
497 static bool deltest10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
498 {
499         int fnum1 = -1;
500
501         del_clean_area(cli1, cli2);
502
503         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
504                                       SEC_FILE_READ_DATA|
505                                       SEC_FILE_WRITE_DATA|
506                                       SEC_STD_DELETE,
507                                       FILE_ATTRIBUTE_NORMAL, 
508                                       NTCREATEX_SHARE_ACCESS_NONE, 
509                                       NTCREATEX_DISP_OVERWRITE_IF, 
510                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
511         torture_assert(tctx, fnum1 != -1, 
512                 talloc_asprintf(tctx, "open of %s failed (%s)", 
513                        fname, smbcli_errstr(cli1->tree)));
514
515         /* This should delete the file. */
516         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
517                 talloc_asprintf(tctx, "close failed (%s)", 
518                        smbcli_errstr(cli1->tree)));
519
520         /* This should fail.. */
521         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
522         torture_assert(tctx, fnum1 == -1, 
523                                 talloc_asprintf(tctx, "open of %s succeeded should have been deleted on close !",
524                        fname));
525         return true;
526 }
527
528 /* Test 11 ... */
529 static bool deltest11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
530 {
531         int fnum1 = -1;
532         NTSTATUS status;
533
534         del_clean_area(cli1, cli2);
535
536         /* test 11 - does having read only attribute still allow delete on close. */
537
538         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
539                                       SEC_RIGHTS_FILE_ALL,
540                                       FILE_ATTRIBUTE_READONLY, 
541                                       NTCREATEX_SHARE_ACCESS_NONE, 
542                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
543         
544         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
545                        fname, smbcli_errstr(cli1->tree)));
546
547         status = smbcli_nt_delete_on_close(cli1->tree, fnum1, true);
548
549         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE, 
550                 talloc_asprintf(tctx, "setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)", smbcli_errstr(cli1->tree)));
551
552         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1),
553                 talloc_asprintf(tctx, "close failed (%s)", 
554                        smbcli_errstr(cli1->tree)));
555
556         return true;
557 }
558
559 /* Test 12 ... */
560 static bool deltest12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
561 {
562         int fnum1 = -1;
563         NTSTATUS status;
564
565         del_clean_area(cli1, cli2);
566
567         /* test 12 - does having read only attribute still allow delete on
568          * close at time of open. */
569
570         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
571                                       SEC_RIGHTS_FILE_ALL,
572                                       FILE_ATTRIBUTE_READONLY,
573                                       NTCREATEX_SHARE_ACCESS_DELETE,
574                                       NTCREATEX_DISP_OVERWRITE_IF, 
575                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
576         
577         torture_assert(tctx, fnum1 == -1, 
578                  talloc_asprintf(tctx, "open of %s succeeded. Should fail with "
579                        "NT_STATUS_CANNOT_DELETE.\n", fname));
580
581         status = smbcli_nt_error(cli1->tree);
582         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_CANNOT_DELETE, 
583                          talloc_asprintf(tctx, "setting delete_on_close on open should "
584                                "fail with NT_STATUS_CANNOT_DELETE. Got %s "
585                                "instead)", 
586                                smbcli_errstr(cli1->tree)));
587         
588         return true;
589 }
590
591 /* Test 13 ... */
592 static bool deltest13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
593 {
594         int fnum1 = -1;
595         int fnum2 = -1;
596         bool correct = true;
597
598         del_clean_area(cli1, cli2);
599
600         /* Test 13: Does resetting the delete on close flag affect a second
601          * fd? */
602
603         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
604                                       SEC_FILE_READ_DATA|
605                                       SEC_FILE_WRITE_DATA|
606                                       SEC_STD_DELETE,
607                                       FILE_ATTRIBUTE_NORMAL, 
608                                       NTCREATEX_SHARE_ACCESS_READ|
609                                       NTCREATEX_SHARE_ACCESS_WRITE|
610                                       NTCREATEX_SHARE_ACCESS_DELETE,
611                                       NTCREATEX_DISP_OVERWRITE_IF,
612                                       0, 0);
613         
614         torture_assert(tctx, fnum1 != -1, 
615                 talloc_asprintf(tctx, "open of %s failed (%s)", 
616                        fname, smbcli_errstr(cli1->tree)));
617
618         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
619                                       SEC_FILE_READ_DATA|
620                                       SEC_FILE_WRITE_DATA|
621                                       SEC_STD_DELETE,
622                                       FILE_ATTRIBUTE_NORMAL, 
623                                       NTCREATEX_SHARE_ACCESS_READ|
624                                       NTCREATEX_SHARE_ACCESS_WRITE|
625                                       NTCREATEX_SHARE_ACCESS_DELETE,
626                                       NTCREATEX_DISP_OPEN, 0, 0);
627         
628         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, 
629                                 "open of %s failed (%s)", 
630                        fname, smbcli_errstr(cli2->tree)));
631
632         torture_assert_ntstatus_ok(tctx, 
633                                                 smbcli_nt_delete_on_close(cli1->tree, fnum1,
634                                                        true), 
635                  "setting delete_on_close on file failed !");
636
637         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
638         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
639
640         torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli2->tree, fnum2,
641                                                        false), 
642                  "setting delete_on_close on file failed !");
643
644         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
645         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
646         
647         torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), 
648                 talloc_asprintf(tctx, "close - 1 failed (%s)", 
649                        smbcli_errstr(cli1->tree)));
650
651         torture_assert_ntstatus_ok(tctx, smbcli_close(cli2->tree, fnum2),
652                         talloc_asprintf(tctx, "close - 2 failed (%s)", 
653                        smbcli_errstr(cli2->tree)));
654
655         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
656
657         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed!", 
658                        fname));
659
660         smbcli_close(cli1->tree, fnum1);
661
662         return correct;
663 }
664
665 /* Test 14 ... */
666 static bool deltest14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
667 {
668         int dnum1 = -1;
669         bool correct = true;
670
671         del_clean_area(cli1, cli2);
672
673         /* Test 14 -- directory */
674
675         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
676                                       SEC_FILE_READ_DATA|
677                                       SEC_FILE_WRITE_DATA|
678                                       SEC_STD_DELETE,
679                                       FILE_ATTRIBUTE_DIRECTORY, 
680                                       NTCREATEX_SHARE_ACCESS_READ|
681                                       NTCREATEX_SHARE_ACCESS_WRITE|
682                                       NTCREATEX_SHARE_ACCESS_DELETE,
683                                       NTCREATEX_DISP_CREATE, 0, 0);
684         torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!", 
685                        dname, smbcli_errstr(cli1->tree)));
686
687         correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
688         torture_assert_ntstatus_ok(tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true),
689                         "setting delete_on_close on file failed !");
690         correct &= check_delete_on_close(tctx, cli1, dnum1, dname, true, __location__);
691         smbcli_close(cli1->tree, dnum1);
692
693         /* Now it should be gone... */
694
695         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
696                                       SEC_FILE_READ_DATA|
697                                       SEC_FILE_WRITE_DATA|
698                                       SEC_STD_DELETE,
699                                       FILE_ATTRIBUTE_DIRECTORY, 
700                                       NTCREATEX_SHARE_ACCESS_READ|
701                                       NTCREATEX_SHARE_ACCESS_WRITE|
702                                       NTCREATEX_SHARE_ACCESS_DELETE,
703                                       NTCREATEX_DISP_OPEN, 0, 0);
704         torture_assert(tctx, dnum1 == -1, "setting delete_on_close on file succeeded !");
705
706         return correct;
707 }
708
709 /* Test 15 ... */
710 static bool deltest15(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
711 {
712         int fnum1 = -1;
713         bool correct = true;
714         int fnum2 = -1;
715         NTSTATUS status;
716
717         del_clean_area(cli1, cli2);
718
719         /* Test 15: delete on close under rename */
720
721         smbcli_setatr(cli1->tree, fname, 0, 0);
722         smbcli_unlink(cli1->tree, fname);
723         smbcli_unlink(cli1->tree, fname_new);
724         
725         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
726                                       SEC_FILE_READ_DATA,
727                                       FILE_ATTRIBUTE_NORMAL, 
728                                       NTCREATEX_SHARE_ACCESS_READ|
729                                       NTCREATEX_SHARE_ACCESS_WRITE|
730                                       NTCREATEX_SHARE_ACCESS_DELETE,
731                                       NTCREATEX_DISP_OVERWRITE_IF,
732                                       0, 0);
733
734         torture_assert(tctx, fnum1 != -1, 
735                 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
736
737         status = smbcli_rename(cli2->tree, fname, fname_new);
738
739         torture_assert_ntstatus_ok(tctx, status, "renaming failed!");
740
741         fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0, 
742                                       SEC_GENERIC_ALL,
743                                       FILE_ATTRIBUTE_NORMAL, 
744                                       NTCREATEX_SHARE_ACCESS_READ|
745                                       NTCREATEX_SHARE_ACCESS_WRITE|
746                                       NTCREATEX_SHARE_ACCESS_DELETE,
747                                       NTCREATEX_DISP_OVERWRITE_IF,
748                                       0, 0);
749
750         torture_assert(tctx, fnum2 != -1, 
751                 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
752                        fname_new, smbcli_errstr(cli1->tree)));
753
754         status = smbcli_nt_delete_on_close(cli2->tree, fnum2, true);
755
756         torture_assert_ntstatus_ok(tctx, status, 
757                 "setting delete_on_close on file failed !");
758
759         smbcli_close(cli2->tree, fnum2);
760
761         /* The file should be around under the new name, there's a second
762          * handle open */
763
764         correct &= check_delete_on_close(tctx, cli1, fnum1, fname_new, true, __location__);
765
766         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
767                                       SEC_GENERIC_ALL,
768                                       FILE_ATTRIBUTE_NORMAL, 
769                                       NTCREATEX_SHARE_ACCESS_READ|
770                                       NTCREATEX_SHARE_ACCESS_WRITE|
771                                       NTCREATEX_SHARE_ACCESS_DELETE,
772                                       NTCREATEX_DISP_OVERWRITE_IF,
773                                       0, 0);
774
775         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
776                        fname, smbcli_errstr(cli1->tree)));
777
778         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
779
780         smbcli_close(cli2->tree, fnum2);
781         smbcli_close(cli1->tree, fnum1);
782
783         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
784                                       SEC_FILE_READ_EA,
785                                       FILE_ATTRIBUTE_NORMAL, 
786                                       NTCREATEX_SHARE_ACCESS_READ|
787                                       NTCREATEX_SHARE_ACCESS_WRITE|
788                                       NTCREATEX_SHARE_ACCESS_DELETE,
789                                       NTCREATEX_DISP_OPEN,
790                                       0, 0);
791
792         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
793                        fname, smbcli_errstr(cli1->tree)));
794
795         smbcli_close(cli1->tree, fnum1);
796
797         fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0, 
798                                       SEC_FILE_READ_EA,
799                                       FILE_ATTRIBUTE_NORMAL, 
800                                       NTCREATEX_SHARE_ACCESS_READ|
801                                       NTCREATEX_SHARE_ACCESS_WRITE|
802                                       NTCREATEX_SHARE_ACCESS_DELETE,
803                                       NTCREATEX_DISP_OPEN,
804                                       0, 0);
805
806         torture_assert(tctx, fnum1 == -1, 
807                 "smbcli_open succeeded, should have "
808                        "failed");
809
810         return correct;
811 }
812
813 /* Test 16 ... */
814 static bool deltest16(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
815 {
816         int fnum1 = -1;
817         int fnum2 = -1;
818         bool correct = true;
819
820         del_clean_area(cli1, cli2);
821
822         /* Test 16. */
823
824         /* Ensure the file doesn't already exist. */
825         smbcli_close(cli1->tree, fnum1);
826         smbcli_close(cli1->tree, fnum2);
827         smbcli_setatr(cli1->tree, fname, 0, 0);
828         smbcli_unlink(cli1->tree, fname);
829
830         /* Firstly create with all access, but delete on close. */
831         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
832                                       SEC_RIGHTS_FILE_ALL,
833                                       FILE_ATTRIBUTE_NORMAL,
834                                       NTCREATEX_SHARE_ACCESS_READ|
835                                       NTCREATEX_SHARE_ACCESS_WRITE|
836                                       NTCREATEX_SHARE_ACCESS_DELETE,
837                                       NTCREATEX_DISP_CREATE,
838                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
839         
840         torture_assert (tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
841
842         /* The delete on close bit is *not* reported as being set. */
843         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
844
845         /* The delete on close bit is *not* reported as being set. */
846         correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
847         correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
848
849         /* Now try opening again for read-only. */
850         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
851                                       SEC_RIGHTS_FILE_READ,
852                                       FILE_ATTRIBUTE_NORMAL,
853                                       NTCREATEX_SHARE_ACCESS_READ|
854                                       NTCREATEX_SHARE_ACCESS_WRITE|
855                                       NTCREATEX_SHARE_ACCESS_DELETE,
856                                       NTCREATEX_DISP_OPEN,
857                                       0, 0);
858         
859         /* Should work. */
860         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
861                       fname, smbcli_errstr(cli1->tree)));
862
863         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
864         correct &= check_delete_on_close(tctx, cli1, -1, fname, false, __location__);
865         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
866         correct &= check_delete_on_close(tctx, cli2, -1, fname, false, __location__);
867
868         smbcli_close(cli1->tree, fnum1);
869
870         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, true, __location__);
871         correct &= check_delete_on_close(tctx, cli2, -1, fname, true, __location__);
872
873         smbcli_close(cli2->tree, fnum2);
874
875         /* And the file should be deleted ! */
876         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
877         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)", 
878                        fname));
879
880         return correct;
881 }
882
883 /* Test 17 ... */
884 static bool deltest17(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
885 {
886         int fnum1 = -1;
887         int fnum2 = -1;
888         bool correct = true;
889
890         del_clean_area(cli1, cli2);
891
892         /* Test 17. */
893
894         /* Ensure the file doesn't already exist. */
895         smbcli_close(cli1->tree, fnum1);
896         smbcli_close(cli1->tree, fnum2);
897         smbcli_setatr(cli1->tree, fname, 0, 0);
898         smbcli_unlink(cli1->tree, fname);
899
900         /* Firstly open and create with all access */
901         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
902                                       SEC_RIGHTS_FILE_ALL,
903                                       FILE_ATTRIBUTE_NORMAL,
904                                       NTCREATEX_SHARE_ACCESS_READ|
905                                       NTCREATEX_SHARE_ACCESS_WRITE|
906                                       NTCREATEX_SHARE_ACCESS_DELETE,
907                                       NTCREATEX_DISP_CREATE, 
908                                       0, 0);
909         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
910                        fname, smbcli_errstr(cli1->tree)));
911
912         /* And close - just to create the file. */
913         smbcli_close(cli1->tree, fnum1);
914         
915         /* Next open with all access, but add delete on close. */
916         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
917                                       SEC_RIGHTS_FILE_ALL,
918                                       FILE_ATTRIBUTE_NORMAL,
919                                       NTCREATEX_SHARE_ACCESS_READ|
920                                       NTCREATEX_SHARE_ACCESS_WRITE|
921                                       NTCREATEX_SHARE_ACCESS_DELETE,
922                                       NTCREATEX_DISP_OPEN,
923                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
924         
925         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
926                        fname, smbcli_errstr(cli1->tree)));
927
928         /* The delete on close bit is *not* reported as being set. */
929         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
930
931         /* Now try opening again for read-only. */
932         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
933                                       SEC_RIGHTS_FILE_READ|
934                                       SEC_STD_DELETE,
935                                       FILE_ATTRIBUTE_NORMAL,
936                                       NTCREATEX_SHARE_ACCESS_READ|
937                                       NTCREATEX_SHARE_ACCESS_WRITE|
938                                       NTCREATEX_SHARE_ACCESS_DELETE,
939                                       NTCREATEX_DISP_OPEN,
940                                       0, 0);
941         
942         /* Should work. */
943         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
944                        fname, smbcli_errstr(cli1->tree)));
945
946         /* still not reported as being set on either */
947         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
948         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, false, __location__);
949
950         smbcli_close(cli1->tree, fnum1);
951
952         /* After the first close, the files has the delete on close bit set. */
953         correct &= check_delete_on_close(tctx, cli1, fnum2, fname, true, __location__);
954
955         smbcli_close(cli1->tree, fnum2);
956
957         /* Make sure the file has been deleted */
958         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
959         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s failed (should succeed) - %s",
960                        fname, smbcli_errstr(cli1->tree)));
961
962         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
963
964         return correct;
965 }
966
967 /* Test 18 ... */
968 static bool deltest18(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
969 {
970         int fnum1 = -1;
971         int fnum2 = -1;
972         bool correct = true;
973
974         del_clean_area(cli1, cli2);
975
976         /* Test 18. With directories. */
977
978         /* Ensure the file doesn't already exist. */
979         smbcli_close(cli1->tree, fnum1);
980         smbcli_close(cli1->tree, fnum2);
981
982         smbcli_deltree(cli1->tree, dname);
983
984         /* Firstly create with all access, but delete on close. */
985         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
986                                       SEC_FILE_READ_DATA|
987                                       SEC_FILE_WRITE_DATA|
988                                       SEC_STD_DELETE,
989                                       FILE_ATTRIBUTE_DIRECTORY,
990                                       NTCREATEX_SHARE_ACCESS_READ|
991                                       NTCREATEX_SHARE_ACCESS_WRITE|
992                                       NTCREATEX_SHARE_ACCESS_DELETE,
993                                       NTCREATEX_DISP_CREATE,
994                                       NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
995         
996         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
997                        dname, smbcli_errstr(cli1->tree)));
998
999         /*
1000          * The delete on close bit is *not* reported as being set.
1001          * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1002          * close as being set.  This causes the subsequent create to fail with
1003          * NT_STATUS_DELETE_PENDING.
1004          */
1005         correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1006
1007         /* Now try opening again for read-only. */
1008         fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1009                                       SEC_RIGHTS_FILE_READ,
1010                                       FILE_ATTRIBUTE_DIRECTORY,
1011                                       NTCREATEX_SHARE_ACCESS_READ|
1012                                       NTCREATEX_SHARE_ACCESS_WRITE|
1013                                       NTCREATEX_SHARE_ACCESS_DELETE,
1014                                       NTCREATEX_DISP_OPEN,
1015                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1016         
1017
1018         /* Should work. */
1019         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1020                        dname, smbcli_errstr(cli1->tree)));
1021
1022         correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1023         correct &= check_delete_on_close(tctx, cli1, fnum2, dname, false, __location__);
1024
1025         smbcli_close(cli1->tree, fnum1);
1026
1027         correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1028
1029         smbcli_close(cli1->tree, fnum2);
1030
1031         /* And the directory should be deleted ! */
1032         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1033                                       SEC_RIGHTS_FILE_READ,
1034                                       FILE_ATTRIBUTE_DIRECTORY,
1035                                       NTCREATEX_SHARE_ACCESS_READ|
1036                                       NTCREATEX_SHARE_ACCESS_WRITE|
1037                                       NTCREATEX_SHARE_ACCESS_DELETE,
1038                                       NTCREATEX_DISP_OPEN,
1039                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1040         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail)", 
1041                        dname));
1042
1043         return correct;
1044 }
1045
1046 /* Test 19 ... */
1047 static bool deltest19(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1048 {
1049         int fnum1 = -1;
1050         int fnum2 = -1;
1051         bool correct = true;
1052
1053         del_clean_area(cli1, cli2);
1054
1055         /* Test 19. */
1056
1057         smbcli_deltree(cli1->tree, dname);
1058
1059         /* Firstly open and create with all access */
1060         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1061                                       SEC_FILE_READ_DATA|
1062                                       SEC_FILE_WRITE_DATA|
1063                                       SEC_STD_DELETE,
1064                                       FILE_ATTRIBUTE_DIRECTORY,
1065                                       NTCREATEX_SHARE_ACCESS_READ|
1066                                       NTCREATEX_SHARE_ACCESS_WRITE|
1067                                       NTCREATEX_SHARE_ACCESS_DELETE,
1068                                       NTCREATEX_DISP_CREATE,
1069                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1070         
1071         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1072                        dname, smbcli_errstr(cli1->tree)));
1073
1074         /* And close - just to create the directory. */
1075         smbcli_close(cli1->tree, fnum1);
1076         
1077         /* Next open with all access, but add delete on close. */
1078         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1079                                       SEC_FILE_READ_DATA|
1080                                       SEC_FILE_WRITE_DATA|
1081                                       SEC_STD_DELETE,
1082                                       FILE_ATTRIBUTE_DIRECTORY,
1083                                       NTCREATEX_SHARE_ACCESS_READ|
1084                                       NTCREATEX_SHARE_ACCESS_WRITE|
1085                                       NTCREATEX_SHARE_ACCESS_DELETE,
1086                                       NTCREATEX_DISP_OPEN,
1087                                       NTCREATEX_OPTIONS_DIRECTORY|NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1088         
1089         torture_assert(tctx, fnum1 != -1, 
1090                 talloc_asprintf(tctx, "open - 1 of %s failed (%s)", fname, smbcli_errstr(cli1->tree)));
1091
1092         /*
1093          * The delete on close bit is *not* reported as being set.
1094          * Win2k3/win2k8 should pass this check, but WinXPsp2 reports delete on
1095          * close as being set.  This causes the subsequent create to fail with
1096          * NT_STATUS_DELETE_PENDING.
1097          */
1098         correct &= check_delete_on_close(tctx, cli1, fnum1, dname, false, __location__);
1099
1100         /* Now try opening again for read-only. */
1101         fnum2 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1102                                       SEC_RIGHTS_FILE_READ,
1103                                       FILE_ATTRIBUTE_DIRECTORY,
1104                                       NTCREATEX_SHARE_ACCESS_READ|
1105                                       NTCREATEX_SHARE_ACCESS_WRITE|
1106                                       NTCREATEX_SHARE_ACCESS_DELETE,
1107                                       NTCREATEX_DISP_OPEN,
1108                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1109         
1110         /* Should work. */
1111         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1112                        dname, smbcli_errstr(cli1->tree)));
1113
1114         smbcli_close(cli1->tree, fnum1);
1115
1116         correct &= check_delete_on_close(tctx, cli1, fnum2, dname, true, __location__);
1117
1118         smbcli_close(cli1->tree, fnum2);
1119
1120         /* See if the file is deleted - for a directory this seems to be true ! */
1121         fnum1 = smbcli_nt_create_full(cli1->tree, dname, 0, 
1122                                       SEC_RIGHTS_FILE_READ,
1123                                       FILE_ATTRIBUTE_DIRECTORY,
1124                                       NTCREATEX_SHARE_ACCESS_READ|
1125                                       NTCREATEX_SHARE_ACCESS_WRITE|
1126                                       NTCREATEX_SHARE_ACCESS_DELETE,
1127                                       NTCREATEX_DISP_OPEN,
1128                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1129
1130         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1131
1132         torture_assert(tctx, fnum1 == -1, 
1133                 talloc_asprintf(tctx, "open of %s succeeded (should fail)", dname));
1134
1135         return correct;
1136 }
1137
1138 /* Test 20 ... */
1139 static bool deltest20(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1140 {
1141         int fnum1 = -1;
1142         int dnum1 = -1;
1143         bool correct = true;
1144         NTSTATUS status;
1145
1146         del_clean_area(cli1, cli2);
1147
1148         /* Test 20 -- non-empty directory hardest to get right... */
1149
1150         if (torture_setting_bool(tctx, "samba3", false)) {
1151                 return true;
1152         }
1153
1154         smbcli_deltree(cli1->tree, dname);
1155
1156         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1157                                       SEC_FILE_READ_DATA|
1158                                       SEC_FILE_WRITE_DATA|
1159                                       SEC_STD_DELETE,
1160                                       FILE_ATTRIBUTE_DIRECTORY, 
1161                                       NTCREATEX_SHARE_ACCESS_READ|
1162                                       NTCREATEX_SHARE_ACCESS_WRITE|
1163                                       NTCREATEX_SHARE_ACCESS_DELETE,
1164                                       NTCREATEX_DISP_CREATE, 
1165                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1166         torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx, "open of %s failed: %s!", 
1167                        dname, smbcli_errstr(cli1->tree)));
1168
1169         correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false, __location__);
1170         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1171
1172         {
1173                 char *fullname;
1174                 asprintf(&fullname, "\\%s%s", dname, fname);
1175                 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1176                                     DENY_NONE);
1177                 torture_assert(tctx, fnum1 == -1, 
1178                                 "smbcli_open succeeded, should have "
1179                                "failed with NT_STATUS_DELETE_PENDING"
1180                                );
1181
1182                 torture_assert_ntstatus_equal(tctx, 
1183                                          smbcli_nt_error(cli1->tree),
1184                                      NT_STATUS_DELETE_PENDING, 
1185                                         "smbcli_open failed");
1186         }
1187
1188         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, false);
1189         torture_assert_ntstatus_ok(tctx, status, 
1190                                         "setting delete_on_close on file failed !");
1191                 
1192         {
1193                 char *fullname;
1194                 asprintf(&fullname, "\\%s%s", dname, fname);
1195                 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
1196                                     DENY_NONE);
1197                 torture_assert(tctx, fnum1 != -1, 
1198                                 talloc_asprintf(tctx, "smbcli_open failed: %s\n",
1199                                smbcli_errstr(cli1->tree)));
1200                 smbcli_close(cli1->tree, fnum1);
1201         }
1202
1203         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1204
1205         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_DIRECTORY_NOT_EMPTY,
1206                  "setting delete_on_close failed");
1207         smbcli_close(cli1->tree, dnum1);
1208
1209         return correct;
1210 }
1211
1212 /* Test 20a ... */
1213 static bool deltest20a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1214 {
1215         int fnum1 = -1;
1216         int fnum2 = -1;
1217         bool correct = true;
1218
1219         del_clean_area(cli1, cli2);
1220
1221         /* Test 20a. */
1222
1223         /* Ensure the file doesn't already exist. */
1224         smbcli_close(cli1->tree, fnum1);
1225         smbcli_close(cli1->tree, fnum2);
1226         smbcli_setatr(cli1->tree, fname, 0, 0);
1227         smbcli_unlink(cli1->tree, fname);
1228
1229         /* Firstly open and create with all access */
1230         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1231                                       SEC_RIGHTS_FILE_ALL,
1232                                       FILE_ATTRIBUTE_NORMAL,
1233                                       NTCREATEX_SHARE_ACCESS_READ|
1234                                       NTCREATEX_SHARE_ACCESS_WRITE|
1235                                       NTCREATEX_SHARE_ACCESS_DELETE,
1236                                       NTCREATEX_DISP_CREATE, 
1237                                       0, 0);
1238         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1239                        fname, smbcli_errstr(cli1->tree)));
1240
1241         /* Next open with all access, but add delete on close. */
1242         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
1243                                       SEC_RIGHTS_FILE_ALL,
1244                                       FILE_ATTRIBUTE_NORMAL,
1245                                       NTCREATEX_SHARE_ACCESS_READ|
1246                                       NTCREATEX_SHARE_ACCESS_WRITE|
1247                                       NTCREATEX_SHARE_ACCESS_DELETE,
1248                                       NTCREATEX_DISP_OPEN,
1249                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1250         
1251         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)", 
1252                        fname, smbcli_errstr(cli2->tree)));
1253
1254         /* The delete on close bit is *not* reported as being set. */
1255         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1256         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1257
1258         smbcli_close(cli1->tree, fnum1);
1259
1260         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1261
1262         smbcli_close(cli2->tree, fnum2);
1263
1264         /* See if the file is deleted - should be.... */
1265         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1266         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
1267                        fname, smbcli_errstr(cli1->tree)));
1268
1269         return correct;
1270 }
1271
1272 /* Test 20b ... */
1273 /* This is the delete semantics that the cifsfs client depends on when
1274  * trying to delete an open file on a Windows server. It
1275  * opens a file with initial delete on close set, renames it then closes
1276  * all open handles. The file goes away on Windows.
1277  */
1278
1279 static bool deltest20b(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1280 {
1281         int fnum1 = -1;
1282         int fnum2 = -1;
1283         bool correct = true;
1284
1285         del_clean_area(cli1, cli2);
1286
1287         /* Test 20b. */
1288
1289         /* Ensure the file doesn't already exist. */
1290         smbcli_close(cli1->tree, fnum1);
1291         smbcli_close(cli1->tree, fnum2);
1292         smbcli_setatr(cli1->tree, fname, 0, 0);
1293         smbcli_unlink(cli1->tree, fname);
1294         smbcli_setatr(cli1->tree, fname_new, 0, 0);
1295         smbcli_unlink(cli1->tree, fname_new);
1296
1297         /* Firstly open and create with all access */
1298         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1299                                       SEC_RIGHTS_FILE_ALL,
1300                                       FILE_ATTRIBUTE_NORMAL,
1301                                       NTCREATEX_SHARE_ACCESS_READ|
1302                                       NTCREATEX_SHARE_ACCESS_WRITE|
1303                                       NTCREATEX_SHARE_ACCESS_DELETE,
1304                                       NTCREATEX_DISP_CREATE, 
1305                                       0, 0);
1306         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1307                        fname, smbcli_errstr(cli1->tree)));
1308
1309         /* And close - just to create the file. */
1310         smbcli_close(cli1->tree, fnum1);
1311         
1312         /* Firstly open and create with all access */
1313         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1314                                       SEC_RIGHTS_FILE_ALL,
1315                                       FILE_ATTRIBUTE_NORMAL,
1316                                       NTCREATEX_SHARE_ACCESS_READ|
1317                                       NTCREATEX_SHARE_ACCESS_WRITE|
1318                                       NTCREATEX_SHARE_ACCESS_DELETE,
1319                                       NTCREATEX_DISP_OPEN, 
1320                                       0, 0);
1321         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open - 1 of %s failed (%s)", 
1322                        fname, smbcli_errstr(cli1->tree)));
1323
1324         /* Next open with all access, but add delete on close. */
1325         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
1326                                       SEC_RIGHTS_FILE_ALL,
1327                                       FILE_ATTRIBUTE_NORMAL,
1328                                       NTCREATEX_SHARE_ACCESS_READ|
1329                                       NTCREATEX_SHARE_ACCESS_WRITE|
1330                                       NTCREATEX_SHARE_ACCESS_DELETE,
1331                                       NTCREATEX_DISP_OPEN,
1332                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
1333         
1334         torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx, "open - 2 of %s failed (%s)", 
1335                        fname, smbcli_errstr(cli2->tree)));
1336
1337         /* The delete on close bit is *not* reported as being set. */
1338         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, false, __location__);
1339         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1340
1341         smbcli_close(cli1->tree, fnum1);
1342
1343         correct &= check_delete_on_close(tctx, cli2, fnum2, fname, false, __location__);
1344
1345         /* Rename the file by handle. */
1346
1347         {
1348                 union smb_setfileinfo sfinfo;
1349                 NTSTATUS status;
1350
1351                 memset(&sfinfo, '\0', sizeof(sfinfo));
1352                 sfinfo.generic.level = RAW_SFILEINFO_RENAME_INFORMATION;
1353                 sfinfo.generic.in.file.fnum = fnum2;
1354                 sfinfo.rename_information.in.root_fid  = 0;
1355                 /* Don't start the filename with '\\', we get NT_STATUS_NOT_SUPPORTED if so. */
1356                 sfinfo.rename_information.in.new_name  = fname_new + 1;
1357                 sfinfo.rename_information.in.overwrite = 1;
1358
1359                 status = smb_raw_setfileinfo(cli2->tree, &sfinfo);
1360
1361                 torture_assert_ntstatus_equal(tctx,status,NT_STATUS_OK,talloc_asprintf(tctx, "rename of %s to %s failed (%s)",
1362                         fname, fname_new, smbcli_errstr(cli2->tree)));
1363         }
1364
1365         correct &= check_delete_on_close(tctx, cli2, fnum2, fname_new, false, __location__);
1366
1367         smbcli_close(cli2->tree, fnum2);
1368
1369         /* See if the file is deleted - should be.... */
1370         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
1371         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
1372                        fname, smbcli_errstr(cli1->tree)));
1373         fnum1 = smbcli_open(cli1->tree, fname_new, O_RDWR, DENY_NONE);
1374         torture_assert(tctx, fnum1 == -1, talloc_asprintf(tctx, "open of %s succeeded (should fail) - %s", 
1375                        fname_new, smbcli_errstr(cli1->tree)));
1376
1377         return correct;
1378 }
1379
1380
1381 /* Test 21 ... */
1382 static bool deltest21(struct torture_context *tctx)
1383 {
1384         int fnum1 = -1;
1385         struct smbcli_state *cli1;
1386         struct smbcli_state *cli2;
1387         bool correct = true;
1388
1389         if (!torture_open_connection(&cli1, tctx, 0))
1390                 return false;
1391
1392         if (!torture_open_connection(&cli2, tctx, 1))
1393                 return false;
1394
1395         del_clean_area(cli1, cli2);
1396
1397         /* Test 21 -- Test removal of file after socket close. */
1398
1399         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1400                                       SEC_RIGHTS_FILE_ALL,
1401                                       FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, 
1402                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1403         
1404         torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open of %s failed (%s)", 
1405                        fname, smbcli_errstr(cli1->tree)));
1406         
1407         torture_assert_ntstatus_ok(tctx, 
1408                                 smbcli_nt_delete_on_close(cli1->tree, fnum1, true),
1409                                 talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
1410                        smbcli_errstr(cli1->tree)));
1411         
1412         /* Ensure delete on close is set. */
1413         correct &= check_delete_on_close(tctx, cli1, fnum1, fname, true, __location__);
1414
1415         /* Now yank the rug from under cli1. */
1416         smbcli_transport_dead(cli1->transport, NT_STATUS_LOCAL_DISCONNECT);
1417
1418         fnum1 = -1;
1419
1420         if (!torture_open_connection(&cli1, tctx, 0)) {
1421                 return false;
1422         }
1423
1424         /* On slow build farm machines it might happen that they are not fast
1425          * enogh to delete the file for this test */
1426         smb_msleep(200);
1427
1428         /* File should not be there. */
1429         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1430                                       SEC_RIGHTS_FILE_READ,
1431                                       FILE_ATTRIBUTE_NORMAL,
1432                                       NTCREATEX_SHARE_ACCESS_READ|
1433                                       NTCREATEX_SHARE_ACCESS_WRITE|
1434                                       NTCREATEX_SHARE_ACCESS_DELETE,
1435                                       NTCREATEX_DISP_OPEN,
1436                                       0, 0);
1437         
1438         CHECK_STATUS(cli1, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1439
1440         return correct;
1441 }
1442
1443 /* Test 22 ... */
1444
1445 /*
1446  * Test whether a second *directory* handle inhibits delete if the first has
1447  * del-on-close set and is closed
1448  */
1449 static bool deltest22(struct torture_context *tctx)
1450 {
1451         int dnum1 = -1;
1452         int dnum2 = -1;
1453         struct smbcli_state *cli1;
1454         bool correct = true;
1455
1456         if (!torture_open_connection(&cli1, tctx, 0))
1457                 return false;
1458
1459         smbcli_deltree(cli1->tree, dname);
1460
1461         torture_assert_ntstatus_ok(
1462                 tctx, smbcli_mkdir(cli1->tree, dname),
1463                 talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n",
1464                                 smbcli_errstr(cli1->tree)));
1465
1466         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1467                                       SEC_FILE_READ_DATA|
1468                                       SEC_FILE_WRITE_DATA|
1469                                       SEC_STD_DELETE,
1470                                       FILE_ATTRIBUTE_DIRECTORY, 
1471                                       NTCREATEX_SHARE_ACCESS_READ|
1472                                       NTCREATEX_SHARE_ACCESS_WRITE|
1473                                       NTCREATEX_SHARE_ACCESS_DELETE,
1474                                       NTCREATEX_DISP_OPEN, 
1475                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1476
1477         torture_assert(tctx, dnum1 != -1,
1478                        talloc_asprintf(tctx, "open of %s failed: %s!", 
1479                                        dname, smbcli_errstr(cli1->tree)));
1480
1481         dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1482                                       SEC_FILE_READ_DATA|
1483                                       SEC_FILE_WRITE_DATA,
1484                                       FILE_ATTRIBUTE_DIRECTORY, 
1485                                       NTCREATEX_SHARE_ACCESS_READ|
1486                                       NTCREATEX_SHARE_ACCESS_WRITE|
1487                                       NTCREATEX_SHARE_ACCESS_DELETE,
1488                                       NTCREATEX_DISP_OPEN, 
1489                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1490
1491         torture_assert(tctx, dnum2 != -1,
1492                        talloc_asprintf(tctx, "open of %s failed: %s!", 
1493                                        dname, smbcli_errstr(cli1->tree)));
1494
1495         torture_assert_ntstatus_ok(
1496                 tctx, smbcli_nt_delete_on_close(cli1->tree, dnum1, true), 
1497                 talloc_asprintf(tctx, "setting delete_on_close failed (%s)", 
1498                                 smbcli_errstr(cli1->tree)));
1499
1500         smbcli_close(cli1->tree, dnum1);
1501
1502         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1503                                       SEC_FILE_READ_DATA|
1504                                       SEC_FILE_WRITE_DATA|
1505                                       SEC_STD_DELETE,
1506                                       FILE_ATTRIBUTE_DIRECTORY, 
1507                                       NTCREATEX_SHARE_ACCESS_READ|
1508                                       NTCREATEX_SHARE_ACCESS_WRITE|
1509                                       NTCREATEX_SHARE_ACCESS_DELETE,
1510                                       NTCREATEX_DISP_OPEN, 
1511                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1512
1513         torture_assert(tctx, dnum1 == -1,
1514                        talloc_asprintf(tctx, "open of %s succeeded!\n",
1515                                        dname));
1516
1517         CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
1518
1519         smbcli_close(cli1->tree, dnum2);
1520         CHECK_STATUS(cli1, NT_STATUS_OK);
1521
1522         return correct;
1523 }
1524
1525 /* Test 23 - Second directory open fails when delete is pending. */
1526 static bool deltest23(struct torture_context *tctx,
1527                         struct smbcli_state *cli1,
1528                         struct smbcli_state *cli2)
1529 {
1530         int dnum1 = -1;
1531         int dnum2 = -1;
1532         bool correct = true;
1533
1534         del_clean_area(cli1, cli2);
1535
1536         /* Test 23 -- Basic delete on close for directories. */
1537
1538         /* Open a directory */
1539         dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
1540                                       SEC_FILE_READ_DATA|
1541                                       SEC_FILE_WRITE_DATA|
1542                                       SEC_STD_DELETE,
1543                                       FILE_ATTRIBUTE_DIRECTORY,
1544                                       NTCREATEX_SHARE_ACCESS_READ|
1545                                       NTCREATEX_SHARE_ACCESS_WRITE|
1546                                       NTCREATEX_SHARE_ACCESS_DELETE,
1547                                       NTCREATEX_DISP_CREATE,
1548                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1549
1550         torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx,
1551                            "open of %s failed: %s!",
1552                            dname, smbcli_errstr(cli1->tree)));
1553
1554         correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false,
1555             __location__);
1556
1557         /* Set delete on close */
1558         (void)smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
1559
1560         /* Attempt opening the directory again.  It should fail. */
1561         dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
1562                                       SEC_FILE_READ_DATA|
1563                                       SEC_FILE_WRITE_DATA|
1564                                       SEC_STD_DELETE,
1565                                       FILE_ATTRIBUTE_DIRECTORY,
1566                                       NTCREATEX_SHARE_ACCESS_READ|
1567                                       NTCREATEX_SHARE_ACCESS_WRITE|
1568                                       NTCREATEX_SHARE_ACCESS_DELETE,
1569                                       NTCREATEX_DISP_OPEN,
1570                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
1571
1572         torture_assert(tctx, dnum2 == -1, talloc_asprintf(tctx,
1573                            "open of %s succeeded: %s. It should have failed "
1574                            "with NT_STATUS_DELETE_PENDING",
1575                            dname, smbcli_errstr(cli1->tree)));
1576
1577         torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree),
1578             NT_STATUS_DELETE_PENDING, "smbcli_open failed");
1579
1580         return true;
1581 }
1582
1583 /*
1584   Test delete on close semantics.
1585  */
1586 struct torture_suite *torture_test_delete(void)
1587 {
1588         struct torture_suite *suite = torture_suite_create(
1589                 talloc_autofree_context(), "delete");
1590
1591         torture_suite_add_2smb_test(suite, "deltest1", deltest1);
1592         torture_suite_add_2smb_test(suite, "deltest2", deltest2);
1593         torture_suite_add_2smb_test(suite, "deltest3", deltest3);
1594         torture_suite_add_2smb_test(suite, "deltest4", deltest4);
1595         torture_suite_add_2smb_test(suite, "deltest5", deltest5);
1596         torture_suite_add_2smb_test(suite, "deltest6", deltest6);
1597         torture_suite_add_2smb_test(suite, "deltest7", deltest7);
1598         torture_suite_add_2smb_test(suite, "deltest8", deltest8);
1599         torture_suite_add_2smb_test(suite, "deltest9", deltest9);
1600         torture_suite_add_2smb_test(suite, "deltest10", deltest10);
1601         torture_suite_add_2smb_test(suite, "deltest11", deltest11);
1602         torture_suite_add_2smb_test(suite, "deltest12", deltest12);
1603         torture_suite_add_2smb_test(suite, "deltest13", deltest13);
1604         torture_suite_add_2smb_test(suite, "deltest14", deltest14);
1605         torture_suite_add_2smb_test(suite, "deltest15", deltest15);
1606         torture_suite_add_2smb_test(suite, "deltest16", deltest16);
1607         torture_suite_add_2smb_test(suite, "deltest17", deltest17);
1608         torture_suite_add_2smb_test(suite, "deltest18", deltest18);
1609         torture_suite_add_2smb_test(suite, "deltest19", deltest19);
1610         torture_suite_add_2smb_test(suite, "deltest20", deltest20);
1611         torture_suite_add_2smb_test(suite, "deltest20a", deltest20a);
1612         torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
1613         torture_suite_add_simple_test(suite, "deltest21", deltest21);
1614         torture_suite_add_simple_test(suite, "deltest22", deltest22);
1615         torture_suite_add_2smb_test(suite, "deltest23", deltest23);
1616
1617         return suite;
1618 }