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