s3:smbd: change a loglevel from 0 to 1 when SMB_VFS_CONNECT fails
[Samba.git] / lib / util / server_id_db.c
blob087412973ad1d5d332dc7679ec71edb49e34c22f
1 /*
2 * Map names to server_ids
4 * Copyright Volker Lendecke <vl@samba.org> 2014
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "replace.h"
21 #include "system/filesys.h"
22 #include "lib/util/server_id_db.h"
23 #include "lib/tdb_wrap/tdb_wrap.h"
24 #include "lib/util/strv.h"
25 #include "lib/util/util_tdb.h"
26 #include "lib/util/samba_util.h"
28 static TDB_DATA talloc_tdb_data(void *ptr)
30 return (TDB_DATA) { .dptr = ptr, .dsize = talloc_get_size(ptr) };
33 struct server_id_db {
34 struct server_id pid;
35 struct tdb_wrap *tdb;
36 char *names;
39 static int server_id_db_destructor(struct server_id_db *db);
41 struct server_id_db *server_id_db_init(TALLOC_CTX *mem_ctx,
42 struct server_id pid,
43 const char *base_path,
44 int hash_size, int tdb_flags)
46 struct server_id_db *db;
47 size_t pathlen = strlen(base_path) + 11;
48 char path[pathlen];
50 db = talloc(mem_ctx, struct server_id_db);
51 if (db == NULL) {
52 return NULL;
54 db->pid = pid;
55 db->names = NULL;
57 snprintf(path, pathlen, "%s/names.tdb", base_path);
59 db->tdb = tdb_wrap_open(db, path, hash_size, tdb_flags,
60 O_RDWR|O_CREAT, 0660);
61 if (db->tdb == NULL) {
62 TALLOC_FREE(db);
63 return NULL;
66 talloc_set_destructor(db, server_id_db_destructor);
68 return db;
71 void server_id_db_reinit(struct server_id_db *db, struct server_id pid)
73 db->pid = pid;
74 TALLOC_FREE(db->names);
77 struct server_id server_id_db_pid(struct server_id_db *db)
79 return db->pid;
82 static int server_id_db_destructor(struct server_id_db *db)
84 char *name = NULL;
86 while ((name = strv_next(db->names, name)) != NULL) {
87 server_id_db_remove(db, name);
90 return 0;
93 int server_id_db_add(struct server_id_db *db, const char *name)
95 struct tdb_context *tdb = db->tdb->tdb;
96 struct server_id_buf buf;
97 TDB_DATA key, data;
98 char *n;
99 int ret;
101 n = strv_find(db->names, name);
102 if (n != NULL) {
103 return EEXIST;
106 ret = strv_add(db, &db->names, name);
107 if (ret != 0) {
108 return ret;
111 key = string_term_tdb_data(name);
113 server_id_str_buf(db->pid, &buf);
114 data = string_term_tdb_data(buf.buf);
116 ret = tdb_append(tdb, key, data);
117 if (ret != 0) {
118 enum TDB_ERROR err = tdb_error(tdb);
119 strv_delete(&db->names, strv_find(db->names, name));
120 return map_unix_error_from_tdb(err);
123 return 0;
126 int server_id_db_prune_name(struct server_id_db *db, const char *name,
127 struct server_id server)
129 struct tdb_context *tdb = db->tdb->tdb;
130 struct server_id_buf buf;
131 TDB_DATA key;
132 uint8_t *data;
133 char *ids, *id;
134 int ret;
136 key = string_term_tdb_data(name);
137 server_id_str_buf(server, &buf);
139 ret = tdb_chainlock(tdb, key);
140 if (ret == -1) {
141 enum TDB_ERROR err = tdb_error(tdb);
142 return map_unix_error_from_tdb(err);
145 ret = tdb_fetch_talloc(tdb, key, db, &data);
146 if (ret != 0) {
147 tdb_chainunlock(tdb, key);
148 return ret;
151 ids = (char *)data;
153 id = strv_find(ids, buf.buf);
154 if (id == NULL) {
155 tdb_chainunlock(tdb, key);
156 TALLOC_FREE(data);
157 return ENOENT;
160 strv_delete(&ids, id);
161 ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY);
162 TALLOC_FREE(data);
164 tdb_chainunlock(tdb, key);
166 return 0;
169 int server_id_db_remove(struct server_id_db *db, const char *name)
171 char *n;
172 int ret;
174 n = strv_find(db->names, name);
175 if (n == NULL) {
176 return ENOENT;
179 ret = server_id_db_prune_name(db, name, db->pid);
180 if (ret != 0) {
181 return ret;
184 strv_delete(&db->names, n);
185 return 0;
188 int server_id_db_lookup(struct server_id_db *db, const char *name,
189 TALLOC_CTX *mem_ctx, unsigned *pnum_servers,
190 struct server_id **pservers)
192 struct tdb_context *tdb = db->tdb->tdb;
193 TDB_DATA key;
194 uint8_t *data;
195 char *ids, *id;
196 unsigned num_servers;
197 struct server_id *servers;
198 int i, ret;
200 key = string_term_tdb_data(name);
202 ret = tdb_fetch_talloc(tdb, key, mem_ctx, &data);
203 if (ret != 0) {
204 return ret;
207 ids = (char *)data;
208 num_servers = strv_count(ids);
210 servers = talloc_array(mem_ctx, struct server_id, num_servers);
211 if (servers == NULL) {
212 TALLOC_FREE(data);
213 return ENOMEM;
216 i = 0;
218 for (id = ids; id != NULL; id = strv_next(ids, id)) {
219 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
222 TALLOC_FREE(data);
224 *pnum_servers = num_servers;
225 *pservers = servers;
227 return 0;
230 bool server_id_db_lookup_one(struct server_id_db *db, const char *name,
231 struct server_id *server)
233 int ret;
234 unsigned num_servers;
235 struct server_id *servers;
237 ret = server_id_db_lookup(db, name, db, &num_servers, &servers);
238 if (ret != 0) {
239 return false;
241 if (num_servers == 0) {
242 TALLOC_FREE(servers);
243 return false;
245 *server = servers[0];
246 TALLOC_FREE(servers);
247 return true;
250 struct server_id_db_traverse_state {
251 TALLOC_CTX *mem_ctx;
252 int (*fn)(const char *name,
253 unsigned num_servers,
254 const struct server_id *servers,
255 void *private_data);
256 void *private_data;
259 static int server_id_db_traverse_fn(struct tdb_context *tdb,
260 TDB_DATA key, TDB_DATA data,
261 void *private_data)
263 struct server_id_db_traverse_state *state = private_data;
264 const char *name;
265 char *ids, *id;
266 unsigned num_servers;
267 struct server_id *servers;
268 int i, ret;
270 if (key.dsize == 0) {
271 return 0;
273 if (key.dptr[key.dsize-1] != '\0') {
274 return 0;
276 name = (const char *)key.dptr;
278 ids = (char *)talloc_memdup(state->mem_ctx, data.dptr, data.dsize);
279 if (ids == NULL) {
280 return 0;
283 num_servers = strv_count(ids);
284 servers = talloc_array(ids, struct server_id, num_servers);
286 i = 0;
288 for (id = ids; id != NULL; id = strv_next(ids, id)) {
289 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
292 ret = state->fn(name, num_servers, servers, state->private_data);
294 TALLOC_FREE(ids);
296 return ret;
299 int server_id_db_traverse_read(struct server_id_db *db,
300 int (*fn)(const char *name,
301 unsigned num_servers,
302 const struct server_id *servers,
303 void *private_data),
304 void *private_data)
306 struct server_id_db_traverse_state state;
307 int ret;
309 state = (struct server_id_db_traverse_state) {
310 .fn = fn, .private_data = private_data,
311 .mem_ctx = talloc_new(db)
314 if (state.mem_ctx == NULL) {
315 return ENOMEM;
318 ret = tdb_traverse_read(db->tdb->tdb, server_id_db_traverse_fn,
319 &state);
320 TALLOC_FREE(state.mem_ctx);
321 return ret;