r12154: Torture test for bug # 3303.
[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 "system/filesys.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26 #include "libcli/raw/libcliraw.h"
27
28 static BOOL check_delete_on_close(struct smbcli_state *cli, int fnum,
29                                   const char *fname, BOOL expect_it)
30 {
31         TALLOC_CTX *mem_ctx = talloc_init("single_search");
32         union smb_search_data data;
33         NTSTATUS status;
34
35         time_t c_time, a_time, m_time;
36         size_t size;
37         uint16_t mode;
38
39         BOOL res = True;
40
41         status = torture_single_search(cli, mem_ctx,
42                                        fname, RAW_SEARCH_FULL_DIRECTORY_INFO,
43                                        FILE_ATTRIBUTE_DIRECTORY,
44                                        &data);
45         if (!NT_STATUS_IS_OK(status)) {
46                 printf("(%s) single_search failed (%s)\n", 
47                        __location__, nt_errstr(status));
48                 res = False;
49                 goto done;
50         }
51
52         if (fnum != -1) {
53                 union smb_fileinfo io;
54                 int nlink = expect_it ? 0 : 1;
55
56                 io.all_info.level = RAW_FILEINFO_ALL_INFO;
57                 io.all_info.in.fnum = fnum;
58
59                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &io);
60                 if (!NT_STATUS_IS_OK(status)) {
61                         printf("(%s) qpathinfo failed (%s)\n", __location__,
62                                nt_errstr(status));
63                         res = False;
64                         goto done;
65                 }
66
67                 if (expect_it != io.all_info.out.delete_pending) {
68                         printf("Expected del_on_close flag %d, qfileinfo gave %d\n",
69                                expect_it, io.all_info.out.delete_pending);
70                         res = False;
71                         goto done;
72                 }
73
74                 if (nlink != io.all_info.out.nlink) {
75                         printf("Expected nlink %d, qfileinfo gave %d\n",
76                                nlink, io.all_info.out.nlink);
77                         res = False;
78                         goto done;
79                 }
80
81                 io.standard_info.level = RAW_FILEINFO_STANDARD_INFO;
82                 io.standard_info.in.fnum = fnum;
83
84                 status = smb_raw_fileinfo(cli->tree, mem_ctx, &io);
85                 if (!NT_STATUS_IS_OK(status)) {
86                         printf("(%s) qpathinfo failed (%s)\n", __location__,
87                                nt_errstr(status));
88                         res = False;
89                         goto done;
90                 }
91
92                 if (expect_it != io.standard_info.out.delete_pending) {
93                         printf("Expected del_on_close flag %d, qfileinfo gave %d\n",
94                                expect_it, io.standard_info.out.delete_pending);
95                         res = False;
96                         goto done;
97                 }
98
99                 if (nlink != io.standard_info.out.nlink) {
100                         printf("Expected nlink %d, qfileinfo gave %d\n",
101                                nlink, io.all_info.out.nlink);
102                         res = False;
103                         goto done;
104                 }
105
106         }
107
108         status = smbcli_qpathinfo(cli->tree, fname,
109                                   &c_time, &a_time, &m_time,
110                                   &size, &mode);
111
112         if (expect_it) {
113                 if (!NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
114                         printf("(%s) qpathinfo did not give correct error "
115                                "code (%s) -- NT_STATUS_DELETE_PENDING "
116                                "expected\n", __location__,
117                                nt_errstr(status));
118                         res = False;
119                         goto done;
120                 }
121         } else {
122                 if (!NT_STATUS_IS_OK(status)) {
123                         printf("(%s) qpathinfo failed (%s)\n", __location__,
124                                nt_errstr(status));
125                         res = False;
126                         goto done;
127                 }
128         }
129
130  done:
131         talloc_free(mem_ctx);
132         return res;
133 }
134
135 #define CHECK_STATUS(_cli, _expected) do { \
136         if (!NT_STATUS_EQUAL(_cli->tree->session->transport->error.e.nt_status, _expected)) { \
137                 printf("(%d) Incorrect status %s - should be %s\n", \
138                        __LINE__, nt_errstr(_cli->tree->session->transport->error.e.nt_status), nt_errstr(_expected)); \
139                 correct = False; \
140                 goto fail; \
141         }} while (0)
142
143 /*
144   Test delete on close semantics.
145  */
146 BOOL torture_test_delete(void)
147 {
148         struct smbcli_state *cli1;
149         struct smbcli_state *cli2 = NULL;
150         const char *fname = "\\delete.file";
151         const char *fname_new = "\\delete.new";
152         const char *dirname = "\\delete.dir";
153         int fnum1 = -1;
154         int fnum2 = -1;
155         int dnum1 = -1;
156         BOOL correct = True;
157         NTSTATUS status;
158         
159         printf("starting delete test\n");
160         
161         if (!torture_open_connection(&cli1)) {
162                 return False;
163         }
164
165         smbcli_deltree(cli1->tree, dirname);
166
167         /* Test 1 - this should delete the file on close. */
168         
169         smbcli_setatr(cli1->tree, fname, 0, 0);
170         smbcli_unlink(cli1->tree, fname);
171         
172         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
173                                       SEC_RIGHTS_FILE_ALL,
174                                       FILE_ATTRIBUTE_NORMAL,
175                                       NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 
176                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
177         
178         if (fnum1 == -1) {
179                 printf("(%s) open of %s failed (%s)\n", 
180                        __location__, fname, smbcli_errstr(cli1->tree));
181                 correct = False;
182                 goto fail;
183         }
184         
185         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
186                 printf("(%s) close failed (%s)\n", 
187                        __location__, smbcli_errstr(cli1->tree));
188                 correct = False;
189                 goto fail;
190         }
191
192         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
193         if (fnum1 != -1) {
194                 printf("(%s) open of %s succeeded (should fail)\n", 
195                        __location__, fname);
196                 correct = False;
197                 goto fail;
198         }
199         
200         printf("first delete on close test succeeded.\n");
201         
202         /* Test 2 - this should delete the file on close. */
203         
204         smbcli_setatr(cli1->tree, fname, 0, 0);
205         smbcli_unlink(cli1->tree, fname);
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                 correct = False;
216                 goto fail;
217         }
218         
219         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
220                 printf("(%s) setting delete_on_close failed (%s)\n", 
221                        __location__, smbcli_errstr(cli1->tree));
222                 correct = False;
223                 goto fail;
224         }
225         
226         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
227                 printf("(%s) close failed (%s)\n", 
228                        __location__, smbcli_errstr(cli1->tree));
229                 correct = False;
230                 goto fail;
231         }
232         
233         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
234         if (fnum1 != -1) {
235                 printf("(%s) open of %s succeeded should have been deleted on close !\n", 
236                        __location__, fname);
237                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
238                         printf("(%s) close failed (%s)\n", 
239                                __location__, smbcli_errstr(cli1->tree));
240                         correct = False;
241                         goto fail;
242                 }
243                 smbcli_unlink(cli1->tree, fname);
244         } else
245                 printf("second delete on close test succeeded.\n");
246         
247         /* Test 3 - ... */
248         smbcli_setatr(cli1->tree, fname, 0, 0);
249         smbcli_unlink(cli1->tree, fname);
250
251         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
252                                       SEC_RIGHTS_FILE_ALL,
253                                       FILE_ATTRIBUTE_NORMAL,
254                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
255                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
256
257         if (fnum1 == -1) {
258                 printf("(%s) open - 1 of %s failed (%s)\n", 
259                        __location__, fname, smbcli_errstr(cli1->tree));
260                 correct = False;
261                 goto fail;
262         }
263
264         /* This should fail with a sharing violation - open for delete is only compatible
265            with SHARE_DELETE. */
266
267         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
268                                       SEC_RIGHTS_FILE_READ, 
269                                       FILE_ATTRIBUTE_NORMAL,
270                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
271                                       NTCREATEX_DISP_OPEN, 0, 0);
272
273         if (fnum2 != -1) {
274                 printf("(%s) open  - 2 of %s succeeded - should have failed.\n", 
275                        __location__, fname);
276                 correct = False;
277                 goto fail;
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                 correct = False;
292                 goto fail;
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                 correct = False;
299                 goto fail;
300         }
301         
302         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
303                 printf("(%s) close 1 failed (%s)\n", 
304                        __location__, smbcli_errstr(cli1->tree));
305                 correct = False;
306                 goto fail;
307         }
308         
309         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
310                 printf("(%s) close 2 failed (%s)\n", 
311                        __location__, smbcli_errstr(cli1->tree));
312                 correct = False;
313                 goto fail;
314         }
315         
316         /* This should fail - file should no longer be there. */
317
318         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
319         if (fnum1 != -1) {
320                 printf("(%s) open of %s succeeded should have been deleted on close !\n", 
321                        __location__, fname);
322                 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
323                         printf("(%s) close failed (%s)\n", 
324                                __location__, smbcli_errstr(cli1->tree));
325                 }
326                 smbcli_unlink(cli1->tree, fname);
327                 correct = False;
328                 goto fail;
329         } else
330                 printf("third delete on close test succeeded.\n");
331
332         /* Test 4 ... */
333         smbcli_setatr(cli1->tree, fname, 0, 0);
334         status = smbcli_unlink(cli1->tree, fname);
335         if (NT_STATUS_IS_OK(status)) {
336                 printf("(%s) succeeded unlink of %s\n", __location__, fname);
337                 correct = False;
338                 goto fail;
339         }
340
341         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
342                                       SEC_FILE_READ_DATA  | 
343                                       SEC_FILE_WRITE_DATA |
344                                       SEC_STD_DELETE,
345                                       FILE_ATTRIBUTE_NORMAL, 
346                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, 
347                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
348                                                                 
349         if (fnum1 == -1) {
350                 printf("(%s) open of %s failed (%s)\n", 
351                        __location__, fname, smbcli_errstr(cli1->tree));
352                 correct = False;
353                 goto fail;
354         }
355
356         /* This should succeed. */
357         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
358                                       SEC_RIGHTS_FILE_READ,
359                                       FILE_ATTRIBUTE_NORMAL, 
360                                       NTCREATEX_SHARE_ACCESS_READ  | 
361                                       NTCREATEX_SHARE_ACCESS_WRITE |
362                                       NTCREATEX_SHARE_ACCESS_DELETE, 
363                                       NTCREATEX_DISP_OPEN, 0, 0);
364         if (fnum2 == -1) {
365                 printf("(%s) open  - 2 of %s failed (%s)\n", 
366                        __location__, fname, smbcli_errstr(cli1->tree));
367                 correct = False;
368                 goto fail;
369         }
370         
371         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
372                 printf("(%s) close - 1 failed (%s)\n", 
373                        __location__, smbcli_errstr(cli1->tree));
374                 correct = False;
375                 goto fail;
376         }
377         
378         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
379                 printf("(%s) setting delete_on_close failed (%s)\n", 
380                        __location__, smbcli_errstr(cli1->tree));
381                 correct = False;
382                 goto fail;
383         }
384         
385         /* This should fail - no more opens once delete on close set. */
386         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0, 
387                                       SEC_RIGHTS_FILE_READ,
388                                       FILE_ATTRIBUTE_NORMAL, 
389                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
390                                       NTCREATEX_DISP_OPEN, 0, 0);
391         if (fnum2 != -1) {
392                 printf("(%s) open  - 3 of %s succeeded ! Should have failed.\n",
393                        __location__, fname );
394                 correct = False;
395                 goto fail;
396         }
397         CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
398
399         printf("fourth delete on close test succeeded.\n");
400         
401         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
402                 printf("(%s) close - 2 failed (%s)\n", 
403                        __location__, smbcli_errstr(cli1->tree));
404                 correct = False;
405                 goto fail;
406         }
407         
408         /* Test 5 ... */
409         smbcli_setatr(cli1->tree, fname, 0, 0);
410         smbcli_unlink(cli1->tree, fname);
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                 correct = False;
417                 goto fail;
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                 correct = False;
426                 goto fail;
427         }
428
429         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
430                 printf("(%s) close - 2 failed (%s)\n", 
431                        __location__, smbcli_errstr(cli1->tree));
432                 correct = False;
433                 goto fail;
434         }
435         
436         printf("fifth delete on close test succeeded.\n");
437         
438         /* Test 6 ... */
439         smbcli_setatr(cli1->tree, fname, 0, 0);
440         smbcli_unlink(cli1->tree, fname);
441         
442         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
443                                    SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
444                                    FILE_ATTRIBUTE_NORMAL, 
445                                    NTCREATEX_SHARE_ACCESS_READ  |
446                                    NTCREATEX_SHARE_ACCESS_WRITE |
447                                    NTCREATEX_SHARE_ACCESS_DELETE,
448                                    NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
449         
450         if (fnum1 == -1) {
451                 printf("(%s) open of %s failed (%s)\n", 
452                        __location__, fname, smbcli_errstr(cli1->tree));
453                 correct = False;
454                 goto fail;
455         }
456         
457         /* This should fail - only allowed on NT opens with DELETE access. */
458         
459         if (NT_STATUS_IS_OK(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
460                 printf("(%s) setting delete_on_close on file with no delete access succeeded - should fail !\n",
461                        __location__);
462                 correct = False;
463                 goto fail;
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                 correct = False;
470                 goto fail;
471         }
472
473         printf("sixth delete on close test succeeded.\n");
474         
475         /* Test 7 ... */
476         smbcli_setatr(cli1->tree, fname, 0, 0);
477         smbcli_unlink(cli1->tree, fname);
478         
479         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
480                                       SEC_FILE_READ_DATA  | 
481                                       SEC_FILE_WRITE_DATA |
482                                       SEC_STD_DELETE,
483                                       FILE_ATTRIBUTE_NORMAL, 0, 
484                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
485                                                                 
486         if (fnum1 == -1) {
487                 printf("(%s) open of %s failed (%s)\n", 
488                        __location__, fname, smbcli_errstr(cli1->tree));
489                 correct = False;
490                 goto fail;
491         }
492
493         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
494                 printf("(%s) setting delete_on_close on file failed !\n",
495                        __location__);
496                 correct = False;
497                 goto fail;
498         }
499
500         correct &= check_delete_on_close(cli1, fnum1, fname, True);
501         
502         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, False))) {
503                 printf("(%s) unsetting delete_on_close on file failed !\n",
504                        __location__);
505                 correct = False;
506                 goto fail;
507         }
508
509         correct &= check_delete_on_close(cli1, fnum1, fname, False);
510         
511         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
512                 printf("(%s) close - 2 failed (%s)\n", 
513                        __location__, smbcli_errstr(cli1->tree));
514                 correct = False;
515                 goto fail;
516         }
517         
518         /* This next open should succeed - we reset the flag. */
519         
520         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
521         if (fnum1 == -1) {
522                 printf("(%s) open of %s failed (%s)\n", 
523                        __location__, fname, smbcli_errstr(cli1->tree));
524                 correct = False;
525                 goto fail;
526         }
527
528         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
529                 printf("(%s) close - 2 failed (%s)\n", 
530                        __location__, smbcli_errstr(cli1->tree));
531                 correct = False;
532                 goto fail;
533         }
534
535         printf("seventh delete on close test succeeded.\n");
536         
537         /* Test 7 ... */
538         smbcli_setatr(cli1->tree, fname, 0, 0);
539         smbcli_unlink(cli1->tree, fname);
540         
541         if (!torture_open_connection(&cli2)) {
542                 printf("(%s) failed to open second connection.\n",
543                        __location__);
544                 correct = False;
545                 goto fail;
546         }
547
548         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
549                                       SEC_FILE_READ_DATA|
550                                       SEC_FILE_WRITE_DATA|
551                                       SEC_STD_DELETE,
552                                       FILE_ATTRIBUTE_NORMAL, 
553                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
554                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
555         
556         if (fnum1 == -1) {
557                 printf("(%s) open of %s failed (%s)\n", 
558                        __location__, fname, smbcli_errstr(cli1->tree));
559                 correct = False;
560                 goto fail;
561         }
562
563         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
564                                       SEC_FILE_READ_DATA|
565                                       SEC_FILE_WRITE_DATA|
566                                       SEC_STD_DELETE,
567                                       FILE_ATTRIBUTE_NORMAL, 
568                                       NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE,
569                                       NTCREATEX_DISP_OPEN, 0, 0);
570         
571         if (fnum2 == -1) {
572                 printf("(%s) open of %s failed (%s)\n", 
573                        __location__, fname, smbcli_errstr(cli1->tree));
574                 correct = False;
575                 goto fail;
576         }
577
578         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1, True))) {
579                 printf("(%s) setting delete_on_close on file failed !\n",
580                        __location__);
581                 correct = False;
582                 goto fail;
583         }
584
585         correct &= check_delete_on_close(cli1, fnum1, fname, True);
586         correct &= check_delete_on_close(cli2, fnum2, fname, True);
587
588         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
589                 printf("(%s) close - 1 failed (%s)\n", 
590                        __location__, smbcli_errstr(cli1->tree));
591                 correct = False;
592                 goto fail;
593         }
594
595         correct &= check_delete_on_close(cli1, -1, fname, True);
596         correct &= check_delete_on_close(cli2, fnum2, fname, True);
597         
598         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
599                 printf("(%s) close - 2 failed (%s)\n", 
600                        __location__, smbcli_errstr(cli2->tree));
601                 correct = False;
602                 goto fail;
603         }
604
605         /* This should fail.. */
606         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
607         if (fnum1 != -1) {
608                 printf("(%s) open of %s succeeded should have been deleted on close !\n",
609                        __location__, fname);
610                 goto fail;
611                 correct = False;
612         } else
613                 printf("eighth delete on close test succeeded.\n");
614
615         /* This should fail - we need to set DELETE_ACCESS. */
616         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
617                                       SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA,
618                                       FILE_ATTRIBUTE_NORMAL, 
619                                       NTCREATEX_SHARE_ACCESS_NONE, 
620                                       NTCREATEX_DISP_OVERWRITE_IF, 
621                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
622         
623         if (fnum1 != -1) {
624                 printf("(%s) open of %s succeeded should have failed!\n", 
625                        __location__, fname);
626                 correct = False;
627                 goto fail;
628         }
629
630         printf("ninth delete on close test succeeded.\n");
631
632         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
633                                       SEC_FILE_READ_DATA|
634                                       SEC_FILE_WRITE_DATA|
635                                       SEC_STD_DELETE,
636                                       FILE_ATTRIBUTE_NORMAL, 
637                                       NTCREATEX_SHARE_ACCESS_NONE, 
638                                       NTCREATEX_DISP_OVERWRITE_IF, 
639                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
640         if (fnum1 == -1) {
641                 printf("(%s) open of %s failed (%s)\n", 
642                        __location__, fname, smbcli_errstr(cli1->tree));
643                 correct = False;
644                 goto fail;
645         }
646
647         /* This should delete the file. */
648         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
649                 printf("(%s) close failed (%s)\n", 
650                        __location__, smbcli_errstr(cli1->tree));
651                 correct = False;
652                 goto fail;
653         }
654
655         /* This should fail.. */
656         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
657         if (fnum1 != -1) {
658                 printf("(%s) open of %s succeeded should have been deleted on close !\n",
659                        __location__, fname);
660                 goto fail;
661                 correct = False;
662         } else
663                 printf("tenth delete on close test succeeded.\n");
664
665         /* test 11 - does having read only attribute still allow delete on close. */
666
667         smbcli_setatr(cli1->tree, fname, 0, 0);
668         smbcli_unlink(cli1->tree, fname);
669
670         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
671                                       SEC_RIGHTS_FILE_ALL,
672                                       FILE_ATTRIBUTE_READONLY, 
673                                       NTCREATEX_SHARE_ACCESS_NONE, 
674                                       NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
675         
676         if (fnum1 == -1) {
677                 printf("(%s) open of %s failed (%s)\n", 
678                        __location__, fname, smbcli_errstr(cli1->tree));
679                 correct = False;
680                 goto fail;
681         }
682
683         status = smbcli_nt_delete_on_close(cli1->tree, fnum1, True);
684
685         if (!NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
686                 printf("(%s) setting delete_on_close should fail with NT_STATUS_CANNOT_DELETE. Got %s instead)\n", 
687                        __location__, smbcli_errstr(cli1->tree));
688                 correct = False;
689                 goto fail;
690         }
691
692         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
693                 printf("(%s) close failed (%s)\n", 
694                        __location__, smbcli_errstr(cli1->tree));
695                 correct = False;
696                 goto fail;
697         }
698
699         smbcli_setatr(cli1->tree, fname, 0, 0);
700         smbcli_unlink(cli1->tree, fname);
701         printf("eleventh delete on close test succeeded.\n");
702
703         /* test 12 - does having read only attribute still allow delete on
704          * close at time of open. */
705
706         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
707                                       SEC_RIGHTS_FILE_ALL,
708                                       FILE_ATTRIBUTE_READONLY,
709                                       NTCREATEX_SHARE_ACCESS_DELETE,
710                                       NTCREATEX_DISP_OVERWRITE_IF, 
711                                       NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0);
712         
713         if (fnum1 != -1) {
714                 printf("(%s) open of %s succeeded. Should fail with "
715                        "NT_STATUS_CANNOT_DELETE.\n", __location__, fname);
716                 smbcli_close(cli1->tree, fnum1);
717                 correct = False;
718                 goto fail;
719         } else {
720                 status = smbcli_nt_error(cli1->tree);
721                 if (!NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
722                         printf("(%s) setting delete_on_close on open should "
723                                "fail with NT_STATUS_CANNOT_DELETE. Got %s "
724                                "instead)\n", 
725                                __location__, smbcli_errstr(cli1->tree));
726                         correct = False;
727                         goto fail;
728                 }
729         }
730         
731         printf("twelvth delete on close test succeeded.\n");
732
733         /* Test 13: Does resetting the delete on close flag affect a second
734          * fd? */
735
736         smbcli_setatr(cli1->tree, fname, 0, 0);
737         smbcli_unlink(cli1->tree, fname);
738         
739         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
740                                       SEC_FILE_READ_DATA|
741                                       SEC_FILE_WRITE_DATA|
742                                       SEC_STD_DELETE,
743                                       FILE_ATTRIBUTE_NORMAL, 
744                                       NTCREATEX_SHARE_ACCESS_READ|
745                                       NTCREATEX_SHARE_ACCESS_WRITE|
746                                       NTCREATEX_SHARE_ACCESS_DELETE,
747                                       NTCREATEX_DISP_OVERWRITE_IF,
748                                       0, 0);
749         
750         if (fnum1 == -1) {
751                 printf("(%s) open of %s failed (%s)\n", 
752                        __location__, fname, smbcli_errstr(cli1->tree));
753                 correct = False;
754                 goto fail;
755         }
756
757         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
758                                       SEC_FILE_READ_DATA|
759                                       SEC_FILE_WRITE_DATA|
760                                       SEC_STD_DELETE,
761                                       FILE_ATTRIBUTE_NORMAL, 
762                                       NTCREATEX_SHARE_ACCESS_READ|
763                                       NTCREATEX_SHARE_ACCESS_WRITE|
764                                       NTCREATEX_SHARE_ACCESS_DELETE,
765                                       NTCREATEX_DISP_OPEN, 0, 0);
766         
767         if (fnum2 == -1) {
768                 printf("(%s) open of %s failed (%s)\n", 
769                        __location__, fname, smbcli_errstr(cli2->tree));
770                 correct = False;
771                 goto fail;
772         }
773
774         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, fnum1,
775                                                        True))) {
776                 printf("(%s) setting delete_on_close on file failed !\n",
777                        __location__);
778                 correct = False;
779                 goto fail;
780         }
781
782         correct &= check_delete_on_close(cli1, fnum1, fname, True);
783         correct &= check_delete_on_close(cli2, fnum2, fname, True);
784
785         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli2->tree, fnum2,
786                                                        False))) {
787                 printf("(%s) setting delete_on_close on file failed !\n",
788                        __location__);
789                 correct = False;
790                 goto fail;
791         }
792
793         correct &= check_delete_on_close(cli1, fnum1, fname, False);
794         correct &= check_delete_on_close(cli2, fnum2, fname, False);
795         
796         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
797                 printf("(%s) close - 1 failed (%s)\n", 
798                        __location__, smbcli_errstr(cli1->tree));
799                 correct = False;
800                 goto fail;
801         }
802
803         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
804                 printf("(%s) close - 2 failed (%s)\n", 
805                        __location__, smbcli_errstr(cli2->tree));
806                 correct = False;
807                 goto fail;
808         }
809
810         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_NONE);
811
812         if (fnum1 == -1) {
813                 printf("(%s) open of %s failed!\n", 
814                        __location__, fname);
815                 correct = False;
816                 goto fail;
817         }
818
819         smbcli_close(cli1->tree, fnum1);
820         smbcli_unlink(cli1->tree, fname);
821
822         printf("thirteenth delete on close test succeeded.\n");
823
824         /* Test 14 -- directory */
825
826         dnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
827                                       SEC_FILE_READ_DATA|
828                                       SEC_FILE_WRITE_DATA|
829                                       SEC_STD_DELETE,
830                                       FILE_ATTRIBUTE_DIRECTORY, 
831                                       NTCREATEX_SHARE_ACCESS_READ|
832                                       NTCREATEX_SHARE_ACCESS_WRITE|
833                                       NTCREATEX_SHARE_ACCESS_DELETE,
834                                       NTCREATEX_DISP_CREATE, 0, 0);
835         if (dnum1 == -1) {
836                 printf("(%s) open of %s failed: %s!\n", 
837                        __location__, dirname, smbcli_errstr(cli1->tree));
838                 correct = False;
839                 goto fail;
840         }
841
842         check_delete_on_close(cli1, dnum1, dirname, False);
843         if (NT_STATUS_IS_ERR(smbcli_nt_delete_on_close(cli1->tree, dnum1, True))) {
844                 printf("(%s) setting delete_on_close on file failed !\n",
845                        __location__);
846                 correct = False;
847                 goto fail;
848         }
849         check_delete_on_close(cli1, dnum1, dirname, True);
850         smbcli_close(cli1->tree, dnum1);
851
852         /* Now it should be gone... */
853
854         dnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
855                                       SEC_FILE_READ_DATA|
856                                       SEC_FILE_WRITE_DATA|
857                                       SEC_STD_DELETE,
858                                       FILE_ATTRIBUTE_DIRECTORY, 
859                                       NTCREATEX_SHARE_ACCESS_READ|
860                                       NTCREATEX_SHARE_ACCESS_WRITE|
861                                       NTCREATEX_SHARE_ACCESS_DELETE,
862                                       NTCREATEX_DISP_OPEN, 0, 0);
863         if (dnum1 != -1) {
864                 printf("(%s) setting delete_on_close on file succeeded !\n",
865                        __location__);
866                 correct = False;
867                 goto fail;
868         }
869
870         printf("fourteenth delete on close test succeeded.\n");
871
872         /* Test 15 -- non-empty directory */
873
874         dnum1 = smbcli_nt_create_full(cli1->tree, dirname, 0,
875                                       SEC_FILE_READ_DATA|
876                                       SEC_FILE_WRITE_DATA|
877                                       SEC_STD_DELETE,
878                                       FILE_ATTRIBUTE_DIRECTORY, 
879                                       NTCREATEX_SHARE_ACCESS_READ|
880                                       NTCREATEX_SHARE_ACCESS_WRITE|
881                                       NTCREATEX_SHARE_ACCESS_DELETE,
882                                       NTCREATEX_DISP_CREATE, 
883                                       NTCREATEX_OPTIONS_DIRECTORY, 0);
884         if (dnum1 == -1) {
885                 printf("(%s) open of %s failed: %s!\n", 
886                        __location__, dirname, smbcli_errstr(cli1->tree));
887                 correct = False;
888                 goto fail;
889         }
890
891         check_delete_on_close(cli1, dnum1, dirname, False);
892         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
893
894         {
895                 char *fullname;
896                 asprintf(&fullname, "\\%s%s", dirname, fname);
897                 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
898                                     DENY_NONE);
899                 if (fnum1 != -1) {
900                         printf("(%s) smbcli_open succeeded, should have "
901                                "failed: %s\n",
902                                __location__, smbcli_errstr(cli1->tree));
903                         correct = False;
904                         goto fail;
905                 }
906
907                 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree),
908                                      NT_STATUS_DELETE_PENDING)) {
909                         printf("(%s) smbcli_open returned %s, expected "
910                                "NT_STATUS_DELETE_PENDING\n",
911                                __location__, smbcli_errstr(cli1->tree));
912                         correct = False;
913                         goto fail;
914                 }
915         }
916
917         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, False);
918         if (!NT_STATUS_IS_OK(status)) {
919                 printf("(%s) setting delete_on_close on file failed !\n",
920                        __location__);
921                 correct = False;
922                 goto fail;
923         }
924                 
925         {
926                 char *fullname;
927                 asprintf(&fullname, "\\%s%s", dirname, fname);
928                 fnum1 = smbcli_open(cli1->tree, fullname, O_CREAT|O_RDWR,
929                                     DENY_NONE);
930                 if (fnum1 == -1) {
931                         printf("(%s) smbcli_open failed: %s\n",
932                                __location__, smbcli_errstr(cli1->tree));
933                         correct = False;
934                         goto fail;
935                 }
936                 smbcli_close(cli1->tree, fnum1);
937         }
938
939         status = smbcli_nt_delete_on_close(cli1->tree, dnum1, True);
940
941         if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
942                 printf("(%s) setting delete_on_close returned %s, expected "
943                        "NT_STATUS_DIRECTORY_NOT_EMPTY\n", __location__,
944                        smbcli_errstr(cli1->tree));
945                 correct = False;
946                 goto fail;
947         }
948
949         smbcli_close(cli1->tree, dnum1);
950
951         /* Now it should be gone... */
952
953         printf("fifteenth delete on close test succeeded.\n");
954
955         /* Test 16: delete on close under rename */
956
957         smbcli_setatr(cli1->tree, fname, 0, 0);
958         smbcli_unlink(cli1->tree, fname);
959         smbcli_unlink(cli1->tree, fname_new);
960         
961         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
962                                       SEC_FILE_READ_DATA,
963                                       FILE_ATTRIBUTE_NORMAL, 
964                                       NTCREATEX_SHARE_ACCESS_READ|
965                                       NTCREATEX_SHARE_ACCESS_WRITE|
966                                       NTCREATEX_SHARE_ACCESS_DELETE,
967                                       NTCREATEX_DISP_OVERWRITE_IF,
968                                       0, 0);
969
970         if (fnum1 == -1) {
971                 printf("(%s) open - 1 of %s failed (%s)\n", 
972                        __location__, fname, smbcli_errstr(cli1->tree));
973                 correct = False;
974                 goto fail;
975         }
976
977         status = smbcli_rename(cli2->tree, fname, fname_new);
978
979         if (!NT_STATUS_IS_OK(status)) {
980                 printf("(%s) renaming failed: %s !\n",
981                        __location__, nt_errstr(status));
982                 correct = False;
983                 goto fail;
984         }
985
986         fnum2 = smbcli_nt_create_full(cli2->tree, fname_new, 0, 
987                                       SEC_GENERIC_ALL,
988                                       FILE_ATTRIBUTE_NORMAL, 
989                                       NTCREATEX_SHARE_ACCESS_READ|
990                                       NTCREATEX_SHARE_ACCESS_WRITE|
991                                       NTCREATEX_SHARE_ACCESS_DELETE,
992                                       NTCREATEX_DISP_OVERWRITE_IF,
993                                       0, 0);
994
995         if (fnum2 == -1) {
996                 printf("(%s) open - 1 of %s failed (%s)\n", 
997                        __location__, fname_new, smbcli_errstr(cli1->tree));
998                 correct = False;
999                 goto fail;
1000         }
1001
1002         status = smbcli_nt_delete_on_close(cli2->tree, fnum2, True);
1003
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 printf("(%s) setting delete_on_close on file failed !\n",
1006                        __location__);
1007                 correct = False;
1008                 goto fail;
1009         }
1010
1011         smbcli_close(cli2->tree, fnum2);
1012
1013         /* The file should be around under the new name, there's a second
1014          * handle open */
1015
1016         if (!check_delete_on_close(cli1, fnum1, fname_new, True)) {
1017                 printf("(%s) checking delete on close on file %s failed!\n",
1018                        __location__, fname_new);
1019                 correct = False;
1020                 goto fail;
1021         }
1022
1023         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, 
1024                                       SEC_GENERIC_ALL,
1025                                       FILE_ATTRIBUTE_NORMAL, 
1026                                       NTCREATEX_SHARE_ACCESS_READ|
1027                                       NTCREATEX_SHARE_ACCESS_WRITE|
1028                                       NTCREATEX_SHARE_ACCESS_DELETE,
1029                                       NTCREATEX_DISP_OVERWRITE_IF,
1030                                       0, 0);
1031
1032         if (fnum2 == -1) {
1033                 printf("(%s) open - 1 of %s failed (%s)\n", 
1034                        __location__, fname, smbcli_errstr(cli1->tree));
1035                 correct = False;
1036                 goto fail;
1037         }
1038
1039         smbcli_close(cli2->tree, fnum2);
1040         smbcli_close(cli1->tree, fnum1);
1041
1042         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, 
1043                                       SEC_FILE_READ_EA,
1044                                       FILE_ATTRIBUTE_NORMAL, 
1045                                       NTCREATEX_SHARE_ACCESS_READ|
1046                                       NTCREATEX_SHARE_ACCESS_WRITE|
1047                                       NTCREATEX_SHARE_ACCESS_DELETE,
1048                                       NTCREATEX_DISP_OPEN,
1049                                       0, 0);
1050
1051         if (fnum1 == -1) {
1052                 printf("(%s) open - 1 of %s failed (%s)\n", 
1053                        __location__, fname, smbcli_errstr(cli1->tree));
1054                 correct = False;
1055                 goto fail;
1056         }
1057
1058         smbcli_close(cli1->tree, fnum1);
1059
1060         fnum1 = smbcli_nt_create_full(cli1->tree, fname_new, 0, 
1061                                       SEC_FILE_READ_EA,
1062                                       FILE_ATTRIBUTE_NORMAL, 
1063                                       NTCREATEX_SHARE_ACCESS_READ|
1064                                       NTCREATEX_SHARE_ACCESS_WRITE|
1065                                       NTCREATEX_SHARE_ACCESS_DELETE,
1066                                       NTCREATEX_DISP_OPEN,
1067                                       0, 0);
1068
1069         if (fnum1 != -1) {
1070                 printf("(%s) smbcli_open succeeded, should have "
1071                        "failed\n", __location__);
1072                 smbcli_close(cli1->tree, fnum1);
1073                 correct = False;
1074                 goto fail;
1075         }
1076
1077         printf("sixteenth delete on close test succeeded.\n");
1078
1079         printf("finished delete test\n");
1080
1081   fail:
1082         /* FIXME: This will crash if we aborted before cli2 got
1083          * intialized, because these functions don't handle
1084          * uninitialized connections. */
1085                 
1086         smbcli_close(cli1->tree, fnum1);
1087         smbcli_close(cli1->tree, fnum2);
1088         smbcli_setatr(cli1->tree, fname, 0, 0);
1089         smbcli_unlink(cli1->tree, fname);
1090
1091         if (!torture_close_connection(cli1)) {
1092                 correct = False;
1093         }
1094         if (!torture_close_connection(cli2)) {
1095                 correct = False;
1096         }
1097         return correct;
1098 }
1099