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.
24 static struct timeval tp1,tp2;
26 void start_timer(void)
28 gettimeofday(&tp1,NULL);
31 double end_timer(void)
33 gettimeofday(&tp2,NULL);
34 return((tp2.tv_sec - tp1.tv_sec) +
35 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
40 create a directory, returning a handle to it
42 int create_directory_handle(struct cli_tree *tree, const char *dname)
48 mem_ctx = talloc_init("create_directory_handle");
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;
63 status = smb_raw_open(tree, mem_ctx, &io);
64 if (!NT_STATUS_IS_OK(status)) {
65 talloc_destroy(mem_ctx);
69 talloc_destroy(mem_ctx);
70 return io.ntcreatex.out.fnum;
74 sometimes we need a fairly complex file to work with, so we can test
75 all possible attributes.
77 int create_complex_file(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *fname)
81 union smb_setfileinfo setfile;
82 union smb_fileinfo fileinfo;
83 time_t t = (time(NULL) & ~1);
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,
94 if (fnum == -1) return -1;
96 cli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
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);
105 status = smb_raw_setfileinfo(cli->tree, &setfile);
106 if (!NT_STATUS_IS_OK(status)) {
107 printf("Failed to setup EAs\n");
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");
117 /* make sure all the timestamps aren't the same */
118 setfile.generic.level = RAW_SFILEINFO_SETATTRE;
119 setfile.generic.file.fnum = fnum;
121 setfile.setattre.in.create_time = t + 60;
122 setfile.setattre.in.access_time = t + 120;
123 setfile.setattre.in.write_time = t + 180;
125 status = smb_raw_setfileinfo(cli->tree, &setfile);
126 if (!NT_STATUS_IS_OK(status)) {
127 printf("Failed to setup file times - %s\n", nt_errstr(status));
130 /* make sure all the timestamps aren't the same */
131 fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
132 fileinfo.generic.in.fnum = fnum;
134 status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
135 if (!NT_STATUS_IS_OK(status)) {
136 printf("Failed to query file times - %s\n", nt_errstr(status));
139 if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
140 printf("create_time not setup correctly\n");
142 if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
143 printf("access_time not setup correctly\n");
145 if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
146 printf("write_time not setup correctly\n");
154 /* return a pointer to a anonymous shared memory segment of size "size"
155 which will persist across fork() but will disappear when all processes
158 The memory is not zeroed
160 This function uses system5 shared memory. It takes advantage of a property
161 that the memory is not destroyed if it is attached when the id is removed
163 void *shm_setup(int size)
168 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
170 printf("can't get shared memory\n");
173 ret = (void *)shmat(shmid, 0, 0);
174 if (!ret || ret == (void *)-1) {
175 printf("can't attach to shared memory\n");
178 /* the following releases the ipc, but note that this process
179 and all its children will still have access to the memory, its
180 just that the shmid is no longer valid for other shm calls. This
181 means we don't leave behind lots of shm segments after we exit
183 See Stevens "advanced programming in unix env" for details
185 shmctl(shmid, IPC_RMID, 0);
192 check that a wire string matches the flags specified
193 not 100% accurate, but close enough for testing
195 BOOL wire_bad_flags(WIRE_STRING *str, int flags)
198 if (!str || !str->s) return True;
199 len = strlen(str->s);
200 if (flags & STR_TERMINATE) len++;
201 if ((flags & STR_UNICODE) || !getenv("CLI_FORCE_ASCII")) {
203 } else if (flags & STR_TERMINATE_ASCII) {
206 if (str->private_length != len) {
207 printf("Expected wire_length %d but got %d for '%s'\n",
208 len, str->private_length, str->s);
215 return a talloced string representing a time_t for human consumption
217 const char *time_string(TALLOC_CTX *mem_ctx, time_t t)
219 return talloc_strdup(mem_ctx, http_timestring(mem_ctx, t));
223 check if 2 NTTIMEs are equal
225 BOOL nt_time_equal(NTTIME *t1, NTTIME *t2)
227 return t1->low == t2->low && t1->high == t2->high;
231 dump a all_info QFILEINFO structure
233 void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo)
235 d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.create_time));
236 d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.access_time));
237 d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.write_time));
238 d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.change_time));
239 d_printf("\tattrib: 0x%x\n", finfo->all_info.out.attrib);
240 d_printf("\talloc_size: %llu\n", (unsigned long long)finfo->all_info.out.alloc_size);
241 d_printf("\tsize: %llu\n", (unsigned long long)finfo->all_info.out.size);
242 d_printf("\tnlink: %u\n", finfo->all_info.out.nlink);
243 d_printf("\tdelete_pending: %u\n", finfo->all_info.out.delete_pending);
244 d_printf("\tdirectory: %u\n", finfo->all_info.out.directory);
245 d_printf("\tea_size: %u\n", finfo->all_info.out.ea_size);
246 d_printf("\tfname: '%s'\n", finfo->all_info.out.fname.s);
250 dump file infor by name
252 void torture_all_info(struct cli_tree *tree, const char *fname)
254 TALLOC_CTX *mem_ctx = talloc_init(fname);
255 union smb_fileinfo finfo;
258 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
259 finfo.generic.in.fname = fname;
260 status = smb_raw_pathinfo(tree, mem_ctx, &finfo);
261 if (!NT_STATUS_IS_OK(status)) {
262 d_printf("%s - %s\n", fname, nt_errstr(status));
266 d_printf("%s:\n", fname);
267 dump_all_info(mem_ctx, &finfo);
268 talloc_destroy(mem_ctx);
273 split a UNC name into server and share names
275 BOOL split_unc_name(const char *unc, char **server, char **share)
277 char *p = strdup(unc);
278 if (!p) return False;
279 all_string_sub(p, "\\", "/", 0);
280 if (strncmp(p, "//", 2) != 0) return False;
283 p = strchr(*server, '/');
284 if (!p) return False;
293 split a USER%PASS pair into username and password
295 BOOL split_username(const char *pair, char **user, char **pass)
297 char *p = strdup(pair);
298 if (!p) return False;
302 p = strchr(*user, '%');
303 if (!p) return False;
312 set a attribute on a file
314 BOOL torture_set_file_attribute(struct cli_tree *tree, const char *fname, uint16 attrib)
316 union smb_setfileinfo sfinfo;
319 sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
320 sfinfo.generic.file.fname = fname;
322 ZERO_STRUCT(sfinfo.basic_info.in);
323 sfinfo.basic_info.in.attrib = attrib;
324 status = smb_raw_setpathinfo(tree, &sfinfo);
325 return NT_STATUS_IS_OK(status);
330 set a file descriptor as sparse
332 NTSTATUS torture_set_sparse(struct cli_tree *tree, int fnum)
338 mem_ctx = talloc_init("torture_set_sparse");
340 return NT_STATUS_NO_MEMORY;
343 nt.ntioctl.level = RAW_IOCTL_NTIOCTL;
344 nt.ntioctl.in.function = 0x900c4;
345 nt.ntioctl.in.fnum = fnum;
346 nt.ntioctl.in.fsctl = True;
347 nt.ntioctl.in.filter = 0;
349 status = smb_raw_ioctl(tree, mem_ctx, &nt);
351 talloc_destroy(mem_ctx);