*/
#include "includes.h"
+#include "system/filesys.h"
#include "libcli/raw/libcliraw.h"
/*
do a single file (non-wildcard) search
*/
-static NTSTATUS single_search(struct smbcli_state *cli,
- TALLOC_CTX *mem_ctx,
- const char *pattern,
- enum smb_search_level level,
- union smb_search_data *data)
+NTSTATUS torture_single_search(struct smbcli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ const char *pattern,
+ enum smb_search_level level,
+ uint16_t attrib,
+ union smb_search_data *data)
{
union smb_search_first io;
union smb_search_close c;
level == RAW_SEARCH_FFIRST ||
level == RAW_SEARCH_FUNIQUE) {
io.search_first.in.max_count = 1;
- io.search_first.in.search_attrib = 0;
+ io.search_first.in.search_attrib = attrib;
io.search_first.in.pattern = pattern;
} else {
- io.t2ffirst.in.search_attrib = 0;
+ io.t2ffirst.in.search_attrib = attrib;
io.t2ffirst.in.max_count = 1;
io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
io.t2ffirst.in.storage_type = 0;
printf("testing %s\n", levels[i].name);
- levels[i].status = single_search(cli, mem_ctx, fname,
- levels[i].level, &levels[i].data);
+ levels[i].status = torture_single_search(cli, mem_ctx, fname,
+ levels[i].level, 0,
+ &levels[i].data);
/* see if this server claims to support this level */
if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
continue;
}
- status = single_search(cli, mem_ctx, fname2,
- levels[i].level, &levels[i].data);
+ status = torture_single_search(cli, mem_ctx, fname2,
+ levels[i].level, 0,
+ &levels[i].data);
expected_status = NT_STATUS_NO_SUCH_FILE;
if (levels[i].level == RAW_SEARCH_SEARCH ||
data->count++;
- data->list = talloc_realloc_p(data->mem_ctx,
+ data->list = talloc_realloc(data->mem_ctx,
data->list,
union smb_search_data,
data->count);
union smb_search_first io;
union smb_search_next io2;
NTSTATUS status;
- const int per_search = 300;
+ const int per_search = 100;
struct multiple_result *result = data;
io.generic.level = level;
#define CHECK_VALUE(v, correct) do { \
if ((v) != (correct)) { \
printf("(%s) Incorrect value %s=%d - should be %d\n", \
+ __location__, #v, v, (int)correct); \
+ ret = False; \
+ goto done; \
+ }} while (0)
+
+#define CHECK_STRING(v, correct) do { \
+ if (strcasecmp_m(v, correct) != 0) { \
+ printf("(%s) Incorrect value %s='%s' - should be '%s'\n", \
__location__, #v, v, correct); \
ret = False; \
}} while (0)
{"DIRECTORY_INFO", "NAME", RAW_SEARCH_DIRECTORY_INFO, CONT_NAME}
};
- if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
- NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
- printf("Failed to create " BASEDIR " - %s\n", smbcli_errstr(cli->tree));
+ if (!torture_setup_dir(cli, BASEDIR)) {
return False;
}
printf("Creating %d files\n", num_files);
for (i=0;i<num_files;i++) {
- asprintf(&fname, BASEDIR "\\t%03d-%d.txt", i, i);
+ fname = talloc_asprintf(cli, BASEDIR "\\t%03d-%d.txt", i, i);
fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
if (fnum == -1) {
printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
ret = False;
goto done;
}
- free(fname);
+ talloc_free(fname);
smbcli_close(cli->tree, fnum);
}
for (t=0;t<ARRAY_SIZE(search_types);t++) {
ZERO_STRUCT(result);
- result.mem_ctx = talloc(mem_ctx, 0);
+ result.mem_ctx = talloc_new(mem_ctx);
printf("Continue %s via %s\n", search_types[t].name, search_types[t].cont_name);
} else {
s = result.list[i].search.name;
}
- asprintf(&fname, "t%03d-%d.txt", i, i);
+ fname = talloc_asprintf(cli, "t%03d-%d.txt", i, i);
if (strcmp(fname, s)) {
printf("Incorrect name %s at entry %d\n", s, i);
ret = False;
break;
}
- free(fname);
+ talloc_free(fname);
}
talloc_free(result.mem_ctx);
}
union smb_search_next io2;
union smb_setfileinfo sfinfo;
- if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
- NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
- printf("Failed to create " BASEDIR " - %s\n", smbcli_errstr(cli->tree));
+ if (!torture_setup_dir(cli, BASEDIR)) {
return False;
}
printf("Creating %d files\n", num_files);
for (i=num_files-1;i>=0;i--) {
- asprintf(&fname, BASEDIR "\\t%03d-%d.txt", i, i);
+ fname = talloc_asprintf(cli, BASEDIR "\\t%03d-%d.txt", i, i);
fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
if (fnum == -1) {
printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
ret = False;
goto done;
}
- free(fname);
+ talloc_free(fname);
smbcli_close(cli->tree, fnum);
}
printf("pulling the first file\n");
ZERO_STRUCT(result);
- result.mem_ctx = talloc(mem_ctx, 0);
+ result.mem_ctx = talloc_new(mem_ctx);
io.generic.level = RAW_SEARCH_BOTH_DIRECTORY_INFO;
io.t2ffirst.in.search_attrib = 0;
io2.t2fnext.in.max_count = 1;
io2.t2fnext.in.resume_key = 0;
io2.t2fnext.in.flags = 0;
- if (result.count == 0) {
- io2.t2fnext.in.last_name = "";
- } else {
- io2.t2fnext.in.last_name = result.list[result.count-1].both_directory_info.name.s;
- }
+ io2.t2fnext.in.last_name = result.list[result.count-1].both_directory_info.name.s;
status = smb_raw_search_next(cli->tree, mem_ctx,
&io2, &result, multiple_search_callback);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VALUE(result.count, 2);
+ result.count = 0;
+
printf("Changing attributes and deleting\n");
smbcli_open(cli->tree, BASEDIR "\\T003-03.txt.2", O_CREAT|O_RDWR, DENY_NONE);
smbcli_open(cli->tree, BASEDIR "\\T013-13.txt.2", O_CREAT|O_RDWR, DENY_NONE);
io2.generic.level = RAW_SEARCH_BOTH_DIRECTORY_INFO;
io2.t2fnext.in.handle = io.t2ffirst.out.handle;
- io2.t2fnext.in.max_count = num_files - 1;
+ io2.t2fnext.in.max_count = num_files + 3;
io2.t2fnext.in.resume_key = 0;
io2.t2fnext.in.flags = 0;
- io2.t2fnext.in.last_name = result.list[result.count-2].both_directory_info.name.s;
+ io2.t2fnext.in.last_name = ".";
status = smb_raw_search_next(cli->tree, mem_ctx,
&io2, &result, multiple_search_callback);
CHECK_STATUS(status, NT_STATUS_OK);
- CHECK_VALUE(result.count, 21);
+ CHECK_VALUE(result.count, 20);
ret &= check_result(&result, "t009-9.txt", True, FILE_ATTRIBUTE_ARCHIVE);
ret &= check_result(&result, "t014-14.txt", False, 0);
NTSTATUS status;
struct multiple_result result;
- if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
- NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
- printf("Failed to create " BASEDIR " - %s\n", smbcli_errstr(cli->tree));
+ if (!torture_setup_dir(cli, BASEDIR)) {
return False;
}
printf("Creating %d files\n", num_files);
for (i=0;i<num_files;i++) {
- asprintf(&fname, BASEDIR "\\%s.txt", generate_random_str_list(mem_ctx, 10, "abcdefgh"));
+ fname = talloc_asprintf(cli, BASEDIR "\\%s.txt", generate_random_str_list(mem_ctx, 10, "abcdefgh"));
fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
if (fnum == -1) {
printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
ret = False;
goto done;
}
- free(fname);
+ talloc_free(fname);
smbcli_close(cli->tree, fnum);
}
const char *name1, *name2;
name1 = result.list[i].both_directory_info.name.s;
name2 = result.list[i+1].both_directory_info.name.s;
- if (StrCaseCmp(name1, name2) > 0) {
+ if (strcasecmp_m(name1, name2) > 0) {
printf("non-alphabetical order at entry %d '%s' '%s'\n",
i, name1, name2);
printf("Server does not produce sorted directory listings (not an error)\n");
*/
static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
{
- const int num_dirs = 300;
+ const int num_dirs = 100;
int i, fnum, n;
char *fname, *dname;
BOOL ret = True;
NTSTATUS status;
union smb_search_data *file, *file2, *file3;
- if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
- NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
- printf("Failed to create " BASEDIR " - %s\n", smbcli_errstr(cli->tree));
+ if (!torture_setup_dir(cli, BASEDIR)) {
return False;
}
printf("Creating %d dirs\n", num_dirs);
for (i=0;i<num_dirs;i++) {
- asprintf(&dname, BASEDIR "\\d%d", i);
+ dname = talloc_asprintf(cli, BASEDIR "\\d%d", i);
status = smbcli_mkdir(cli->tree, dname);
if (!NT_STATUS_IS_OK(status)) {
printf("(%s) Failed to create %s - %s\n",
}
for (n=0;n<3;n++) {
- asprintf(&fname, BASEDIR "\\d%d\\f%d-%d.txt", i, i, n);
+ fname = talloc_asprintf(cli, BASEDIR "\\d%d\\f%d-%d.txt", i, i, n);
fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
if (fnum == -1) {
printf("(%s) Failed to create %s - %s\n",
ret = False;
goto done;
}
- free(fname);
+ talloc_free(fname);
+ smbcli_close(cli->tree, fnum);
}
- free(dname);
- smbcli_close(cli->tree, fnum);
+ talloc_free(dname);
}
- file = talloc_zero_array_p(mem_ctx, union smb_search_data, num_dirs);
- file2 = talloc_zero_array_p(mem_ctx, union smb_search_data, num_dirs);
- file3 = talloc_zero_array_p(mem_ctx, union smb_search_data, num_dirs);
+ file = talloc_zero_array(mem_ctx, union smb_search_data, num_dirs);
+ file2 = talloc_zero_array(mem_ctx, union smb_search_data, num_dirs);
+ file3 = talloc_zero_array(mem_ctx, union smb_search_data, num_dirs);
printf("Search first on %d dirs\n", num_dirs);
return ret;
}
+
+/*
+ testing of OS/2 style delete
+*/
+static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+ const int num_files = 700;
+ const int delete_count = 4;
+ int total_deleted = 0;
+ int i, fnum;
+ char *fname;
+ BOOL ret = True;
+ NTSTATUS status;
+ union smb_search_first io;
+ union smb_search_next io2;
+ struct multiple_result result;
+
+ if (!torture_setup_dir(cli, BASEDIR)) {
+ return False;
+ }
+
+ printf("Testing OS/2 style delete on %d files\n", num_files);
+
+ for (i=0;i<num_files;i++) {
+ fname = talloc_asprintf(cli, BASEDIR "\\file%u.txt", i);
+ fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
+ if (fnum == -1) {
+ printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
+ ret = False;
+ goto done;
+ }
+ talloc_free(fname);
+ smbcli_close(cli->tree, fnum);
+ }
+
+
+ ZERO_STRUCT(result);
+ result.mem_ctx = mem_ctx;
+
+ io.t2ffirst.level = RAW_SEARCH_EA_SIZE;
+ io.t2ffirst.in.search_attrib = 0;
+ io.t2ffirst.in.max_count = 100;
+ io.t2ffirst.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME;
+ io.t2ffirst.in.storage_type = 0;
+ io.t2ffirst.in.pattern = BASEDIR "\\*";
+
+ status = smb_raw_search_first(cli->tree, mem_ctx,
+ &io, &result, multiple_search_callback);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ for (i=0;i<MIN(result.count, delete_count);i++) {
+ fname = talloc_asprintf(cli, BASEDIR "\\%s", result.list[i].ea_size.name.s);
+ status = smbcli_unlink(cli->tree, fname);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ total_deleted++;
+ talloc_free(fname);
+ }
+
+ io2.t2fnext.level = RAW_SEARCH_EA_SIZE;
+ io2.t2fnext.in.handle = io.t2ffirst.out.handle;
+ io2.t2fnext.in.max_count = 100;
+ io2.t2fnext.in.resume_key = result.list[i-1].ea_size.resume_key;
+ io2.t2fnext.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME;
+ io2.t2fnext.in.last_name = result.list[i-1].ea_size.name.s;
+
+ do {
+ ZERO_STRUCT(result);
+ result.mem_ctx = mem_ctx;
+
+ status = smb_raw_search_next(cli->tree, mem_ctx,
+ &io2, &result, multiple_search_callback);
+ if (!NT_STATUS_IS_OK(status)) {
+ break;
+ }
+
+ for (i=0;i<MIN(result.count, delete_count);i++) {
+ fname = talloc_asprintf(cli, BASEDIR "\\%s", result.list[i].ea_size.name.s);
+ status = smbcli_unlink(cli->tree, fname);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ total_deleted++;
+ talloc_free(fname);
+ }
+
+ if (i>0) {
+ io2.t2fnext.in.resume_key = result.list[i-1].ea_size.resume_key;
+ io2.t2fnext.in.last_name = result.list[i-1].ea_size.name.s;
+ }
+ } while (NT_STATUS_IS_OK(status) && result.count != 0);
+
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ if (total_deleted != num_files) {
+ printf("error: deleted %d - expected to delete %d\n",
+ total_deleted, num_files);
+ ret = False;
+ }
+
+done:
+ smb_raw_exit(cli->session);
+ smbcli_deltree(cli->tree, BASEDIR);
+
+ return ret;
+}
+
+
+static int ealist_cmp(union smb_search_data *r1, union smb_search_data *r2)
+{
+ return strcmp(r1->ea_list.name.s, r2->ea_list.name.s);
+}
+
+/*
+ testing of the rather strange ea_list level
+*/
+static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+ int fnum;
+ BOOL ret = True;
+ NTSTATUS status;
+ union smb_search_first io;
+ union smb_search_next nxt;
+ struct multiple_result result;
+ union smb_setfileinfo setfile;
+
+ if (!torture_setup_dir(cli, BASEDIR)) {
+ return False;
+ }
+
+ printf("Testing RAW_SEARCH_EA_LIST level\n");
+
+ fnum = smbcli_open(cli->tree, BASEDIR "\\file1.txt", O_CREAT|O_RDWR, DENY_NONE);
+ smbcli_close(cli->tree, fnum);
+
+ fnum = smbcli_open(cli->tree, BASEDIR "\\file2.txt", O_CREAT|O_RDWR, DENY_NONE);
+ smbcli_close(cli->tree, fnum);
+
+ fnum = smbcli_open(cli->tree, BASEDIR "\\file3.txt", O_CREAT|O_RDWR, DENY_NONE);
+ smbcli_close(cli->tree, fnum);
+
+ setfile.generic.level = RAW_SFILEINFO_EA_SET;
+ setfile.generic.file.fname = BASEDIR "\\file2.txt";
+ setfile.ea_set.in.num_eas = 2;
+ setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2);
+ setfile.ea_set.in.eas[0].flags = 0;
+ setfile.ea_set.in.eas[0].name.s = "EA ONE";
+ setfile.ea_set.in.eas[0].value = data_blob_string_const("VALUE 1");
+ setfile.ea_set.in.eas[1].flags = 0;
+ setfile.ea_set.in.eas[1].name.s = "SECOND EA";
+ setfile.ea_set.in.eas[1].value = data_blob_string_const("Value Two");
+
+ status = smb_raw_setpathinfo(cli->tree, &setfile);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ setfile.generic.file.fname = BASEDIR "\\file3.txt";
+ status = smb_raw_setpathinfo(cli->tree, &setfile);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ ZERO_STRUCT(result);
+ result.mem_ctx = mem_ctx;
+
+ io.t2ffirst.level = RAW_SEARCH_EA_LIST;
+ io.t2ffirst.in.search_attrib = 0;
+ io.t2ffirst.in.max_count = 2;
+ io.t2ffirst.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME;
+ io.t2ffirst.in.storage_type = 0;
+ io.t2ffirst.in.pattern = BASEDIR "\\*";
+ io.t2ffirst.in.num_names = 2;
+ io.t2ffirst.in.ea_names = talloc_array(mem_ctx, struct ea_name, 2);
+ io.t2ffirst.in.ea_names[0].name.s = "SECOND EA";
+ io.t2ffirst.in.ea_names[1].name.s = "THIRD EA";
+
+ status = smb_raw_search_first(cli->tree, mem_ctx,
+ &io, &result, multiple_search_callback);
+ CHECK_STATUS(status, NT_STATUS_OK);
+ CHECK_VALUE(result.count, 2);
+
+ nxt.t2fnext.level = RAW_SEARCH_EA_LIST;
+ nxt.t2fnext.in.handle = io.t2ffirst.out.handle;
+ nxt.t2fnext.in.max_count = 2;
+ nxt.t2fnext.in.resume_key = result.list[1].ea_list.resume_key;
+ nxt.t2fnext.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME | FLAG_TRANS2_FIND_CONTINUE;
+ nxt.t2fnext.in.last_name = result.list[1].ea_list.name.s;
+ nxt.t2fnext.in.num_names = 2;
+ nxt.t2fnext.in.ea_names = talloc_array(mem_ctx, struct ea_name, 2);
+ nxt.t2fnext.in.ea_names[0].name.s = "SECOND EA";
+ nxt.t2fnext.in.ea_names[1].name.s = "THIRD EA";
+
+ status = smb_raw_search_next(cli->tree, mem_ctx,
+ &nxt, &result, multiple_search_callback);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ /* we have to sort the result as different servers can return directories
+ in different orders */
+ qsort(result.list, result.count, sizeof(result.list[0]),
+ (comparison_fn_t)ealist_cmp);
+
+ CHECK_VALUE(result.count, 3);
+ CHECK_VALUE(result.list[0].ea_list.eas.num_eas, 2);
+ CHECK_STRING(result.list[0].ea_list.name.s, "file1.txt");
+ CHECK_STRING(result.list[0].ea_list.eas.eas[0].name.s, "SECOND EA");
+ CHECK_VALUE(result.list[0].ea_list.eas.eas[0].value.length, 0);
+ CHECK_STRING(result.list[0].ea_list.eas.eas[1].name.s, "THIRD EA");
+ CHECK_VALUE(result.list[0].ea_list.eas.eas[1].value.length, 0);
+
+ CHECK_STRING(result.list[1].ea_list.name.s, "file2.txt");
+ CHECK_STRING(result.list[1].ea_list.eas.eas[0].name.s, "SECOND EA");
+ CHECK_VALUE(result.list[1].ea_list.eas.eas[0].value.length, 9);
+ CHECK_STRING(result.list[1].ea_list.eas.eas[0].value.data, "Value Two");
+ CHECK_STRING(result.list[1].ea_list.eas.eas[1].name.s, "THIRD EA");
+ CHECK_VALUE(result.list[1].ea_list.eas.eas[1].value.length, 0);
+
+ CHECK_STRING(result.list[2].ea_list.name.s, "file3.txt");
+ CHECK_STRING(result.list[2].ea_list.eas.eas[0].name.s, "SECOND EA");
+ CHECK_VALUE(result.list[2].ea_list.eas.eas[0].value.length, 9);
+ CHECK_STRING(result.list[2].ea_list.eas.eas[0].value.data, "Value Two");
+ CHECK_STRING(result.list[2].ea_list.eas.eas[1].name.s, "THIRD EA");
+ CHECK_VALUE(result.list[2].ea_list.eas.eas[1].value.length, 0);
+
+done:
+ smb_raw_exit(cli->session);
+ smbcli_deltree(cli->tree, BASEDIR);
+
+ return ret;
+}
+
+
+
/*
basic testing of all RAW_SEARCH_* calls using a single file
*/
ret &= test_sorted(cli, mem_ctx);
ret &= test_modify_search(cli, mem_ctx);
ret &= test_many_dirs(cli, mem_ctx);
+ ret &= test_os2_delete(cli, mem_ctx);
+ ret &= test_ea_list(cli, mem_ctx);
torture_close_connection(cli);
- talloc_destroy(mem_ctx);
+ talloc_free(mem_ctx);
return ret;
}