c839100e7cbe1d364171dcfdd9b0f32de6e18731
[samba.git] / source4 / torture / raw / rename.c
1 /* 
2    Unix SMB/CIFS implementation.
3    rename test suite
4    Copyright (C) Andrew Tridgell 2003
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "librpc/gen_ndr/ndr_security.h"
23
24 #define CHECK_STATUS(status, correct) do { \
25         if (!NT_STATUS_EQUAL(status, correct)) { \
26                 printf("(%d) Incorrect status %s - should be %s\n", \
27                        __LINE__, nt_errstr(status), nt_errstr(correct)); \
28                 ret = False; \
29                 goto done; \
30         }} while (0)
31
32 #define CHECK_VALUE(v, correct) do { \
33         if ((v) != (correct)) { \
34                 printf("(%d) Incorrect %s %d - should be %d\n", \
35                        __LINE__, #v, (int)v, (int)correct); \
36                 ret = False; \
37         }} while (0)
38
39 #define BASEDIR "\\testrename"
40
41 /*
42   test SMBmv ops
43 */
44 static BOOL test_mv(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
45 {
46         union smb_rename io;
47         NTSTATUS status;
48         BOOL ret = True;
49         int fnum = -1;
50         const char *fname1 = BASEDIR "\\test1.txt";
51         const char *fname2 = BASEDIR "\\test2.txt";
52         union smb_open op;
53
54         printf("Testing SMBmv\n");
55
56         if (!torture_setup_dir(cli, BASEDIR)) {
57                 return False;
58         }
59
60         printf("Trying simple rename\n");
61
62         op.generic.level = RAW_OPEN_NTCREATEX;
63         op.ntcreatex.in.root_fid = 0;
64         op.ntcreatex.in.flags = 0;
65         op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
66         op.ntcreatex.in.create_options = 0;
67         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
68         op.ntcreatex.in.share_access = 
69                 NTCREATEX_SHARE_ACCESS_READ | 
70                 NTCREATEX_SHARE_ACCESS_WRITE;
71         op.ntcreatex.in.alloc_size = 0;
72         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
73         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
74         op.ntcreatex.in.security_flags = 0;
75         op.ntcreatex.in.fname = fname1;
76
77         status = smb_raw_open(cli->tree, mem_ctx, &op);
78         CHECK_STATUS(status, NT_STATUS_OK);
79         fnum = op.ntcreatex.out.fnum;
80
81         io.generic.level = RAW_RENAME_RENAME;
82         io.rename.in.pattern1 = fname1;
83         io.rename.in.pattern2 = fname2;
84         io.rename.in.attrib = 0;
85         
86         printf("trying rename while first file open\n");
87         status = smb_raw_rename(cli->tree, &io);
88         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
89
90         smbcli_close(cli->tree, fnum);
91
92         op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
93         op.ntcreatex.in.share_access = 
94                 NTCREATEX_SHARE_ACCESS_DELETE | 
95                 NTCREATEX_SHARE_ACCESS_READ |
96                 NTCREATEX_SHARE_ACCESS_WRITE;
97         status = smb_raw_open(cli->tree, mem_ctx, &op);
98         CHECK_STATUS(status, NT_STATUS_OK);
99         fnum = op.ntcreatex.out.fnum;
100
101         printf("trying rename while first file open with SHARE_ACCESS_DELETE\n");
102         status = smb_raw_rename(cli->tree, &io);
103         CHECK_STATUS(status, NT_STATUS_OK);
104
105         io.rename.in.pattern1 = fname2;
106         io.rename.in.pattern2 = fname1;
107         status = smb_raw_rename(cli->tree, &io);
108         CHECK_STATUS(status, NT_STATUS_OK);
109
110         io.rename.in.pattern1 = fname1;
111         io.rename.in.pattern2 = fname2;
112
113         printf("trying rename while not open\n");
114         smb_raw_exit(cli->session);
115         status = smb_raw_rename(cli->tree, &io);
116         CHECK_STATUS(status, NT_STATUS_OK);
117         
118         printf("Trying self rename\n");
119         io.rename.in.pattern1 = fname2;
120         io.rename.in.pattern2 = fname2;
121         status = smb_raw_rename(cli->tree, &io);
122         CHECK_STATUS(status, NT_STATUS_OK);
123
124         io.rename.in.pattern1 = fname1;
125         io.rename.in.pattern2 = fname1;
126         status = smb_raw_rename(cli->tree, &io);
127         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
128
129
130         printf("trying wildcard rename\n");
131         io.rename.in.pattern1 = BASEDIR "\\*.txt";
132         io.rename.in.pattern2 = fname1;
133         
134         status = smb_raw_rename(cli->tree, &io);
135         CHECK_STATUS(status, NT_STATUS_OK);
136
137         printf("and again\n");
138         status = smb_raw_rename(cli->tree, &io);
139         CHECK_STATUS(status, NT_STATUS_OK);
140
141         printf("Trying extension change\n");
142         io.rename.in.pattern1 = BASEDIR "\\*.txt";
143         io.rename.in.pattern2 = BASEDIR "\\*.bak";
144         status = smb_raw_rename(cli->tree, &io);
145         CHECK_STATUS(status, NT_STATUS_OK);
146
147         status = smb_raw_rename(cli->tree, &io);
148         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
149
150         printf("Checking attrib handling\n");
151         torture_set_file_attribute(cli->tree, BASEDIR "\\test1.bak", FILE_ATTRIBUTE_HIDDEN);
152         io.rename.in.pattern1 = BASEDIR "\\test1.bak";
153         io.rename.in.pattern2 = BASEDIR "\\*.txt";
154         io.rename.in.attrib = 0;
155         status = smb_raw_rename(cli->tree, &io);
156         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
157
158         io.rename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
159         status = smb_raw_rename(cli->tree, &io);
160         CHECK_STATUS(status, NT_STATUS_OK);
161
162 done:
163         smbcli_close(cli->tree, fnum);
164         smb_raw_exit(cli->session);
165         smbcli_deltree(cli->tree, BASEDIR);
166         return ret;
167 }
168
169
170
171 /*
172   test SMBntrename ops
173 */
174 static BOOL test_ntrename(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
175 {
176         union smb_rename io;
177         NTSTATUS status;
178         BOOL ret = True;
179         int fnum, i;
180         const char *fname1 = BASEDIR "\\test1.txt";
181         const char *fname2 = BASEDIR "\\test2.txt";
182         union smb_fileinfo finfo;
183
184         printf("Testing SMBntrename\n");
185
186         if (!torture_setup_dir(cli, BASEDIR)) {
187                 return False;
188         }
189
190         printf("Trying simple rename\n");
191
192         fnum = create_complex_file(cli, mem_ctx, fname1);
193         
194         io.generic.level = RAW_RENAME_NTRENAME;
195         io.ntrename.in.old_name = fname1;
196         io.ntrename.in.new_name = fname2;
197         io.ntrename.in.attrib = 0;
198         io.ntrename.in.cluster_size = 0;
199         io.ntrename.in.flags = RENAME_FLAG_RENAME;
200         
201         status = smb_raw_rename(cli->tree, &io);
202         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
203         
204         smb_raw_exit(cli->session);
205         status = smb_raw_rename(cli->tree, &io);
206         CHECK_STATUS(status, NT_STATUS_OK);
207
208         printf("Trying self rename\n");
209         io.ntrename.in.old_name = fname2;
210         io.ntrename.in.new_name = fname2;
211         status = smb_raw_rename(cli->tree, &io);
212         CHECK_STATUS(status, NT_STATUS_OK);
213
214         io.ntrename.in.old_name = fname1;
215         io.ntrename.in.new_name = fname1;
216         status = smb_raw_rename(cli->tree, &io);
217         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
218
219         printf("trying wildcard rename\n");
220         io.ntrename.in.old_name = BASEDIR "\\*.txt";
221         io.ntrename.in.new_name = fname1;
222         
223         status = smb_raw_rename(cli->tree, &io);
224         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
225
226         printf("Checking attrib handling\n");
227         torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN);
228         io.ntrename.in.old_name = fname2;
229         io.ntrename.in.new_name = fname1;
230         io.ntrename.in.attrib = 0;
231         status = smb_raw_rename(cli->tree, &io);
232         CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
233
234         io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
235         status = smb_raw_rename(cli->tree, &io);
236         CHECK_STATUS(status, NT_STATUS_OK);
237
238         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
239
240         printf("Checking hard link\n");
241         io.ntrename.in.old_name = fname1;
242         io.ntrename.in.new_name = fname2;
243         io.ntrename.in.attrib = 0;
244         io.ntrename.in.flags = RENAME_FLAG_HARD_LINK;
245         status = smb_raw_rename(cli->tree, &io);
246         CHECK_STATUS(status, NT_STATUS_OK);
247
248         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
249
250         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
251         finfo.generic.in.fname = fname2;
252         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
253         CHECK_STATUS(status, NT_STATUS_OK);
254         CHECK_VALUE(finfo.all_info.out.nlink, 2);
255         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
256
257         finfo.generic.in.fname = fname1;
258         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
259         CHECK_STATUS(status, NT_STATUS_OK);
260         CHECK_VALUE(finfo.all_info.out.nlink, 2);
261         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
262
263         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
264
265         smbcli_unlink(cli->tree, fname2);
266
267         finfo.generic.in.fname = fname1;
268         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
269         CHECK_STATUS(status, NT_STATUS_OK);
270         CHECK_VALUE(finfo.all_info.out.nlink, 1);
271
272         printf("Checking copy\n");
273         io.ntrename.in.old_name = fname1;
274         io.ntrename.in.new_name = fname2;
275         io.ntrename.in.attrib = 0;
276         io.ntrename.in.flags = RENAME_FLAG_COPY;
277         status = smb_raw_rename(cli->tree, &io);
278         CHECK_STATUS(status, NT_STATUS_OK);
279
280         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
281
282         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
283         finfo.generic.in.fname = fname2;
284         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
285         CHECK_STATUS(status, NT_STATUS_OK);
286         CHECK_VALUE(finfo.all_info.out.nlink, 1);
287         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
288
289         finfo.generic.in.fname = fname1;
290         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
291         CHECK_STATUS(status, NT_STATUS_OK);
292         CHECK_VALUE(finfo.all_info.out.nlink, 1);
293         CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
294
295         torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
296
297         smbcli_unlink(cli->tree, fname2);
298
299         finfo.generic.in.fname = fname1;
300         status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
301         CHECK_STATUS(status, NT_STATUS_OK);
302         CHECK_VALUE(finfo.all_info.out.nlink, 1);
303
304         printf("Checking invalid flags\n");
305         io.ntrename.in.old_name = fname1;
306         io.ntrename.in.new_name = fname2;
307         io.ntrename.in.attrib = 0;
308         io.ntrename.in.flags = 0;
309         status = smb_raw_rename(cli->tree, &io);
310         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
311
312         io.ntrename.in.flags = 300;
313         status = smb_raw_rename(cli->tree, &io);
314         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
315
316         io.ntrename.in.flags = 0x106;
317         status = smb_raw_rename(cli->tree, &io);
318         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
319
320         printf("Checking unknown field\n");
321         io.ntrename.in.old_name = fname1;
322         io.ntrename.in.new_name = fname2;
323         io.ntrename.in.attrib = 0;
324         io.ntrename.in.flags = RENAME_FLAG_RENAME;
325         io.ntrename.in.cluster_size = 0xff;
326         status = smb_raw_rename(cli->tree, &io);
327         CHECK_STATUS(status, NT_STATUS_OK);
328
329         printf("Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n");
330
331         io.ntrename.in.old_name = fname2;
332         io.ntrename.in.new_name = fname1;
333         io.ntrename.in.attrib = 0;
334         io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
335         io.ntrename.in.cluster_size = 1;
336         status = smb_raw_rename(cli->tree, &io);
337         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
338
339         io.ntrename.in.flags = RENAME_FLAG_COPY;
340         status = smb_raw_rename(cli->tree, &io);
341         CHECK_STATUS(status, NT_STATUS_OK);
342
343 #if 0
344         {
345                 char buf[16384];
346                 fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE);
347                 memset(buf, 1, sizeof(buf));
348                 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
349                 smbcli_close(cli->tree, fnum);
350
351                 fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE);
352                 memset(buf, 1, sizeof(buf));
353                 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1);
354                 smbcli_close(cli->tree, fnum);
355
356                 torture_all_info(cli->tree, fname1);
357                 torture_all_info(cli->tree, fname2);
358         }
359         
360
361         io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
362         status = smb_raw_rename(cli->tree, &io);
363         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
364
365         for (i=0;i<20000;i++) {
366                 io.ntrename.in.cluster_size = i;
367                 status = smb_raw_rename(cli->tree, &io);
368                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
369                         printf("i=%d status=%s\n", i, nt_errstr(status));
370                 }
371         }
372 #endif
373
374         printf("Checking other flags\n");
375
376         for (i=0;i<0xFFF;i++) {
377                 if (i == RENAME_FLAG_RENAME ||
378                     i == RENAME_FLAG_HARD_LINK ||
379                     i == RENAME_FLAG_COPY) {
380                         continue;
381                 }
382
383                 io.ntrename.in.old_name = fname2;
384                 io.ntrename.in.new_name = fname1;
385                 io.ntrename.in.flags = i;
386                 io.ntrename.in.attrib = 0;
387                 io.ntrename.in.cluster_size = 0;
388                 status = smb_raw_rename(cli->tree, &io);
389                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
390                         printf("flags=0x%x status=%s\n", i, nt_errstr(status));
391                 }
392         }
393         
394 done:
395         smb_raw_exit(cli->session);
396         smbcli_deltree(cli->tree, BASEDIR);
397         return ret;
398 }
399
400
401 /* 
402    basic testing of rename calls
403 */
404 BOOL torture_raw_rename(void)
405 {
406         struct smbcli_state *cli;
407         BOOL ret = True;
408         TALLOC_CTX *mem_ctx;
409
410         if (!torture_open_connection(&cli)) {
411                 return False;
412         }
413
414         mem_ctx = talloc_init("torture_raw_rename");
415
416         if (!test_mv(cli, mem_ctx)) {
417                 ret = False;
418         }
419
420         if (!test_ntrename(cli, mem_ctx)) {
421                 ret = False;
422         }
423
424         torture_close_connection(cli);
425         talloc_destroy(mem_ctx);
426         return ret;
427 }