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/>.
21 #include "system/filesys.h"
22 #include "lib/util/server_id.h"
23 #include "lib/util/server_id_db.h"
24 #include "lib/tdb_wrap/tdb_wrap.h"
25 #include "lib/util/strv.h"
26 #include "lib/util/util_tdb.h"
27 #include "lib/util/samba_util.h"
29 static TDB_DATA
talloc_tdb_data(void *ptr
)
31 return (TDB_DATA
) { .dptr
= ptr
, .dsize
= talloc_get_size(ptr
) };
40 static int server_id_db_destructor(struct server_id_db
*db
);
42 struct server_id_db
*server_id_db_init(TALLOC_CTX
*mem_ctx
,
44 const char *base_path
,
45 int hash_size
, int tdb_flags
)
47 struct server_id_db
*db
;
48 size_t pathlen
= strlen(base_path
) + 11;
51 db
= talloc(mem_ctx
, struct server_id_db
);
58 snprintf(path
, pathlen
, "%s/names.tdb", base_path
);
60 db
->tdb
= tdb_wrap_open(db
, path
, hash_size
, tdb_flags
,
61 O_RDWR
|O_CREAT
, 0660);
62 if (db
->tdb
== NULL
) {
67 talloc_set_destructor(db
, server_id_db_destructor
);
72 void server_id_db_reinit(struct server_id_db
*db
, struct server_id pid
)
75 TALLOC_FREE(db
->names
);
78 struct server_id
server_id_db_pid(struct server_id_db
*db
)
83 static int server_id_db_destructor(struct server_id_db
*db
)
87 while ((name
= strv_next(db
->names
, name
)) != NULL
) {
88 server_id_db_remove(db
, name
);
94 int server_id_db_add(struct server_id_db
*db
, const char *name
)
96 struct tdb_context
*tdb
= db
->tdb
->tdb
;
101 n
= strv_find(db
->names
, name
);
106 ret
= strv_add(db
, &db
->names
, name
);
111 key
= string_term_tdb_data(name
);
114 size_t idlen
= server_id_str_buf_unique(db
->pid
, NULL
, 0);
117 server_id_str_buf_unique(db
->pid
, idbuf
, idlen
);
121 (TDB_DATA
) { .dptr
= (uint8_t *)idbuf
, .dsize
= idlen
});
125 enum TDB_ERROR err
= tdb_error(tdb
);
126 strv_delete(&db
->names
, strv_find(db
->names
, name
));
127 return map_unix_error_from_tdb(err
);
133 int server_id_db_prune_name(struct server_id_db
*db
, const char *name
,
134 struct server_id server
)
136 struct tdb_context
*tdb
= db
->tdb
->tdb
;
137 size_t idbuf_len
= server_id_str_buf_unique(server
, NULL
, 0);
138 char idbuf
[idbuf_len
];
145 key
= string_term_tdb_data(name
);
146 server_id_str_buf_unique(server
, idbuf
, idbuf_len
);
148 ret
= tdb_chainlock(tdb
, key
);
150 enum TDB_ERROR err
= tdb_error(tdb
);
151 return map_unix_error_from_tdb(err
);
154 ret
= tdb_fetch_talloc(tdb
, key
, db
, &data
);
156 tdb_chainunlock(tdb
, key
);
160 datalen
= talloc_get_size(data
);
161 if ((datalen
== 0) || (data
[datalen
-1] != '\0')) {
162 tdb_chainunlock(tdb
, key
);
169 id
= strv_find(ids
, idbuf
);
171 tdb_chainunlock(tdb
, key
);
176 strv_delete(&ids
, id
);
178 if (talloc_get_size(ids
) == 0) {
179 ret
= tdb_delete(tdb
, key
);
181 ret
= tdb_store(tdb
, key
, talloc_tdb_data(ids
), TDB_MODIFY
);
185 tdb_chainunlock(tdb
, key
);
188 enum TDB_ERROR err
= tdb_error(tdb
);
189 return map_unix_error_from_tdb(err
);
195 int server_id_db_remove(struct server_id_db
*db
, const char *name
)
200 n
= strv_find(db
->names
, name
);
205 ret
= server_id_db_prune_name(db
, name
, db
->pid
);
210 strv_delete(&db
->names
, n
);
214 int server_id_db_lookup(struct server_id_db
*db
, const char *name
,
215 TALLOC_CTX
*mem_ctx
, unsigned *pnum_servers
,
216 struct server_id
**pservers
)
218 struct tdb_context
*tdb
= db
->tdb
->tdb
;
223 unsigned num_servers
;
224 struct server_id
*servers
;
227 key
= string_term_tdb_data(name
);
229 ret
= tdb_fetch_talloc(tdb
, key
, mem_ctx
, &data
);
234 datalen
= talloc_get_size(data
);
235 if ((datalen
== 0) || (data
[datalen
-1] != '\0')) {
241 num_servers
= strv_count(ids
);
243 servers
= talloc_array(mem_ctx
, struct server_id
, num_servers
);
244 if (servers
== NULL
) {
251 for (id
= ids
; id
!= NULL
; id
= strv_next(ids
, id
)) {
252 servers
[i
++] = server_id_from_string(NONCLUSTER_VNN
, id
);
257 *pnum_servers
= num_servers
;
263 bool server_id_db_lookup_one(struct server_id_db
*db
, const char *name
,
264 struct server_id
*server
)
267 unsigned num_servers
;
268 struct server_id
*servers
;
270 ret
= server_id_db_lookup(db
, name
, db
, &num_servers
, &servers
);
274 if (num_servers
== 0) {
275 TALLOC_FREE(servers
);
278 *server
= servers
[0];
279 TALLOC_FREE(servers
);
283 struct server_id_db_traverse_state
{
285 int (*fn
)(const char *name
,
286 unsigned num_servers
,
287 const struct server_id
*servers
,
292 static int server_id_db_traverse_fn(struct tdb_context
*tdb
,
293 TDB_DATA key
, TDB_DATA data
,
296 struct server_id_db_traverse_state
*state
= private_data
;
299 unsigned num_servers
;
300 struct server_id
*servers
;
303 if (key
.dsize
== 0) {
306 if (key
.dptr
[key
.dsize
-1] != '\0') {
309 name
= (const char *)key
.dptr
;
311 ids
= (char *)talloc_memdup(state
->mem_ctx
, data
.dptr
, data
.dsize
);
316 num_servers
= strv_count(ids
);
317 servers
= talloc_array(ids
, struct server_id
, num_servers
);
321 for (id
= ids
; id
!= NULL
; id
= strv_next(ids
, id
)) {
322 servers
[i
++] = server_id_from_string(NONCLUSTER_VNN
, id
);
325 ret
= state
->fn(name
, num_servers
, servers
, state
->private_data
);
332 int server_id_db_traverse_read(struct server_id_db
*db
,
333 int (*fn
)(const char *name
,
334 unsigned num_servers
,
335 const struct server_id
*servers
,
339 struct server_id_db_traverse_state state
;
342 state
= (struct server_id_db_traverse_state
) {
343 .fn
= fn
, .private_data
= private_data
,
344 .mem_ctx
= talloc_new(db
)
347 if (state
.mem_ctx
== NULL
) {
351 ret
= tdb_traverse_read(db
->tdb
->tdb
, server_id_db_traverse_fn
,
353 TALLOC_FREE(state
.mem_ctx
);