Unix SMB/CIFS implementation.
SMB torture tester
Copyright (C) Andrew Tridgell 1997-1998
+ Copyright (C) Jeremy Allison 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "includes.h"
#include "nsswitch/libwbclient/wbc_async.h"
+#include "torture/proto.h"
extern char *optarg;
extern int optind;
static fstring multishare_conn_fname;
static bool use_multishare_conn = False;
static bool do_encrypt;
+static const char *local_path = NULL;
bool torture_showall = False;
static double create_procs(bool (*fn)(int), bool *result);
-static struct timeval tp1,tp2;
-
-
-void start_timer(void)
-{
- GetTimeOfDay(&tp1);
-}
-
-double end_timer(void)
-{
- GetTimeOfDay(&tp2);
- return((tp2.tv_sec - tp1.tv_sec) +
- (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
-}
-
-
/* return a pointer to a anonymous shared memory segment of size "size"
which will persist across fork() but will disappear when all processes
exit
return false;
}
- if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
+ status = cli_unix_extensions_version(c, &major, &minor, &caplow,
+ &caphigh);
+ if (!NT_STATUS_IS_OK(status)) {
d_printf("Encryption required and "
"can't get UNIX CIFS extensions "
- "version from server.\n");
+ "version from server: %s\n", nt_errstr(status));
return false;
}
return correct;
}
+/*
+ * This test is designed to be run in conjunction with
+ * external NFS or POSIX locks taken in the filesystem.
+ * It checks that the smbd server will block until the
+ * lock is released and then acquire it. JRA.
+ */
+
+static bool got_alarm;
+static int alarm_fd;
+
+static void alarm_handler(int dummy)
+{
+ got_alarm = True;
+}
+
+static void alarm_handler_parent(int dummy)
+{
+ close(alarm_fd);
+}
+
+static void do_local_lock(int read_fd, int write_fd)
+{
+ int fd;
+ char c = '\0';
+ struct flock lock;
+ const char *local_pathname = NULL;
+ int ret;
+
+ local_pathname = talloc_asprintf(talloc_tos(),
+ "%s/lockt9.lck", local_path);
+ if (!local_pathname) {
+ printf("child: alloc fail\n");
+ exit(1);
+ }
+
+ unlink(local_pathname);
+ fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
+ if (fd == -1) {
+ printf("child: open of %s failed %s.\n",
+ local_pathname, strerror(errno));
+ exit(1);
+ }
+
+ /* Now take a fcntl lock. */
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 4;
+ lock.l_pid = getpid();
+
+ ret = fcntl(fd,F_SETLK,&lock);
+ if (ret == -1) {
+ printf("child: failed to get lock 0:4 on file %s. Error %s\n",
+ local_pathname, strerror(errno));
+ exit(1);
+ } else {
+ printf("child: got lock 0:4 on file %s.\n",
+ local_pathname );
+ fflush(stdout);
+ }
+
+ CatchSignal(SIGALRM, alarm_handler);
+ alarm(5);
+ /* Signal the parent. */
+ if (write(write_fd, &c, 1) != 1) {
+ printf("child: start signal fail %s.\n",
+ strerror(errno));
+ exit(1);
+ }
+ alarm(0);
+
+ alarm(10);
+ /* Wait for the parent to be ready. */
+ if (read(read_fd, &c, 1) != 1) {
+ printf("child: reply signal fail %s.\n",
+ strerror(errno));
+ exit(1);
+ }
+ alarm(0);
+
+ sleep(5);
+ close(fd);
+ printf("child: released lock 0:4 on file %s.\n",
+ local_pathname );
+ fflush(stdout);
+ exit(0);
+}
+
+static bool run_locktest9(int dummy)
+{
+ struct cli_state *cli1;
+ const char *fname = "\\lockt9.lck";
+ uint16_t fnum;
+ bool correct = False;
+ int pipe_in[2], pipe_out[2];
+ pid_t child_pid;
+ char c = '\0';
+ int ret;
+ struct timeval start;
+ double seconds;
+ NTSTATUS status;
+
+ printf("starting locktest9\n");
+
+ if (local_path == NULL) {
+ d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
+ return false;
+ }
+
+ if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
+ return false;
+ }
+
+ child_pid = fork();
+ if (child_pid == -1) {
+ return false;
+ }
+
+ if (child_pid == 0) {
+ /* Child. */
+ do_local_lock(pipe_out[0], pipe_in[1]);
+ exit(0);
+ }
+
+ close(pipe_out[0]);
+ close(pipe_in[1]);
+ pipe_out[0] = -1;
+ pipe_in[1] = -1;
+
+ /* Parent. */
+ ret = read(pipe_in[0], &c, 1);
+ if (ret != 1) {
+ d_fprintf(stderr, "failed to read start signal from child. %s\n",
+ strerror(errno));
+ return false;
+ }
+
+ if (!torture_open_connection(&cli1, 0)) {
+ return false;
+ }
+
+ cli_sockopt(cli1, sockops);
+
+ status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
+ &fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "cli_open returned %s\n", cli_errstr(cli1));
+ return false;
+ }
+
+ /* Ensure the child has the lock. */
+ if (cli_lock(cli1, fnum, 0, 4, 0, WRITE_LOCK)) {
+ d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
+ goto fail;
+ } else {
+ d_printf("Child has the lock.\n");
+ }
+
+ /* Tell the child to wait 5 seconds then exit. */
+ ret = write(pipe_out[1], &c, 1);
+ if (ret != 1) {
+ d_fprintf(stderr, "failed to send exit signal to child. %s\n",
+ strerror(errno));
+ goto fail;
+ }
+
+ /* Wait 20 seconds for the lock. */
+ alarm_fd = cli1->fd;
+ CatchSignal(SIGALRM, alarm_handler_parent);
+ alarm(20);
+
+ start = timeval_current();
+
+ if (!cli_lock(cli1, fnum, 0, 4, -1, WRITE_LOCK)) {
+ d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
+ "%s\n", cli_errstr(cli1));
+ goto fail_nofd;
+ }
+ alarm(0);
+
+ seconds = timeval_elapsed(&start);
+
+ printf("Parent got the lock after %.2f seconds.\n",
+ seconds);
+
+ status = cli_close(cli1, fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "cli_close(fnum1) %s\n", cli_errstr(cli1));
+ goto fail;
+ }
+
+ correct = true;
+
+fail:
+ cli_close(cli1, fnum);
+ torture_close_connection(cli1);
+
+fail_nofd:
+
+ printf("finished locktest9\n");
+ return correct;
+}
+
/*
test whether fnums and tids open on one VC are available on another (a major
security hole)
const char *fname2 = "\\trans2\\trans2.tst";
char pname[1024];
bool correct = True;
+ NTSTATUS status;
+ uint32_t fs_attr;
printf("starting trans2 test\n");
return False;
}
+ status = cli_get_fs_attr_info(cli, &fs_attr);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ERROR: cli_get_fs_attr_info returned %s\n",
+ nt_errstr(status));
+ correct = false;
+ }
+
cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
cli_open(cli, fname,
O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
uint16_t fnum1 = (uint16_t)-1;
SMB_STRUCT_STAT sbuf;
bool correct = false;
+ NTSTATUS status;
printf("Starting simple POSIX open test\n");
return false;
}
- if (!cli_unix_extensions_version(cli1, &major,
- &minor, &caplow, &caphigh)) {
- printf("Server didn't return UNIX CIFS extensions.\n");
+ status = cli_unix_extensions_version(cli1, &major, &minor, &caplow,
+ &caphigh);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Server didn't return UNIX CIFS extensions: %s\n",
+ nt_errstr(status));
return false;
}
- if (!cli_set_unix_extensions_capabilities(cli1,
- major, minor, caplow, caphigh)) {
- printf("Server doesn't support setting UNIX CIFS extensions.\n");
+ status = cli_set_unix_extensions_capabilities(cli1, major, minor,
+ caplow, caphigh);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Server doesn't support setting UNIX CIFS extensions: "
+ "%s.\n", nt_errstr(status));
return false;
}
int i;
static struct cli_state *cli;
uint16_t fnum;
- double t1;
+ struct timeval core_start;
bool correct = True;
printf("starting directory test\n");
cli_close(cli, fnum);
}
- t1 = end_timer();
+ core_start = timeval_current();
printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
- printf("dirtest core %g seconds\n", end_timer() - t1);
+ printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
srandom(0);
for (i=0;i<torture_numops;i++) {
int i;
bool ret = false;
const char *fname = "\\writetest.txt";
+ struct timeval start;
double seconds;
double kbytes;
cli_sockopt(cli1, sockops);
- start_timer();
+ start = timeval_current();
for (i=0; i<torture_numops; i++) {
char c = 0;
}
}
- seconds = end_timer();
+ seconds = timeval_elapsed(&start);
kbytes = (double)torture_blocksize * torture_numops;
kbytes /= 1024;
return False;
}
+ if (!gencache_get("foo", NULL, NULL)) {
+ d_printf("%s: gencache_get() failed\n", __location__);
+ return False;
+ }
+
if (!gencache_get("foo", &val, &tm)) {
d_printf("%s: gencache_get() failed\n", __location__);
return False;
volatile bool *child_status_out;
int synccount;
int tries = 8;
+ struct timeval start;
synccount = 0;
child_status_out[i] = True;
}
- start_timer();
+ start = timeval_current();
for (i=0;i<nprocs;i++) {
procnum = i;
child_status[i] = getpid();
- while (child_status[i] && end_timer() < 5) smb_msleep(2);
+ while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
child_status_out[i] = fn(i);
_exit(0);
}
if (synccount == nprocs) break;
smb_msleep(10);
- } while (end_timer() < 30);
+ } while (timeval_elapsed(&start) < 30);
if (synccount != nprocs) {
printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
*result = False;
- return end_timer();
+ return timeval_elapsed(&start);
}
/* start the client load */
- start_timer();
+ start = timeval_current();
for (i=0;i<nprocs;i++) {
child_status[i] = 0;
*result = False;
}
}
- return end_timer();
+ return timeval_elapsed(&start);
}
#define FLAG_MULTIPROC 1
{"LOCK6", run_locktest6, 0},
{"LOCK7", run_locktest7, 0},
{"LOCK8", run_locktest8, 0},
+ {"LOCK9", run_locktest9, 0},
{"UNLINK", run_unlinktest, 0},
{"BROWSE", run_browsetest, 0},
{"ATTR", run_attrtest, 0},
printf("TEST %s FAILED!\n", name);
}
} else {
- start_timer();
+ struct timeval start;
+ start = timeval_current();
if (!torture_ops[i].fn(0)) {
ret = False;
printf("TEST %s FAILED!\n", name);
}
- t = end_timer();
+ t = timeval_elapsed(&start);
}
printf("%s took %g secs\n\n", name, t);
}
fstrcpy(workgroup, lp_workgroup());
- while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ld:Aec:ks:b:B:")) != EOF) {
+ while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:")) != EOF) {
switch (opt) {
case 'p':
port_to_use = atoi(optarg);
case 'L':
use_oplocks = True;
break;
+ case 'l':
+ local_path = optarg;
+ break;
case 'A':
torture_showall = True;
break;