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