Line data Source code
1 : #define NBDEBUG 0
2 :
3 : /*
4 : Unix SMB/CIFS implementation.
5 : SMB torture tester
6 : Copyright (C) Andrew Tridgell 1997-1998
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "torture/proto.h"
24 : #include "../libcli/security/security.h"
25 : #include "libsmb/libsmb.h"
26 : #include "libsmb/clirap.h"
27 :
28 : #define MAX_FILES 1000
29 :
30 : static char buf[70000];
31 : extern int line_count;
32 : extern int nbio_id;
33 : static int nprocs;
34 : static struct timeval nb_start;
35 :
36 : static struct {
37 : int fd;
38 : int handle;
39 : } ftable[MAX_FILES];
40 :
41 : static struct children {
42 : double bytes_in, bytes_out;
43 : int line;
44 : int done;
45 : } *children;
46 :
47 0 : double nbio_total(void)
48 : {
49 0 : int i;
50 0 : double total = 0;
51 0 : for (i=0;i<nprocs;i++) {
52 0 : total += children[i].bytes_out + children[i].bytes_in;
53 : }
54 0 : return total;
55 : }
56 :
57 0 : void nb_alarm(int ignore)
58 : {
59 0 : int i;
60 0 : int lines=0, num_clients=0;
61 0 : if (nbio_id != -1) return;
62 :
63 0 : for (i=0;i<nprocs;i++) {
64 0 : lines += children[i].line;
65 0 : if (!children[i].done) num_clients++;
66 : }
67 :
68 0 : printf("%4d %8d %.2f MB/sec\r",
69 : num_clients, lines/nprocs,
70 0 : 1.0e-6 * nbio_total() / timeval_elapsed(&nb_start));
71 :
72 0 : signal(SIGALRM, nb_alarm);
73 0 : alarm(1);
74 : }
75 :
76 0 : void nbio_shmem(int n)
77 : {
78 0 : nprocs = n;
79 0 : children = (struct children *)anonymous_shared_allocate(sizeof(*children) * nprocs);
80 0 : if (!children) {
81 0 : printf("Failed to setup shared memory!\n");
82 0 : exit(1);
83 : }
84 0 : }
85 :
86 : #if 0
87 : static int ne_find_handle(int handle)
88 : {
89 : int i;
90 : children[nbio_id].line = line_count;
91 : for (i=0;i<MAX_FILES;i++) {
92 : if (ftable[i].handle == handle) return i;
93 : }
94 : return -1;
95 : }
96 : #endif
97 :
98 0 : static int find_handle(int handle)
99 : {
100 0 : int i;
101 0 : children[nbio_id].line = line_count;
102 0 : for (i=0;i<MAX_FILES;i++) {
103 0 : if (ftable[i].handle == handle) return i;
104 : }
105 0 : printf("(%d) ERROR: handle %d was not found\n",
106 : line_count, handle);
107 0 : exit(1);
108 :
109 : return -1; /* Not reached */
110 : }
111 :
112 :
113 : static struct cli_state *c;
114 :
115 0 : static void sigsegv(int sig)
116 : {
117 0 : char line[200];
118 0 : printf("segv at line %d\n", line_count);
119 0 : slprintf(line, sizeof(line), "/usr/X11R6/bin/xterm -e gdb /proc/%d/exe %d",
120 0 : (int)getpid(), (int)getpid());
121 0 : if (system(line) == -1) {
122 0 : printf("system() failed\n");
123 : }
124 0 : exit(1);
125 : }
126 :
127 0 : void nb_setup(struct cli_state *cli)
128 : {
129 0 : signal(SIGSEGV, sigsegv);
130 0 : c = cli;
131 0 : nb_start = timeval_current();
132 0 : children[nbio_id].done = 0;
133 0 : }
134 :
135 :
136 0 : void nb_unlink(const char *fname)
137 : {
138 0 : NTSTATUS status;
139 :
140 0 : status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
141 0 : if (!NT_STATUS_IS_OK(status)) {
142 : #if NBDEBUG
143 : printf("(%d) unlink %s failed (%s)\n",
144 : line_count, fname, nt_errstr(status));
145 : #endif
146 0 : }
147 0 : }
148 :
149 :
150 0 : void nb_createx(const char *fname,
151 : unsigned create_options, unsigned create_disposition, int handle)
152 : {
153 0 : uint16_t fd = (uint16_t)-1;
154 0 : int i;
155 0 : NTSTATUS status;
156 0 : uint32_t desired_access;
157 :
158 0 : if (create_options & FILE_DIRECTORY_FILE) {
159 0 : desired_access = FILE_READ_DATA;
160 : } else {
161 0 : desired_access = FILE_READ_DATA | FILE_WRITE_DATA;
162 : }
163 :
164 0 : status = cli_ntcreate(c, fname, 0,
165 : desired_access,
166 : 0x0,
167 : FILE_SHARE_READ|FILE_SHARE_WRITE,
168 : create_disposition,
169 : create_options, 0, &fd, NULL);
170 0 : if (!NT_STATUS_IS_OK(status) && handle != -1) {
171 0 : printf("ERROR: cli_ntcreate failed for %s - %s\n",
172 : fname, nt_errstr(status));
173 0 : exit(1);
174 : }
175 0 : if (NT_STATUS_IS_OK(status) && handle == -1) {
176 0 : printf("ERROR: cli_ntcreate succeeded for %s\n", fname);
177 0 : exit(1);
178 : }
179 0 : if (fd == (uint16_t)-1) return;
180 :
181 0 : for (i=0;i<MAX_FILES;i++) {
182 0 : if (ftable[i].handle == 0) break;
183 : }
184 0 : if (i == MAX_FILES) {
185 0 : printf("(%d) file table full for %s\n", line_count,
186 : fname);
187 0 : exit(1);
188 : }
189 0 : ftable[i].handle = handle;
190 0 : ftable[i].fd = fd;
191 : }
192 :
193 0 : void nb_writex(int handle, int offset, int size, int ret_size)
194 : {
195 0 : int i;
196 0 : NTSTATUS status;
197 :
198 0 : if (buf[0] == 0) memset(buf, 1, sizeof(buf));
199 :
200 0 : i = find_handle(handle);
201 0 : status = cli_writeall(c, ftable[i].fd, 0, (uint8_t *)buf, offset, size,
202 : NULL);
203 0 : if (!NT_STATUS_IS_OK(status)) {
204 0 : printf("(%d) ERROR: write failed on handle %d, fd %d "
205 : "error %s\n", line_count, handle, ftable[i].fd,
206 : nt_errstr(status));
207 0 : exit(1);
208 : }
209 :
210 0 : children[nbio_id].bytes_out += ret_size;
211 0 : }
212 :
213 0 : void nb_readx(int handle, int offset, int size, int ret_size)
214 : {
215 0 : int i;
216 0 : NTSTATUS status;
217 0 : size_t nread;
218 :
219 0 : i = find_handle(handle);
220 0 : status = cli_read(c, ftable[i].fd, buf, offset, size, &nread);
221 0 : if (!NT_STATUS_IS_OK(status)) {
222 0 : printf("(%d) ERROR: read failed on handle %d ofs=%d size=%d "
223 : "fd %d nterror %s\n",
224 : line_count, handle, offset, size,
225 : ftable[i].fd, nt_errstr(status));
226 0 : exit(1);
227 0 : } else if (nread != ret_size) {
228 0 : printf("(%d) ERROR: read failed on handle %d ofs=%d size=%d "
229 : "nread=%lu ret_size=%d fd %d\n",
230 : line_count, handle, offset, size, (unsigned long)nread,
231 : ret_size, ftable[i].fd);
232 0 : exit(1);
233 : }
234 0 : children[nbio_id].bytes_in += ret_size;
235 0 : }
236 :
237 0 : void nb_close(int handle)
238 : {
239 0 : int i;
240 0 : i = find_handle(handle);
241 0 : if (!NT_STATUS_IS_OK(cli_close(c, ftable[i].fd))) {
242 0 : printf("(%d) close failed on handle %d\n", line_count, handle);
243 0 : exit(1);
244 : }
245 0 : ftable[i].handle = 0;
246 0 : }
247 :
248 0 : void nb_rmdir(const char *fname)
249 : {
250 0 : NTSTATUS status;
251 :
252 0 : status = cli_rmdir(c, fname);
253 0 : if (!NT_STATUS_IS_OK(status)) {
254 0 : printf("ERROR: rmdir %s failed (%s)\n",
255 : fname, nt_errstr(status));
256 0 : exit(1);
257 : }
258 0 : }
259 :
260 0 : void nb_rename(const char *oldname, const char *newname)
261 : {
262 0 : NTSTATUS status;
263 :
264 0 : status = cli_rename(c, oldname, newname, false);
265 0 : if (!NT_STATUS_IS_OK(status)) {
266 0 : printf("ERROR: rename %s %s failed (%s)\n",
267 : oldname, newname, nt_errstr(status));
268 0 : exit(1);
269 : }
270 0 : }
271 :
272 :
273 0 : void nb_qpathinfo(const char *fname)
274 : {
275 0 : cli_qpathinfo1(c, fname, NULL, NULL, NULL, NULL, NULL);
276 0 : }
277 :
278 0 : void nb_qfileinfo(int fnum)
279 : {
280 0 : int i;
281 0 : i = find_handle(fnum);
282 0 : cli_qfileinfo_basic(c, ftable[i].fd, NULL, NULL, NULL, NULL, NULL,
283 : NULL, NULL);
284 0 : }
285 :
286 0 : void nb_qfsinfo(int level)
287 : {
288 0 : uint64_t bsize, total, avail;
289 : /* this is not the right call - we need cli_qfsinfo() */
290 0 : cli_disk_size(c, "", &bsize, &total, &avail);
291 0 : }
292 :
293 0 : static NTSTATUS find_fn(struct file_info *finfo, const char *name,
294 : void *state)
295 : {
296 : /* noop */
297 0 : return NT_STATUS_OK;
298 : }
299 :
300 0 : void nb_findfirst(const char *mask)
301 : {
302 0 : cli_list(c, mask, 0, find_fn, NULL);
303 0 : }
304 :
305 0 : void nb_flush(int fnum)
306 : {
307 0 : int i;
308 0 : i = find_handle(fnum);
309 :
310 0 : cli_flush(NULL, c, i);
311 0 : }
312 :
313 : static int total_deleted;
314 :
315 0 : static NTSTATUS delete_fn(struct file_info *finfo,
316 : const char *name, void *state)
317 : {
318 0 : NTSTATUS status;
319 0 : char *s, *n;
320 0 : if (finfo->name[0] == '.') {
321 0 : return NT_STATUS_OK;
322 : }
323 :
324 0 : n = SMB_STRDUP(name);
325 0 : n[strlen(n)-1] = 0;
326 0 : if (asprintf(&s, "%s%s", n, finfo->name) == -1) {
327 0 : free(n);
328 0 : printf("asprintf failed\n");
329 0 : return NT_STATUS_NO_MEMORY;
330 : }
331 0 : if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
332 0 : char *s2;
333 0 : if (asprintf(&s2, "%s\\*", s) == -1) {
334 0 : printf("asprintf failed\n");
335 0 : free(s);
336 0 : free(n);
337 0 : return NT_STATUS_NO_MEMORY;
338 : }
339 0 : status = cli_list(c, s2, FILE_ATTRIBUTE_DIRECTORY, delete_fn, NULL);
340 0 : free(s2);
341 0 : if (!NT_STATUS_IS_OK(status)) {
342 0 : free(s);
343 0 : free(n);
344 0 : return status;
345 : }
346 0 : nb_rmdir(s);
347 : } else {
348 0 : total_deleted++;
349 0 : nb_unlink(s);
350 : }
351 0 : free(s);
352 0 : free(n);
353 0 : return NT_STATUS_OK;
354 : }
355 :
356 0 : void nb_deltree(const char *dname)
357 : {
358 0 : char *mask;
359 0 : if (asprintf(&mask, "%s\\*", dname) == -1) {
360 0 : printf("asprintf failed\n");
361 0 : return;
362 : }
363 :
364 0 : total_deleted = 0;
365 0 : cli_list(c, mask, FILE_ATTRIBUTE_DIRECTORY, delete_fn, NULL);
366 0 : free(mask);
367 0 : cli_rmdir(c, dname);
368 :
369 0 : if (total_deleted) printf("WARNING: Cleaned up %d files\n", total_deleted);
370 : }
371 :
372 :
373 0 : void nb_cleanup(void)
374 : {
375 0 : cli_rmdir(c, "clients");
376 0 : children[nbio_id].done = 1;
377 0 : }
|