⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 notify.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    Unix SMB/CIFS implementation.   basic raw test suite for change notify   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 "libcli/libcli.h"#include "system/filesys.h"#include "torture/util.h"#include "param/param.h"#define BASEDIR "\\test_notify"#define CHECK_STATUS(status, correct) do { \	if (!NT_STATUS_EQUAL(status, correct)) { \		printf("(%d) Incorrect status %s - should be %s\n", \		       __LINE__, nt_errstr(status), nt_errstr(correct)); \		ret = false; \		goto done; \	}} while (0)#define CHECK_VAL(v, correct) do { \	if ((v) != (correct)) { \		printf("(%d) wrong value for %s  0x%x should be 0x%x\n", \		       __LINE__, #v, (int)v, (int)correct); \		ret = false; \		goto done; \	}} while (0)#define CHECK_WSTR(field, value, flags) do { \	if (!field.s || strcmp(field.s, value) || wire_bad_flags(&field, flags, cli->transport)) { \		printf("(%d) %s [%s] != %s\n",  __LINE__, #field, field.s, value); \			ret = false; \		goto done; \	}} while (0)/*    basic testing of change notify on directories*/static bool test_notify_dir(struct smbcli_state *cli, struct smbcli_state *cli2, 			    TALLOC_CTX *mem_ctx){	bool ret = true;	NTSTATUS status;	union smb_notify notify;	union smb_open io;	union smb_close cl;	int i, count, fnum, fnum2;	struct smbcli_request *req, *req2;	extern int torture_numops;	printf("TESTING CHANGE NOTIFY ON DIRECTRIES\n");			/*	  get a handle on the directory	*/	io.generic.level = RAW_OPEN_NTCREATEX;	io.ntcreatex.in.root_fid = 0;	io.ntcreatex.in.flags = 0;	io.ntcreatex.in.access_mask = SEC_FILE_ALL;	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;	io.ntcreatex.in.alloc_size = 0;	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;	io.ntcreatex.in.security_flags = 0;	io.ntcreatex.in.fname = BASEDIR;	status = smb_raw_open(cli->tree, mem_ctx, &io);	CHECK_STATUS(status, NT_STATUS_OK);	fnum = io.ntcreatex.out.file.fnum;	status = smb_raw_open(cli->tree, mem_ctx, &io);	CHECK_STATUS(status, NT_STATUS_OK);	fnum2 = io.ntcreatex.out.file.fnum;	/* ask for a change notify,	   on file or directory name changes */	notify.nttrans.level = RAW_NOTIFY_NTTRANS;	notify.nttrans.in.buffer_size = 1000;	notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;	notify.nttrans.in.file.fnum = fnum;	notify.nttrans.in.recursive = true;	printf("testing notify cancel\n");	req = smb_raw_changenotify_send(cli->tree, &notify);	smb_raw_ntcancel(req);	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_CANCELLED);	printf("testing notify mkdir\n");	req = smb_raw_changenotify_send(cli->tree, &notify);	smbcli_mkdir(cli2->tree, BASEDIR "\\subdir-name");	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 1);	CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);	CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);	printf("testing notify rmdir\n");	req = smb_raw_changenotify_send(cli->tree, &notify);	smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 1);	CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);	printf("testing notify mkdir - rmdir - mkdir - rmdir\n");	smbcli_mkdir(cli2->tree, BASEDIR "\\subdir-name");	smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");	smbcli_mkdir(cli2->tree, BASEDIR "\\subdir-name");	smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");	msleep(200);	req = smb_raw_changenotify_send(cli->tree, &notify);	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 4);	CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);	CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_ADDED);	CHECK_WSTR(notify.nttrans.out.changes[2].name, "subdir-name", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[3].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[3].name, "subdir-name", STR_UNICODE);	count = torture_numops;	printf("testing buffered notify on create of %d files\n", count);	for (i=0;i<count;i++) {		char *fname = talloc_asprintf(cli, BASEDIR "\\test%d.txt", i);		int fnum3 = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);		if (fnum3 == -1) {			printf("Failed to create %s - %s\n", 			       fname, smbcli_errstr(cli->tree));			ret = false;			goto done;		}		talloc_free(fname);		smbcli_close(cli->tree, fnum3);	}	/* (1st notify) setup a new notify on a different directory handle.	   This new notify won't see the events above. */	notify.nttrans.in.file.fnum = fnum2;	req2 = smb_raw_changenotify_send(cli->tree, &notify);	/* (2nd notify) whereas this notify will see the above buffered events,	   and it directly returns the buffered events */	notify.nttrans.in.file.fnum = fnum;	req = smb_raw_changenotify_send(cli->tree, &notify);	status = smbcli_unlink(cli->tree, BASEDIR "\\nonexistant.txt");	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);	/* (1st unlink) as the 2nd notify directly returns,	   this unlink is only seen by the 1st notify and 	   the 3rd notify (later) */	printf("testing notify on unlink for the first file\n");	status = smbcli_unlink(cli2->tree, BASEDIR "\\test0.txt");	CHECK_STATUS(status, NT_STATUS_OK);	/* receive the reply from the 2nd notify */	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, count);	for (i=1;i<count;i++) {		CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_ADDED);	}	CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);	printf("and now from the 1st notify\n");	status = smb_raw_changenotify_recv(req2, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 1);	CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);	printf("(3rd notify) this notify will only see the 1st unlink\n");	req = smb_raw_changenotify_send(cli->tree, &notify);	status = smbcli_unlink(cli->tree, BASEDIR "\\nonexistant.txt");	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);	printf("testing notify on wildcard unlink for %d files\n", count-1);	/* (2nd unlink) do a wildcard unlink */	status = smbcli_unlink(cli2->tree, BASEDIR "\\test*.txt");	CHECK_STATUS(status, NT_STATUS_OK);	/* receive the 3rd notify */	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 1);	CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[0].name, "test0.txt", STR_UNICODE);	/* and we now see the rest of the unlink calls on both directory handles */	notify.nttrans.in.file.fnum = fnum;	sleep(3);	req = smb_raw_changenotify_send(cli->tree, &notify);	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, count-1);	for (i=0;i<notify.nttrans.out.num_changes;i++) {		CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_REMOVED);	}	notify.nttrans.in.file.fnum = fnum2;	req = smb_raw_changenotify_send(cli->tree, &notify);	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, count-1);	for (i=0;i<notify.nttrans.out.num_changes;i++) {		CHECK_VAL(notify.nttrans.out.changes[i].action, NOTIFY_ACTION_REMOVED);	}	printf("testing if a close() on the dir handle triggers the notify reply\n");	notify.nttrans.in.file.fnum = fnum;	req = smb_raw_changenotify_send(cli->tree, &notify);	cl.close.level = RAW_CLOSE_CLOSE;	cl.close.in.file.fnum = fnum;	cl.close.in.write_time = 0;	status = smb_raw_close(cli->tree, &cl);	CHECK_STATUS(status, NT_STATUS_OK);	status = smb_raw_changenotify_recv(req, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 0);done:	smb_raw_exit(cli->session);	return ret;}/* * Check notify reply for a rename action. Not sure if this is a valid thing * to do, but depending on timing between inotify and messaging we get the * add/remove/modify in any order. This routines tries to find the action/name * pair in any of the three following notify_changes. */static bool check_rename_reply(struct smbcli_state *cli,			       int line,			       struct notify_changes *actions,			       uint32_t action, const char *name){	int i;	for (i=0; i<3; i++) {		if (actions[i].action == action) {			if ((actions[i].name.s == NULL)			    || (strcmp(actions[i].name.s, name) != 0)			    || (wire_bad_flags(&actions[i].name, STR_UNICODE,					       cli->transport))) {				printf("(%d) name [%s] != %s\n", line,				       actions[i].name.s, name);				return false;			}			return true;		}	}	printf("(%d) expected action %d, not found\n", line, action);	return false;}/*    testing of recursive change notify*/static bool test_notify_recursive(struct smbcli_state *cli, TALLOC_CTX *mem_ctx){	bool ret = true;	NTSTATUS status;	union smb_notify notify;	union smb_open io;	int fnum;	struct smbcli_request *req1, *req2;	printf("TESTING CHANGE NOTIFY WITH RECURSION\n");			/*	  get a handle on the directory	*/	io.generic.level = RAW_OPEN_NTCREATEX;	io.ntcreatex.in.root_fid = 0;	io.ntcreatex.in.flags = 0;	io.ntcreatex.in.access_mask = SEC_FILE_ALL;	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;	io.ntcreatex.in.alloc_size = 0;	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;	io.ntcreatex.in.security_flags = 0;	io.ntcreatex.in.fname = BASEDIR;	status = smb_raw_open(cli->tree, mem_ctx, &io);	CHECK_STATUS(status, NT_STATUS_OK);	fnum = io.ntcreatex.out.file.fnum;	/* ask for a change notify, on file or directory name	   changes. Setup both with and without recursion */	notify.nttrans.level = RAW_NOTIFY_NTTRANS;	notify.nttrans.in.buffer_size = 1000;	notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_CREATION;	notify.nttrans.in.file.fnum = fnum;	notify.nttrans.in.recursive = true;	req1 = smb_raw_changenotify_send(cli->tree, &notify);	notify.nttrans.in.recursive = false;	req2 = smb_raw_changenotify_send(cli->tree, &notify);	/* cancel initial requests so the buffer is setup */	smb_raw_ntcancel(req1);	status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_CANCELLED);	smb_raw_ntcancel(req2);	status = smb_raw_changenotify_recv(req2, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_CANCELLED);	smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name");	smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name\\subname1");	smbcli_close(cli->tree, 		     smbcli_open(cli->tree, BASEDIR "\\subdir-name\\subname2", O_CREAT, 0));	smbcli_rename(cli->tree, BASEDIR "\\subdir-name\\subname1", BASEDIR "\\subdir-name\\subname1-r");	smbcli_rename(cli->tree, BASEDIR "\\subdir-name\\subname2", BASEDIR "\\subname2-r");	smbcli_rename(cli->tree, BASEDIR "\\subname2-r", BASEDIR "\\subname3-r");	notify.nttrans.in.completion_filter = 0;	notify.nttrans.in.recursive = true;	msleep(200);	req1 = smb_raw_changenotify_send(cli->tree, &notify);	smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name\\subname1-r");	smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name");	smbcli_unlink(cli->tree, BASEDIR "\\subname3-r");	notify.nttrans.in.recursive = false;	req2 = smb_raw_changenotify_send(cli->tree, &notify);	status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 11);	CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED);	CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_ADDED);	CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name\\subname1", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_ADDED);	CHECK_WSTR(notify.nttrans.out.changes[2].name, "subdir-name\\subname2", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[3].action, NOTIFY_ACTION_OLD_NAME);	CHECK_WSTR(notify.nttrans.out.changes[3].name, "subdir-name\\subname1", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[4].action, NOTIFY_ACTION_NEW_NAME);	CHECK_WSTR(notify.nttrans.out.changes[4].name, "subdir-name\\subname1-r", STR_UNICODE);	ret &= check_rename_reply(		cli, __LINE__, &notify.nttrans.out.changes[5],		NOTIFY_ACTION_ADDED, "subname2-r");	ret &= check_rename_reply(		cli, __LINE__, &notify.nttrans.out.changes[5],		NOTIFY_ACTION_REMOVED, "subdir-name\\subname2");	ret &= check_rename_reply(		cli, __LINE__, &notify.nttrans.out.changes[5],		NOTIFY_ACTION_MODIFIED, "subname2-r");			ret &= check_rename_reply(		cli, __LINE__, &notify.nttrans.out.changes[8],		NOTIFY_ACTION_OLD_NAME, "subname2-r");	ret &= check_rename_reply(		cli, __LINE__, &notify.nttrans.out.changes[8],		NOTIFY_ACTION_NEW_NAME, "subname3-r");	ret &= check_rename_reply(		cli, __LINE__, &notify.nttrans.out.changes[8],		NOTIFY_ACTION_MODIFIED, "subname3-r");	if (!ret) {		goto done;	}	status = smb_raw_changenotify_recv(req2, mem_ctx, &notify);	CHECK_STATUS(status, NT_STATUS_OK);	CHECK_VAL(notify.nttrans.out.num_changes, 3);	CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name\\subname1-r", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[1].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[1].name, "subdir-name", STR_UNICODE);	CHECK_VAL(notify.nttrans.out.changes[2].action, NOTIFY_ACTION_REMOVED);	CHECK_WSTR(notify.nttrans.out.changes[2].name, "subname3-r", STR_UNICODE);done:	smb_raw_exit(cli->session);	return ret;}/*    testing of change notify mask change*/static bool test_notify_mask_change(struct smbcli_state *cli, TALLOC_CTX *mem_ctx){	bool ret = true;	NTSTATUS status;	union smb_notify notify;	union smb_open io;	int fnum;	struct smbcli_request *req1, *req2;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -