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

📄 notify.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   Copyright (C) Andrew Tridgell 2006      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/>.*//*  this is the change notify database. It implements mechanisms for  storing current change notify waiters in a tdb, and checking if a  given event matches any of the stored notify waiiters.*/#include "includes.h"#include "system/filesys.h"#include "lib/tdb/include/tdb.h"#include "lib/util/util_tdb.h"#include "messaging/messaging.h"#include "tdb_wrap.h"#include "lib/messaging/irpc.h"#include "librpc/gen_ndr/ndr_notify.h"#include "lib/util/dlinklist.h"#include "ntvfs/common/ntvfs_common.h"#include "ntvfs/sysdep/sys_notify.h"#include "cluster/cluster.h"#include "param/param.h"struct notify_context {	struct tdb_wrap *w;	struct server_id server;	struct messaging_context *messaging_ctx;	struct notify_list *list;	struct notify_array *array;	int seqnum;	struct sys_notify_context *sys_notify_ctx;	struct smb_iconv_convenience *iconv_convenience;};struct notify_list {	struct notify_list *next, *prev;	void *private_data;	void (*callback)(void *, const struct notify_event *);	void *sys_notify_handle;	int depth;};#define NOTIFY_KEY "notify array"#define NOTIFY_ENABLE		"notify:enable"#define NOTIFY_ENABLE_DEFAULT	truestatic NTSTATUS notify_remove_all(struct notify_context *notify);static void notify_handler(struct messaging_context *msg_ctx, void *private_data, 			   uint32_t msg_type, struct server_id server_id, DATA_BLOB *data);/*  destroy the notify context*/static int notify_destructor(struct notify_context *notify){	messaging_deregister(notify->messaging_ctx, MSG_PVFS_NOTIFY, notify);	notify_remove_all(notify);	return 0;}/*  Open up the notify.tdb database. You should close it down using  talloc_free(). We need the messaging_ctx to allow for notifications  via internal messages*/struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server, 				   struct messaging_context *messaging_ctx,				   struct loadparm_context *lp_ctx,				   struct event_context *ev,				   struct share_config *scfg){	struct notify_context *notify;	if (share_bool_option(scfg, NOTIFY_ENABLE, NOTIFY_ENABLE_DEFAULT) != true) {		return NULL;	}	if (ev == NULL) {		return NULL;	}	notify = talloc(mem_ctx, struct notify_context);	if (notify == NULL) {		return NULL;	}	notify->w = cluster_tdb_tmp_open(notify, lp_ctx, "notify.tdb", TDB_SEQNUM);	if (notify->w == NULL) {		talloc_free(notify);		return NULL;	}	notify->server = server;	notify->messaging_ctx = messaging_ctx;	notify->list = NULL;	notify->array = NULL;	notify->iconv_convenience = lp_iconv_convenience(lp_ctx);	notify->seqnum = tdb_get_seqnum(notify->w->tdb);	talloc_set_destructor(notify, notify_destructor);	/* register with the messaging subsystem for the notify	   message type */	messaging_register(notify->messaging_ctx, notify, 			   MSG_PVFS_NOTIFY, notify_handler);	notify->sys_notify_ctx = sys_notify_context_create(scfg, notify, ev);	return notify;}/*  lock the notify db*/static NTSTATUS notify_lock(struct notify_context *notify){	if (tdb_lock_bystring(notify->w->tdb, NOTIFY_KEY) != 0) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	return NT_STATUS_OK;}/*  unlock the notify db*/static void notify_unlock(struct notify_context *notify){	tdb_unlock_bystring(notify->w->tdb, NOTIFY_KEY);}/*  load the notify array*/static NTSTATUS notify_load(struct notify_context *notify){	TDB_DATA dbuf;	DATA_BLOB blob;	enum ndr_err_code ndr_err;	int seqnum;	seqnum = tdb_get_seqnum(notify->w->tdb);	if (seqnum == notify->seqnum && notify->array != NULL) {		return NT_STATUS_OK;	}	notify->seqnum = seqnum;	talloc_free(notify->array);	notify->array = talloc_zero(notify, struct notify_array);	NT_STATUS_HAVE_NO_MEMORY(notify->array);	dbuf = tdb_fetch_bystring(notify->w->tdb, NOTIFY_KEY);	if (dbuf.dptr == NULL) {		return NT_STATUS_OK;	}	blob.data = dbuf.dptr;	blob.length = dbuf.dsize;	ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->iconv_convenience,				       notify->array,				       (ndr_pull_flags_fn_t)ndr_pull_notify_array);	free(dbuf.dptr);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return ndr_map_error2ntstatus(ndr_err);	}	return NT_STATUS_OK;}/*  compare notify entries for sorting*/static int notify_compare(const void *p1, const void *p2){	const struct notify_entry *e1 = p1, *e2 = p2;	return strcmp(e1->path, e2->path);}/*  save the notify array*/static NTSTATUS notify_save(struct notify_context *notify){	TDB_DATA dbuf;	DATA_BLOB blob;	enum ndr_err_code ndr_err;	int ret;	TALLOC_CTX *tmp_ctx;	/* if possible, remove some depth arrays */	while (notify->array->num_depths > 0 &&	       notify->array->depth[notify->array->num_depths-1].num_entries == 0) {		notify->array->num_depths--;	}	/* we might just be able to delete the record */	if (notify->array->num_depths == 0) {		ret = tdb_delete_bystring(notify->w->tdb, NOTIFY_KEY);		if (ret != 0) {			return NT_STATUS_INTERNAL_DB_CORRUPTION;		}		return NT_STATUS_OK;	}	tmp_ctx = talloc_new(notify);	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);	ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->iconv_convenience, notify->array,				       (ndr_push_flags_fn_t)ndr_push_notify_array);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		talloc_free(tmp_ctx);		return ndr_map_error2ntstatus(ndr_err);	}	dbuf.dptr = blob.data;	dbuf.dsize = blob.length;			ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE);	talloc_free(tmp_ctx);	if (ret != 0) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	return NT_STATUS_OK;}/*  handle incoming notify messages*/static void notify_handler(struct messaging_context *msg_ctx, void *private_data, 			   uint32_t msg_type, struct server_id server_id, DATA_BLOB *data){	struct notify_context *notify = talloc_get_type(private_data, struct notify_context);	enum ndr_err_code ndr_err;	struct notify_event ev;	TALLOC_CTX *tmp_ctx = talloc_new(notify);	struct notify_list *listel;	if (tmp_ctx == NULL) {		return;	}	ndr_err = ndr_pull_struct_blob(data, tmp_ctx, notify->iconv_convenience, &ev,				      (ndr_pull_flags_fn_t)ndr_pull_notify_event);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		talloc_free(tmp_ctx);		return;	}	for (listel=notify->list;listel;listel=listel->next) {		if (listel->private_data == ev.private_data) {			listel->callback(listel->private_data, &ev);			break;		}	}	talloc_free(tmp_ctx);	}/*  callback from sys_notify telling us about changes from the OS*/static void sys_notify_callback(struct sys_notify_context *ctx, 				void *ptr, struct notify_event *ev){	struct notify_list *listel = talloc_get_type(ptr, struct notify_list);	ev->private_data = listel;	listel->callback(listel->private_data, ev);}/*  add an entry to the notify array*/static NTSTATUS notify_add_array(struct notify_context *notify, struct notify_entry *e,				 void *private_data, int depth){	int i;	struct notify_depth *d;	struct notify_entry *ee;	/* possibly expand the depths array */	if (depth >= notify->array->num_depths) {		d = talloc_realloc(notify->array, notify->array->depth, 				   struct notify_depth, depth+1);		NT_STATUS_HAVE_NO_MEMORY(d);		for (i=notify->array->num_depths;i<=depth;i++) {			ZERO_STRUCT(d[i]);		}		notify->array->depth = d;		notify->array->num_depths = depth+1;	}	d = &notify->array->depth[depth];	/* expand the entries array */	ee = talloc_realloc(notify->array->depth, d->entries, struct notify_entry,			    d->num_entries+1);	NT_STATUS_HAVE_NO_MEMORY(ee);	d->entries = ee;	d->entries[d->num_entries] = *e;	d->entries[d->num_entries].private_data = private_data;	d->entries[d->num_entries].server = notify->server;	d->entries[d->num_entries].path_len = strlen(e->path);	d->num_entries++;	d->max_mask |= e->filter;	d->max_mask_subdir |= e->subdir_filter;	if (d->num_entries > 1) {		qsort(d->entries, d->num_entries, sizeof(d->entries[0]), notify_compare);	}	/* recalculate the maximum masks */	d->max_mask = 0;	d->max_mask_subdir = 0;

⌨️ 快捷键说明

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