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