ctdb: Remove an unnecessary cast
[vlendec/samba-autobuild/.git] / source3 / torture / test_cleanup.c
1 /*
2    Unix SMB/CIFS implementation.
3    Test cleanup behaviour
4    Copyright (C) Volker Lendecke 2011
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "locking/proto.h"
22 #include "torture/proto.h"
23 #include "system/filesys.h"
24 #include "system/select.h"
25 #include "libsmb/libsmb.h"
26 #include "libcli/smb/smbXcli_base.h"
27 #include "libcli/security/security.h"
28 #include "librpc/gen_ndr/open_files.h"
29
30 bool run_cleanup1(int dummy)
31 {
32         struct cli_state *cli;
33         const char *fname = "\\cleanup1";
34         uint16_t fnum;
35         NTSTATUS status;
36
37         printf("CLEANUP1: Checking that a conflicting share mode is cleaned "
38                "up\n");
39
40         if (!torture_open_connection(&cli, 0)) {
41                 return false;
42         }
43         status = cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_ALL, &fnum);
44         if (!NT_STATUS_IS_OK(status)) {
45                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
46                 return false;
47         }
48         status = smbXcli_conn_samba_suicide(cli->conn, 1);
49         if (!NT_STATUS_IS_OK(status)) {
50                 printf("smbXcli_conn_samba_suicide failed: %s\n",
51                        nt_errstr(status));
52                 return false;
53         }
54
55         if (!torture_open_connection(&cli, 1)) {
56                 return false;
57         }
58         status = cli_ntcreate(
59                 cli, fname, 0,
60                 FILE_GENERIC_READ|FILE_GENERIC_WRITE|DELETE_ACCESS,
61                 FILE_ATTRIBUTE_NORMAL,
62                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
63                 FILE_OPEN, FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
64         if (!NT_STATUS_IS_OK(status)) {
65                 printf("2nd open of %s failed (%s)\n", fname,
66                        nt_errstr(status));
67                 return false;
68         }
69         cli_close(cli, fnum);
70
71         torture_close_connection(cli);
72         return NT_STATUS_IS_OK(status);
73 }
74
75 bool run_cleanup2(int dummy)
76 {
77         struct cli_state *cli1, *cli2, *cli3;
78         const char *fname = "\\cleanup2";
79         uint16_t fnum1, fnum2, fnum3;
80         NTSTATUS status;
81         char buf;
82
83         printf("CLEANUP2: Checking that a conflicting brlock is cleaned up\n");
84
85         if (!torture_open_connection(&cli1, 0)) {
86                 return false;
87         }
88         status = cli_ntcreate(
89                 cli1, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE,
90                 FILE_ATTRIBUTE_NORMAL,
91                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
92                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
93         if (!NT_STATUS_IS_OK(status)) {
94                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
95                 return false;
96         }
97         status = cli_lock32(cli1, fnum1, 0, 1, 0, WRITE_LOCK);
98         if (!NT_STATUS_IS_OK(status)) {
99                 printf("lock failed (%s)\n", nt_errstr(status));
100                 return false;
101         }
102
103         if (!torture_open_connection(&cli3, 1)) {
104                 return false;
105         }
106         status = cli_ntcreate(
107                 cli3, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE,
108                 FILE_ATTRIBUTE_NORMAL,
109                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
110                 FILE_OVERWRITE_IF, 0, 0, &fnum3, NULL);
111         if (!NT_STATUS_IS_OK(status)) {
112                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
113                 return false;
114         }
115         status = cli_lock32(cli3, fnum3, 1, 1, 0, WRITE_LOCK);
116         if (!NT_STATUS_IS_OK(status)) {
117                 printf("lock failed (%s)\n", nt_errstr(status));
118                 return false;
119         }
120
121         status = cli_lock32(cli1, fnum1, 2, 1, 0, WRITE_LOCK);
122         if (!NT_STATUS_IS_OK(status)) {
123                 printf("lock failed (%s)\n", nt_errstr(status));
124                 return false;
125         }
126
127         /*
128          * Check the file is indeed locked
129          */
130         if (!torture_open_connection(&cli2, 1)) {
131                 return false;
132         }
133         status = cli_ntcreate(
134                 cli2, fname, 0, FILE_GENERIC_READ|FILE_GENERIC_WRITE,
135                 FILE_ATTRIBUTE_NORMAL,
136                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
137                 FILE_OPEN, 0, 0, &fnum2, NULL);
138         if (!NT_STATUS_IS_OK(status)) {
139                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
140                 return false;
141         }
142         buf = 'x';
143         status = cli_smbwrite(cli2, fnum2, &buf, 0, 1, NULL);
144         if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
145                 printf("write succeeded\n");
146                 return false;
147         }
148
149         /*
150          * Kill the lock holder
151          */
152         status = smbXcli_conn_samba_suicide(cli1->conn, 1);
153         if (!NT_STATUS_IS_OK(status)) {
154                 printf("smbXcli_conn_samba_suicide failed: %s\n",
155                        nt_errstr(status));
156                 return false;
157         }
158
159         /*
160          * Give the suicidal smbd a bit of time to really pass away
161          */
162         smb_msleep(1000);
163
164         status = cli_smbwrite(cli2, fnum2, &buf, 0, 1, NULL);
165         if (!NT_STATUS_IS_OK(status)) {
166                 printf("write failed: %s\n", nt_errstr(status));
167                 return false;
168         }
169         return true;
170 }
171
172 bool run_cleanup4(int dummy)
173 {
174         struct cli_state *cli1, *cli2;
175         const char *fname = "\\cleanup4";
176         uint16_t fnum1, fnum2;
177         NTSTATUS status;
178
179         printf("CLEANUP4: Checking that a conflicting share mode is cleaned "
180                "up\n");
181
182         if (!torture_open_connection(&cli1, 0)) {
183                 return false;
184         }
185         if (!torture_open_connection(&cli2, 0)) {
186                 return false;
187         }
188
189         status = cli_ntcreate(
190                 cli1, fname, 0,
191                 FILE_GENERIC_READ|DELETE_ACCESS,
192                 FILE_ATTRIBUTE_NORMAL,
193                 FILE_SHARE_READ|FILE_SHARE_DELETE,
194                 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
195         if (!NT_STATUS_IS_OK(status)) {
196                 printf("creating file failed: %s\n",
197                        nt_errstr(status));
198                 return false;
199         }
200
201         status = cli_ntcreate(
202                 cli2, fname, 0,
203                 FILE_GENERIC_READ|DELETE_ACCESS,
204                 FILE_ATTRIBUTE_NORMAL,
205                 FILE_SHARE_READ|FILE_SHARE_DELETE,
206                 FILE_OPEN, 0, 0, &fnum2, NULL);
207         if (!NT_STATUS_IS_OK(status)) {
208                 printf("opening file 1st time failed: %s\n",
209                        nt_errstr(status));
210                 return false;
211         }
212
213         status = smbXcli_conn_samba_suicide(cli1->conn, 1);
214         if (!NT_STATUS_IS_OK(status)) {
215                 printf("smbXcli_conn_samba_suicide failed: %s\n",
216                        nt_errstr(status));
217                 return false;
218         }
219
220         /*
221          * The next open will conflict with both opens above. The first open
222          * above will be correctly cleaned up. A bug in smbd iterating over
223          * the share mode array made it skip the share conflict check for the
224          * second open. Trigger this bug.
225          */
226
227         status = cli_ntcreate(
228                 cli2, fname, 0,
229                 FILE_GENERIC_WRITE|DELETE_ACCESS,
230                 FILE_ATTRIBUTE_NORMAL,
231                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
232                 FILE_OPEN, 0, 0, &fnum2, NULL);
233         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
234                 printf("opening file 2nd time returned: %s\n",
235                        nt_errstr(status));
236                 return false;
237         }
238
239         return true;
240 }