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"
+#include "libcli/security/dom_sid.h"
+#include "tldap.h"
+#include "tldap_util.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
int shmid;
void *ret;
+#ifdef __QNXNTO__
+ shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ if (shmid == -1) {
+ printf("can't get shared memory\n");
+ exit(1);
+ }
+ shm_unlink("private");
+ if (ftruncate(shmid, size) == -1) {
+ printf("can't set shared memory size\n");
+ exit(1);
+ }
+ ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
+ if (ret == MAP_FAILED) {
+ printf("can't map shared memory\n");
+ exit(1);
+ }
+#else
shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
if (shmid == -1) {
printf("can't get shared memory\n");
See Stevens "advanced programming in unix env" for details
*/
shmctl(shmid, IPC_RMID, 0);
+#endif
return ret;
}
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;
}
bool torture_close_connection(struct cli_state *c)
{
bool ret = True;
- if (!cli_tdis(c)) {
- printf("tdis failed (%s)\n", cli_errstr(c));
+ NTSTATUS status;
+
+ status = cli_tdis(c);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("tdis failed (%s)\n", nt_errstr(status));
ret = False;
}
cli->cnum = cnum2;
- if (!cli_tdis(cli)) {
- printf("secondary tdis failed (%s)\n", cli_errstr(cli));
+ status = cli_tdis(cli);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("secondary tdis failed (%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);
}
cli_close(cli, fnum);
- if (!cli_qpathinfo(cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
- printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(cli));
+ status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
+ NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
correct = False;
} else {
if (c_time != m_time) {
cli_open(cli, fname,
O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
cli_close(cli, fnum);
- if (!cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
- &m_time_ts, &size, NULL, NULL)) {
- printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
+ status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
+ &m_time_ts, &size, NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
correct = False;
} else {
if (w_time_ts.tv_sec < 60*60*24*2) {
correct = False;
}
sleep(3);
- if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts, &w_time_ts,
- &m_time_ts, &size, NULL, NULL)) {
- printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
+ status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
+ &w_time_ts, &m_time_ts, &size, NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
correct = False;
}
O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
cli_write(cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
cli_close(cli, fnum);
- if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts, &w_time_ts,
- &m_time2_ts, &size, NULL, NULL)) {
- printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
+ status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
+ &w_time_ts, &m_time2_ts, &size, NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
correct = False;
} else {
if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
const char *fname1 = "\\test1.txt";
bool correct = True;
uint16_t fnum1;
+ uint16_t attr;
NTSTATUS status;
printf("starting rename test\n");
} */
/*--*/
-
-
if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
printf("close - 5 failed (%s)\n", cli_errstr(cli1));
return False;
}
+ /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
+ if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname1, &attr, NULL, NULL))) {
+ printf("getatr on file %s failed - %s ! \n",
+ fname1,
+ cli_errstr(cli1));
+ correct = False;
+ } else {
+ if (attr != FILE_ATTRIBUTE_ARCHIVE) {
+ printf("Renamed file %s has wrong attr 0x%x "
+ "(should be 0x%x)\n",
+ fname1,
+ attr,
+ (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
+ correct = False;
+ } else {
+ printf("Renamed file %s has archive bit set\n", fname1);
+ }
+ }
+
cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
return correct;
}
+NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
+{
+ uint16 major, minor;
+ uint32 caplow, caphigh;
+ NTSTATUS status;
+
+ if (!SERVER_HAS_UNIX_CIFS(cli)) {
+ printf("Server doesn't support UNIX CIFS extensions.\n");
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
+ &caphigh);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Server didn't return UNIX CIFS extensions: %s\n",
+ nt_errstr(status));
+ return status;
+ }
+
+ status = cli_set_unix_extensions_capabilities(cli, 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 status;
+ }
+
+ return NT_STATUS_OK;
+}
+
/*
Test POSIX open /mkdir calls.
*/
const char *dname = "posix:dir";
char buf[10];
char namebuf[11];
- uint16 major, minor;
- uint32 caplow, caphigh;
uint16_t fnum1 = (uint16_t)-1;
SMB_STRUCT_STAT sbuf;
bool correct = false;
+ NTSTATUS status;
printf("Starting simple POSIX open test\n");
cli_sockopt(cli1, sockops);
- if (!SERVER_HAS_UNIX_CIFS(cli1)) {
- printf("Server doesn't support UNIX CIFS extensions.\n");
- return false;
- }
-
- if (!cli_unix_extensions_version(cli1, &major,
- &minor, &caplow, &caphigh)) {
- printf("Server didn't return UNIX CIFS extensions.\n");
+ status = torture_setup_unix_extensions(cli1);
+ if (!NT_STATUS_IS_OK(status)) {
return false;
}
- if (!cli_set_unix_extensions_capabilities(cli1,
- major, minor, caplow, caphigh)) {
- printf("Server doesn't support setting UNIX CIFS extensions.\n");
- return false;
- }
-
cli_setatr(cli1, fname, 0, 0);
cli_posix_unlink(cli1, fname);
cli_setatr(cli1, dname, 0, 0);
return correct;
}
-static void list_fn(const char *mnt, file_info *finfo, const char *name, void *state)
+static void list_fn(const char *mnt, struct file_info *finfo,
+ const char *name, void *state)
{
}
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++) {
return correct;
}
-static void del_fn(const char *mnt, file_info *finfo, const char *mask, void *state)
+static void del_fn(const char *mnt, struct file_info *finfo, const char *mask,
+ void *state)
{
struct cli_state *pcli = (struct cli_state *)state;
fstring fname;
}
status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
- printf("ioctl device info: %s\n", cli_errstr(cli));
+ printf("ioctl device info: %s\n", nt_errstr(status));
status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
- printf("ioctl job info: %s\n", cli_errstr(cli));
+ printf("ioctl job info: %s\n", nt_errstr(status));
for (device=0;device<0x100;device++) {
printf("testing device=0x%x\n", device);
size_t num_eas;
struct ea_struct *ea_list = NULL;
TALLOC_CTX *mem_ctx = talloc_init("eatest");
+ NTSTATUS status;
printf("starting eatest\n");
}
}
- if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) {
- printf("ea_get list failed - %s\n", cli_errstr(cli));
+ status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ea_get list failed - %s\n", nt_errstr(status));
correct = False;
}
}
#endif
- if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) {
- printf("ea_get list failed - %s\n", cli_errstr(cli));
+ status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("ea_get list failed - %s\n", nt_errstr(status));
correct = False;
}
d_printf("\r%d ", (int)c->vuid);
- if (!cli_ulogoff(c)) {
+ status = cli_ulogoff(c);
+ if (!NT_STATUS_IS_OK(status)) {
d_printf("(%s) cli_ulogoff failed: %s\n",
- __location__, cli_errstr(c));
+ __location__, nt_errstr(status));
return false;
}
c->vuid = 0;
NTSTATUS status;
printf("starting chain2 test\n");
- if (!torture_open_connection(&cli1, 0)) {
+ status = cli_start_connection(&cli1, global_myname(), host, NULL,
+ port_to_use, Undefined, 0, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
return False;
}
return True;
}
-static bool run_mangle1(int dummy)
-{
+
+struct torture_createdel_state {
+ struct tevent_context *ev;
struct cli_state *cli;
- const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
- uint16_t fnum;
- fstring alt_name;
- NTSTATUS status;
- time_t change_time, access_time, write_time;
- SMB_OFF_T size;
- uint16_t mode;
+};
- printf("starting mangle1 test\n");
- if (!torture_open_connection(&cli, 0)) {
- return False;
- }
+static void torture_createdel_created(struct tevent_req *subreq);
+static void torture_createdel_closed(struct tevent_req *subreq);
- cli_sockopt(cli, sockops);
+static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *name)
+{
+ struct tevent_req *req, *subreq;
+ struct torture_createdel_state *state;
- if (!NT_STATUS_IS_OK(cli_ntcreate(
- cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
- FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
- d_printf("open %s failed: %s\n", fname, cli_errstr(cli));
- return false;
+ req = tevent_req_create(mem_ctx, &state,
+ struct torture_createdel_state);
+ if (req == NULL) {
+ return NULL;
}
- cli_close(cli, fnum);
+ state->ev = ev;
+ state->cli = cli;
- status = cli_qpathinfo_alt_name(cli, fname, alt_name);
- if (!NT_STATUS_IS_OK(status)) {
- d_printf("cli_qpathinfo_alt_name failed: %s\n",
- nt_errstr(status));
- return false;
- }
- d_printf("alt_name: %s\n", alt_name);
+ subreq = cli_ntcreate_send(
+ state, ev, cli, name, 0,
+ FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
- if (!NT_STATUS_IS_OK(cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum))) {
- d_printf("cli_open(%s) failed: %s\n", alt_name,
- cli_errstr(cli));
- return false;
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
- cli_close(cli, fnum);
+ tevent_req_set_callback(subreq, torture_createdel_created, req);
+ return req;
+}
- if (!cli_qpathinfo(cli, alt_name, &change_time, &access_time,
- &write_time, &size, &mode)) {
- d_printf("cli_qpathinfo(%s) failed: %s\n", alt_name,
- cli_errstr(cli));
- return false;
+static void torture_createdel_created(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct torture_createdel_state *state = tevent_req_data(
+ req, struct torture_createdel_state);
+ NTSTATUS status;
+ uint16_t fnum;
+
+ status = cli_ntcreate_recv(subreq, &fnum);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("cli_ntcreate_recv returned %s\n",
+ nt_errstr(status)));
+ tevent_req_nterror(req, status);
+ return;
}
- return true;
+ subreq = cli_close_send(state, state->ev, state->cli, fnum);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, torture_createdel_closed, req);
}
-static size_t null_source(uint8_t *buf, size_t n, void *priv)
+static void torture_createdel_closed(struct tevent_req *subreq)
{
- size_t *to_pull = (size_t *)priv;
- size_t thistime = *to_pull;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
- thistime = MIN(thistime, n);
- if (thistime == 0) {
- return 0;
+ status = cli_close_recv(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
+ tevent_req_nterror(req, status);
+ return;
}
+ tevent_req_done(req);
+}
- memset(buf, 0, thistime);
- *to_pull -= thistime;
- return thistime;
+static NTSTATUS torture_createdel_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
}
-static bool run_windows_write(int dummy)
+struct torture_createdels_state {
+ struct tevent_context *ev;
+ struct cli_state *cli;
+ const char *base_name;
+ int sent;
+ int received;
+ int num_files;
+ struct tevent_req **reqs;
+};
+
+static void torture_createdels_done(struct tevent_req *subreq);
+
+static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ const char *base_name,
+ int num_parallel,
+ int num_files)
{
- struct cli_state *cli1;
- uint16_t fnum;
+ struct tevent_req *req;
+ struct torture_createdels_state *state;
int i;
- bool ret = false;
- const char *fname = "\\writetest.txt";
- double seconds;
- double kbytes;
- printf("starting windows_write test\n");
+ req = tevent_req_create(mem_ctx, &state,
+ struct torture_createdels_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->cli = cli;
+ state->base_name = talloc_strdup(state, base_name);
+ if (tevent_req_nomem(state->base_name, req)) {
+ return tevent_req_post(req, ev);
+ }
+ state->num_files = MAX(num_parallel, num_files);
+ state->sent = 0;
+ state->received = 0;
+
+ state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
+ if (tevent_req_nomem(state->reqs, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ for (i=0; i<num_parallel; i++) {
+ char *name;
+
+ name = talloc_asprintf(state, "%s%8.8d", state->base_name,
+ state->sent);
+ if (tevent_req_nomem(name, req)) {
+ return tevent_req_post(req, ev);
+ }
+ state->reqs[i] = torture_createdel_send(
+ state->reqs, state->ev, state->cli, name);
+ if (tevent_req_nomem(state->reqs[i], req)) {
+ return tevent_req_post(req, ev);
+ }
+ name = talloc_move(state->reqs[i], &name);
+ tevent_req_set_callback(state->reqs[i],
+ torture_createdels_done, req);
+ state->sent += 1;
+ }
+ return req;
+}
+
+static void torture_createdels_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct torture_createdels_state *state = tevent_req_data(
+ req, struct torture_createdels_state);
+ size_t num_parallel = talloc_array_length(state->reqs);
+ NTSTATUS status;
+ char *name;
+ int i;
+
+ status = torture_createdel_recv(subreq);
+ if (!NT_STATUS_IS_OK(status)){
+ DEBUG(10, ("torture_createdel_recv returned %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ for (i=0; i<num_parallel; i++) {
+ if (subreq == state->reqs[i]) {
+ break;
+ }
+ }
+ if (i == num_parallel) {
+ DEBUG(10, ("received something we did not send\n"));
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+ TALLOC_FREE(state->reqs[i]);
+
+ if (state->sent >= state->num_files) {
+ tevent_req_done(req);
+ return;
+ }
+
+ name = talloc_asprintf(state, "%s%8.8d", state->base_name,
+ state->sent);
+ if (tevent_req_nomem(name, req)) {
+ return;
+ }
+ state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
+ state->cli, name);
+ if (tevent_req_nomem(state->reqs[i], req)) {
+ return;
+ }
+ name = talloc_move(state->reqs[i], &name);
+ tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
+ state->sent += 1;
+}
+
+static NTSTATUS torture_createdels_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+struct swallow_notify_state {
+ struct tevent_context *ev;
+ struct cli_state *cli;
+ uint16_t fnum;
+ uint32_t completion_filter;
+ bool recursive;
+ bool (*fn)(uint32_t action, const char *name, void *priv);
+ void *priv;
+};
+
+static void swallow_notify_done(struct tevent_req *subreq);
+
+static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum,
+ uint32_t completion_filter,
+ bool recursive,
+ bool (*fn)(uint32_t action,
+ const char *name,
+ void *priv),
+ void *priv)
+{
+ struct tevent_req *req, *subreq;
+ struct swallow_notify_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct swallow_notify_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->cli = cli;
+ state->fnum = fnum;
+ state->completion_filter = completion_filter;
+ state->recursive = recursive;
+ state->fn = fn;
+ state->priv = priv;
+
+ subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
+ 0xffff, state->completion_filter,
+ state->recursive);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, swallow_notify_done, req);
+ return req;
+}
+
+static void swallow_notify_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct swallow_notify_state *state = tevent_req_data(
+ req, struct swallow_notify_state);
+ NTSTATUS status;
+ uint32_t i, num_changes;
+ struct notify_change *changes;
+
+ status = cli_notify_recv(subreq, state, &num_changes, &changes);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("cli_notify_recv returned %s\n",
+ nt_errstr(status)));
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ for (i=0; i<num_changes; i++) {
+ state->fn(changes[i].action, changes[i].name, state->priv);
+ }
+ TALLOC_FREE(changes);
+
+ subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
+ 0xffff, state->completion_filter,
+ state->recursive);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, swallow_notify_done, req);
+}
+
+static bool print_notifies(uint32_t action, const char *name, void *priv)
+{
+ if (DEBUGLEVEL > 5) {
+ d_printf("%d %s\n", (int)action, name);
+ }
+ return true;
+}
+
+static void notify_bench_done(struct tevent_req *req)
+{
+ int *num_finished = (int *)tevent_req_callback_data_void(req);
+ *num_finished += 1;
+}
+
+static bool run_notify_bench(int dummy)
+{
+ const char *dname = "\\notify-bench";
+ struct tevent_context *ev;
+ NTSTATUS status;
+ uint16_t dnum;
+ struct tevent_req *req1;
+ struct tevent_req *req2 = NULL;
+ int i, num_unc_names;
+ int num_finished = 0;
+
+ printf("starting notify-bench test\n");
+
+ if (use_multishare_conn) {
+ char **unc_list;
+ unc_list = file_lines_load(multishare_conn_fname,
+ &num_unc_names, 0, NULL);
+ if (!unc_list || num_unc_names <= 0) {
+ d_printf("Failed to load unc names list from '%s'\n",
+ multishare_conn_fname);
+ return false;
+ }
+ TALLOC_FREE(unc_list);
+ } else {
+ num_unc_names = 1;
+ }
+
+ ev = tevent_context_init(talloc_tos());
+ if (ev == NULL) {
+ d_printf("tevent_context_init failed\n");
+ return false;
+ }
+
+ for (i=0; i<num_unc_names; i++) {
+ struct cli_state *cli;
+ char *base_fname;
+
+ base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
+ dname, i);
+ if (base_fname == NULL) {
+ return false;
+ }
+
+ if (!torture_open_connection(&cli, i)) {
+ return false;
+ }
+
+ status = cli_ntcreate(cli, dname, 0,
+ MAXIMUM_ALLOWED_ACCESS,
+ 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
+ FILE_SHARE_DELETE,
+ FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
+ &dnum);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Could not create %s: %s\n", dname,
+ nt_errstr(status));
+ return false;
+ }
+
+ req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
+ FILE_NOTIFY_CHANGE_FILE_NAME |
+ FILE_NOTIFY_CHANGE_DIR_NAME |
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_LAST_WRITE,
+ false, print_notifies, NULL);
+ if (req1 == NULL) {
+ d_printf("Could not create notify request\n");
+ return false;
+ }
+
+ req2 = torture_createdels_send(talloc_tos(), ev, cli,
+ base_fname, 10, torture_numops);
+ if (req2 == NULL) {
+ d_printf("Could not create createdels request\n");
+ return false;
+ }
+ TALLOC_FREE(base_fname);
+
+ tevent_req_set_callback(req2, notify_bench_done,
+ &num_finished);
+ }
+
+ while (num_finished < num_unc_names) {
+ int ret;
+ ret = tevent_loop_once(ev);
+ if (ret != 0) {
+ d_printf("tevent_loop_once failed\n");
+ return false;
+ }
+ }
+
+ if (!tevent_req_poll(req2, ev)) {
+ d_printf("tevent_req_poll failed\n");
+ }
+
+ status = torture_createdels_recv(req2);
+ d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
+
+ return true;
+}
+
+static bool run_mangle1(int dummy)
+{
+ struct cli_state *cli;
+ const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
+ uint16_t fnum;
+ fstring alt_name;
+ NTSTATUS status;
+ time_t change_time, access_time, write_time;
+ SMB_OFF_T size;
+ uint16_t mode;
+
+ printf("starting mangle1 test\n");
+ if (!torture_open_connection(&cli, 0)) {
+ return False;
+ }
+
+ cli_sockopt(cli, sockops);
+
+ if (!NT_STATUS_IS_OK(cli_ntcreate(
+ cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
+ FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
+ d_printf("open %s failed: %s\n", fname, cli_errstr(cli));
+ return false;
+ }
+ cli_close(cli, fnum);
+
+ status = cli_qpathinfo_alt_name(cli, fname, alt_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("cli_qpathinfo_alt_name failed: %s\n",
+ nt_errstr(status));
+ return false;
+ }
+ d_printf("alt_name: %s\n", alt_name);
+
+ if (!NT_STATUS_IS_OK(cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum))) {
+ d_printf("cli_open(%s) failed: %s\n", alt_name,
+ cli_errstr(cli));
+ return false;
+ }
+ cli_close(cli, fnum);
+
+ status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
+ &write_time, &size, &mode);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
+ nt_errstr(status));
+ return false;
+ }
+
+ return true;
+}
+
+static size_t null_source(uint8_t *buf, size_t n, void *priv)
+{
+ size_t *to_pull = (size_t *)priv;
+ size_t thistime = *to_pull;
+
+ thistime = MIN(thistime, n);
+ if (thistime == 0) {
+ return 0;
+ }
+
+ memset(buf, 0, thistime);
+ *to_pull -= thistime;
+ return thistime;
+}
+
+static bool run_windows_write(int dummy)
+{
+ struct cli_state *cli1;
+ uint16_t fnum;
+ int i;
+ bool ret = false;
+ const char *fname = "\\writetest.txt";
+ struct timeval start_time;
+ double seconds;
+ double kbytes;
+
+ printf("starting windows_write test\n");
if (!torture_open_connection(&cli1, 0)) {
return False;
}
cli_sockopt(cli1, sockops);
- start_timer();
+ start_time = timeval_current();
for (i=0; i<torture_numops; i++) {
char c = 0;
}
}
- seconds = end_timer();
+ seconds = timeval_elapsed(&start_time);
kbytes = (double)torture_blocksize * torture_numops;
kbytes /= 1024;
int16_t old_vuid;
int16_t old_cnum;
bool correct = True;
+ NTSTATUS status;
printf("starting uid regression test\n");
/* Ok - now save then logoff our current user. */
old_vuid = cli->vuid;
- if (!cli_ulogoff(cli)) {
+ status = cli_ulogoff(cli);
+ if (!NT_STATUS_IS_OK(status)) {
d_printf("(%s) cli_ulogoff failed: %s\n",
- __location__, cli_errstr(cli));
+ __location__, nt_errstr(status));
correct = false;
goto out;
}
cli->vuid = 0;
/* This should succeed. */
- if (cli_tdis(cli)) {
+ status = cli_tdis(cli);
+
+ if (NT_STATUS_IS_OK(status)) {
printf("First tdis with invalid vuid should succeed.\n");
} else {
- printf("First tdis failed (%s)\n", cli_errstr(cli));
+ printf("First tdis failed (%s)\n", nt_errstr(status));
}
cli->vuid = old_vuid;
cli->cnum = old_cnum;
/* This should fail. */
- if (cli_tdis(cli)) {
+ status = cli_tdis(cli);
+ if (NT_STATUS_IS_OK(status)) {
printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
} else {
/* Should be bad tid. */
static const char *illegal_chars = "*\\/?<>|\":";
static char force_shortname_chars[] = " +,.[];=\177";
-static void shortname_del_fn(const char *mnt, file_info *finfo, const char *mask, void *state)
+static void shortname_del_fn(const char *mnt, struct file_info *finfo,
+ const char *mask, void *state)
{
struct cli_state *pcli = (struct cli_state *)state;
fstring fname;
bool val;
};
-static void shortname_list_fn(const char *mnt, file_info *finfo, const char *name, void *state)
+static void shortname_list_fn(const char *mnt, struct file_info *finfo,
+ const char *name, void *state)
{
struct sn_state *s = (struct sn_state *)state;
int i = s->i;
struct tevent_context *ev;
struct tevent_req *req;
char *basedn;
+ const char *filter;
- if (!resolve_name(host, &addr, 0)) {
+ if (!resolve_name(host, &addr, 0, false)) {
d_printf("could not find host %s\n", host);
return false;
}
TALLOC_FREE(req);
+ /* test search filters against rootDSE */
+ filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
+ "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
+
+ rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
+ NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
+ talloc_tos(), NULL, NULL);
+ if (rc != TLDAP_SUCCESS) {
+ d_printf("tldap_search with complex filter failed: %s\n",
+ tldap_errstr(talloc_tos(), ld, rc));
+ return false;
+ }
+
TALLOC_FREE(ld);
return true;
}
+/* Torture test to ensure no regression of :
+https://bugzilla.samba.org/show_bug.cgi?id=7084
+*/
+
+static bool run_dir_createtime(int dummy)
+{
+ struct cli_state *cli;
+ const char *dname = "\\testdir";
+ const char *fname = "\\testdir\\testfile";
+ NTSTATUS status;
+ struct timespec create_time;
+ struct timespec create_time1;
+ uint16_t fnum;
+ bool ret = false;
+
+ if (!torture_open_connection(&cli, 0)) {
+ return false;
+ }
+
+ cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
+ cli_rmdir(cli, dname);
+
+ status = cli_mkdir(cli, dname);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("mkdir failed: %s\n", nt_errstr(status));
+ goto out;
+ }
+
+ status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_qpathinfo2 returned %s\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ /* Sleep 3 seconds, then create a file. */
+ sleep(3);
+
+ status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
+ DENY_NONE, &fnum);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_open failed: %s\n", nt_errstr(status));
+ goto out;
+ }
+
+ status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("cli_qpathinfo2 (2) returned %s\n",
+ nt_errstr(status));
+ goto out;
+ }
+
+ if (timespec_compare(&create_time1, &create_time)) {
+ printf("run_dir_createtime: create time was updated (error)\n");
+ } else {
+ printf("run_dir_createtime: create time was not updated (correct)\n");
+ ret = true;
+ }
+
+ out:
+
+ cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
+ cli_rmdir(cli, dname);
+ if (!torture_close_connection(cli)) {
+ ret = false;
+ }
+ return ret;
+}
+
+
static bool run_streamerror(int dummy)
{
struct cli_state *cli;
return false;
}
+ cli_unlink(cli, "\\testdir\\*", aSYSTEM | aHIDDEN);
cli_rmdir(cli, dname);
status = cli_mkdir(cli, dname);
return false;
}
- cli_qpathinfo(cli, streamname, &change_time, &access_time, &write_time,
+ cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
&size, &mode);
status = cli_nt_error(cli);
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;
return False;
}
- if (!gencache_get_data_blob("foo", &blob, NULL)) {
+ if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
d_printf("%s: gencache_get_data_blob() failed\n", __location__);
return False;
}
return False;
}
- if (gencache_get_data_blob("foo", &blob, NULL)) {
+ if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
d_printf("%s: gencache_get_data_blob() on deleted entry "
"succeeded\n", __location__);
return False;
return ret;
}
+struct talloc_dict_test {
+ int content;
+};
+
+static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
+{
+ int *count = (int *)priv;
+ *count += 1;
+ return 0;
+}
+
+static bool run_local_talloc_dict(int dummy)
+{
+ struct talloc_dict *dict;
+ struct talloc_dict_test *t;
+ int key, count;
+
+ dict = talloc_dict_init(talloc_tos());
+ if (dict == NULL) {
+ return false;
+ }
+
+ t = talloc(talloc_tos(), struct talloc_dict_test);
+ if (t == NULL) {
+ return false;
+ }
+
+ key = 1;
+ t->content = 1;
+ if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
+ return false;
+ }
+
+ count = 0;
+ if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
+ return false;
+ }
+
+ if (count != 1) {
+ return false;
+ }
+
+ TALLOC_FREE(dict);
+
+ return true;
+}
+
+static bool run_local_string_to_sid(int dummy) {
+ struct dom_sid sid;
+
+ if (string_to_sid(&sid, "S--1-5-32-545")) {
+ printf("allowing S--1-5-32-545\n");
+ return false;
+ }
+ if (string_to_sid(&sid, "S-1-5-32-+545")) {
+ printf("allowing S-1-5-32-+545\n");
+ return false;
+ }
+ if (string_to_sid(&sid, "S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0")) {
+ printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
+ return false;
+ }
+ if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
+ printf("allowing S-1-5-32-545-abc\n");
+ return false;
+ }
+ if (!string_to_sid(&sid, "S-1-5-32-545")) {
+ printf("could not parse S-1-5-32-545\n");
+ return false;
+ }
+ if (!sid_equal(&sid, &global_sid_Builtin_Users)) {
+ printf("mis-parsed S-1-5-32-545 as %s\n",
+ sid_string_tos(&sid));
+ return false;
+ }
+ return true;
+}
+
/* Split a path name into filename and stream name components. Canonicalise
* such that an implicit $DATA token is always explicit.
*
return result;
}
+static bool dbtrans_inc(struct db_context *db)
+{
+ struct db_record *rec;
+ uint32_t *val;
+ bool ret = false;
+ NTSTATUS status;
+
+ rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
+ if (rec == NULL) {
+ printf(__location__ "fetch_lock failed\n");
+ return false;
+ }
+
+ if (rec->value.dsize != sizeof(uint32_t)) {
+ printf(__location__ "value.dsize = %d\n",
+ (int)rec->value.dsize);
+ goto fail;
+ }
+
+ val = (uint32_t *)rec->value.dptr;
+ *val += 1;
+
+ status = rec->store(rec, make_tdb_data((uint8_t *)val,
+ sizeof(uint32_t)),
+ 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf(__location__ "store failed: %s\n",
+ nt_errstr(status));
+ goto fail;
+ }
+
+ ret = true;
+fail:
+ TALLOC_FREE(rec);
+ return ret;
+}
+
+static bool run_local_dbtrans(int dummy)
+{
+ struct db_context *db;
+ struct db_record *rec;
+ NTSTATUS status;
+ uint32_t initial;
+ int res;
+
+ db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
+ O_RDWR|O_CREAT, 0600);
+ if (db == NULL) {
+ printf("Could not open transtest.db\n");
+ return false;
+ }
+
+ res = db->transaction_start(db);
+ if (res == -1) {
+ printf(__location__ "transaction_start failed\n");
+ return false;
+ }
+
+ rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
+ if (rec == NULL) {
+ printf(__location__ "fetch_lock failed\n");
+ return false;
+ }
+
+ if (rec->value.dptr == NULL) {
+ initial = 0;
+ status = rec->store(
+ rec, make_tdb_data((uint8_t *)&initial,
+ sizeof(initial)),
+ 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf(__location__ "store returned %s\n",
+ nt_errstr(status));
+ return false;
+ }
+ }
+
+ TALLOC_FREE(rec);
+
+ res = db->transaction_commit(db);
+ if (res == -1) {
+ printf(__location__ "transaction_commit failed\n");
+ return false;
+ }
+
+ while (true) {
+ uint32_t val, val2;
+ int i;
+
+ res = db->transaction_start(db);
+ if (res == -1) {
+ printf(__location__ "transaction_start failed\n");
+ break;
+ }
+
+ if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
+ printf(__location__ "dbwrap_fetch_uint32 failed\n");
+ break;
+ }
+
+ for (i=0; i<10; i++) {
+ if (!dbtrans_inc(db)) {
+ return false;
+ }
+ }
+
+ if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
+ printf(__location__ "dbwrap_fetch_uint32 failed\n");
+ break;
+ }
+
+ if (val2 != val + 10) {
+ printf(__location__ "val=%d, val2=%d\n",
+ (int)val, (int)val2);
+ break;
+ }
+
+ printf("val2=%d\r", val2);
+
+ res = db->transaction_commit(db);
+ if (res == -1) {
+ printf(__location__ "transaction_commit failed\n");
+ break;
+ }
+ }
+
+ TALLOC_FREE(db);
+ return true;
+}
+
+/*
+ * Just a dummy test to be run under a debugger. There's no real way
+ * to inspect the tevent_select specific function from outside of
+ * tevent_select.c.
+ */
+
+static bool run_local_tevent_select(int dummy)
+{
+ struct tevent_context *ev;
+ struct tevent_fd *fd1, *fd2;
+ bool result = false;
+
+ ev = tevent_context_init_byname(NULL, "select");
+ if (ev == NULL) {
+ d_fprintf(stderr, "tevent_context_init_byname failed\n");
+ goto fail;
+ }
+
+ fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
+ if (fd1 == NULL) {
+ d_fprintf(stderr, "tevent_add_fd failed\n");
+ goto fail;
+ }
+ fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
+ if (fd2 == NULL) {
+ d_fprintf(stderr, "tevent_add_fd failed\n");
+ goto fail;
+ }
+ TALLOC_FREE(fd2);
+
+ fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
+ if (fd2 == NULL) {
+ d_fprintf(stderr, "tevent_add_fd failed\n");
+ goto fail;
+ }
+
+ result = true;
+fail:
+ TALLOC_FREE(ev);
+ return result;
+}
static double create_procs(bool (*fn)(int), bool *result)
{
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},
{"RANDOMIPC", run_randomipc, 0},
{"NEGNOWAIT", run_negprot_nowait, 0},
{"NBENCH", run_nbench, 0},
+ {"NBENCH2", run_nbench2, 0},
{"OPLOCK1", run_oplock1, 0},
{"OPLOCK2", run_oplock2, 0},
{"OPLOCK3", run_oplock3, 0},
{"DIR", run_dirtest, 0},
{"DIR1", run_dirtest1, 0},
+ {"DIR-CREATETIME", run_dir_createtime, 0},
{"DENY1", torture_denytest1, 0},
{"DENY2", torture_denytest2, 0},
{"TCON", run_tcon_test, 0},
{"RW3", run_readwritelarge, 0},
{"OPEN", run_opentest, 0},
{"POSIX", run_simple_posix_open_test, 0},
+ {"POSIX-APPEND", run_posix_append, 0},
{ "UID-REGRESSION-TEST", run_uid_regression_test, 0},
{ "SHORTNAME-TEST", run_shortname_test, 0},
#if 1
{ "GETADDRINFO", run_getaddrinfo_send, 0},
{ "TLDAP", run_tldap },
{ "STREAMERROR", run_streamerror },
+ { "NOTIFY-BENCH", run_notify_bench },
{ "LOCAL-SUBSTITUTE", run_local_substitute, 0},
{ "LOCAL-GENCACHE", run_local_gencache, 0},
+ { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
{ "LOCAL-BASE64", run_local_base64, 0},
{ "LOCAL-RBTREE", run_local_rbtree, 0},
{ "LOCAL-MEMCACHE", run_local_memcache, 0},
{ "LOCAL-STREAM-NAME", run_local_stream_name, 0},
{ "LOCAL-WBCLIENT", run_local_wbclient, 0},
+ { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
+ { "LOCAL-DBTRANS", run_local_dbtrans, 0},
+ { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
{NULL, NULL, 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);
}
load_case_tables();
+ setup_logging("smbtorture", true);
+
if (is_default_dyn_CONFIGFILE()) {
if(getenv("SMB_CONF_PATH")) {
set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
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;