vfs: Remove files_struct->posix_flags
[Samba.git] / lib / util / server_id_db.c
blobc5cbdee9eef8fa171612c6c2e1b2d3db4a82b21d
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.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) };
34 struct server_id_db {
35 struct server_id pid;
36 struct tdb_wrap *tdb;
37 char *names;
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,
43 struct server_id pid,
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;
49 char path[pathlen];
51 db = talloc(mem_ctx, struct server_id_db);
52 if (db == NULL) {
53 return NULL;
55 db->pid = pid;
56 db->names = NULL;
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) {
63 TALLOC_FREE(db);
64 return NULL;
67 talloc_set_destructor(db, server_id_db_destructor);
69 return db;
72 void server_id_db_reinit(struct server_id_db *db, struct server_id pid)
74 db->pid = pid;
75 TALLOC_FREE(db->names);
78 struct server_id server_id_db_pid(struct server_id_db *db)
80 return db->pid;
83 static int server_id_db_destructor(struct server_id_db *db)
85 char *name = NULL;
87 while ((name = strv_next(db->names, name)) != NULL) {
88 server_id_db_remove(db, name);
91 return 0;
94 int server_id_db_add(struct server_id_db *db, const char *name)
96 struct tdb_context *tdb = db->tdb->tdb;
97 TDB_DATA key;
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);
114 struct server_id_buf _buf;
115 char *idbuf = server_id_str_buf_unique(db->pid, &_buf);
116 size_t idlen = strlen(idbuf) + 1;
118 ret = tdb_append(
119 tdb, key,
120 (TDB_DATA) { .dptr = (uint8_t *)idbuf, .dsize = idlen });
123 if (ret != 0) {
124 enum TDB_ERROR err = tdb_error(tdb);
125 strv_delete(&db->names, strv_find(db->names, name));
126 return map_unix_error_from_tdb(err);
129 return 0;
132 int server_id_db_prune_name(struct server_id_db *db, const char *name,
133 struct server_id server)
135 struct tdb_context *tdb = db->tdb->tdb;
136 struct server_id_buf _buf;
137 char *idbuf = server_id_str_buf_unique(server, &_buf);
138 TDB_DATA key;
139 uint8_t *data;
140 size_t datalen;
141 char *ids, *id;
142 int ret;
144 key = string_term_tdb_data(name);
146 ret = tdb_chainlock(tdb, key);
147 if (ret == -1) {
148 enum TDB_ERROR err = tdb_error(tdb);
149 return map_unix_error_from_tdb(err);
152 ret = tdb_fetch_talloc(tdb, key, db, &data);
153 if (ret != 0) {
154 tdb_chainunlock(tdb, key);
155 return ret;
158 datalen = talloc_get_size(data);
159 if ((datalen == 0) || (data[datalen-1] != '\0')) {
160 tdb_chainunlock(tdb, key);
161 TALLOC_FREE(data);
162 return EINVAL;
165 ids = (char *)data;
167 id = strv_find(ids, idbuf);
168 if (id == NULL) {
169 tdb_chainunlock(tdb, key);
170 TALLOC_FREE(data);
171 return ENOENT;
174 strv_delete(&ids, id);
176 if (talloc_get_size(ids) == 0) {
177 ret = tdb_delete(tdb, key);
178 } else {
179 ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY);
181 TALLOC_FREE(data);
183 tdb_chainunlock(tdb, key);
185 if (ret == -1) {
186 enum TDB_ERROR err = tdb_error(tdb);
187 return map_unix_error_from_tdb(err);
190 return 0;
193 int server_id_db_remove(struct server_id_db *db, const char *name)
195 char *n;
196 int ret;
198 n = strv_find(db->names, name);
199 if (n == NULL) {
200 return ENOENT;
203 ret = server_id_db_prune_name(db, name, db->pid);
204 if (ret != 0) {
205 return ret;
208 strv_delete(&db->names, n);
209 return 0;
212 int server_id_db_lookup(struct server_id_db *db, const char *name,
213 TALLOC_CTX *mem_ctx, unsigned *pnum_servers,
214 struct server_id **pservers)
216 struct tdb_context *tdb = db->tdb->tdb;
217 TDB_DATA key;
218 uint8_t *data;
219 size_t datalen;
220 char *ids, *id;
221 unsigned num_servers;
222 struct server_id *servers;
223 int i, ret;
225 key = string_term_tdb_data(name);
227 ret = tdb_fetch_talloc(tdb, key, mem_ctx, &data);
228 if (ret != 0) {
229 return ret;
232 datalen = talloc_get_size(data);
233 if ((datalen == 0) || (data[datalen-1] != '\0')) {
234 TALLOC_FREE(data);
235 return EINVAL;
238 ids = (char *)data;
239 num_servers = strv_count(ids);
241 servers = talloc_array(mem_ctx, struct server_id, num_servers);
242 if (servers == NULL) {
243 TALLOC_FREE(data);
244 return ENOMEM;
247 i = 0;
249 for (id = ids; id != NULL; id = strv_next(ids, id)) {
250 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
253 TALLOC_FREE(data);
255 *pnum_servers = num_servers;
256 *pservers = servers;
258 return 0;
261 bool server_id_db_lookup_one(struct server_id_db *db, const char *name,
262 struct server_id *server)
264 int ret;
265 unsigned num_servers;
266 struct server_id *servers;
268 ret = server_id_db_lookup(db, name, db, &num_servers, &servers);
269 if (ret != 0) {
270 return false;
272 if (num_servers == 0) {
273 TALLOC_FREE(servers);
274 return false;
276 *server = servers[0];
277 TALLOC_FREE(servers);
278 return true;
281 struct server_id_db_traverse_state {
282 TALLOC_CTX *mem_ctx;
283 int (*fn)(const char *name,
284 unsigned num_servers,
285 const struct server_id *servers,
286 void *private_data);
287 void *private_data;
290 static int server_id_db_traverse_fn(struct tdb_context *tdb,
291 TDB_DATA key, TDB_DATA data,
292 void *private_data)
294 struct server_id_db_traverse_state *state = private_data;
295 const char *name;
296 char *ids, *id;
297 unsigned num_servers;
298 struct server_id *servers;
299 int i, ret;
301 if (key.dsize == 0) {
302 return 0;
304 if (key.dptr[key.dsize-1] != '\0') {
305 return 0;
307 name = (const char *)key.dptr;
309 ids = (char *)talloc_memdup(state->mem_ctx, data.dptr, data.dsize);
310 if (ids == NULL) {
311 return 0;
314 num_servers = strv_count(ids);
315 servers = talloc_array(ids, struct server_id, num_servers);
317 i = 0;
319 for (id = ids; id != NULL; id = strv_next(ids, id)) {
320 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
323 ret = state->fn(name, num_servers, servers, state->private_data);
325 TALLOC_FREE(ids);
327 return ret;
330 int server_id_db_traverse_read(struct server_id_db *db,
331 int (*fn)(const char *name,
332 unsigned num_servers,
333 const struct server_id *servers,
334 void *private_data),
335 void *private_data)
337 struct server_id_db_traverse_state state;
338 int ret;
340 state = (struct server_id_db_traverse_state) {
341 .fn = fn, .private_data = private_data,
342 .mem_ctx = talloc_new(db)
345 if (state.mem_ctx == NULL) {
346 return ENOMEM;
349 ret = tdb_traverse_read(db->tdb->tdb, server_id_db_traverse_fn,
350 &state);
351 TALLOC_FREE(state.mem_ctx);
352 return ret;