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