summaryrefslogtreecommitdiff
path: root/source4/torture/torture_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/torture_util.c')
-rw-r--r--source4/torture/torture_util.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/source4/torture/torture_util.c b/source4/torture/torture_util.c
new file mode 100644
index 0000000000..c8fb8a84b2
--- /dev/null
+++ b/source4/torture/torture_util.c
@@ -0,0 +1,306 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB torture tester utility functions
+ Copyright (C) Andrew Tridgell 2003
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+
+static struct timeval tp1,tp2;
+
+void start_timer(void)
+{
+ gettimeofday(&tp1,NULL);
+}
+
+double end_timer(void)
+{
+ gettimeofday(&tp2,NULL);
+ return((tp2.tv_sec - tp1.tv_sec) +
+ (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+}
+
+/*
+ sometimes we need a fairly complex file to work with, so we can test
+ all possible attributes.
+*/
+int create_complex_file(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *fname)
+{
+ int fnum;
+ char buf[7] = "abc";
+ union smb_setfileinfo setfile;
+ union smb_fileinfo fileinfo;
+ time_t t = (time(NULL) & ~1);
+ NTSTATUS status;
+
+ cli_unlink(cli, fname);
+ fnum = cli_nt_create_full(cli, fname, 0, GENERIC_RIGHTS_FILE_ALL_ACCESS,
+ FILE_ATTRIBUTE_NORMAL,
+ NTCREATEX_SHARE_ACCESS_DELETE|
+ NTCREATEX_SHARE_ACCESS_READ|
+ NTCREATEX_SHARE_ACCESS_WRITE,
+ NTCREATEX_DISP_OVERWRITE_IF,
+ 0, 0);
+ if (fnum == -1) return -1;
+
+ cli_write(cli, fnum, 0, buf, 0, sizeof(buf));
+
+ /* setup some EAs */
+ setfile.generic.level = RAW_SFILEINFO_EA_SET;
+ setfile.generic.file.fnum = fnum;
+ setfile.ea_set.in.ea.flags = 0;
+ setfile.ea_set.in.ea.name.s = "EAONE";
+ setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "VALUE1", 6);
+
+ status = smb_raw_setfileinfo(cli->tree, &setfile);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to setup EAs\n");
+ }
+
+ setfile.ea_set.in.ea.name.s = "SECONDEA";
+ setfile.ea_set.in.ea.value = data_blob_talloc(mem_ctx, "ValueTwo", 8);
+ status = smb_raw_setfileinfo(cli->tree, &setfile);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to setup EAs\n");
+ }
+
+ /* make sure all the timestamps aren't the same */
+ setfile.generic.level = RAW_SFILEINFO_SETATTRE;
+ setfile.generic.file.fnum = fnum;
+
+ setfile.setattre.in.create_time = t + 60;
+ setfile.setattre.in.access_time = t + 120;
+ setfile.setattre.in.write_time = t + 180;
+
+ status = smb_raw_setfileinfo(cli->tree, &setfile);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to setup file times - %s\n", nt_errstr(status));
+ }
+
+ /* make sure all the timestamps aren't the same */
+ fileinfo.generic.level = RAW_FILEINFO_GETATTRE;
+ fileinfo.generic.in.fnum = fnum;
+
+ status = smb_raw_fileinfo(cli->tree, mem_ctx, &fileinfo);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to query file times - %s\n", nt_errstr(status));
+ }
+
+ if (setfile.setattre.in.create_time != fileinfo.getattre.out.create_time) {
+ printf("create_time not setup correctly\n");
+ }
+ if (setfile.setattre.in.access_time != fileinfo.getattre.out.access_time) {
+ printf("access_time not setup correctly\n");
+ }
+ if (setfile.setattre.in.write_time != fileinfo.getattre.out.write_time) {
+ printf("write_time not setup correctly\n");
+ }
+
+ return fnum;
+}
+
+
+
+/* return a pointer to a anonymous shared memory segment of size "size"
+ which will persist across fork() but will disappear when all processes
+ exit
+
+ The memory is not zeroed
+
+ This function uses system5 shared memory. It takes advantage of a property
+ that the memory is not destroyed if it is attached when the id is removed
+ */
+void *shm_setup(int size)
+{
+ int shmid;
+ void *ret;
+
+ shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
+ if (shmid == -1) {
+ printf("can't get shared memory\n");
+ exit(1);
+ }
+ ret = (void *)shmat(shmid, 0, 0);
+ if (!ret || ret == (void *)-1) {
+ printf("can't attach to shared memory\n");
+ return NULL;
+ }
+ /* the following releases the ipc, but note that this process
+ and all its children will still have access to the memory, its
+ just that the shmid is no longer valid for other shm calls. This
+ means we don't leave behind lots of shm segments after we exit
+
+ See Stevens "advanced programming in unix env" for details
+ */
+ shmctl(shmid, IPC_RMID, 0);
+
+ return ret;
+}
+
+
+/*
+ check that a wire string matches the flags specified
+ not 100% accurate, but close enough for testing
+*/
+BOOL wire_bad_flags(WIRE_STRING *str, int flags)
+{
+ int len;
+ len = strlen(str->s);
+ if (flags & STR_TERMINATE) len++;
+ if ((flags & STR_UNICODE) || !getenv("CLI_FORCE_ASCII")) {
+ len *= 2;
+ } else if (flags & STR_TERMINATE_ASCII) {
+ len++;
+ }
+ if (str->private_length != len) {
+ printf("Expected wire_length %d but got %d for '%s'\n",
+ len, str->private_length, str->s);
+ return True;
+ }
+ return False;
+}
+
+/*
+ return a talloced string representing a time_t for human consumption
+*/
+const char *time_string(TALLOC_CTX *mem_ctx, time_t t)
+{
+ return talloc_strdup(mem_ctx, http_timestring(mem_ctx, t));
+}
+
+/*
+ check if 2 NTTIMEs are equal
+*/
+BOOL nt_time_equal(NTTIME *t1, NTTIME *t2)
+{
+ return t1->low == t2->low && t1->high == t2->high;
+}
+
+/*
+ dump a all_info QFILEINFO structure
+*/
+void dump_all_info(TALLOC_CTX *mem_ctx, union smb_fileinfo *finfo)
+{
+ d_printf("\tcreate_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.create_time));
+ d_printf("\taccess_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.access_time));
+ d_printf("\twrite_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.write_time));
+ d_printf("\tchange_time: %s\n", nt_time_string(mem_ctx, &finfo->all_info.out.change_time));
+ d_printf("\tattrib: 0x%x\n", finfo->all_info.out.attrib);
+ d_printf("\talloc_size: %llu\n", (unsigned long long)finfo->all_info.out.alloc_size);
+ d_printf("\tsize: %llu\n", (unsigned long long)finfo->all_info.out.size);
+ d_printf("\tnlink: %u\n", finfo->all_info.out.nlink);
+ d_printf("\tdelete_pending: %u\n", finfo->all_info.out.delete_pending);
+ d_printf("\tdirectory: %u\n", finfo->all_info.out.directory);
+ d_printf("\tea_size: %u\n", finfo->all_info.out.ea_size);
+ d_printf("\tfname: '%s'\n", finfo->all_info.out.fname.s);
+}
+
+/*
+ dump file infor by name
+*/
+void torture_all_info(struct cli_tree *tree, const char *fname)
+{
+ TALLOC_CTX *mem_ctx = talloc_init(fname);
+ union smb_fileinfo finfo;
+ NTSTATUS status;
+
+ finfo.generic.level = RAW_FILEINFO_ALL_INFO;
+ finfo.generic.in.fname = fname;
+ status = smb_raw_pathinfo(tree, mem_ctx, &finfo);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("%s - %s\n", fname, nt_errstr(status));
+ return;
+ }
+
+ d_printf("%s:\n", fname);
+ dump_all_info(mem_ctx, &finfo);
+ talloc_destroy(mem_ctx);
+}
+
+
+/*
+ split a UNC name into server and share names
+*/
+BOOL split_unc_name(const char *unc, char **server, char **share)
+{
+ char *p = strdup(unc);
+ if (!p) return False;
+ all_string_sub(p, "\\", "/", 0);
+ if (strncmp(p, "//", 2) != 0) return False;
+
+ (*server) = p+2;
+ p = strchr(*server, '/');
+ if (!p) return False;
+
+ *p = 0;
+ (*share) = p+1;
+
+ return True;
+}
+
+/*
+ split a USER%PASS pair into username and password
+*/
+BOOL split_username(const char *pair, char **user, char **pass)
+{
+ char *p = strdup(pair);
+ if (!p) return False;
+
+ (*user) = p;
+
+ p = strchr(*user, '%');
+ if (!p) return False;
+
+ *p = 0;
+ (*pass) = p+1;
+
+ return True;
+}
+
+/*
+ set a attribute on a file
+*/
+BOOL torture_set_file_attribute(struct cli_tree *tree, const char *fname, uint16 attrib)
+{
+ union smb_setfileinfo sfinfo;
+ NTSTATUS status;
+
+ sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
+ sfinfo.generic.file.fname = fname;
+
+ ZERO_STRUCT(sfinfo.basic_info.in);
+ sfinfo.basic_info.in.attrib = attrib;
+ status = smb_raw_setpathinfo(tree, &sfinfo);
+ return NT_STATUS_IS_OK(status);
+}
+
+
+/*
+ set a file descriptor as sparse
+*/
+NTSTATUS torture_set_sparse(struct cli_tree *tree, int fnum)
+{
+ struct smb_ntioctl nt;
+
+ nt.in.function = 0x900c4;
+ nt.in.fnum = fnum;
+ nt.in.fsctl = True;
+ nt.in.filter = 0;
+
+ return smb_raw_ntioctl(tree, &nt);
+}