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