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

📄 notify.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
	for (i=0;i<d->num_entries;i++) {		d->max_mask |= d->entries[i].filter;		d->max_mask_subdir |= d->entries[i].subdir_filter;	}	return notify_save(notify);}/*  add a notify watch. This is called when a notify is first setup on a open  directory handle.*/NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,		    void (*callback)(void *, const struct notify_event *), 		    void *private_data){	struct notify_entry e = *e0;	NTSTATUS status;	char *tmp_path = NULL;	struct notify_list *listel;	size_t len;	int depth;	/* see if change notify is enabled at all */	if (notify == NULL) {		return NT_STATUS_NOT_IMPLEMENTED;	}	status = notify_lock(notify);	NT_STATUS_NOT_OK_RETURN(status);	status = notify_load(notify);	if (!NT_STATUS_IS_OK(status)) {		goto done;	}	/* cope with /. on the end of the path */	len = strlen(e.path);	if (len > 1 && e.path[len-1] == '.' && e.path[len-2] == '/') {		tmp_path = talloc_strndup(notify, e.path, len-2);		if (tmp_path == NULL) {			status = NT_STATUS_NO_MEMORY;			goto done;		}		e.path = tmp_path;	}	depth = count_chars(e.path, '/');	listel = talloc_zero(notify, struct notify_list);	if (listel == NULL) {		status = NT_STATUS_NO_MEMORY;		goto done;	}	listel->private_data = private_data;	listel->callback = callback;	listel->depth = depth;	DLIST_ADD(notify->list, listel);	/* ignore failures from sys_notify */	if (notify->sys_notify_ctx != NULL) {		/*		  this call will modify e.filter and e.subdir_filter		  to remove bits handled by the backend		*/		status = sys_notify_watch(notify->sys_notify_ctx, &e,					  sys_notify_callback, listel, 					  &listel->sys_notify_handle);		if (NT_STATUS_IS_OK(status)) {			talloc_steal(listel, listel->sys_notify_handle);		}	}	/* if the system notify handler couldn't handle some of the	   filter bits, or couldn't handle a request for recursion	   then we need to install it in the array used for the	   intra-samba notify handling */	if (e.filter != 0 || e.subdir_filter != 0) {		status = notify_add_array(notify, &e, private_data, depth);	}done:	notify_unlock(notify);	talloc_free(tmp_path);	return status;}/*  remove a notify watch. Called when the directory handle is closed*/NTSTATUS notify_remove(struct notify_context *notify, void *private_data){	NTSTATUS status;	struct notify_list *listel;	int i, depth;	struct notify_depth *d;	/* see if change notify is enabled at all */	if (notify == NULL) {		return NT_STATUS_NOT_IMPLEMENTED;	}	for (listel=notify->list;listel;listel=listel->next) {		if (listel->private_data == private_data) {			DLIST_REMOVE(notify->list, listel);			break;		}	}	if (listel == NULL) {		return NT_STATUS_OBJECT_NAME_NOT_FOUND;	}	depth = listel->depth;	talloc_free(listel);	status = notify_lock(notify);	NT_STATUS_NOT_OK_RETURN(status);	status = notify_load(notify);	if (!NT_STATUS_IS_OK(status)) {		notify_unlock(notify);		return status;	}	if (depth >= notify->array->num_depths) {		notify_unlock(notify);		return NT_STATUS_OBJECT_NAME_NOT_FOUND;	}	/* we only have to search at the depth of this element */	d = &notify->array->depth[depth];	for (i=0;i<d->num_entries;i++) {		if (private_data == d->entries[i].private_data &&		    cluster_id_equal(&notify->server, &d->entries[i].server)) {			break;		}	}	if (i == d->num_entries) {		notify_unlock(notify);		return NT_STATUS_OBJECT_NAME_NOT_FOUND;	}	if (i < d->num_entries-1) {		memmove(&d->entries[i], &d->entries[i+1], 			sizeof(d->entries[i])*(d->num_entries-(i+1)));	}	d->num_entries--;	status = notify_save(notify);	notify_unlock(notify);	return status;}/*  remove all notify watches for this messaging server*/static NTSTATUS notify_remove_all(struct notify_context *notify){	NTSTATUS status;	int i, depth, del_count=0;	if (notify->list == NULL) {		return NT_STATUS_OK;	}	status = notify_lock(notify);	NT_STATUS_NOT_OK_RETURN(status);	status = notify_load(notify);	if (!NT_STATUS_IS_OK(status)) {		notify_unlock(notify);		return status;	}	/* we have to search for all entries across all depths, looking for matches	   for our server id */	for (depth=0;depth<notify->array->num_depths;depth++) {		struct notify_depth *d = &notify->array->depth[depth];		for (i=0;i<d->num_entries;i++) {			if (cluster_id_equal(&notify->server, &d->entries[i].server)) {				if (i < d->num_entries-1) {					memmove(&d->entries[i], &d->entries[i+1], 						sizeof(d->entries[i])*(d->num_entries-(i+1)));				}				i--;				d->num_entries--;				del_count++;			}		}	}	if (del_count > 0) {		status = notify_save(notify);	}	notify_unlock(notify);	return status;}/*  send a notify message to another messaging server*/static void notify_send(struct notify_context *notify, struct notify_entry *e,			const char *path, uint32_t action){	struct notify_event ev;	DATA_BLOB data;	NTSTATUS status;	enum ndr_err_code ndr_err;	TALLOC_CTX *tmp_ctx;	ev.action = action;	ev.path = path;	ev.private_data = e->private_data;	tmp_ctx = talloc_new(notify);	ndr_err = ndr_push_struct_blob(&data, tmp_ctx, notify->iconv_convenience, &ev, (ndr_push_flags_fn_t)ndr_push_notify_event);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		talloc_free(tmp_ctx);		return;	}	status = messaging_send(notify->messaging_ctx, e->server, 				MSG_PVFS_NOTIFY, &data);	talloc_free(tmp_ctx);}/*  trigger a notify message for anyone waiting on a matching event  This function is called a lot, and needs to be very fast. The unusual data structure  and traversal is designed to be fast in the average case, even for large numbers of  notifies*/void notify_trigger(struct notify_context *notify,		    uint32_t action, uint32_t filter, const char *path){	NTSTATUS status;	int depth;	const char *p, *next_p;	/* see if change notify is enabled at all */	if (notify == NULL) {		return;	}	status = notify_load(notify);	if (!NT_STATUS_IS_OK(status)) {		return;	}	/* loop along the given path, working with each directory depth separately */	for (depth=0,p=path;	     p && depth < notify->array->num_depths;	     p=next_p,depth++) {		int p_len = p - path;		int min_i, max_i, i;		struct notify_depth *d = &notify->array->depth[depth];		next_p = strchr(p+1, '/');		/* see if there are any entries at this depth */		if (d->num_entries == 0) continue;				/* try to skip based on the maximum mask. If next_p is		 NULL then we know it will be a 'this directory'		 match, otherwise it must be a subdir match */		if (next_p != NULL) {			if (0 == (filter & d->max_mask_subdir)) {				continue;			}		} else {			if (0 == (filter & d->max_mask)) {				continue;			}		}		/* we know there is an entry here worth looking		 for. Use a bisection search to find the first entry		 with a matching path */		min_i = 0;		max_i = d->num_entries-1;		while (min_i < max_i) {			struct notify_entry *e;			int cmp;			i = (min_i+max_i)/2;			e = &d->entries[i];			cmp = strncmp(path, e->path, p_len);			if (cmp == 0) {				if (p_len == e->path_len) {					max_i = i;				} else {					max_i = i-1;				}			} else if (cmp < 0) {				max_i = i-1;			} else {				min_i = i+1;			}		}		if (min_i != max_i) {			/* none match */			continue;		}		/* we now know that the entries start at min_i */		for (i=min_i;i<d->num_entries;i++) {			struct notify_entry *e = &d->entries[i];			if (p_len != e->path_len ||			    strncmp(path, e->path, p_len) != 0) break;			if (next_p != NULL) {				if (0 == (filter & e->subdir_filter)) {					continue;				}			} else {				if (0 == (filter & e->filter)) {					continue;				}			}			notify_send(notify, e, path + e->path_len + 1, action);		}	}}

⌨️ 快捷键说明

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