📄 locktest.c
字号:
/* Unix SMB/CIFS implementation. randomised byte range lock tester Copyright (C) Andrew Tridgell 1999 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 "lib/cmdline/popt_common.h"#include "lib/events/events.h"#include "system/filesys.h"#include "system/time.h"#include "pstring.h"#include "auth/credentials/credentials.h"#include "auth/gensec/gensec.h"#include "libcli/libcli.h"#include "param/param.h"#include "dynconfig/dynconfig.h"#include "libcli/resolve/resolve.h"static int numops = 1000;static int showall;static int analyze;static int hide_unlock_fails;static int use_oplocks;static uint_t lock_range = 100;static uint_t lock_base = 0;static uint_t min_length = 0;static int exact_error_codes;static int zero_zero;#define FILENAME "\\locktest.dat"#define READ_PCT 50#define LOCK_PCT 45#define UNLOCK_PCT 70#define RANGE_MULTIPLE 1#define NSERVERS 2#define NCONNECTIONS 2#define NFILES 2#define LOCK_TIMEOUT 0static struct cli_credentials *servers[NSERVERS];enum lock_op {OP_LOCK, OP_UNLOCK, OP_REOPEN};struct record { enum lock_op lock_op; enum brl_type lock_type; char conn, f; uint64_t start, len; char needed; uint16_t pid;};#define PRESETS 0#if PRESETSstatic struct record preset[] = {{OP_LOCK, WRITE_LOCK, 0, 0, 2, 0, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 3, 0, 1},{OP_UNLOCK, 0 , 0, 0, 2, 0, 1},{OP_REOPEN, 0, 0, 0, 0, 0, 1},{OP_LOCK, READ_LOCK, 0, 0, 2, 0, 1},{OP_LOCK, READ_LOCK, 0, 0, 1, 1, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},{OP_REOPEN, 0, 0, 0, 0, 0, 1},{OP_LOCK, READ_LOCK, 0, 0, 2, 0, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 3, 1, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},{OP_REOPEN, 0, 0, 0, 0, 0, 1},{OP_LOCK, READ_LOCK, 0, 0, 2, 0, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 1, 1, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},{OP_REOPEN, 0, 0, 0, 0, 0, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 2, 0, 1},{OP_LOCK, READ_LOCK, 0, 0, 1, 1, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},{OP_REOPEN, 0, 0, 0, 0, 0, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 2, 0, 1},{OP_LOCK, READ_LOCK, 0, 0, 3, 1, 1},{OP_LOCK, WRITE_LOCK, 0, 0, 0, 0, 1},{OP_REOPEN, 0, 0, 0, 0, 0, 1},};#endifstatic struct record *recorded;/***************************************************** return a connection to a server*******************************************************/static struct smbcli_state *connect_one(struct event_context *ev, struct loadparm_context *lp_ctx, char *share, int snum, int conn){ struct smbcli_state *c; fstring server, myname; NTSTATUS status; int retries = 10; struct smbcli_options options; lp_smbcli_options(lp_ctx, &options); printf("connect_one(%s, %d, %d)\n", share, snum, conn); fstrcpy(server,share+2); share = strchr_m(server,'\\'); if (!share) return NULL; *share = 0; share++; if (snum == 0) { char **unc_list = NULL; int num_unc_names; const char *p; p = lp_parm_string(lp_ctx, NULL, "torture", "unclist"); if (p) { char *h, *s; unc_list = file_lines_load(p, &num_unc_names, NULL); if (!unc_list || num_unc_names <= 0) { printf("Failed to load unc names list from '%s'\n", p); exit(1); } if (!smbcli_parse_unc(unc_list[conn % num_unc_names], NULL, &h, &s)) { printf("Failed to parse UNC name %s\n", unc_list[conn % num_unc_names]); exit(1); } fstrcpy(server, h); fstrcpy(share, s); } } slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), snum); cli_credentials_set_workstation(servers[snum], myname, CRED_SPECIFIED); do { printf("\\\\%s\\%s\n", server, share); status = smbcli_full_connection(NULL, &c, server, lp_smb_ports(lp_ctx), share, NULL, servers[snum], lp_resolve_context(lp_ctx), ev, &options); if (!NT_STATUS_IS_OK(status)) { sleep(2); } } while (!NT_STATUS_IS_OK(status) && retries--); if (!NT_STATUS_IS_OK(status)) { return NULL; } return c;}static void reconnect(struct event_context *ev, struct loadparm_context *lp_ctx, struct smbcli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES], char *share[NSERVERS]){ int server, conn, f; for (server=0;server<NSERVERS;server++) for (conn=0;conn<NCONNECTIONS;conn++) { if (cli[server][conn]) { for (f=0;f<NFILES;f++) { if (fnum[server][conn][f] != -1) { smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]); fnum[server][conn][f] = -1; } } talloc_free(cli[server][conn]); } cli[server][conn] = connect_one(ev, lp_ctx, share[server], server, conn); if (!cli[server][conn]) { DEBUG(0,("Failed to connect to %s\n", share[server])); exit(1); } }}static bool test_one(struct smbcli_state *cli[NSERVERS][NCONNECTIONS], int fnum[NSERVERS][NCONNECTIONS][NFILES], struct record *rec){ uint_t conn = rec->conn; uint_t f = rec->f; uint64_t start = rec->start; uint64_t len = rec->len; enum brl_type op = rec->lock_type; int server; bool ret[NSERVERS]; NTSTATUS status[NSERVERS]; switch (rec->lock_op) { case OP_LOCK: /* set a lock */ for (server=0;server<NSERVERS;server++) { NTSTATUS res; struct smbcli_tree *tree=cli[server][conn]->tree; int fn=fnum[server][conn][f]; if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) { res=smbcli_lock(tree, fn, start, len, LOCK_TIMEOUT, rec->lock_op); } else { union smb_lock parms; int ltype; struct smb_lock_entry lock[1]; parms.lockx.level = RAW_LOCK_LOCKX; parms.lockx.in.file.fnum = fn; ltype = (rec->lock_op == READ_LOCK? 1 : 0); ltype |= LOCKING_ANDX_LARGE_FILES; parms.lockx.in.mode = ltype; parms.lockx.in.timeout = LOCK_TIMEOUT; parms.lockx.in.ulock_cnt = 0; parms.lockx.in.lock_cnt = 1; lock[0].pid = rec->pid; lock[0].offset = start; lock[0].count = len; parms.lockx.in.locks = &lock[0]; res = smb_raw_lock(tree, &parms); } ret[server] = NT_STATUS_IS_OK(res); status[server] = smbcli_nt_error(cli[server][conn]->tree); if (!exact_error_codes && NT_STATUS_EQUAL(status[server], NT_STATUS_FILE_LOCK_CONFLICT)) { status[server] = NT_STATUS_LOCK_NOT_GRANTED; } } if (showall || !NT_STATUS_EQUAL(status[0],status[1])) { printf("lock conn=%u f=%u range=%.0f(%.0f) op=%s -> %s:%s\n", conn, f, (double)start, (double)len, op==READ_LOCK?"READ_LOCK":"WRITE_LOCK", nt_errstr(status[0]), nt_errstr(status[1])); } if (!NT_STATUS_EQUAL(status[0],status[1])) return false; break; case OP_UNLOCK: /* unset a lock */ for (server=0;server<NSERVERS;server++) { NTSTATUS res; struct smbcli_tree *tree=cli[server][conn]->tree; int fn=fnum[server][conn][f]; if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) { res=smbcli_unlock(tree, fn, start, len); } else { union smb_lock parms; struct smb_lock_entry lock[1]; parms.lockx.level = RAW_LOCK_LOCKX; parms.lockx.in.file.fnum = fn; parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; parms.lockx.in.timeout = 0; parms.lockx.in.ulock_cnt = 1; parms.lockx.in.lock_cnt = 0; lock[0].pid = rec->pid; lock[0].count = len; lock[0].offset = start; parms.lockx.in.locks = &lock[0]; res = smb_raw_lock(tree, &parms); } ret[server] = NT_STATUS_IS_OK(res); status[server] = smbcli_nt_error(cli[server][conn]->tree); } if (showall || (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1]))) { printf("unlock conn=%u f=%u range=%.0f(%.0f) -> %s:%s\n", conn, f, (double)start, (double)len, nt_errstr(status[0]), nt_errstr(status[1])); } if (!hide_unlock_fails && !NT_STATUS_EQUAL(status[0],status[1])) return false; break; case OP_REOPEN: /* reopen the file */ for (server=0;server<NSERVERS;server++) { smbcli_close(cli[server][conn]->tree, fnum[server][conn][f]); fnum[server][conn][f] = -1; } for (server=0;server<NSERVERS;server++) { fnum[server][conn][f] = smbcli_open(cli[server][conn]->tree, FILENAME, O_RDWR|O_CREAT, DENY_NONE); if (fnum[server][conn][f] == -1) { printf("failed to reopen on share%d\n", server);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -