r873: converted samba4 to use real 64 bit integers instead of
[kamenim/samba.git] / source4 / torture / torture_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester utility functions
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
23
24 static struct timeval tp1,tp2;
25
26 void start_timer(void)
27 {
28         gettimeofday(&tp1,NULL);
29 }
30
31 double end_timer(void)
32 {
33         gettimeofday(&tp2,NULL);
34         return((tp2.tv_sec - tp1.tv_sec) + 
35                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
36 }
37
38
39 /*
40   create a directory, returning a handle to it
41 */
42 int create_directory_handle(struct cli_tree *tree, const char *dname)
43 {
44         NTSTATUS status;
45         union smb_open io;
46         TALLOC_CTX *mem_ctx;
47
48         mem_ctx = talloc_init("create_directory_handle");
49
50         io.generic.level = RAW_OPEN_NTCREATEX;
51         io.ntcreatex.in.root_fid = 0;
52         io.ntcreatex.in.flags = 0;
53         io.ntcreatex.in.access_mask = SA_RIGHT_FILE_ALL_ACCESS;
54         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
55         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
56         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
57         io.ntcreatex.in.alloc_size = 0;
58         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
59         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
60         io.ntcreatex.in.security_flags = 0;
61         io.ntcreatex.in.fname = dname;
62
63         status = smb_raw_open(tree, mem_ctx, &io);
64         if (!NT_STATUS_IS_OK(status)) {
65                 talloc_destroy(mem_ctx);
66                 return -1;
67         }
68
69         talloc_destroy(mem_ctx);
70         return io.ntcreatex.out.fnum;
71 }
72
73 /*
74   sometimes we need a fairly complex file to work with, so we can test
75   all possible attributes. 
76 */
77 int create_complex_file(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *fname)
78 {
79         int fnum;
80         char buf[7] = "abc";
81         union smb_setfileinfo setfile;
82         union smb_fileinfo fileinfo;
83         time_t t = (time(NULL) & ~1);
84         NTSTATUS status;
85
86         cli_unlink(cli->tree, fname);
87         fnum = cli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
88                                   FILE_ATTRIBUTE_NORMAL,
89                                   NTCREATEX_SHARE_ACCESS_DELETE|
90                                   NTCREATEX_SHARE_ACCESS_READ|
91                                   NTCREATEX_SHARE_ACCESS_WRITE, 
92                                   NTCREATEX_DISP_OVERWRITE_IF,
93                                   0, 0);
94         if (fnum == -1) return -1;
95
96         cli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
97
98         /* setup some EAs */
99         setfile.generic.level = RAW_SFILEINFO_EA_SET;
100         setfile.generic.file.fnum = fnum;
101         setfile.ea_set.in.ea.flags = 0;
102         setfile.ea_set.in.ea.name.s = "EAONE";
103         setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "VALUE1", 6);
104
105         status = smb_raw_setfileinfo(cli->tree, &setfile);
106         if (!NT_STATUS_IS_OK(status)) {
107                 printf("Failed to setup EAs\n");
108         }
109
110         setfile.ea_set.in.ea.name.s = "SECONDEA";
111         setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
112         status = smb_raw_setfileinfo(cli->tree, &setfile);
113         if (!NT_STATUS_IS_OK(status)) {
114                 printf("Failed to setup EAs\n");
115         }
116
117         /* make sure all the timestamps aren't the same, and are also 
118            in different DST zones*/
119         setfile.generic.level = RAW_SFILEINFO_SETATTRE;
120         setfile.generic.file.fnum = fnum;
121
122         setfile.setattre.in.create_time = t + 9*30*24*60*60;
123         setfile.setattre.in.access_time = t + 6*30*24*60*60;
124         setfile.setattre.in.write_time  = t + 3*30*24*60*60;
125
126         status = smb_raw_setfileinfo(cli->tree, &setfile);
127         if (!NT_STATUS_IS_OK(status)) {
128                 printf("Failed to setup file times - %s\n", nt_errstr(status));
129         }
130
131         /* make sure all the timestamps aren't the same */
132         fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
133         fileinfo.generic.in.fnum = fnum;
134
135         status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
136         if (!NT_STATUS_IS_OK(status)) {
137                 printf("Failed to query file times - %s\n", nt_errstr(status));
138         }
139
140         if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
141                 printf("create_time not setup correctly\n");
142         }
143         if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
144                 printf("access_time not setup correctly\n");
145         }
146         if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
147                 printf("write_time not setup correctly\n");
148         }
149
150         return fnum;
151 }
152
153
154
155 /* return a pointer to a anonymous shared memory segment of size "size"
156    which will persist across fork() but will disappear when all processes
157    exit 
158
159    The memory is not zeroed 
160
161    This function uses system5 shared memory. It takes advantage of a property
162    that the memory is not destroyed if it is attached when the id is removed
163    */
164 void *shm_setup(int size)
165 {
166         int shmid;
167         void *ret;
168
169         shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
170         if (shmid == -1) {
171                 printf("can't get shared memory\n");
172                 exit(1);
173         }
174         ret = (void *)shmat(shmid, 0, 0);
175         if (!ret || ret == (void *)-1) {
176                 printf("can't attach to shared memory\n");
177                 return NULL;
178         }
179         /* the following releases the ipc, but note that this process
180            and all its children will still have access to the memory, its
181            just that the shmid is no longer valid for other shm calls. This
182            means we don't leave behind lots of shm segments after we exit 
183
184            See Stevens "advanced programming in unix env" for details
185            */
186         shmctl(shmid, IPC_RMID, 0);
187         
188         return ret;
189 }
190
191
192 /*
193   check that a wire string matches the flags specified 
194   not 100% accurate, but close enough for testing
195 */
196 BOOL wire_bad_flags(WIRE_STRING *str, int flags)
197 {
198         int len;
199         if (!str || !str->s) return True;
200         len = strlen(str->s);
201         if (flags & STR_TERMINATE) len++;
202         if ((flags & STR_UNICODE) || !getenv("CLI_FORCE_ASCII")) {
203                 len *= 2;
204         } else if (flags & STR_TERMINATE_ASCII) {
205                 len++;
206         }
207         if (str->private_length != len) {
208                 printf("Expected wire_length %d but got %d for '%s'\n", 
209                        len, str->private_length, str->s);
210                 return True;
211         }
212         return False;
213 }
214
215 /*
216   check if 2 NTTIMEs are equal
217 */
218 BOOL nt_time_equal(NTTIME *t1, NTTIME *t2)
219 {
220         return *t1 == *t2;
221 }
222
223 /*
224   dump a all_info QFILEINFO structure
225 */
226 void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo)
227 {
228         d_printf("\tcreate_time:    %s\n", nt_time_string(mem_ctx, finfo->all_info.out.create_time));
229         d_printf("\taccess_time:    %s\n", nt_time_string(mem_ctx, finfo->all_info.out.access_time));
230         d_printf("\twrite_time:     %s\n", nt_time_string(mem_ctx, finfo->all_info.out.write_time));
231         d_printf("\tchange_time:    %s\n", nt_time_string(mem_ctx, finfo->all_info.out.change_time));
232         d_printf("\tattrib:         0x%x\n", finfo->all_info.out.attrib);
233         d_printf("\talloc_size:     %llu\n", (unsigned long long)finfo->all_info.out.alloc_size);
234         d_printf("\tsize:           %llu\n", (unsigned long long)finfo->all_info.out.size);
235         d_printf("\tnlink:          %u\n", finfo->all_info.out.nlink);
236         d_printf("\tdelete_pending: %u\n", finfo->all_info.out.delete_pending);
237         d_printf("\tdirectory:      %u\n", finfo->all_info.out.directory);
238         d_printf("\tea_size:        %u\n", finfo->all_info.out.ea_size);
239         d_printf("\tfname:          '%s'\n", finfo->all_info.out.fname.s);
240 }
241
242 /*
243   dump file infor by name
244 */
245 void torture_all_info(struct cli_tree *tree, const char *fname)
246 {
247         TALLOC_CTX *mem_ctx = talloc_init(fname);
248         union smb_fileinfo finfo;
249         NTSTATUS status;
250
251         finfo.generic.level = RAW_FILEINFO_ALL_INFO;
252         finfo.generic.in.fname = fname;
253         status = smb_raw_pathinfo(tree, mem_ctx, &finfo);
254         if (!NT_STATUS_IS_OK(status)) {
255                 d_printf("%s - %s\n", fname, nt_errstr(status));
256                 return;
257         }
258
259         d_printf("%s:\n", fname);
260         dump_all_info(mem_ctx, &finfo);
261         talloc_destroy(mem_ctx);
262 }
263
264
265 /*
266   split a UNC name into server and share names
267 */
268 BOOL split_unc_name(const char *unc, char **server, char **share)
269 {
270         char *p = strdup(unc);
271         if (!p) return False;
272         all_string_sub(p, "\\", "/", 0);
273         if (strncmp(p, "//", 2) != 0) return False;
274
275         (*server) = p+2;
276         p = strchr(*server, '/');
277         if (!p) return False;
278
279         *p = 0;
280         (*share) = p+1;
281         
282         return True;
283 }
284
285 /*
286   split a USER%PASS pair into username and password
287 */
288 BOOL split_username(const char *pair, char **user, char **pass)
289 {
290         char *p = strdup(pair);
291         if (!p) return False;
292
293         (*user) = p;
294
295         p = strchr(*user, '%');
296         if (!p) return False;
297
298         *p = 0;
299         (*pass) = p+1;
300         
301         return True;
302 }
303
304 /*
305   set a attribute on a file
306 */
307 BOOL torture_set_file_attribute(struct cli_tree *tree, const char *fname, uint16 attrib)
308 {
309         union smb_setfileinfo sfinfo;
310         NTSTATUS status;
311
312         sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
313         sfinfo.generic.file.fname = fname;
314
315         ZERO_STRUCT(sfinfo.basic_info.in);
316         sfinfo.basic_info.in.attrib = attrib;
317         status = smb_raw_setpathinfo(tree, &sfinfo);
318         return NT_STATUS_IS_OK(status);
319 }
320
321
322 /*
323   set a file descriptor as sparse
324 */
325 NTSTATUS torture_set_sparse(struct cli_tree *tree, int fnum)
326 {
327         union smb_ioctl nt;
328         NTSTATUS status;
329         TALLOC_CTX *mem_ctx;
330
331         mem_ctx = talloc_init("torture_set_sparse");
332         if (!mem_ctx) {
333                 return NT_STATUS_NO_MEMORY;
334         }
335
336         nt.ntioctl.level = RAW_IOCTL_NTIOCTL;
337         nt.ntioctl.in.function = 0x900c4;
338         nt.ntioctl.in.fnum = fnum;
339         nt.ntioctl.in.fsctl = True;
340         nt.ntioctl.in.filter = 0;
341
342         status = smb_raw_ioctl(tree, mem_ctx, &nt);
343
344         talloc_destroy(mem_ctx);
345
346         return status;
347 }