📄 search.c
字号:
/* Unix SMB/CIFS implementation. RAW_SEARCH_* individual test suite 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 3 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, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "torture/torture.h"#include "system/filesys.h"#include "libcli/raw/libcliraw.h"#include "libcli/raw/raw_proto.h"#include "libcli/libcli.h"#include "torture/util.h"#define BASEDIR "\\testsearch"/* callback function for single_search*/static bool single_search_callback(void *private, const union smb_search_data *file){ union smb_search_data *data = (union smb_search_data *)private; *data = *file; return true;}/* do a single file (non-wildcard) search */NTSTATUS torture_single_search(struct smbcli_state *cli, TALLOC_CTX *tctx, const char *pattern, enum smb_search_level level, enum smb_search_data_level data_level, uint16_t attrib, union smb_search_data *data){ union smb_search_first io; union smb_search_close c; NTSTATUS status; switch (level) { case RAW_SEARCH_SEARCH: case RAW_SEARCH_FFIRST: case RAW_SEARCH_FUNIQUE: io.search_first.level = level; io.search_first.data_level = RAW_SEARCH_DATA_SEARCH; io.search_first.in.max_count = 1; io.search_first.in.search_attrib = attrib; io.search_first.in.pattern = pattern; break; case RAW_SEARCH_TRANS2: io.t2ffirst.level = RAW_SEARCH_TRANS2; io.t2ffirst.data_level = data_level; 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; io.t2ffirst.in.pattern = pattern; break; case RAW_SEARCH_SMB2: return NT_STATUS_INVALID_LEVEL; } status = smb_raw_search_first(cli->tree, tctx, &io, (void *)data, single_search_callback); if (NT_STATUS_IS_OK(status) && level == RAW_SEARCH_FFIRST) { c.fclose.level = RAW_FINDCLOSE_FCLOSE; c.fclose.in.max_count = 1; c.fclose.in.search_attrib = 0; c.fclose.in.id = data->search.id; status = smb_raw_search_close(cli->tree, &c); } return status;}static struct { const char *name; enum smb_search_level level; enum smb_search_data_level data_level; int name_offset; int resume_key_offset; uint32_t capability_mask; NTSTATUS status; union smb_search_data data;} levels[] = { {"FFIRST", RAW_SEARCH_FFIRST, RAW_SEARCH_DATA_SEARCH, offsetof(union smb_search_data, search.name), -1, }, {"FUNIQUE", RAW_SEARCH_FUNIQUE, RAW_SEARCH_DATA_SEARCH, offsetof(union smb_search_data, search.name), -1, }, {"SEARCH", RAW_SEARCH_SEARCH, RAW_SEARCH_DATA_SEARCH, offsetof(union smb_search_data, search.name), -1, }, {"STANDARD", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_STANDARD, offsetof(union smb_search_data, standard.name.s), offsetof(union smb_search_data, standard.resume_key), }, {"EA_SIZE", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_EA_SIZE, offsetof(union smb_search_data, ea_size.name.s), offsetof(union smb_search_data, ea_size.resume_key), }, {"DIRECTORY_INFO", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_DIRECTORY_INFO, offsetof(union smb_search_data, directory_info.name.s), offsetof(union smb_search_data, directory_info.file_index), }, {"FULL_DIRECTORY_INFO", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_FULL_DIRECTORY_INFO, offsetof(union smb_search_data, full_directory_info.name.s), offsetof(union smb_search_data, full_directory_info.file_index), }, {"NAME_INFO", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_NAME_INFO, offsetof(union smb_search_data, name_info.name.s), offsetof(union smb_search_data, name_info.file_index), }, {"BOTH_DIRECTORY_INFO", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO, offsetof(union smb_search_data, both_directory_info.name.s), offsetof(union smb_search_data, both_directory_info.file_index), }, {"ID_FULL_DIRECTORY_INFO", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO, offsetof(union smb_search_data, id_full_directory_info.name.s), offsetof(union smb_search_data, id_full_directory_info.file_index), }, {"ID_BOTH_DIRECTORY_INFO", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO, offsetof(union smb_search_data, id_both_directory_info.name.s), offsetof(union smb_search_data, id_both_directory_info.file_index), }, {"UNIX_INFO", RAW_SEARCH_TRANS2, RAW_SEARCH_DATA_UNIX_INFO, offsetof(union smb_search_data, unix_info.name), offsetof(union smb_search_data, unix_info.file_index), CAP_UNIX}};/* return level name*/static const char *level_name(enum smb_search_level level, enum smb_search_data_level data_level){ int i; for (i=0;i<ARRAY_SIZE(levels);i++) { if (level == levels[i].level && data_level == levels[i].data_level) { return levels[i].name; } } return NULL;}/* extract the name from a smb_data structure and level*/static const char *extract_name(void *data, enum smb_search_level level, enum smb_search_data_level data_level){ int i; for (i=0;i<ARRAY_SIZE(levels);i++) { if (level == levels[i].level && data_level == levels[i].data_level) { return *(const char **)(levels[i].name_offset + (char *)data); } } return NULL;}/* extract the name from a smb_data structure and level*/static uint32_t extract_resume_key(void *data, enum smb_search_level level, enum smb_search_data_level data_level){ int i; for (i=0;i<ARRAY_SIZE(levels);i++) { if (level == levels[i].level && data_level == levels[i].data_level) { return *(uint32_t *)(levels[i].resume_key_offset + (char *)data); } } return 0;}/* find a level in the table by name */static union smb_search_data *find(const char *name){ int i; for (i=0;i<ARRAY_SIZE(levels);i++) { if (NT_STATUS_IS_OK(levels[i].status) && strcmp(levels[i].name, name) == 0) { return &levels[i].data; } } return NULL;}/* basic testing of all RAW_SEARCH_* calls using a single file*/static bool test_one_file(struct torture_context *tctx, struct smbcli_state *cli){ bool ret = true; int fnum; const char *fname = "\\torture_search.txt"; const char *fname2 = "\\torture_search-NOTEXIST.txt"; NTSTATUS status; int i; union smb_fileinfo all_info, alt_info, name_info, internal_info; union smb_search_data *s; fnum = create_complex_file(cli, tctx, fname); if (fnum == -1) { printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); ret = false; goto done; } /* call all the levels */ for (i=0;i<ARRAY_SIZE(levels);i++) { NTSTATUS expected_status; uint32_t cap = cli->transport->negotiate.capabilities; torture_comment(tctx, "testing %s\n", levels[i].name); levels[i].status = torture_single_search(cli, tctx, fname, levels[i].level, levels[i].data_level, 0, &levels[i].data); /* see if this server claims to support this level */ if ((cap & levels[i].capability_mask) != levels[i].capability_mask) { printf("search level %s(%d) not supported by server\n", levels[i].name, (int)levels[i].level); continue; } if (!NT_STATUS_IS_OK(levels[i].status)) { printf("search level %s(%d) failed - %s\n", levels[i].name, (int)levels[i].level, nt_errstr(levels[i].status)); ret = false; continue; } status = torture_single_search(cli, tctx, fname2, levels[i].level, levels[i].data_level, 0, &levels[i].data); expected_status = NT_STATUS_NO_SUCH_FILE; if (levels[i].level == RAW_SEARCH_SEARCH || levels[i].level == RAW_SEARCH_FFIRST || levels[i].level == RAW_SEARCH_FUNIQUE) { expected_status = STATUS_NO_MORE_FILES; } if (!NT_STATUS_EQUAL(status, expected_status)) { printf("search level %s(%d) should fail with %s - %s\n", levels[i].name, (int)levels[i].level, nt_errstr(expected_status), nt_errstr(status)); ret = false; } } /* get the all_info file into to check against */ all_info.generic.level = RAW_FILEINFO_ALL_INFO; all_info.generic.in.file.path = fname; status = smb_raw_pathinfo(cli->tree, tctx, &all_info); torture_assert_ntstatus_ok(tctx, status, "RAW_FILEINFO_ALL_INFO failed"); alt_info.generic.level = RAW_FILEINFO_ALT_NAME_INFO; alt_info.generic.in.file.path = fname; status = smb_raw_pathinfo(cli->tree, tctx, &alt_info); torture_assert_ntstatus_ok(tctx, status, "RAW_FILEINFO_ALT_NAME_INFO failed"); internal_info.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION; internal_info.generic.in.file.path = fname; status = smb_raw_pathinfo(cli->tree, tctx, &internal_info); torture_assert_ntstatus_ok(tctx, status, "RAW_FILEINFO_INTERNAL_INFORMATION failed"); name_info.generic.level = RAW_FILEINFO_NAME_INFO; name_info.generic.in.file.path = fname; status = smb_raw_pathinfo(cli->tree, tctx, &name_info); torture_assert_ntstatus_ok(tctx, status, "RAW_FILEINFO_NAME_INFO failed");#define CHECK_VAL(name, sname1, field1, v, sname2, field2) do { \ s = find(name); \ if (s) { \ if ((s->sname1.field1) != (v.sname2.out.field2)) { \ printf("(%s) %s/%s [0x%x] != %s/%s [0x%x]\n", \ __location__, \ #sname1, #field1, (int)s->sname1.field1, \ #sname2, #field2, (int)v.sname2.out.field2); \ ret = false; \ } \ }} while (0)#define CHECK_TIME(name, sname1, field1, v, sname2, field2) do { \ s = find(name); \ if (s) { \ if (s->sname1.field1 != (~1 & nt_time_to_unix(v.sname2.out.field2))) { \ printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \ __location__, \ #sname1, #field1, timestring(tctx, s->sname1.field1), \ #sname2, #field2, nt_time_string(tctx, v.sname2.out.field2)); \ ret = false; \ } \ }} while (0)#define CHECK_NTTIME(name, sname1, field1, v, sname2, field2) do { \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -