diff options
author | Volker Lendecke <vl@samba.org> | 2014-10-15 16:14:42 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2014-12-16 18:56:03 +0100 |
commit | 972efb05e0ee467c1049207a803090a056aa17f6 (patch) | |
tree | 1805e5391a8179629010e24cad57b3c76783b6dd /lib | |
parent | 5d7a183b9eb444f12bb501f5314afb01e5944966 (diff) | |
download | samba-972efb05e0ee467c1049207a803090a056aa17f6.tar.gz samba-972efb05e0ee467c1049207a803090a056aa17f6.tar.xz samba-972efb05e0ee467c1049207a803090a056aa17f6.zip |
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@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/util/server_id_db.c | 308 | ||||
-rw-r--r-- | lib/util/server_id_db.h | 47 | ||||
-rwxr-xr-x | lib/util/wscript_build | 5 |
3 files changed, 360 insertions, 0 deletions
diff --git a/lib/util/server_id_db.c b/lib/util/server_id_db.c new file mode 100644 index 0000000000..7f5b055f17 --- /dev/null +++ b/lib/util/server_id_db.c @@ -0,0 +1,308 @@ +/* + * Map names to server_ids + * + * Copyright Volker Lendecke <vl@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 0000000000..31b3305f47 --- /dev/null +++ b/lib/util/server_id_db.h @@ -0,0 +1,47 @@ +/* + * Namedb + * + * Copyright Volker Lendecke <vl@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 83d0bf1d15..c0d07e70f8 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) |