cf/largefile.m4: Fix build with autoconf-2.72
[heimdal.git] / lib / hdb / db.c
blob5fcce7b8e8b305c8421b00fc22106cfae74b6e5f
1 /*
2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "hdb_locl.h"
36 #if defined(HAVE_DB1)
38 #if defined(HAVE_DB_185_H)
39 #include <db_185.h>
40 #elif defined(HAVE_DB_H)
41 #include <db.h>
42 #endif
44 typedef struct {
45 HDB hdb; /* generic members */
46 int lock_fd; /* DB-specific */
47 int do_sync; /* DB-specific */
48 } DB1_HDB;
50 static krb5_error_code
51 DB_close(krb5_context context, HDB *db)
53 DB1_HDB *db1 = (DB1_HDB *)db;
54 DB *d = (DB*)db->hdb_db;
56 heim_assert(d != 0, "Closing already closed HDB");
58 (*d->close)(d);
59 db->hdb_db = 0;
61 if (db1->lock_fd >= 0) {
62 close(db1->lock_fd);
63 db1->lock_fd = -1;
66 return 0;
69 static krb5_error_code
70 DB_destroy(krb5_context context, HDB *db)
72 krb5_error_code ret;
74 ret = hdb_clear_master_key(context, db);
75 krb5_config_free_strings(db->virtual_hostbased_princ_svcs);
76 free(db->hdb_name);
77 free(db);
78 return ret;
81 static krb5_error_code
82 DB_set_sync(krb5_context context, HDB *db, int on)
84 DB1_HDB *db1 = (DB1_HDB *)db;
85 DB *d = (DB*)db->hdb_db;
86 krb5_error_code ret = 0;
88 db1->do_sync = on;
89 if (on) {
90 ret = (*d->sync)(d, 0);
91 if (ret == -1) {
92 ret = errno;
93 krb5_set_error_message(context, ret, "Database %s put sync error: %s",
94 db->hdb_name, strerror(ret));
97 return ret;
100 static krb5_error_code
101 DB_lock(krb5_context context, HDB *db, int operation)
104 return 0;
107 static krb5_error_code
108 DB_unlock(krb5_context context, HDB *db)
111 return 0;
115 static krb5_error_code
116 DB_seq(krb5_context context, HDB *db,
117 unsigned flags, hdb_entry *entry, int flag)
119 DB *d = (DB*)db->hdb_db;
120 DBT key, value;
121 krb5_data key_data, data;
122 int code;
124 code = (*d->seq)(d, &key, &value, flag);
125 if(code == -1) {
126 code = errno;
127 krb5_set_error_message(context, code, "Database %s seq error: %s",
128 db->hdb_name, strerror(code));
129 return code;
131 if(code == 1) {
132 krb5_clear_error_message(context);
133 return HDB_ERR_NOENTRY;
136 key_data.data = key.data;
137 key_data.length = key.size;
138 data.data = value.data;
139 data.length = value.size;
140 memset(entry, 0, sizeof(*entry));
141 if (hdb_value2entry(context, &data, entry))
142 return DB_seq(context, db, flags, entry, R_NEXT);
143 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
144 code = hdb_unseal_keys (context, db, entry);
145 if (code)
146 hdb_free_entry (context, db, entry);
148 if (code == 0 && entry->principal == NULL) {
149 entry->principal = malloc(sizeof(*entry->principal));
150 if (entry->principal == NULL) {
151 code = ENOMEM;
152 krb5_set_error_message(context, code, "malloc: out of memory");
153 hdb_free_entry (context, db, entry);
154 } else {
155 hdb_key2principal(context, &key_data, entry->principal);
158 return code;
162 static krb5_error_code
163 DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
165 return DB_seq(context, db, flags, entry, R_FIRST);
169 static krb5_error_code
170 DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
172 return DB_seq(context, db, flags, entry, R_NEXT);
175 static krb5_error_code
176 DB_rename(krb5_context context, HDB *db, const char *new_name)
178 int ret;
179 char *old, *new;
181 if (strncmp(new_name, "db:", sizeof("db:") - 1) == 0)
182 new_name += sizeof("db:") - 1;
183 else if (strncmp(new_name, "db1:", sizeof("db1:") - 1) == 0)
184 new_name += sizeof("db1:") - 1;
185 asprintf(&old, "%s.db", db->hdb_name);
186 asprintf(&new, "%s.db", new_name);
187 ret = rename(old, new);
188 free(old);
189 free(new);
190 if(ret)
191 return errno;
193 free(db->hdb_name);
194 db->hdb_name = strdup(new_name);
195 return 0;
198 static krb5_error_code
199 DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
201 DB *d = (DB*)db->hdb_db;
202 DBT k, v;
203 int code;
205 k.data = key.data;
206 k.size = key.length;
207 code = (*d->get)(d, &k, &v, 0);
208 if(code < 0) {
209 code = errno;
210 krb5_set_error_message(context, code, "Database %s get error: %s",
211 db->hdb_name, strerror(code));
212 return code;
214 if(code == 1) {
215 krb5_clear_error_message(context);
216 return HDB_ERR_NOENTRY;
219 krb5_data_copy(reply, v.data, v.size);
220 return 0;
223 static krb5_error_code
224 DB__put(krb5_context context, HDB *db, int replace,
225 krb5_data key, krb5_data value)
227 DB1_HDB *db1 = (DB1_HDB *)db;
228 DB *d = (DB*)db->hdb_db;
229 DBT k, v;
230 int code;
232 k.data = key.data;
233 k.size = key.length;
234 v.data = value.data;
235 v.size = value.length;
236 krb5_clear_error_message(context);
237 code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE);
238 if(code < 0) {
239 code = errno;
240 krb5_set_error_message(context, code, "Database %s put error: %s",
241 db->hdb_name, strerror(code));
242 return code;
244 if(code == 1) {
245 return HDB_ERR_EXISTS;
248 return db->hdb_set_sync(context, db, db1->do_sync);
251 static krb5_error_code
252 DB__del(krb5_context context, HDB *db, krb5_data key)
254 DB1_HDB *db1 = (DB1_HDB *)db;
255 DB *d = (DB*)db->hdb_db;
256 DBT k;
257 krb5_error_code code;
258 k.data = key.data;
259 k.size = key.length;
260 krb5_clear_error_message(context);
261 code = (*d->del)(d, &k, 0);
262 if (code == 1)
263 return HDB_ERR_NOENTRY;
264 if (code < 0) {
265 code = errno;
266 krb5_set_error_message(context, code, "Database %s del error: %s",
267 db->hdb_name, strerror(code));
268 return code;
270 return db->hdb_set_sync(context, db, db1->do_sync);
273 static DB *
274 _open_db(char *fn, int flags, int mode, int *fd)
276 #ifndef O_EXLOCK
277 int op;
278 int ret;
280 *fd = open(fn, flags, mode);
281 if (*fd == -1)
282 return NULL;
284 if ((flags & O_ACCMODE) == O_RDONLY)
285 op = LOCK_SH;
286 else
287 op = LOCK_EX;
289 ret = flock(*fd, op);
290 if (ret == -1) {
291 int saved_errno;
293 saved_errno = errno;
294 close(*fd);
295 errno = saved_errno;
296 return NULL;
298 #else
299 if ((flags & O_ACCMODE) == O_RDONLY)
300 flags |= O_SHLOCK;
301 else
302 flags |= O_EXLOCK;
303 #endif
305 return dbopen(fn, flags, mode, DB_BTREE, NULL);
308 static krb5_error_code
309 DB_open(krb5_context context, HDB *db, int flags, mode_t mode)
311 DB1_HDB *db1 = (DB1_HDB *)db;
312 char *fn;
313 krb5_error_code ret;
315 asprintf(&fn, "%s.db", db->hdb_name);
316 if (fn == NULL) {
317 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
318 return ENOMEM;
320 db->hdb_db = _open_db(fn, flags, mode, &db1->lock_fd);
321 free(fn);
322 /* try to open without .db extension */
323 if(db->hdb_db == NULL && errno == ENOENT)
324 db->hdb_db = _open_db(db->hdb_name, flags, mode, &db1->lock_fd);
325 if(db->hdb_db == NULL) {
326 krb5_set_error_message(context, errno, "dbopen (%s): %s",
327 db->hdb_name, strerror(errno));
328 return errno;
330 if((flags & O_ACCMODE) == O_RDONLY)
331 ret = hdb_check_db_format(context, db);
332 else
333 ret = hdb_init_db(context, db);
334 if(ret == HDB_ERR_NOENTRY) {
335 krb5_clear_error_message(context);
336 return 0;
338 if (ret) {
339 DB_close(context, db);
340 krb5_set_error_message(context, ret, "hdb_open: failed %s database %s",
341 (flags & O_ACCMODE) == O_RDONLY ?
342 "checking format of" : "initialize",
343 db->hdb_name);
345 return ret;
348 krb5_error_code
349 hdb_db1_create(krb5_context context, HDB **db,
350 const char *filename)
352 DB1_HDB **db1 = (DB1_HDB **)db;
353 *db = calloc(1, sizeof(**db1)); /* Allocate space for the larger db1 */
354 if (*db == NULL) {
355 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
356 return ENOMEM;
359 (*db)->hdb_db = NULL;
360 (*db)->hdb_name = strdup(filename);
361 if ((*db)->hdb_name == NULL) {
362 free(*db);
363 *db = NULL;
364 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
365 return ENOMEM;
367 (*db)->hdb_master_key_set = 0;
368 (*db)->hdb_openp = 0;
369 (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
370 (*db)->hdb_open = DB_open;
371 (*db)->hdb_close = DB_close;
372 (*db)->hdb_fetch_kvno = _hdb_fetch_kvno;
373 (*db)->hdb_store = _hdb_store;
374 (*db)->hdb_remove = _hdb_remove;
375 (*db)->hdb_firstkey = DB_firstkey;
376 (*db)->hdb_nextkey= DB_nextkey;
377 (*db)->hdb_lock = DB_lock;
378 (*db)->hdb_unlock = DB_unlock;
379 (*db)->hdb_rename = DB_rename;
380 (*db)->hdb__get = DB__get;
381 (*db)->hdb__put = DB__put;
382 (*db)->hdb__del = DB__del;
383 (*db)->hdb_destroy = DB_destroy;
384 (*db)->hdb_set_sync = DB_set_sync;
386 (*db1)->lock_fd = -1;
387 (*db1)->do_sync = 1;
388 return 0;
391 #endif /* defined(HAVE_DB1) */