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 2 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, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#define NO_SYSLOG
24
25#include "includes.h"
26
27#define MAX_FILES 1000
28
29static char buf[70000];
30extern int line_count;
31extern int nbio_id;
32static int nprocs;
33
34static struct {
35	int fd;
36	int handle;
37} ftable[MAX_FILES];
38
39static struct {
40	double bytes_in, bytes_out;
41	int line;
42	int done;
43} *children;
44
45double nbio_total(void)
46{
47	int i;
48	double total = 0;
49	for (i=0;i<nprocs;i++) {
50		total += children[i].bytes_out + children[i].bytes_in;
51	}
52	return total;
53}
54
55void nb_alarm(int ignore)
56{
57	int i;
58	int lines=0, num_clients=0;
59	if (nbio_id != -1) return;
60
61	for (i=0;i<nprocs;i++) {
62		lines += children[i].line;
63		if (!children[i].done) num_clients++;
64	}
65
66	printf("%4d  %8d  %.2f MB/sec\r", num_clients, lines/nprocs, 1.0e-6 * nbio_total() / end_timer());
67
68	signal(SIGALRM, nb_alarm);
69	alarm(1);
70}
71
72void nbio_shmem(int n)
73{
74	nprocs = n;
75	children = shm_setup(sizeof(*children) * nprocs);
76	if (!children) {
77		printf("Failed to setup shared memory!\n");
78		exit(1);
79	}
80}
81
82#if 0
83static int ne_find_handle(int handle)
84{
85	int i;
86	children[nbio_id].line = line_count;
87	for (i=0;i<MAX_FILES;i++) {
88		if (ftable[i].handle == handle) return i;
89	}
90	return -1;
91}
92#endif
93
94static int find_handle(int handle)
95{
96	int i;
97	children[nbio_id].line = line_count;
98	for (i=0;i<MAX_FILES;i++) {
99		if (ftable[i].handle == handle) return i;
100	}
101	printf("(%d) ERROR: handle %d was not found\n",
102	       line_count, handle);
103	exit(1);
104
105	return -1;		/* Not reached */
106}
107
108
109static struct cli_state *c;
110
111static void sigsegv(int sig)
112{
113	char line[200];
114	printf("segv at line %d\n", line_count);
115	slprintf(line, sizeof(line), "/usr/X11R6/bin/xterm -e gdb /proc/%d/exe %d",
116		(int)getpid(), (int)getpid());
117	system(line);
118	exit(1);
119}
120
121void nb_setup(struct cli_state *cli)
122{
123	signal(SIGSEGV, sigsegv);
124	c = cli;
125	start_timer();
126	children[nbio_id].done = 0;
127}
128
129
130void nb_unlink(const char *fname)
131{
132	if (!cli_unlink(c, fname)) {
133#if NBDEBUG
134		printf("(%d) unlink %s failed (%s)\n",
135		       line_count, fname, cli_errstr(c));
136#endif
137	}
138}
139
140
141void nb_createx(const char *fname,
142		unsigned create_options, unsigned create_disposition, int handle)
143{
144	int fd, i;
145	uint32 desired_access;
146
147	if (create_options & FILE_DIRECTORY_FILE) {
148		desired_access = FILE_READ_DATA;
149	} else {
150		desired_access = FILE_READ_DATA | FILE_WRITE_DATA;
151	}
152
153	fd = cli_nt_create_full(c, fname, 0,
154				desired_access,
155				0x0,
156				FILE_SHARE_READ|FILE_SHARE_WRITE,
157				create_disposition,
158				create_options, 0);
159	if (fd == -1 && handle != -1) {
160		printf("ERROR: cli_nt_create_full failed for %s - %s\n",
161		       fname, cli_errstr(c));
162		exit(1);
163	}
164	if (fd != -1 && handle == -1) {
165		printf("ERROR: cli_nt_create_full succeeded for %s\n", fname);
166		exit(1);
167	}
168	if (fd == -1) return;
169
170	for (i=0;i<MAX_FILES;i++) {
171		if (ftable[i].handle == 0) break;
172	}
173	if (i == MAX_FILES) {
174		printf("(%d) file table full for %s\n", line_count,
175		       fname);
176		exit(1);
177	}
178	ftable[i].handle = handle;
179	ftable[i].fd = fd;
180}
181
182void nb_writex(int handle, int offset, int size, int ret_size)
183{
184	int i;
185
186	if (buf[0] == 0) memset(buf, 1, sizeof(buf));
187
188	i = find_handle(handle);
189	if (cli_write(c, ftable[i].fd, 0, buf, offset, size) != ret_size) {
190		printf("(%d) ERROR: write failed on handle %d, fd %d \
191errno %d (%s)\n", line_count, handle, ftable[i].fd, errno, strerror(errno));
192		exit(1);
193	}
194
195	children[nbio_id].bytes_out += ret_size;
196}
197
198void nb_readx(int handle, int offset, int size, int ret_size)
199{
200	int i, ret;
201
202	i = find_handle(handle);
203	if ((ret=cli_read(c, ftable[i].fd, buf, offset, size)) != ret_size) {
204		printf("(%d) ERROR: read failed on handle %d ofs=%d size=%d res=%d fd %d errno %d (%s)\n",
205			line_count, handle, offset, size, ret, ftable[i].fd, errno, strerror(errno));
206		exit(1);
207	}
208	children[nbio_id].bytes_in += ret_size;
209}
210
211void nb_close(int handle)
212{
213	int i;
214	i = find_handle(handle);
215	if (!cli_close(c, ftable[i].fd)) {
216		printf("(%d) close failed on handle %d\n", line_count, handle);
217		exit(1);
218	}
219	ftable[i].handle = 0;
220}
221
222void nb_rmdir(const char *fname)
223{
224	if (!cli_rmdir(c, fname)) {
225		printf("ERROR: rmdir %s failed (%s)\n",
226		       fname, cli_errstr(c));
227		exit(1);
228	}
229}
230
231void nb_rename(const char *old, const char *new)
232{
233	if (!cli_rename(c, old, new)) {
234		printf("ERROR: rename %s %s failed (%s)\n",
235		       old, new, cli_errstr(c));
236		exit(1);
237	}
238}
239
240
241void nb_qpathinfo(const char *fname)
242{
243	cli_qpathinfo(c, fname, NULL, NULL, NULL, NULL, NULL);
244}
245
246void nb_qfileinfo(int fnum)
247{
248	int i;
249	i = find_handle(fnum);
250	cli_qfileinfo(c, ftable[i].fd, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
251}
252
253void nb_qfsinfo(int level)
254{
255	int bsize, total, avail;
256	/* this is not the right call - we need cli_qfsinfo() */
257	cli_dskattr(c, &bsize, &total, &avail);
258}
259
260static void find_fn(const char *mnt, file_info *finfo, const char *name, void *state)
261{
262	/* noop */
263}
264
265void nb_findfirst(const char *mask)
266{
267	cli_list(c, mask, 0, find_fn, NULL);
268}
269
270void nb_flush(int fnum)
271{
272	int i;
273	i = find_handle(fnum);
274	/* hmmm, we don't have cli_flush() yet */
275}
276
277static int total_deleted;
278
279static void delete_fn(const char *mnt, file_info *finfo, const char *name, void *state)
280{
281	char *s, *n;
282	if (finfo->name[0] == '.') return;
283
284	n = strdup(name);
285	n[strlen(n)-1] = 0;
286	asprintf(&s, "%s%s", n, finfo->name);
287	if (finfo->mode & aDIR) {
288		char *s2;
289		asprintf(&s2, "%s\\*", s);
290		cli_list(c, s2, aDIR, delete_fn, NULL);
291		nb_rmdir(s);
292	} else {
293		total_deleted++;
294		nb_unlink(s);
295	}
296	free(s);
297	free(n);
298}
299
300void nb_deltree(const char *dname)
301{
302	char *mask;
303	asprintf(&mask, "%s\\*", dname);
304
305	total_deleted = 0;
306	cli_list(c, mask, aDIR, delete_fn, NULL);
307	free(mask);
308	cli_rmdir(c, dname);
309
310	if (total_deleted) printf("WARNING: Cleaned up %d files\n", total_deleted);
311}
312
313
314void nb_cleanup(void)
315{
316	cli_rmdir(c, "clients");
317	children[nbio_id].done = 1;
318}
319