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