2 Unix SMB/CIFS implementation.
3 SMB torture tester utility functions
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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.
22 #include "libcli/raw/libcliraw.h"
25 static struct timeval tp1,tp2;
27 void start_timer(void)
29 gettimeofday(&tp1,NULL);
32 double end_timer(void)
34 gettimeofday(&tp2,NULL);
35 return((tp2.tv_sec - tp1.tv_sec) +
36 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
41 create a directory, returning a handle to it
43 int create_directory_handle(struct smbcli_tree *tree, const char *dname)
49 mem_ctx = talloc_init("create_directory_handle");
51 io.generic.level = RAW_OPEN_NTCREATEX;
52 io.ntcreatex.in.root_fid = 0;
53 io.ntcreatex.in.flags = 0;
54 io.ntcreatex.in.access_mask = SA_RIGHT_FILE_ALL_ACCESS;
55 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
56 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
57 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
58 io.ntcreatex.in.alloc_size = 0;
59 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
60 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
61 io.ntcreatex.in.security_flags = 0;
62 io.ntcreatex.in.fname = dname;
64 status = smb_raw_open(tree, mem_ctx, &io);
65 if (!NT_STATUS_IS_OK(status)) {
66 talloc_destroy(mem_ctx);
70 talloc_destroy(mem_ctx);
71 return io.ntcreatex.out.fnum;
75 sometimes we need a fairly complex file to work with, so we can test
76 all possible attributes.
78 int create_complex_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *fname)
82 union smb_setfileinfo setfile;
83 union smb_fileinfo fileinfo;
84 time_t t = (time(NULL) & ~1);
87 smbcli_unlink(cli->tree, fname);
88 fnum = smbcli_nt_create_full(cli->tree, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
89 FILE_ATTRIBUTE_NORMAL,
90 NTCREATEX_SHARE_ACCESS_DELETE|
91 NTCREATEX_SHARE_ACCESS_READ|
92 NTCREATEX_SHARE_ACCESS_WRITE,
93 NTCREATEX_DISP_OVERWRITE_IF,
95 if (fnum == -1) return -1;
97 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
100 setfile.generic.level = RAW_SFILEINFO_EA_SET;
101 setfile.generic.file.fnum = fnum;
102 setfile.ea_set.in.ea.flags = 0;
103 setfile.ea_set.in.ea.name.s = "EAONE";
104 setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "VALUE1", 6);
106 status = smb_raw_setfileinfo(cli->tree, &setfile);
107 if (!NT_STATUS_IS_OK(status)) {
108 printf("Failed to setup EAs\n");
111 setfile.ea_set.in.ea.name.s = "SECONDEA";
112 setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
113 status = smb_raw_setfileinfo(cli->tree, &setfile);
114 if (!NT_STATUS_IS_OK(status)) {
115 printf("Failed to setup EAs\n");
118 /* make sure all the timestamps aren't the same, and are also
119 in different DST zones*/
120 setfile.generic.level = RAW_SFILEINFO_SETATTRE;
121 setfile.generic.file.fnum = fnum;
123 setfile.setattre.in.create_time = t + 9*30*24*60*60;
124 setfile.setattre.in.access_time = t + 6*30*24*60*60;
125 setfile.setattre.in.write_time = t + 3*30*24*60*60;
127 status = smb_raw_setfileinfo(cli->tree, &setfile);
128 if (!NT_STATUS_IS_OK(status)) {
129 printf("Failed to setup file times - %s\n", nt_errstr(status));
132 /* make sure all the timestamps aren't the same */
133 fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
134 fileinfo.generic.in.fnum = fnum;
136 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
137 if (!NT_STATUS_IS_OK(status)) {
138 printf("Failed to query file times - %s\n", nt_errstr(status));
141 if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
142 printf("create_time not setup correctly\n");
144 if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
145 printf("access_time not setup correctly\n");
147 if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
148 printf("write_time not setup correctly\n");
156 /* return a pointer to a anonymous shared memory segment of size "size"
157 which will persist across fork() but will disappear when all processes
160 The memory is not zeroed
162 This function uses system5 shared memory. It takes advantage of a property
163 that the memory is not destroyed if it is attached when the id is removed
165 void *shm_setup(int size)
170 /* NetBSD doesn't have these */
179 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
181 printf("can't get shared memory\n");
184 ret = (void *)shmat(shmid, 0, 0);
185 if (!ret || ret == (void *)-1) {
186 printf("can't attach to shared memory\n");
189 /* the following releases the ipc, but note that this process
190 and all its children will still have access to the memory, its
191 just that the shmid is no longer valid for other shm calls. This
192 means we don't leave behind lots of shm segments after we exit
194 See Stevens "advanced programming in unix env" for details
196 shmctl(shmid, IPC_RMID, 0);
203 check that a wire string matches the flags specified
204 not 100% accurate, but close enough for testing
206 BOOL wire_bad_flags(WIRE_STRING *str, int flags, struct smbcli_state *cli)
210 if (!str || !str->s) return True;
211 len = strlen(str->s);
212 if (flags & STR_TERMINATE) len++;
214 server_unicode = (cli->transport->negotiate.capabilities&CAP_UNICODE)?True:False;
215 if (getenv("CLI_FORCE_ASCII") || !lp_unicode()) {
216 server_unicode = False;
219 if ((flags & STR_UNICODE) || server_unicode) {
221 } else if (flags & STR_TERMINATE_ASCII) {
224 if (str->private_length != len) {
225 printf("Expected wire_length %d but got %d for '%s'\n",
226 len, str->private_length, str->s);
233 check if 2 NTTIMEs are equal
235 BOOL nt_time_equal(NTTIME *t1, NTTIME *t2)
241 dump a all_info QFILEINFO structure
243 void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo)
245 d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.create_time));
246 d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.access_time));
247 d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.write_time));
248 d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx, finfo->all_info.out.change_time));
249 d_printf("\tattrib: 0x%x\n", finfo->all_info.out.attrib);
250 d_printf("\talloc_size: %llu\n", (uint64_t)finfo->all_info.out.alloc_size);
251 d_printf("\tsize: %llu\n", (uint64_t)finfo->all_info.out.size);
252 d_printf("\tnlink: %u\n", finfo->all_info.out.nlink);
253 d_printf("\tdelete_pending: %u\n", finfo->all_info.out.delete_pending);
254 d_printf("\tdirectory: %u\n", finfo->all_info.out.directory);
255 d_printf("\tea_size: %u\n", finfo->all_info.out.ea_size);
256 d_printf("\tfname: '%s'\n", finfo->all_info.out.fname.s);
260 dump file infor by name
262 void torture_all_info(struct smbcli_tree *tree, const char *fname)
264 TALLOC_CTX *mem_ctx = talloc_init("%s", fname);
265 union smb_fileinfo finfo;
268 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
269 finfo.generic.in.fname = fname;
270 status = smb_raw_pathinfo(tree, mem_ctx, &finfo);
271 if (!NT_STATUS_IS_OK(status)) {
272 d_printf("%s - %s\n", fname, nt_errstr(status));
276 d_printf("%s:\n", fname);
277 dump_all_info(mem_ctx, &finfo);
278 talloc_destroy(mem_ctx);
283 split a UNC name into server and share names
285 BOOL split_unc_name(const char *unc, char **server, char **share)
287 char *p = strdup(unc);
288 if (!p) return False;
289 all_string_sub(p, "\\", "/", 0);
290 if (strncmp(p, "//", 2) != 0) return False;
293 p = strchr(*server, '/');
294 if (!p) return False;
303 split a USER%PASS pair into username and password
305 BOOL split_username(const char *pair, char **user, char **pass)
307 char *p = strdup(pair);
308 if (!p) return False;
312 p = strchr(*user, '%');
313 if (!p) return False;
322 set a attribute on a file
324 BOOL torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib)
326 union smb_setfileinfo sfinfo;
329 sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
330 sfinfo.generic.file.fname = fname;
332 ZERO_STRUCT(sfinfo.basic_info.in);
333 sfinfo.basic_info.in.attrib = attrib;
334 status = smb_raw_setpathinfo(tree, &sfinfo);
335 return NT_STATUS_IS_OK(status);
340 set a file descriptor as sparse
342 NTSTATUS torture_set_sparse(struct smbcli_tree *tree, int fnum)
348 mem_ctx = talloc_init("torture_set_sparse");
350 return NT_STATUS_NO_MEMORY;
353 nt.ntioctl.level = RAW_IOCTL_NTIOCTL;
354 nt.ntioctl.in.function = 0x900c4;
355 nt.ntioctl.in.fnum = fnum;
356 nt.ntioctl.in.fsctl = True;
357 nt.ntioctl.in.filter = 0;
359 status = smb_raw_ioctl(tree, mem_ctx, &nt);
361 talloc_destroy(mem_ctx);