📄 open.c
字号:
/* Unix SMB/CIFS implementation. RAW_OPEN_* 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 "libcli/raw/libcliraw.h"#include "libcli/raw/raw_proto.h"#include "system/time.h"#include "system/filesys.h"#include "librpc/gen_ndr/security.h"#include "lib/events/events.h"#include "libcli/libcli.h"#include "torture/util.h"#include "auth/credentials/credentials.h"#include "lib/cmdline/popt_common.h"#include "param/param.h"/* enum for whether reads/writes are possible on a file */enum rdwr_mode {RDWR_NONE, RDWR_RDONLY, RDWR_WRONLY, RDWR_RDWR};#define BASEDIR "\\rawopen"/* check if a open file can be read/written*/static enum rdwr_mode check_rdwr(struct smbcli_tree *tree, int fnum){ uint8_t c = 1; bool can_read = (smbcli_read(tree, fnum, &c, 0, 1) == 1); bool can_write = (smbcli_write(tree, fnum, 0, &c, 0, 1) == 1); if ( can_read && can_write) return RDWR_RDWR; if ( can_read && !can_write) return RDWR_RDONLY; if (!can_read && can_write) return RDWR_WRONLY; return RDWR_NONE;}/* describe a RDWR mode as a string*/static const char *rdwr_string(enum rdwr_mode m){ switch (m) { case RDWR_NONE: return "NONE"; case RDWR_RDONLY: return "RDONLY"; case RDWR_WRONLY: return "WRONLY"; case RDWR_RDWR: return "RDWR"; } return "-";}#define CHECK_STATUS(status, correct) do { \ if (!NT_STATUS_EQUAL(status, correct)) { \ printf("(%s) Incorrect status %s - should be %s\n", \ __location__, nt_errstr(status), nt_errstr(correct)); \ ret = false; \ goto done; \ }} while (0)#define CREATE_FILE do { \ fnum = create_complex_file(cli, tctx, fname); \ if (fnum == -1) { \ printf("(%s) Failed to create %s - %s\n", __location__, fname, smbcli_errstr(cli->tree)); \ ret = false; \ goto done; \ }} while (0)#define CHECK_RDWR(fnum, correct) do { \ enum rdwr_mode m = check_rdwr(cli->tree, fnum); \ if (m != correct) { \ printf("(%s) Incorrect readwrite mode %s - expected %s\n", \ __location__, rdwr_string(m), rdwr_string(correct)); \ ret = false; \ }} while (0)#define CHECK_TIME(t, field) do { \ time_t t1, t2; \ finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \ finfo.all_info.in.file.path = fname; \ status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \ CHECK_STATUS(status, NT_STATUS_OK); \ t1 = t & ~1; \ t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \ if (abs(t1-t2) > 2) { \ printf("(%s) wrong time for field %s %s - %s\n", \ __location__, #field, \ timestring(tctx, t1), \ timestring(tctx, t2)); \ dump_all_info(tctx, &finfo); \ ret = false; \ }} while (0)#define CHECK_NTTIME(t, field) do { \ NTTIME t2; \ finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \ finfo.all_info.in.file.path = fname; \ status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \ CHECK_STATUS(status, NT_STATUS_OK); \ t2 = finfo.all_info.out.field; \ if (t != t2) { \ printf("(%s) wrong time for field %s %s - %s\n", \ __location__, #field, \ nt_time_string(tctx, t), \ nt_time_string(tctx, t2)); \ dump_all_info(tctx, &finfo); \ ret = false; \ }} while (0)#define CHECK_ALL_INFO(v, field) do { \ finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \ finfo.all_info.in.file.path = fname; \ status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \ CHECK_STATUS(status, NT_STATUS_OK); \ if ((v) != (finfo.all_info.out.field)) { \ printf("(%s) wrong value for field %s 0x%x - 0x%x\n", \ __location__, #field, (int)v, (int)(finfo.all_info.out.field)); \ dump_all_info(tctx, &finfo); \ ret = false; \ }} while (0)#define CHECK_VAL(v, correct) do { \ if ((v) != (correct)) { \ printf("(%s) wrong value for %s 0x%x - should be 0x%x\n", \ __location__, #v, (int)(v), (int)correct); \ ret = false; \ }} while (0)#define SET_ATTRIB(sattrib) do { \ union smb_setfileinfo sfinfo; \ ZERO_STRUCT(sfinfo.basic_info.in); \ sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \ sfinfo.basic_info.in.file.path = fname; \ sfinfo.basic_info.in.attrib = sattrib; \ status = smb_raw_setpathinfo(cli->tree, &sfinfo); \ if (!NT_STATUS_IS_OK(status)) { \ printf("(%s) Failed to set attrib 0x%x on %s\n", \ __location__, sattrib, fname); \ }} while (0)/* test RAW_OPEN_OPEN*/static bool test_open(struct smbcli_state *cli, struct torture_context *tctx){ union smb_open io; union smb_fileinfo finfo; const char *fname = BASEDIR "\\torture_open.txt"; NTSTATUS status; int fnum = -1, fnum2; bool ret = true; printf("Checking RAW_OPEN_OPEN\n"); io.openold.level = RAW_OPEN_OPEN; io.openold.in.fname = fname; io.openold.in.open_mode = OPEN_FLAGS_FCB; io.openold.in.search_attrs = 0; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); fnum = io.openold.out.file.fnum; smbcli_unlink(cli->tree, fname); CREATE_FILE; smbcli_close(cli->tree, fnum); status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openold.out.file.fnum; CHECK_RDWR(fnum, RDWR_RDWR); status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum2 = io.openold.out.file.fnum; CHECK_RDWR(fnum2, RDWR_RDWR); smbcli_close(cli->tree, fnum2); smbcli_close(cli->tree, fnum); /* check the read/write modes */ io.openold.level = RAW_OPEN_OPEN; io.openold.in.fname = fname; io.openold.in.search_attrs = 0; io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openold.out.file.fnum; CHECK_RDWR(fnum, RDWR_RDONLY); smbcli_close(cli->tree, fnum); io.openold.in.open_mode = OPEN_FLAGS_OPEN_WRITE; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openold.out.file.fnum; CHECK_RDWR(fnum, RDWR_WRONLY); smbcli_close(cli->tree, fnum); io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openold.out.file.fnum; CHECK_RDWR(fnum, RDWR_RDWR); smbcli_close(cli->tree, fnum); /* check the share modes roughly - not a complete matrix */ io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openold.out.file.fnum; CHECK_RDWR(fnum, RDWR_RDWR); if (io.openold.in.open_mode != io.openold.out.rmode) { printf("(%s) rmode should equal open_mode - 0x%x 0x%x\n", __location__, io.openold.out.rmode, io.openold.in.open_mode); } io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum2 = io.openold.out.file.fnum; CHECK_RDWR(fnum2, RDWR_RDONLY); smbcli_close(cli->tree, fnum); smbcli_close(cli->tree, fnum2); /* check the returned write time */ io.openold.level = RAW_OPEN_OPEN; io.openold.in.fname = fname; io.openold.in.search_attrs = 0; io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openold.out.file.fnum; /* check other reply fields */ CHECK_TIME(io.openold.out.write_time, write_time); CHECK_ALL_INFO(io.openold.out.size, size); CHECK_ALL_INFO(io.openold.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);done: smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, fname); return ret;}/* test RAW_OPEN_OPENX*/static bool test_openx(struct smbcli_state *cli, struct torture_context *tctx){ union smb_open io; union smb_fileinfo finfo; const char *fname = BASEDIR "\\torture_openx.txt"; const char *fname_exe = BASEDIR "\\torture_openx.exe"; NTSTATUS status; int fnum = -1, fnum2; bool ret = true; int i; struct timeval tv; struct { uint16_t open_func; bool with_file; NTSTATUS correct_status; } open_funcs[] = { { OPENX_OPEN_FUNC_OPEN, true, NT_STATUS_OK }, { OPENX_OPEN_FUNC_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND }, { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OK }, { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK }, { OPENX_OPEN_FUNC_FAIL, true, NT_STATUS_DOS(ERRDOS, ERRbadaccess) }, { OPENX_OPEN_FUNC_FAIL, false, NT_STATUS_DOS(ERRDOS, ERRbadaccess) }, { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION }, { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK }, { OPENX_OPEN_FUNC_TRUNC, true, NT_STATUS_OK }, { OPENX_OPEN_FUNC_TRUNC, false, NT_STATUS_OBJECT_NAME_NOT_FOUND }, { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OK }, { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK }, }; printf("Checking RAW_OPEN_OPENX\n"); smbcli_unlink(cli->tree, fname); io.openx.level = RAW_OPEN_OPENX; io.openx.in.fname = fname; io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO; io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR; io.openx.in.search_attrs = 0; io.openx.in.file_attrs = 0; io.openx.in.write_time = 0; io.openx.in.size = 1024*1024; io.openx.in.timeout = 0; /* check all combinations of open_func */ for (i=0; i<ARRAY_SIZE(open_funcs); i++) { if (open_funcs[i].with_file) { fnum = create_complex_file(cli, tctx, fname); if (fnum == -1) { d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree)); ret = false; goto done; } smbcli_close(cli->tree, fnum); } io.openx.in.open_func = open_funcs[i].open_func; status = smb_raw_open(cli->tree, tctx, &io); if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) { printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n", __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status), i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func); ret = false; } if (NT_STATUS_IS_OK(status)) { smbcli_close(cli->tree, io.openx.out.file.fnum); } if (open_funcs[i].with_file) { smbcli_unlink(cli->tree, fname); } } smbcli_unlink(cli->tree, fname); /* check the basic return fields */ io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openx.out.file.fnum; CHECK_ALL_INFO(io.openx.out.size, size); CHECK_TIME(io.openx.out.write_time, write_time); CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED); CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR); CHECK_VAL(io.openx.out.ftype, 0); CHECK_VAL(io.openx.out.devstate, 0); CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED); CHECK_VAL(io.openx.out.size, 1024*1024); CHECK_ALL_INFO(io.openx.in.size, size); smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, fname); /* check the fields when the file already existed */ fnum2 = create_complex_file(cli, tctx, fname); if (fnum2 == -1) { ret = false; goto done; } smbcli_close(cli->tree, fnum2); io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN; status = smb_raw_open(cli->tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.openx.out.file.fnum; CHECK_ALL_INFO(io.openx.out.size, size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -