[PATCH] Preparatory patches for new notify

Volker Lendecke Volker.Lendecke at SerNet.DE
Fri Dec 12 06:33:25 MST 2014


Hi!

Attached find some patches that notify_msg/notifyd will make
use of.

Review&push appreciated!

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 2e132d086f7c2b10b149bd514b183640992b6513 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sun, 14 Sep 2014 13:10:58 +0200
Subject: [PATCH 01/10] lib: Add map_unix_error_from_tdb

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/util_tdb.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/util/util_tdb.h |  7 ++++++-
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/lib/util/util_tdb.c b/lib/util/util_tdb.c
index 811c2a4..f84ab33 100644
--- a/lib/util/util_tdb.c
+++ b/lib/util/util_tdb.c
@@ -426,3 +426,60 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err)
 	};
 	return result;
 }
+
+int map_unix_error_from_tdb(enum TDB_ERROR err)
+{
+	int result = EINVAL;
+
+	switch (err) {
+	case TDB_SUCCESS:
+		result = 0;
+		break;
+	case TDB_ERR_CORRUPT:
+		result = EILSEQ;
+		break;
+	case TDB_ERR_IO:
+		result = EIO;
+		break;
+	case TDB_ERR_OOM:
+		result = ENOMEM;
+		break;
+	case TDB_ERR_EXISTS:
+		result = EEXIST;
+		break;
+
+	case TDB_ERR_LOCK:
+		/*
+		 * TDB_ERR_LOCK is very broad, we could for example
+		 * distinguish between fcntl locks and invalid lock
+		 * sequences. EWOULDBLOCK is wrong, but there is no real
+		 * generic lock error code in errno.h
+		 */
+		result = EWOULDBLOCK;
+		break;
+
+	case TDB_ERR_NOLOCK:
+	case TDB_ERR_LOCK_TIMEOUT:
+		/*
+		 * These two ones in the enum are not actually used
+		 */
+		result = ENOLCK;
+		break;
+	case TDB_ERR_NOEXIST:
+		result = ENOENT;
+		break;
+	case TDB_ERR_EINVAL:
+		result = EINVAL;
+		break;
+	case TDB_ERR_RDONLY:
+		result = EROFS;
+		break;
+	case TDB_ERR_NESTING:
+		/*
+		 * Well, this db is already busy...
+		 */
+		result = EBUSY;
+		break;
+	};
+	return result;
+}
diff --git a/lib/util/util_tdb.h b/lib/util/util_tdb.h
index 12c472c..7a457f7 100644
--- a/lib/util/util_tdb.h
+++ b/lib/util/util_tdb.h
@@ -139,5 +139,10 @@ int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA d
 
 NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err);
 
-#endif /* _____LIB_UTIL_UTIL_TDB_H__ */
+/****************************************************************************
+ Return an errno from a TDB_ERROR
+****************************************************************************/
 
+int map_unix_error_from_tdb(enum TDB_ERROR err);
+
+#endif /* _____LIB_UTIL_UTIL_TDB_H__ */
-- 
2.1.2


From f4cb21c092c97df86d06ceb22219312ba8b53462 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 21 Oct 2014 10:39:53 +0000
Subject: [PATCH 02/10] lib: Add tdb_fetch_talloc

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/util_tdb.c | 33 +++++++++++++++++++++++++++++++++
 lib/util/util_tdb.h |  3 +++
 2 files changed, 36 insertions(+)

diff --git a/lib/util/util_tdb.c b/lib/util/util_tdb.c
index f84ab33..9bf18dc 100644
--- a/lib/util/util_tdb.c
+++ b/lib/util/util_tdb.c
@@ -483,3 +483,36 @@ int map_unix_error_from_tdb(enum TDB_ERROR err)
 	};
 	return result;
 }
+
+struct tdb_fetch_talloc_state {
+	TALLOC_CTX *mem_ctx;
+	uint8_t *buf;
+};
+
+static int tdb_fetch_talloc_parser(TDB_DATA key, TDB_DATA data,
+                                   void *private_data)
+{
+	struct tdb_fetch_talloc_state *state = private_data;
+	state->buf = talloc_memdup(state->mem_ctx, data.dptr, data.dsize);
+	return 0;
+}
+
+int tdb_fetch_talloc(struct tdb_context *tdb, TDB_DATA key,
+		     TALLOC_CTX *mem_ctx, uint8_t **buf)
+{
+	struct tdb_fetch_talloc_state state = { .mem_ctx = mem_ctx };
+	int ret;
+
+	ret = tdb_parse_record(tdb, key, tdb_fetch_talloc_parser, &state);
+	if (ret == -1) {
+		enum TDB_ERROR err = tdb_error(tdb);
+		return map_unix_error_from_tdb(err);
+	}
+
+	if (state.buf == NULL) {
+		return ENOMEM;
+	}
+
+	*buf = state.buf;
+	return 0;
+}
diff --git a/lib/util/util_tdb.h b/lib/util/util_tdb.h
index 7a457f7..3b50789 100644
--- a/lib/util/util_tdb.h
+++ b/lib/util/util_tdb.h
@@ -145,4 +145,7 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err);
 
 int map_unix_error_from_tdb(enum TDB_ERROR err);
 
+int tdb_fetch_talloc(struct tdb_context *tdb, TDB_DATA key,
+		     TALLOC_CTX *mem_ctx, uint8_t **buf);
+
 #endif /* _____LIB_UTIL_UTIL_TDB_H__ */
-- 
2.1.2


From ba58eb0633a1127ceebdadeb7e89138c94e43c18 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 15 Oct 2014 13:26:51 +0000
Subject: [PATCH 03/10] lib: Add "strv" string handling routines

This is a little set of routines designed after the glibc argz
routines. It is supposed to eventually replace our inefficient string_list
routines. A talloc blob is an array of strings separated by the \0
character. See argz(3) on a Linux system for the ideas where this came
from. Based on talloc strv is simpler because talloc knows about the
size of the blob, so we don't have to explicitly maintain it.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/strv.c        | 141 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/util/strv.h        |  32 +++++++++++
 lib/util/wscript_build |   5 ++
 3 files changed, 178 insertions(+)
 create mode 100644 lib/util/strv.c
 create mode 100644 lib/util/strv.h

diff --git a/lib/util/strv.c b/lib/util/strv.c
new file mode 100644
index 0000000..2acd145
--- /dev/null
+++ b/lib/util/strv.c
@@ -0,0 +1,141 @@
+/*
+ * String Vector functions modeled after glibc argv_* functions
+ *
+ * Copyright Volker Lendecke <vl at samba.org> 2014
+ *
+ * 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 "replace.h"
+#include "strv.h"
+#include "talloc.h"
+#include <string.h>
+
+static int _strv_append(TALLOC_CTX *mem_ctx, char **dst, const char *src,
+			size_t srclen)
+{
+	size_t dstlen = talloc_array_length(*dst);
+	size_t newlen = dstlen + srclen;
+	char *new_dst;
+
+	if ((newlen < srclen) || (newlen < dstlen)) {
+		return ERANGE;
+	}
+
+	new_dst = talloc_realloc(mem_ctx, *dst, char, newlen);
+	if (new_dst == NULL) {
+		return ENOMEM;
+	}
+	memcpy(&new_dst[dstlen], src, srclen);
+
+	*dst = new_dst;
+	return 0;
+}
+
+int strv_add(TALLOC_CTX *mem_ctx, char **strv, const char *string)
+{
+	return _strv_append(mem_ctx, strv, string, strlen(string)+1);
+}
+
+int strv_append(TALLOC_CTX *mem_ctx, char **strv, const char *src)
+{
+	return _strv_append(mem_ctx, strv, src, talloc_array_length(src));
+}
+
+static bool strv_valid_entry(const char *strv, const char *entry,
+			     size_t *strv_len, size_t *entry_len)
+{
+	size_t len;
+
+	len = talloc_array_length(strv);
+	if (len == 0) {
+		return false;
+	}
+	if (strv[len-1] != '\0') {
+		return false;
+	}
+
+	if (entry < strv) {
+		return false;
+	}
+	if (entry >= (strv+len)) {
+		return false;
+	}
+
+	*strv_len = len;
+	*entry_len = strlen(entry);
+
+	return true;
+}
+
+char *strv_next(char *strv, const char *entry)
+{
+	size_t len, entry_len;
+	char *result;
+
+	if (!strv_valid_entry(strv, entry, &len, &entry_len)) {
+		return NULL;
+	}
+	result = &strv[entry - strv]; /* avoid const problems with this stmt */
+	result += entry_len + 1;
+
+	if (result >= (strv + len)) {
+		return NULL;
+	}
+	return result;
+}
+
+size_t strv_count(char *strv)
+{
+	char *entry;
+	size_t count = 0;
+
+	for (entry = strv; entry != NULL; entry = strv_next(strv, entry)) {
+		count += 1;
+	}
+
+	return count;
+}
+
+char *strv_find(char *strv, const char *entry)
+{
+	char *e = NULL;
+
+	while ((e = strv_next(strv, e)) != NULL) {
+		if (strcmp(e, entry) == 0) {
+			return e;
+		}
+	}
+
+	return NULL;
+}
+
+void strv_delete(char **strv, char *entry)
+{
+	size_t len, entry_len;
+
+	if (entry == NULL) {
+		return;
+	}
+
+	if (!strv_valid_entry(*strv, entry, &len, &entry_len)) {
+		return;
+	}
+	entry_len += 1;
+
+	memmove(entry, entry+entry_len,
+		len - entry_len - (entry - *strv));
+
+	*strv = talloc_realloc(NULL, *strv, char, len - entry_len);
+}
diff --git a/lib/util/strv.h b/lib/util/strv.h
new file mode 100644
index 0000000..843ce5c
--- /dev/null
+++ b/lib/util/strv.h
@@ -0,0 +1,32 @@
+/*
+ * String Vector functions modeled after glibc argv_* functions
+ *
+ * Copyright Volker Lendecke <vl at samba.org> 2014
+ *
+ * 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/>.
+ */
+
+#ifndef _STRV_H_
+#define _STRV_H_
+
+#include "talloc.h"
+
+int strv_add(TALLOC_CTX *mem_ctx, char **strv, const char *string);
+int strv_append(TALLOC_CTX *mem_ctx, char **strv, const char *src);
+char *strv_next(char *strv, const char *entry);
+char *strv_find(char *strv, const char *entry);
+size_t strv_count(char *strv);
+void strv_delete(char **strv, char *entry);
+
+#endif
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index cd23231..83d0bf1 100755
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -15,6 +15,11 @@ bld.SAMBA_SUBSYSTEM('tiniparser',
                     deps='tini',
                     local_include=False)
 
+bld.SAMBA_SUBSYSTEM('strv',
+                    source='strv.c',
+                    deps='talloc',
+                    local_include=False)
+
 bld.SAMBA_SUBSYSTEM('close-low-fd',
                     source='close_low_fd.c',
                     deps='replace',
-- 
2.1.2


From f92b39578a12a8be02f127bd69c0c3752ee05d86 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 15 Oct 2014 16:14:42 +0000
Subject: [PATCH 04/10] lib: Add server_id_db

This is a mapping from names to server_ids. In the future, this will
replace the namedb in source4/messaging.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/server_id_db.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/util/server_id_db.h |  47 ++++++++
 lib/util/wscript_build  |   5 +
 3 files changed, 360 insertions(+)
 create mode 100644 lib/util/server_id_db.c
 create mode 100644 lib/util/server_id_db.h

diff --git a/lib/util/server_id_db.c b/lib/util/server_id_db.c
new file mode 100644
index 0000000..7f5b055
--- /dev/null
+++ b/lib/util/server_id_db.c
@@ -0,0 +1,308 @@
+/*
+ * Map names to server_ids
+ *
+ * Copyright Volker Lendecke <vl at samba.org> 2014
+ *
+ * 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 "replace.h"
+#include "system/filesys.h"
+#include "lib/util/server_id_db.h"
+#include "lib/tdb_wrap/tdb_wrap.h"
+#include "lib/util/strv.h"
+#include "lib/util/util_tdb.h"
+#include "lib/util/samba_util.h"
+
+static TDB_DATA talloc_tdb_data(void *ptr)
+{
+	return (TDB_DATA) { .dptr = ptr, .dsize = talloc_get_size(ptr) };
+}
+
+struct server_id_db {
+	struct server_id pid;
+	struct tdb_wrap *tdb;
+	char *names;
+};
+
+static int server_id_db_destructor(struct server_id_db *db);
+
+struct server_id_db *server_id_db_init(TALLOC_CTX *mem_ctx,
+				       struct server_id pid,
+				       const char *base_path,
+				       int hash_size, int tdb_flags)
+{
+	struct server_id_db *db;
+	size_t pathlen = strlen(base_path) + 11;
+	char path[pathlen];
+
+	db = talloc(mem_ctx, struct server_id_db);
+	if (db == NULL) {
+		return NULL;
+	}
+	db->pid = pid;
+	db->names = NULL;
+
+	snprintf(path, pathlen, "%s/names.tdb", base_path);
+
+	db->tdb = tdb_wrap_open(db, path, hash_size, tdb_flags,
+				O_RDWR|O_CREAT, 0660);
+	if (db->tdb == NULL) {
+		TALLOC_FREE(db);
+		return NULL;
+	}
+
+	talloc_set_destructor(db, server_id_db_destructor);
+
+	return db;
+}
+
+void server_id_db_reinit(struct server_id_db *db, struct server_id pid)
+{
+	db->pid = pid;
+	TALLOC_FREE(db->names);
+}
+
+static int server_id_db_destructor(struct server_id_db *db)
+{
+	char *name = NULL;
+
+	while ((name = strv_next(db->names, name)) != NULL) {
+		server_id_db_remove(db, name);
+	}
+
+	return 0;
+}
+
+int server_id_db_add(struct server_id_db *db, const char *name)
+{
+	struct tdb_context *tdb = db->tdb->tdb;
+	struct server_id_buf buf;
+	TDB_DATA key, data;
+	char *n;
+	int ret;
+
+	n = strv_find(db->names, name);
+	if (n != NULL) {
+		return EEXIST;
+	}
+
+	ret = strv_add(db, &db->names, name);
+	if (ret != 0) {
+		return ret;
+	}
+
+	key = string_term_tdb_data(name);
+
+	server_id_str_buf(db->pid, &buf);
+	data = string_term_tdb_data(buf.buf);
+
+	ret = tdb_append(tdb, key, data);
+	if (ret != 0) {
+		enum TDB_ERROR err = tdb_error(tdb);
+		strv_delete(&db->names, strv_find(db->names, name));
+		return map_unix_error_from_tdb(err);
+	}
+
+	return 0;
+}
+
+int server_id_db_remove(struct server_id_db *db, const char *name)
+{
+	struct tdb_context *tdb = db->tdb->tdb;
+	struct server_id_buf buf;
+	TDB_DATA key;
+	uint8_t *data;
+	char *ids, *n, *id;
+	int ret;
+
+	n = strv_find(db->names, name);
+	if (n == NULL) {
+		return ENOENT;
+	}
+
+	key = string_term_tdb_data(name);
+	server_id_str_buf(db->pid, &buf);
+
+	ret = tdb_chainlock(tdb, key);
+	if (ret == -1) {
+		enum TDB_ERROR err = tdb_error(tdb);
+		return map_unix_error_from_tdb(err);
+	}
+
+	ret = tdb_fetch_talloc(tdb, key, db, &data);
+	if (ret != 0) {
+		tdb_chainunlock(tdb, key);
+		return ret;
+	}
+
+	ids = (char *)data;
+
+	id = strv_find(ids, buf.buf);
+	if (id == NULL) {
+		tdb_chainunlock(tdb, key);
+		TALLOC_FREE(data);
+		return ENOENT;
+	}
+
+	strv_delete(&ids, id);
+	ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY);
+	TALLOC_FREE(data);
+
+	tdb_chainunlock(tdb, key);
+
+	if (ret == -1) {
+		enum TDB_ERROR err = tdb_error(tdb);
+		return map_unix_error_from_tdb(err);
+	}
+
+	strv_delete(&db->names, n);
+	return 0;
+}
+
+int server_id_db_lookup(struct server_id_db *db, const char *name,
+			TALLOC_CTX *mem_ctx, unsigned *pnum_servers,
+			struct server_id **pservers)
+{
+	struct tdb_context *tdb = db->tdb->tdb;
+	TDB_DATA key;
+	uint8_t *data;
+	char *ids, *id;
+	unsigned num_servers;
+	struct server_id *servers;
+	int i, ret;
+
+	key = string_term_tdb_data(name);
+
+	ret = tdb_fetch_talloc(tdb, key, mem_ctx, &data);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ids = (char *)data;
+	num_servers = strv_count(ids);
+
+	servers = talloc_array(mem_ctx, struct server_id, num_servers);
+	if (servers == NULL) {
+		TALLOC_FREE(data);
+		return ENOMEM;
+	}
+
+	i = 0;
+
+	for (id = ids; id != NULL; id = strv_next(ids, id)) {
+		servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
+	}
+
+	TALLOC_FREE(data);
+
+	*pnum_servers = num_servers;
+	*pservers = servers;
+
+	return 0;
+}
+
+bool server_id_db_lookup_one(struct server_id_db *db, const char *name,
+			     struct server_id *server)
+{
+	int ret;
+	unsigned num_servers;
+	struct server_id *servers;
+
+	ret = server_id_db_lookup(db, name, db, &num_servers, &servers);
+	if (ret != 0) {
+		return false;
+	}
+	if (num_servers == 0) {
+		TALLOC_FREE(servers);
+		return false;
+	}
+	*server = servers[0];
+	TALLOC_FREE(servers);
+	return true;
+}
+
+struct server_id_db_traverse_state {
+	TALLOC_CTX *mem_ctx;
+	int (*fn)(const char *name,
+		  unsigned num_servers,
+		  const struct server_id *servers,
+		  void *private_data);
+	void *private_data;
+};
+
+static int server_id_db_traverse_fn(struct tdb_context *tdb,
+				    TDB_DATA key, TDB_DATA data,
+				    void *private_data)
+{
+	struct server_id_db_traverse_state *state = private_data;
+	const char *name;
+	char *ids, *id;
+	unsigned num_servers;
+	struct server_id *servers;
+	int i, ret;
+
+	if (key.dsize == 0) {
+		return 0;
+	}
+	if (key.dptr[key.dsize-1] != '\0') {
+		return 0;
+	}
+	name = (const char *)key.dptr;
+
+	ids = (char *)talloc_memdup(state->mem_ctx, data.dptr, data.dsize);
+	if (ids == NULL) {
+		return 0;
+	}
+
+	num_servers = strv_count(ids);
+	servers = talloc_array(ids, struct server_id, num_servers);
+
+	i = 0;
+
+	for (id = ids; id != NULL; id = strv_next(ids, id)) {
+		servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
+	}
+
+	ret = state->fn(name, num_servers, servers, state->private_data);
+
+	TALLOC_FREE(ids);
+
+	return ret;
+}
+
+int server_id_db_traverse_read(struct server_id_db *db,
+			       int (*fn)(const char *name,
+					 unsigned num_servers,
+					 const struct server_id *servers,
+					 void *private_data),
+			       void *private_data)
+{
+	struct server_id_db_traverse_state state;
+	int ret;
+
+	state = (struct server_id_db_traverse_state) {
+		.fn = fn, .private_data = private_data,
+		.mem_ctx = talloc_new(db)
+	};
+
+	if (state.mem_ctx == NULL) {
+		return ENOMEM;
+	}
+
+	ret = tdb_traverse_read(db->tdb->tdb, server_id_db_traverse_fn,
+				&state);
+	TALLOC_FREE(state.mem_ctx);
+	return ret;
+}
diff --git a/lib/util/server_id_db.h b/lib/util/server_id_db.h
new file mode 100644
index 0000000..31b3305
--- /dev/null
+++ b/lib/util/server_id_db.h
@@ -0,0 +1,47 @@
+/*
+ * Namedb
+ *
+ * Copyright Volker Lendecke <vl at samba.org> 2014
+ *
+ * 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/>.
+ */
+
+#ifndef _SERVER_ID_DB_H_
+#define _SERVER_ID_DB_H_
+
+#include "talloc.h"
+#include "librpc/gen_ndr/server_id.h"
+
+struct server_id_db;
+
+struct server_id_db *server_id_db_init(TALLOC_CTX *mem_ctx,
+				       struct server_id pid,
+				       const char *base_path,
+				       int hash_size, int tdb_flags);
+void server_id_db_reinit(struct server_id_db *db, struct server_id pid);
+int server_id_db_add(struct server_id_db *db, const char *name);
+int server_id_db_remove(struct server_id_db *db, const char *name);
+int server_id_db_lookup(struct server_id_db *db, const char *name,
+			TALLOC_CTX *mem_ctx, unsigned *num_servers,
+			struct server_id **servers);
+bool server_id_db_lookup_one(struct server_id_db *db, const char *name,
+			     struct server_id *server);
+int server_id_db_traverse_read(struct server_id_db *db,
+			       int (*fn)(const char *name,
+					 unsigned num_servers,
+					 const struct server_id *servers,
+					 void *private_data),
+			       void *private_data);
+
+#endif
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index 83d0bf1..c0d07e7 100755
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -139,3 +139,8 @@ if not bld.env.SAMBA_UTIL_CORE_ONLY:
                         public_deps='talloc'
 	                )
 
+    bld.SAMBA_LIBRARY('server_id_db',
+                      source='server_id_db.c',
+                      deps='talloc tdb strv util_tdb tdb-wrap samba-util',
+                      local_include=False,
+                      private_library=True)
-- 
2.1.2


From e59ef1f2891623945aa21fad165d820a851fd4ff Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 5 Nov 2014 13:02:38 +0000
Subject: [PATCH 05/10] dbwrap: Add code to marshall a db_context's db

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/dbwrap/dbwrap.h      |   9 +++
 lib/dbwrap/dbwrap_util.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 175 insertions(+)

diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h
index e56e036..00c7672 100644
--- a/lib/dbwrap/dbwrap.h
+++ b/lib/dbwrap/dbwrap.h
@@ -155,6 +155,15 @@ NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
 NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
 				     const char *key, TDB_DATA *value);
 
+size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize);
+NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen,
+				   bool (*fn)(TDB_DATA key, TDB_DATA value,
+					      void *private_data),
+				   void *private_data);
+NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf,
+			   size_t buflen);
+
+
 /**
  * This opens an ntdb or tdb file: you can hand it a .ntdb or .tdb extension
  * and it will decide (based on parameter settings, or else what exists) which
diff --git a/lib/dbwrap/dbwrap_util.c b/lib/dbwrap/dbwrap_util.c
index 4185fff..901ef56 100644
--- a/lib/dbwrap/dbwrap_util.c
+++ b/lib/dbwrap/dbwrap_util.c
@@ -595,3 +595,169 @@ NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
 	talloc_free(key_upper);
 	return status;
 }
+
+struct dbwrap_marshall_state {
+	uint8_t *buf;
+	size_t bufsize;
+	size_t dbsize;
+};
+
+static int dbwrap_marshall_fn(struct db_record *rec, void *private_data)
+{
+	struct dbwrap_marshall_state *state = private_data;
+	TDB_DATA key, value;
+	size_t new_dbsize;
+
+	key = dbwrap_record_get_key(rec);
+	value = dbwrap_record_get_value(rec);
+
+	new_dbsize = state->dbsize;
+	new_dbsize += 8 + key.dsize;
+	new_dbsize += 8 + value.dsize;
+
+	if (new_dbsize <= state->bufsize) {
+		uint8_t *p = state->buf + state->dbsize;
+
+		SBVAL(p, 0, key.dsize);
+		p += 8;
+		memcpy(p, key.dptr, key.dsize);
+		p += key.dsize;
+
+		SBVAL(p, 0, value.dsize);
+		p += 8;
+		memcpy(p, value.dptr, value.dsize);
+	}
+	state->dbsize = new_dbsize;
+	return 0;
+}
+
+size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize)
+{
+	struct dbwrap_marshall_state state;
+
+	state.bufsize = bufsize;
+	state.buf = buf;
+	state.dbsize = 0;
+
+	dbwrap_traverse_read(db, dbwrap_marshall_fn, &state, NULL);
+
+	return state.dbsize;
+}
+
+static ssize_t dbwrap_unmarshall_get_data(const uint8_t *buf, size_t buflen,
+					  size_t ofs, TDB_DATA *pdata)
+{
+	uint64_t space, len;
+	const uint8_t *p;
+
+	if (ofs == buflen) {
+		return 0;
+	}
+	if (ofs > buflen) {
+		return -1;
+	}
+
+	space = buflen - ofs;
+	if (space < 8) {
+		return -1;
+	}
+
+	p = buf + ofs;
+	len = BVAL(p, 0);
+
+	p += 8;
+	space -= 8;
+
+	if (len > space) {
+		return -1;
+	}
+
+	*pdata = (TDB_DATA) { .dptr = discard_const_p(uint8_t, p),
+			      .dsize = len };
+	return len + 8;
+}
+
+NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen,
+				   bool (*fn)(TDB_DATA key, TDB_DATA value,
+					      void *private_data),
+				   void *private_data)
+{
+	size_t ofs = 0;
+
+	while (true) {
+		ssize_t len;
+		TDB_DATA key, value;
+		bool ok;
+
+		len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &key);
+		if (len == 0) {
+			break;
+		}
+		if (len == -1) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+		ofs += len;
+
+		len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &value);
+		if (len == 0) {
+			break;
+		}
+		if (len == -1) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+		ofs += len;
+
+		ok = fn(key, value, private_data);
+		if (!ok) {
+			break;
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
+struct dbwrap_unmarshall_state {
+	struct db_context *db;
+	NTSTATUS ret;
+};
+
+static bool dbwrap_unmarshall_fn(TDB_DATA key, TDB_DATA value,
+				 void *private_data)
+{
+	struct dbwrap_unmarshall_state *state = private_data;
+	struct db_record *rec;
+	NTSTATUS status;
+
+	rec = dbwrap_fetch_locked(state->db, state->db, key);
+	if (rec == NULL) {
+		DEBUG(10, ("%s: dbwrap_fetch_locked failed\n",
+			   __func__));
+		state->ret = NT_STATUS_NO_MEMORY;
+		return false;
+	}
+
+	status = dbwrap_record_store(rec, value, 0);
+	TALLOC_FREE(rec);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(10, ("%s: dbwrap_record_store failed: %s\n",
+			   __func__, nt_errstr(status)));
+		state->ret = status;
+		return false;
+	}
+
+	return true;
+}
+
+NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf,
+			   size_t buflen)
+{
+	struct dbwrap_unmarshall_state state = { .db = db };
+	NTSTATUS status;
+
+	status = dbwrap_parse_marshall_buf(buf, buflen,
+					   dbwrap_unmarshall_fn, &state);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	return state.ret;
+}
-- 
2.1.2


From 4aa959ffaf62aa14ba195ada11f88315167e4b91 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 17 Oct 2014 12:09:03 +0000
Subject: [PATCH 06/10] messaging3: Add messaging_names_db

This will enable messaging3 users to more easily register themselves
under a name

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/include/messages.h |  1 +
 source3/lib/messages.c     | 19 +++++++++++++++++++
 source3/wscript_build      |  1 +
 3 files changed, 21 insertions(+)

diff --git a/source3/include/messages.h b/source3/include/messages.h
index fac561b..80b6c19 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -89,6 +89,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 struct server_id messaging_server_id(const struct messaging_context *msg_ctx);
 struct tevent_context *messaging_tevent_context(
 	struct messaging_context *msg_ctx);
+struct server_id_db *messaging_names_db(struct messaging_context *msg_ctx);
 
 /*
  * re-init after a fork
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 1fd7601..2711468 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -53,6 +53,7 @@
 #include "lib/background.h"
 #include "lib/messages_dgm.h"
 #include "lib/iov_buf.h"
+#include "lib/util/server_id_db.h"
 
 struct messaging_callback {
 	struct messaging_callback *prev, *next;
@@ -75,6 +76,8 @@ struct messaging_context {
 	unsigned num_waiters;
 
 	struct messaging_backend *remote;
+
+	struct server_id_db *names_db;
 };
 
 struct messaging_hdr {
@@ -314,6 +317,15 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 		return NULL;
 	}
 
+	ctx->names_db = server_id_db_init(
+		ctx, ctx->id, lp_cache_directory(), 0,
+		TDB_INCOMPATIBLE_HASH|TDB_CLEAR_IF_FIRST);
+	if (ctx->names_db == NULL) {
+		DEBUG(10, ("%s: server_id_db_init failed\n", __func__));
+		TALLOC_FREE(ctx);
+		return NULL;
+	}
+
 	talloc_set_destructor(ctx, messaging_context_destructor);
 
 	if (lp_clustering()) {
@@ -377,6 +389,8 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
 		}
 	}
 
+	server_id_db_reinit(msg_ctx->names_db, msg_ctx->id);
+
 	return NT_STATUS_OK;
 }
 
@@ -963,4 +977,9 @@ struct tevent_context *messaging_tevent_context(
 	return msg_ctx->event_ctx;
 }
 
+struct server_id_db *messaging_names_db(struct messaging_context *msg_ctx)
+{
+	return msg_ctx->names_db;
+}
+
 /** @} **/
diff --git a/source3/wscript_build b/source3/wscript_build
index 5128b96..9376576 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -363,6 +363,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core',
                         dbwrap
                         samba3-util
                         errors3
+                        server_id_db
                         TDB_LIB''')
 
 bld.SAMBA3_LIBRARY('smbd_shim',
-- 
2.1.2


From 8b5eadd3686e6d7eb40464d6876bb11644e7a55e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 12 Nov 2014 16:42:59 +0100
Subject: [PATCH 07/10] messaging3: Add messaging_send_iov_from

In the notifyd code it will be very helpful to fake source server_ids

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/include/messages.h |  5 +++++
 source3/lib/messages.c     | 30 ++++++++++++++++++++----------
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/source3/include/messages.h b/source3/include/messages.h
index 80b6c19..3db6756 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -123,6 +123,11 @@ NTSTATUS messaging_send(struct messaging_context *msg_ctx,
 NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
 			    struct server_id server, uint32_t msg_type,
 			    const uint8_t *buf, size_t len);
+NTSTATUS messaging_send_iov_from(struct messaging_context *msg_ctx,
+				 struct server_id src, struct server_id dst,
+				 uint32_t msg_type,
+				 const struct iovec *iov, int iovlen,
+				 const int *fds, size_t num_fds);
 NTSTATUS messaging_send_iov(struct messaging_context *msg_ctx,
 			    struct server_id server, uint32_t msg_type,
 			    const struct iovec *iov, int iovlen,
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 2711468..0866e7d 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -489,16 +489,17 @@ NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
 	return messaging_send(msg_ctx, server, msg_type, &blob);
 }
 
-NTSTATUS messaging_send_iov(struct messaging_context *msg_ctx,
-			    struct server_id server, uint32_t msg_type,
-			    const struct iovec *iov, int iovlen,
-			    const int *fds, size_t num_fds)
+NTSTATUS messaging_send_iov_from(struct messaging_context *msg_ctx,
+				 struct server_id src, struct server_id dst,
+				 uint32_t msg_type,
+				 const struct iovec *iov, int iovlen,
+				 const int *fds, size_t num_fds)
 {
 	int ret;
 	struct messaging_hdr hdr;
 	struct iovec iov2[iovlen+1];
 
-	if (server_id_is_disconnected(&server)) {
+	if (server_id_is_disconnected(&dst)) {
 		return NT_STATUS_INVALID_PARAMETER_MIX;
 	}
 
@@ -506,12 +507,12 @@ NTSTATUS messaging_send_iov(struct messaging_context *msg_ctx,
 		return NT_STATUS_INVALID_PARAMETER_MIX;
 	}
 
-	if (!procid_is_local(&server)) {
+	if (!procid_is_local(&dst)) {
 		if (num_fds > 0) {
 			return NT_STATUS_NOT_SUPPORTED;
 		}
 
-		ret = msg_ctx->remote->send_fn(msg_ctx->id, server,
+		ret = msg_ctx->remote->send_fn(src, dst,
 					       msg_type, iov, iovlen,
 					       NULL, 0,
 					       msg_ctx->remote);
@@ -524,14 +525,14 @@ NTSTATUS messaging_send_iov(struct messaging_context *msg_ctx,
 	ZERO_STRUCT(hdr);
 	hdr = (struct messaging_hdr) {
 		.msg_type = msg_type,
-		.dst = server,
-		.src = msg_ctx->id
+		.dst = dst,
+		.src = src
 	};
 	iov2[0] = (struct iovec){ .iov_base = &hdr, .iov_len = sizeof(hdr) };
 	memcpy(&iov2[1], iov, iovlen * sizeof(*iov));
 
 	become_root();
-	ret = messaging_dgm_send(server.pid, iov2, iovlen+1, fds, num_fds);
+	ret = messaging_dgm_send(dst.pid, iov2, iovlen+1, fds, num_fds);
 	unbecome_root();
 
 	if (ret != 0) {
@@ -540,6 +541,15 @@ NTSTATUS messaging_send_iov(struct messaging_context *msg_ctx,
 	return NT_STATUS_OK;
 }
 
+NTSTATUS messaging_send_iov(struct messaging_context *msg_ctx,
+			    struct server_id dst, uint32_t msg_type,
+			    const struct iovec *iov, int iovlen,
+			    const int *fds, size_t num_fds)
+{
+	return messaging_send_iov_from(msg_ctx, msg_ctx->id, dst, msg_type,
+				       iov, iovlen, fds, num_fds);
+}
+
 static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx,
 					       struct messaging_rec *rec)
 {
-- 
2.1.2


From 97678277610d88633eb69d1e8e216c0ec5fbafc4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 13 Nov 2014 11:25:40 +0000
Subject: [PATCH 08/10] messaging3: Add messaging_handler_send/recv

This repeatedly listens on msg_type. It's similar to messaging_register
with talloc based autocleanup. The handler is free to talloc_move a way
the record for later use.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/include/messages.h |  8 +++++
 source3/lib/messages.c     | 81 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+)

diff --git a/source3/include/messages.h b/source3/include/messages.h
index 3db6756..6b5e3da 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -150,6 +150,14 @@ struct tevent_req *messaging_read_send(TALLOC_CTX *mem_ctx,
 int messaging_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 			struct messaging_rec **presult);
 
+struct tevent_req *messaging_handler_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	struct messaging_context *msg_ctx, uint32_t msg_type,
+	bool (*handler)(struct messaging_context *msg_ctx,
+			struct messaging_rec **rec, void *private_data),
+	void *private_data);
+int messaging_handler_recv(struct tevent_req *req);
+
 int messaging_cleanup(struct messaging_context *msg_ctx, pid_t pid);
 
 bool messaging_parent_dgm_cleanup_init(struct messaging_context *msg);
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 0866e7d..7eadb02 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -792,6 +792,87 @@ int messaging_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 	return 0;
 }
 
+struct messaging_handler_state {
+	struct tevent_context *ev;
+	struct messaging_context *msg_ctx;
+	uint32_t msg_type;
+	bool (*handler)(struct messaging_context *msg_ctx,
+			struct messaging_rec **rec, void *private_data);
+	void *private_data;
+};
+
+static void messaging_handler_got_msg(struct tevent_req *subreq);
+
+struct tevent_req *messaging_handler_send(
+	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+	struct messaging_context *msg_ctx, uint32_t msg_type,
+	bool (*handler)(struct messaging_context *msg_ctx,
+			struct messaging_rec **rec, void *private_data),
+	void *private_data)
+{
+	struct tevent_req *req, *subreq;
+	struct messaging_handler_state *state;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct messaging_handler_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->ev = ev;
+	state->msg_ctx = msg_ctx;
+	state->msg_type = msg_type;
+	state->handler = handler;
+	state->private_data = private_data;
+
+	subreq = messaging_read_send(state, state->ev, state->msg_ctx,
+				     state->msg_type);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, messaging_handler_got_msg, req);
+	return req;
+}
+
+static void messaging_handler_got_msg(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct messaging_handler_state *state = tevent_req_data(
+		req, struct messaging_handler_state);
+	struct messaging_rec *rec;
+	int ret;
+	bool ok;
+
+	ret = messaging_read_recv(subreq, state, &rec);
+	TALLOC_FREE(subreq);
+	if (tevent_req_error(req, ret)) {
+		return;
+	}
+
+	subreq = messaging_read_send(state, state->ev, state->msg_ctx,
+				     state->msg_type);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, messaging_handler_got_msg, req);
+
+	ok = state->handler(state->msg_ctx, &rec, state->private_data);
+	TALLOC_FREE(rec);
+	if (ok) {
+		/*
+		 * Next round
+		 */
+		return;
+	}
+	TALLOC_FREE(subreq);
+	tevent_req_done(req);
+}
+
+int messaging_handler_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_unix(req);
+}
+
 static bool messaging_append_new_waiters(struct messaging_context *msg_ctx)
 {
 	if (msg_ctx->num_new_waiters == 0) {
-- 
2.1.2


From abdb7b4f7da9453a77d2229a89f15bc2d6f24271 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 12 Nov 2014 10:08:36 +0000
Subject: [PATCH 09/10] lib: Add ctdbd_messaging_send to ctdb_dummy.c

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/ctdb_dummy.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/source3/lib/ctdb_dummy.c b/source3/lib/ctdb_dummy.c
index 4b360a8..e19765b 100644
--- a/source3/lib/ctdb_dummy.c
+++ b/source3/lib/ctdb_dummy.c
@@ -30,6 +30,13 @@ NTSTATUS ctdbd_probe(void)
 	return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+NTSTATUS ctdbd_messaging_send(struct ctdbd_connection *conn,
+			      uint32_t dst_vnn, uint64_t dst_srvid,
+			      struct messaging_rec *msg)
+{
+	return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 NTSTATUS ctdbd_messaging_send_blob(struct ctdbd_connection *conn,
 				   uint32_t dst_vnn, uint64_t dst_srvid,
 				   const uint8_t *buf, size_t buflen)
-- 
2.1.2


From f273693c8a1f8983fa821af8f422f9518e07fc4c Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 2 Jan 2014 17:54:53 +0100
Subject: [PATCH 10/10] notify: Move path construction to notify_trigger

notify_msg won't need to construct the path anymore, it will be able to
put the parts into iovecs

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/notify.c          | 13 ++-----------
 source3/smbd/notify_internal.c | 19 ++++++++++++++++---
 source3/smbd/proto.h           |  3 ++-
 3 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index ac1a55c..5ac8c0c 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -442,21 +442,12 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
 		  const char *path)
 {
 	struct notify_context *notify_ctx = conn->sconn->notify_ctx;
-	char *fullpath, *to_free;
-	char tmpbuf[PATH_MAX];
-	ssize_t len;
 
 	if (path[0] == '.' && path[1] == '/') {
 		path += 2;
 	}
-	len = full_path_tos(conn->connectpath, path, tmpbuf, sizeof(tmpbuf),
-			    &fullpath, &to_free);
-	if (len == -1) {
-		DEBUG(0, ("full_path_tos failed\n"));
-		return;
-	}
-	notify_trigger(notify_ctx, action, filter, fullpath);
-	TALLOC_FREE(to_free);
+
+	notify_trigger(notify_ctx, action, filter, conn->connectpath, path);
 }
 
 static void notify_fsp(files_struct *fsp, struct timespec when,
diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c
index 9c0b190..e612f16 100644
--- a/source3/smbd/notify_internal.c
+++ b/source3/smbd/notify_internal.c
@@ -616,7 +616,8 @@ static bool notify_pull_remote_blob(TALLOC_CTX *mem_ctx,
 }
 
 void notify_trigger(struct notify_context *notify,
-		    uint32_t action, uint32_t filter, const char *path)
+		    uint32_t action, uint32_t filter,
+		    const char *dir, const char *name)
 {
 	struct ctdbd_connection *ctdbd_conn;
 	struct notify_trigger_index_state idx_state;
@@ -625,22 +626,33 @@ void notify_trigger(struct notify_context *notify,
 	uint32_t last_vnn;
 	uint8_t *remote_blob = NULL;
 	size_t remote_blob_len = 0;
+	char *path, *to_free;
+	char tmpbuf[PATH_MAX];
+	ssize_t len;
 
 	DEBUG(10, ("notify_trigger called action=0x%x, filter=0x%x, "
-		   "path=%s\n", (unsigned)action, (unsigned)filter, path));
+		   "dir=%s, name=%s\n", (unsigned)action, (unsigned)filter,
+		   dir, name));
 
 	/* see if change notify is enabled at all */
 	if (notify == NULL) {
 		return;
 	}
 
-	if (path[0] != '/') {
+	if (dir[0] != '/') {
 		/*
 		 * The rest of this routine assumes an absolute path.
 		 */
 		return;
 	}
 
+	len = full_path_tos(dir, name, tmpbuf, sizeof(tmpbuf),
+			    &path, &to_free);
+	if (len == -1) {
+		DEBUG(1, ("full_path_tos failed\n"));
+		return;
+	}
+
 	idx_state.mem_ctx = talloc_tos();
 	idx_state.vnns = NULL;
 	idx_state.found_my_vnn = false;
@@ -708,6 +720,7 @@ void notify_trigger(struct notify_context *notify,
 done:
 	TALLOC_FREE(remote_blob);
 	TALLOC_FREE(idx_state.vnns);
+	TALLOC_FREE(to_free);
 }
 
 static void notify_trigger_local(struct notify_context *notify,
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 44ea6f0..121682c 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -554,7 +554,8 @@ NTSTATUS notify_add(struct notify_context *notify,
 		    void *private_data);
 NTSTATUS notify_remove(struct notify_context *notify, void *private_data);
 void notify_trigger(struct notify_context *notify,
-		    uint32_t action, uint32_t filter, const char *path);
+		    uint32_t action, uint32_t filter,
+		    const char *dir, const char *path);
 void notify_walk_idx(struct notify_context *notify,
 		     void (*fn)(const char *path,
 				uint32_t *vnns, size_t num_vnns,
-- 
2.1.2



More information about the samba-technical mailing list