Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : trivial database library
5 :
6 : Copyright (C) Andrew Tridgell 1999-2005
7 : Copyright (C) Paul `Rusty' Russell 2000
8 : Copyright (C) Jeremy Allison 2000-2003
9 :
10 : ** NOTE! The following LGPL license applies to the tdb
11 : ** library. This does NOT imply that all of Samba is released
12 : ** under the LGPL
13 :
14 : This library is free software; you can redistribute it and/or
15 : modify it under the terms of the GNU Lesser General Public
16 : License as published by the Free Software Foundation; either
17 : version 3 of the License, or (at your option) any later version.
18 :
19 : This library is distributed in the hope that it will be useful,
20 : but WITHOUT ANY WARRANTY; without even the implied warranty of
21 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 : Lesser General Public License for more details.
23 :
24 : You should have received a copy of the GNU Lesser General Public
25 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 : */
27 :
28 : #include "tdb_private.h"
29 :
30 : /* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
31 : static struct tdb_context *tdbs = NULL;
32 :
33 : /* We use two hashes to double-check they're using the right hash function. */
34 5048094 : void tdb_header_hash(struct tdb_context *tdb,
35 : uint32_t *magic1_hash, uint32_t *magic2_hash)
36 : {
37 : TDB_DATA hash_key;
38 5048094 : uint32_t tdb_magic = TDB_MAGIC;
39 :
40 5048094 : hash_key.dptr = discard_const_p(unsigned char, TDB_MAGIC_FOOD);
41 5048094 : hash_key.dsize = sizeof(TDB_MAGIC_FOOD);
42 5048094 : *magic1_hash = tdb->hash_fn(&hash_key);
43 :
44 5048094 : hash_key.dptr = (unsigned char *)CONVERT(tdb_magic);
45 5048094 : hash_key.dsize = sizeof(tdb_magic);
46 5048094 : *magic2_hash = tdb->hash_fn(&hash_key);
47 :
48 : /* Make sure at least one hash is non-zero! */
49 5048094 : if (*magic1_hash == 0 && *magic2_hash == 0)
50 0 : *magic1_hash = 1;
51 5048094 : }
52 :
53 : /* initialise a new database with a specified hash size */
54 4468450 : static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *header,
55 : int hash_size)
56 : {
57 : struct tdb_header *newdb;
58 : size_t size;
59 4468450 : int ret = -1;
60 :
61 : /* We make it up in memory, then write it out if not internal */
62 4468450 : size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
63 4468450 : if (!(newdb = (struct tdb_header *)calloc(size, 1))) {
64 0 : tdb->ecode = TDB_ERR_OOM;
65 0 : return -1;
66 : }
67 :
68 : /* Fill in the header */
69 4468450 : newdb->version = TDB_VERSION;
70 4468450 : newdb->hash_size = hash_size;
71 :
72 4468450 : tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash);
73 :
74 : /* Make sure older tdbs (which don't check the magic hash fields)
75 : * will refuse to open this TDB. */
76 4468450 : if (tdb->flags & TDB_INCOMPATIBLE_HASH)
77 4438784 : newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC;
78 :
79 : /*
80 : * We create a tdb with TDB_FEATURE_FLAG_MUTEX support,
81 : * the flag combination and runtime feature checks
82 : * are done by the caller already.
83 : */
84 4468450 : if (tdb->flags & TDB_MUTEX_LOCKING) {
85 52873 : newdb->feature_flags |= TDB_FEATURE_FLAG_MUTEX;
86 : }
87 :
88 : /*
89 : * If we have any features we add the FEATURE_FLAG_MAGIC, overwriting the
90 : * TDB_HASH_RWLOCK_MAGIC above.
91 : */
92 4468450 : if (newdb->feature_flags != 0) {
93 52873 : newdb->rwlocks = TDB_FEATURE_FLAG_MAGIC;
94 : }
95 :
96 : /*
97 : * It's required for some following code pathes
98 : * to have the fields on 'tdb' up-to-date.
99 : *
100 : * E.g. tdb_mutex_size() requires it
101 : */
102 4468450 : tdb->feature_flags = newdb->feature_flags;
103 4468450 : tdb->hash_size = newdb->hash_size;
104 :
105 4468450 : if (tdb->flags & TDB_INTERNAL) {
106 4370029 : tdb->map_size = size;
107 4370029 : tdb->map_ptr = (char *)newdb;
108 4370029 : memcpy(header, newdb, sizeof(*header));
109 : /* Convert the `ondisk' version if asked. */
110 4370029 : CONVERT(*newdb);
111 4370029 : return 0;
112 : }
113 98421 : if (lseek(tdb->fd, 0, SEEK_SET) == -1)
114 0 : goto fail;
115 :
116 98421 : if (ftruncate(tdb->fd, 0) == -1)
117 0 : goto fail;
118 :
119 98421 : if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
120 52873 : newdb->mutex_size = tdb_mutex_size(tdb);
121 52873 : tdb->hdr_ofs = newdb->mutex_size;
122 : }
123 :
124 : /* This creates an endian-converted header, as if read from disk */
125 98421 : CONVERT(*newdb);
126 98421 : memcpy(header, newdb, sizeof(*header));
127 : /* Don't endian-convert the magic food! */
128 98421 : memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
129 :
130 98421 : if (!tdb_write_all(tdb->fd, newdb, size))
131 0 : goto fail;
132 :
133 98421 : if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
134 :
135 : /*
136 : * Now we init the mutex area
137 : * followed by a second header.
138 : */
139 :
140 52873 : ret = ftruncate(
141 : tdb->fd,
142 52873 : newdb->mutex_size + sizeof(struct tdb_header));
143 52873 : if (ret == -1) {
144 0 : goto fail;
145 : }
146 52873 : ret = tdb_mutex_init(tdb);
147 52873 : if (ret == -1) {
148 0 : goto fail;
149 : }
150 :
151 : /*
152 : * Write a second header behind the mutexes. That's the area
153 : * that will be mmapp'ed.
154 : */
155 52873 : ret = lseek(tdb->fd, newdb->mutex_size, SEEK_SET);
156 52873 : if (ret == -1) {
157 0 : goto fail;
158 : }
159 52873 : if (!tdb_write_all(tdb->fd, newdb, size)) {
160 0 : goto fail;
161 : }
162 : }
163 :
164 98421 : ret = 0;
165 98421 : fail:
166 98421 : SAFE_FREE(newdb);
167 98421 : return ret;
168 : }
169 :
170 :
171 :
172 514201 : static int tdb_already_open(dev_t device,
173 : ino_t ino)
174 : {
175 : struct tdb_context *i;
176 :
177 4996628 : for (i = tdbs; i; i = i->next) {
178 4482427 : if (i->device == device && i->inode == ino) {
179 0 : return 1;
180 : }
181 : }
182 :
183 514201 : return 0;
184 : }
185 :
186 : /* open the database, creating it if necessary
187 :
188 : The open_flags and mode are passed straight to the open call on the
189 : database file. A flags value of O_WRONLY is invalid. The hash size
190 : is advisory, use zero for a default value.
191 :
192 : Return is NULL on error, in which case errno is also set. Don't
193 : try to call tdb_error or tdb_errname, just do strerror(errno).
194 :
195 : @param name may be NULL for internal databases. */
196 4370433 : _PUBLIC_ struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
197 : int open_flags, mode_t mode)
198 : {
199 4370433 : return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
200 : }
201 :
202 : /* a default logging function */
203 : static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
204 154 : static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
205 : {
206 154 : }
207 :
208 514288 : static bool check_header_hash(struct tdb_context *tdb,
209 : struct tdb_header *header,
210 : bool default_hash, uint32_t *m1, uint32_t *m2)
211 : {
212 514288 : tdb_header_hash(tdb, m1, m2);
213 910664 : if (header->magic1_hash == *m1 &&
214 514193 : header->magic2_hash == *m2) {
215 514193 : return true;
216 : }
217 :
218 : /* If they explicitly set a hash, always respect it. */
219 95 : if (!default_hash)
220 8 : return false;
221 :
222 : /* Otherwise, try the other inbuilt hash. */
223 87 : if (tdb->hash_fn == tdb_old_hash)
224 52 : tdb->hash_fn = tdb_jenkins_hash;
225 : else
226 35 : tdb->hash_fn = tdb_old_hash;
227 87 : return check_header_hash(tdb, header, false, m1, m2);
228 : }
229 :
230 59726 : static bool tdb_mutex_open_ok(struct tdb_context *tdb,
231 : const struct tdb_header *header)
232 : {
233 59726 : if (tdb->flags & TDB_NOLOCK) {
234 : /*
235 : * We don't look at locks, so it does not matter to have a
236 : * compatible mutex implementation. Allow the open.
237 : */
238 1 : return true;
239 : }
240 :
241 59725 : if (!(tdb->flags & TDB_MUTEX_LOCKING)) {
242 20 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_mutex_open_ok[%s]: "
243 : "Can use mutexes only with "
244 : "MUTEX_LOCKING or NOLOCK\n",
245 : tdb->name));
246 20 : return false;
247 : }
248 :
249 59705 : if (tdb_mutex_size(tdb) != header->mutex_size) {
250 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_mutex_open_ok[%s]: "
251 : "Mutex size changed from %"PRIu32" to %zu\n.",
252 : tdb->name,
253 : header->mutex_size,
254 : tdb_mutex_size(tdb)));
255 0 : return false;
256 : }
257 :
258 59705 : return true;
259 : }
260 :
261 4893576 : _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
262 : int open_flags, mode_t mode,
263 : const struct tdb_logging_context *log_ctx,
264 : tdb_hash_func hash_fn)
265 : {
266 4893576 : int orig_errno = errno;
267 4893576 : struct tdb_header header = {
268 : .version = 0,
269 : };
270 : struct tdb_context *tdb;
271 : struct stat st;
272 4893576 : int rev = 0;
273 4893576 : bool locked = false;
274 : unsigned char *vp;
275 : uint32_t vertest;
276 : unsigned v;
277 : const char *hash_alg;
278 : uint32_t magic1, magic2;
279 : int ret;
280 :
281 4893576 : if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
282 : /* Can't log this */
283 0 : errno = ENOMEM;
284 0 : goto fail;
285 : }
286 4893576 : tdb_io_init(tdb);
287 :
288 4893576 : if (tdb_flags & TDB_INTERNAL) {
289 4370030 : tdb_flags |= TDB_INCOMPATIBLE_HASH;
290 : }
291 4893576 : if (tdb_flags & TDB_MUTEX_LOCKING) {
292 59708 : tdb_flags |= TDB_INCOMPATIBLE_HASH;
293 : }
294 :
295 4893576 : tdb->fd = -1;
296 : #ifdef TDB_TRACE
297 : tdb->tracefd = -1;
298 : #endif
299 4893576 : tdb->name = NULL;
300 4893576 : tdb->map_ptr = NULL;
301 4893576 : tdb->flags = tdb_flags;
302 4893576 : tdb->open_flags = open_flags;
303 4893576 : if (log_ctx) {
304 523143 : tdb->log = *log_ctx;
305 : } else {
306 4370433 : tdb->log.log_fn = null_log_fn;
307 4370433 : tdb->log.log_private = NULL;
308 : }
309 :
310 4893576 : if (name == NULL && (tdb_flags & TDB_INTERNAL)) {
311 4369906 : name = "__TDB_INTERNAL__";
312 : }
313 :
314 4893576 : if (name == NULL) {
315 0 : tdb->name = discard_const_p(char, "__NULL__");
316 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: called with name == NULL\n"));
317 0 : tdb->name = NULL;
318 0 : errno = EINVAL;
319 0 : goto fail;
320 : }
321 :
322 : /* now make a copy of the name, as the caller memory might go away */
323 4893576 : if (!(tdb->name = (char *)strdup(name))) {
324 : /*
325 : * set the name as the given string, so that tdb_name() will
326 : * work in case of an error.
327 : */
328 0 : tdb->name = discard_const_p(char, name);
329 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't strdup(%s)\n",
330 : name));
331 0 : tdb->name = NULL;
332 0 : errno = ENOMEM;
333 0 : goto fail;
334 : }
335 :
336 4893576 : if (hash_fn) {
337 21 : tdb->hash_fn = hash_fn;
338 21 : hash_alg = "the user defined";
339 : } else {
340 : /* This controls what we use when creating a tdb. */
341 4893555 : if (tdb->flags & TDB_INCOMPATIBLE_HASH) {
342 4450433 : tdb->hash_fn = tdb_jenkins_hash;
343 : } else {
344 443122 : tdb->hash_fn = tdb_old_hash;
345 : }
346 4893555 : hash_alg = "either default";
347 : }
348 :
349 : /* cache the page size */
350 4893576 : tdb->page_size = getpagesize();
351 4893576 : if (tdb->page_size <= 0) {
352 0 : tdb->page_size = 0x2000;
353 : }
354 :
355 4893576 : tdb->max_dead_records = (tdb_flags & TDB_VOLATILE) ? 5 : 0;
356 :
357 4893576 : if ((open_flags & O_ACCMODE) == O_WRONLY) {
358 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n",
359 : name));
360 0 : errno = EINVAL;
361 0 : goto fail;
362 : }
363 :
364 4893576 : if (hash_size == 0)
365 244513 : hash_size = DEFAULT_HASH_SIZE;
366 4893576 : if ((open_flags & O_ACCMODE) == O_RDONLY) {
367 349 : tdb->read_only = 1;
368 : /* read only databases don't do locking or clear if first */
369 349 : tdb->flags |= TDB_NOLOCK;
370 349 : tdb->flags &= ~(TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING);
371 : }
372 :
373 4893576 : if ((tdb->flags & TDB_ALLOW_NESTING) &&
374 0 : (tdb->flags & TDB_DISALLOW_NESTING)) {
375 0 : tdb->ecode = TDB_ERR_NESTING;
376 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
377 : "allow_nesting and disallow_nesting are not allowed together!"));
378 0 : errno = EINVAL;
379 0 : goto fail;
380 : }
381 :
382 4893576 : if (tdb->flags & TDB_MUTEX_LOCKING) {
383 : /*
384 : * Here we catch bugs in the callers,
385 : * the runtime check for existing tdb's comes later.
386 : */
387 :
388 59707 : if (tdb->flags & TDB_INTERNAL) {
389 1 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
390 : "invalid flags for %s - TDB_MUTEX_LOCKING and "
391 : "TDB_INTERNAL are not allowed together\n", name));
392 1 : errno = EINVAL;
393 1 : goto fail;
394 : }
395 :
396 59706 : if (tdb->flags & TDB_NOMMAP) {
397 1 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
398 : "invalid flags for %s - TDB_MUTEX_LOCKING and "
399 : "TDB_NOMMAP are not allowed together\n", name));
400 1 : errno = EINVAL;
401 1 : goto fail;
402 : }
403 :
404 59705 : if (tdb->read_only) {
405 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
406 : "invalid flags for %s - TDB_MUTEX_LOCKING "
407 : "not allowed read only\n", name));
408 0 : errno = EINVAL;
409 0 : goto fail;
410 : }
411 :
412 : /*
413 : * The callers should have called
414 : * tdb_runtime_check_for_robust_mutexes()
415 : * before using TDB_MUTEX_LOCKING!
416 : *
417 : * This makes sure the caller understands
418 : * that the locking may behave a bit differently
419 : * than with pure fcntl locking. E.g. multiple
420 : * read locks are not supported.
421 : */
422 59705 : if (!tdb_runtime_check_for_robust_mutexes()) {
423 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
424 : "invalid flags for %s - TDB_MUTEX_LOCKING "
425 : "requires support for robust_mutexes\n",
426 : name));
427 0 : errno = ENOSYS;
428 0 : goto fail;
429 : }
430 : }
431 :
432 4893574 : if (getenv("TDB_NO_FSYNC")) {
433 4893472 : tdb->flags |= TDB_NOSYNC;
434 : }
435 :
436 : /*
437 : * TDB_ALLOW_NESTING is the default behavior.
438 : * Note: this may change in future versions!
439 : */
440 4893574 : if (!(tdb->flags & TDB_DISALLOW_NESTING)) {
441 4657186 : tdb->flags |= TDB_ALLOW_NESTING;
442 : }
443 :
444 : /* internal databases don't mmap or lock, and start off cleared */
445 4893574 : if (tdb->flags & TDB_INTERNAL) {
446 4370029 : tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
447 4370029 : tdb->flags &= ~TDB_CLEAR_IF_FIRST;
448 4370029 : if (tdb_new_database(tdb, &header, hash_size) != 0) {
449 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!"));
450 0 : goto fail;
451 : }
452 4370029 : tdb->hash_size = hash_size;
453 4370029 : goto internal;
454 : }
455 :
456 523545 : if ((tdb->fd = open(name, open_flags, mode)) == -1) {
457 9292 : TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n",
458 : name, strerror(errno)));
459 9292 : goto fail; /* errno set by open(2) */
460 : }
461 :
462 : /* on exec, don't inherit the fd */
463 514253 : v = fcntl(tdb->fd, F_GETFD, 0);
464 514253 : fcntl(tdb->fd, F_SETFD, v | FD_CLOEXEC);
465 :
466 : /* ensure there is only one process initialising at once */
467 514253 : if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
468 20 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get open lock on %s: %s\n",
469 : name, strerror(errno)));
470 20 : goto fail; /* errno set by tdb_brlock */
471 : }
472 :
473 : /* we need to zero database if we are the only one with it open */
474 572605 : if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
475 87208 : (!tdb->read_only)) {
476 87198 : ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK,
477 : TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
478 87198 : locked = (ret == 0);
479 :
480 87198 : if (locked) {
481 82357 : ret = tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0,
482 : TDB_LOCK_WAIT);
483 82357 : if (ret == -1) {
484 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
485 : "tdb_brlock failed for %s: %s\n",
486 : name, strerror(errno)));
487 0 : goto fail;
488 : }
489 82357 : ret = tdb_new_database(tdb, &header, hash_size);
490 82357 : if (ret == -1) {
491 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
492 : "tdb_new_database failed for "
493 : "%s: %s\n", name, strerror(errno)));
494 0 : tdb_unlockall(tdb);
495 0 : goto fail;
496 : }
497 82357 : ret = tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0);
498 82357 : if (ret == -1) {
499 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
500 : "tdb_unlockall failed for %s: %s\n",
501 : name, strerror(errno)));
502 0 : goto fail;
503 : }
504 82357 : ret = lseek(tdb->fd, 0, SEEK_SET);
505 82357 : if (ret == -1) {
506 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
507 : "lseek failed for %s: %s\n",
508 : name, strerror(errno)));
509 0 : goto fail;
510 : }
511 : }
512 : }
513 :
514 514233 : errno = 0;
515 514233 : if (read(tdb->fd, &header, sizeof(header)) != sizeof(header)
516 498168 : || strcmp(header.magic_food, TDB_MAGIC_FOOD) != 0) {
517 32129 : if (!(open_flags & O_CREAT) ||
518 16064 : tdb_new_database(tdb, &header, hash_size) == -1) {
519 1 : if (errno == 0) {
520 1 : errno = EIO; /* ie bad format or something */
521 : }
522 1 : goto fail;
523 : }
524 16064 : rev = (tdb->flags & TDB_CONVERT);
525 498168 : } else if (header.version != TDB_VERSION
526 20 : && !(rev = (header.version==TDB_BYTEREV(TDB_VERSION)))) {
527 : /* wrong version */
528 1 : errno = EIO;
529 1 : goto fail;
530 : }
531 514231 : vp = (unsigned char *)&header.version;
532 1307059 : vertest = (((uint32_t)vp[0]) << 24) | (((uint32_t)vp[1]) << 16) |
533 910645 : (((uint32_t)vp[2]) << 8) | (uint32_t)vp[3];
534 514231 : tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
535 514231 : if (!rev)
536 514207 : tdb->flags &= ~TDB_CONVERT;
537 : else {
538 24 : tdb->flags |= TDB_CONVERT;
539 24 : tdb_convert(&header, sizeof(header));
540 : }
541 :
542 : /*
543 : * We only use st.st_dev and st.st_ino from the raw fstat()
544 : * call, everything else needs to use tdb_fstat() in order
545 : * to skip tdb->hdr_ofs!
546 : */
547 514231 : if (fstat(tdb->fd, &st) == -1) {
548 0 : goto fail;
549 : }
550 514231 : tdb->device = st.st_dev;
551 514231 : tdb->inode = st.st_ino;
552 514231 : ZERO_STRUCT(st);
553 :
554 568341 : if (header.rwlocks != 0 &&
555 93557 : header.rwlocks != TDB_FEATURE_FLAG_MAGIC &&
556 20717 : header.rwlocks != TDB_HASH_RWLOCK_MAGIC) {
557 2 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
558 2 : errno = ENOSYS;
559 2 : goto fail;
560 : }
561 :
562 514229 : if (header.hash_size == 0) {
563 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: invalid database: 0 hash_size\n"));
564 0 : errno = ENOSYS;
565 0 : goto fail;
566 : }
567 :
568 514229 : tdb->hash_size = header.hash_size;
569 :
570 514229 : if (header.rwlocks == TDB_FEATURE_FLAG_MAGIC) {
571 59726 : tdb->feature_flags = header.feature_flags;
572 : }
573 :
574 514229 : if (tdb->feature_flags & ~TDB_SUPPORTED_FEATURE_FLAGS) {
575 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: unsupported "
576 : "features in tdb %s: 0x%08x (supported: 0x%08x)\n",
577 : name, (unsigned)tdb->feature_flags,
578 : (unsigned)TDB_SUPPORTED_FEATURE_FLAGS));
579 0 : errno = ENOSYS;
580 0 : goto fail;
581 : }
582 :
583 514229 : if (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
584 59726 : if (!tdb_mutex_open_ok(tdb, &header)) {
585 20 : errno = EINVAL;
586 20 : goto fail;
587 : }
588 :
589 : /*
590 : * We need to remember the hdr_ofs
591 : * also for the TDB_NOLOCK case
592 : * if the current library doesn't support
593 : * mutex locking.
594 : */
595 59706 : tdb->hdr_ofs = header.mutex_size;
596 :
597 59706 : if ((!(tdb_flags & TDB_CLEAR_IF_FIRST)) && (!tdb->read_only)) {
598 : /*
599 : * Open an existing mutexed tdb, but without
600 : * CLEAR_IF_FIRST. We need to initialize the
601 : * mutex array and keep the CLEAR_IF_FIRST
602 : * lock locked.
603 : */
604 6904 : ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK,
605 : TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
606 6904 : locked = (ret == 0);
607 :
608 6904 : if (locked) {
609 4769 : ret = tdb_mutex_init(tdb);
610 4769 : if (ret == -1) {
611 0 : TDB_LOG((tdb,
612 : TDB_DEBUG_FATAL,
613 : "tdb_open_ex: tdb_mutex_init "
614 : "failed for ""%s: %s\n",
615 : name, strerror(errno)));
616 0 : goto fail;
617 : }
618 : }
619 : }
620 : }
621 :
622 514209 : if ((header.magic1_hash == 0) && (header.magic2_hash == 0)) {
623 : /* older TDB without magic hash references */
624 8 : tdb->hash_fn = tdb_old_hash;
625 514201 : } else if (!check_header_hash(tdb, &header, !hash_fn,
626 : &magic1, &magic2)) {
627 8 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
628 : "%s was not created with %s hash function we are using\n"
629 : "magic1_hash[0x%08X %s 0x%08X] "
630 : "magic2_hash[0x%08X %s 0x%08X]\n",
631 : name, hash_alg,
632 : header.magic1_hash,
633 : (header.magic1_hash == magic1) ? "==" : "!=",
634 : magic1,
635 : header.magic2_hash,
636 : (header.magic2_hash == magic2) ? "==" : "!=",
637 : magic2));
638 8 : errno = EINVAL;
639 8 : goto fail;
640 : }
641 :
642 : /* Is it already in the open list? If so, fail. */
643 514201 : if (tdb_already_open(tdb->device, tdb->inode)) {
644 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
645 : "%s (%d,%d) is already open in this process\n",
646 : name, (int)tdb->device, (int)tdb->inode));
647 0 : errno = EBUSY;
648 0 : goto fail;
649 : }
650 :
651 : /*
652 : * We had tdb_mmap(tdb) here before,
653 : * but we need to use tdb_fstat(),
654 : * which is triggered from tdb_oob() before calling tdb_mmap().
655 : * As this skips tdb->hdr_ofs.
656 : */
657 514201 : tdb->map_size = 0;
658 514201 : ret = tdb_oob(tdb, 0, 1, 0);
659 514201 : if (ret == -1) {
660 0 : errno = EIO;
661 0 : goto fail;
662 : }
663 :
664 514201 : if (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
665 59706 : if (!(tdb->flags & TDB_NOLOCK)) {
666 59705 : ret = tdb_mutex_mmap(tdb);
667 59705 : if (ret != 0) {
668 0 : goto fail;
669 : }
670 : }
671 : }
672 :
673 514201 : if (tdb->hash_size > UINT32_MAX/4) {
674 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
675 : "hash size %"PRIu32" too large\n", tdb->hash_size));
676 0 : errno = EINVAL;
677 0 : goto fail;
678 : }
679 :
680 514201 : ret = tdb_oob(tdb, FREELIST_TOP, 4*tdb->hash_size, 1);
681 514201 : if (ret == -1) {
682 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
683 : "hash size %"PRIu32" does not fit\n", tdb->hash_size));
684 0 : errno = EINVAL;
685 0 : goto fail;
686 : }
687 :
688 514201 : if (locked) {
689 87126 : if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) {
690 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
691 : "failed to release ACTIVE_LOCK on %s: %s\n",
692 : name, strerror(errno)));
693 0 : goto fail;
694 : }
695 :
696 :
697 : }
698 :
699 514201 : if (locked || (tdb_flags & TDB_CLEAR_IF_FIRST)) {
700 : /*
701 : * We always need to do this if the CLEAR_IF_FIRST
702 : * flag is set, even if we didn't get the initial
703 : * exclusive lock as we need to let all other users
704 : * know we're using it.
705 : */
706 :
707 91976 : ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT);
708 91976 : if (ret == -1) {
709 0 : goto fail;
710 : }
711 : }
712 :
713 : /* if needed, run recovery */
714 514201 : if (tdb_transaction_recover(tdb) == -1) {
715 0 : goto fail;
716 : }
717 :
718 : #ifdef TDB_TRACE
719 : {
720 : char tracefile[strlen(name) + 32];
721 :
722 : snprintf(tracefile, sizeof(tracefile),
723 : "%s.trace.%li", name, (long)getpid());
724 : tdb->tracefd = open(tracefile, O_WRONLY|O_CREAT|O_EXCL, 0600);
725 : if (tdb->tracefd >= 0) {
726 : tdb_enable_seqnum(tdb);
727 : tdb_trace_open(tdb, "tdb_open", hash_size, tdb_flags,
728 : open_flags);
729 : } else
730 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to open trace file %s!\n", tracefile));
731 : }
732 : #endif
733 :
734 514201 : internal:
735 : /* Internal (memory-only) databases skip all the code above to
736 : * do with disk files, and resume here by releasing their
737 : * open lock and hooking into the active list. */
738 4884230 : if (tdb_nest_unlock(tdb, OPEN_LOCK, F_WRLCK, false) == -1) {
739 0 : goto fail;
740 : }
741 4884230 : tdb->next = tdbs;
742 4884230 : tdbs = tdb;
743 4884230 : errno = orig_errno;
744 4884230 : return tdb;
745 :
746 9346 : fail:
747 9346 : { int save_errno = errno;
748 :
749 9346 : if (!tdb)
750 0 : return NULL;
751 :
752 : #ifdef TDB_TRACE
753 : close(tdb->tracefd);
754 : #endif
755 9346 : if (tdb->map_ptr) {
756 0 : if (tdb->flags & TDB_INTERNAL)
757 0 : SAFE_FREE(tdb->map_ptr);
758 : else
759 0 : tdb_munmap(tdb);
760 : }
761 9346 : if (tdb->fd != -1)
762 52 : if (close(tdb->fd) != 0)
763 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
764 9346 : SAFE_FREE(tdb->lockrecs);
765 9346 : SAFE_FREE(tdb->name);
766 9346 : SAFE_FREE(tdb);
767 9346 : errno = save_errno;
768 9346 : return NULL;
769 : }
770 : }
771 :
772 : /*
773 : * Set the maximum number of dead records per hash chain
774 : */
775 :
776 2 : _PUBLIC_ void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
777 : {
778 2 : tdb->max_dead_records = max_dead;
779 2 : }
780 :
781 : /**
782 : * Close a database.
783 : *
784 : * @returns -1 for error; 0 for success.
785 : **/
786 4769340 : _PUBLIC_ int tdb_close(struct tdb_context *tdb)
787 : {
788 : struct tdb_context **i;
789 4769340 : int ret = 0;
790 :
791 4769340 : if (tdb->transaction) {
792 171 : tdb_transaction_cancel(tdb);
793 : }
794 : tdb_trace(tdb, "tdb_close");
795 :
796 4769340 : if (tdb->map_ptr) {
797 4769281 : if (tdb->flags & TDB_INTERNAL)
798 4370003 : SAFE_FREE(tdb->map_ptr);
799 : else
800 399278 : tdb_munmap(tdb);
801 : }
802 :
803 4769340 : tdb_mutex_munmap(tdb);
804 :
805 4769340 : SAFE_FREE(tdb->name);
806 4769340 : if (tdb->fd != -1) {
807 399337 : ret = close(tdb->fd);
808 399337 : tdb->fd = -1;
809 : }
810 4769340 : SAFE_FREE(tdb->lockrecs);
811 :
812 : /* Remove from contexts list */
813 10409905 : for (i = &tdbs; *i; i = &(*i)->next) {
814 10409905 : if (*i == tdb) {
815 4769340 : *i = tdb->next;
816 4769340 : break;
817 : }
818 : }
819 :
820 : #ifdef TDB_TRACE
821 : close(tdb->tracefd);
822 : #endif
823 4769340 : memset(tdb, 0, sizeof(*tdb));
824 4769340 : SAFE_FREE(tdb);
825 :
826 4769340 : return ret;
827 : }
828 :
829 : /* register a loging function */
830 0 : _PUBLIC_ void tdb_set_logging_function(struct tdb_context *tdb,
831 : const struct tdb_logging_context *log_ctx)
832 : {
833 0 : tdb->log = *log_ctx;
834 0 : }
835 :
836 632 : _PUBLIC_ void *tdb_get_logging_private(struct tdb_context *tdb)
837 : {
838 632 : return tdb->log.log_private;
839 : }
840 :
841 552524 : static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock)
842 : {
843 : #if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \
844 : !defined(LIBREPLACE_PWRITE_NOT_REPLACED)
845 : struct stat st;
846 : #endif
847 :
848 552524 : if (tdb->flags & TDB_INTERNAL) {
849 0 : return 0; /* Nothing to do. */
850 : }
851 :
852 552524 : if (tdb_have_extra_locks(tdb)) {
853 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
854 0 : goto fail;
855 : }
856 :
857 552524 : if (tdb->transaction != 0) {
858 1 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n"));
859 1 : goto fail;
860 : }
861 :
862 : /* If we have real pread & pwrite, we can skip reopen. */
863 : #if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \
864 : !defined(LIBREPLACE_PWRITE_NOT_REPLACED)
865 : if (tdb_munmap(tdb) != 0) {
866 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
867 : goto fail;
868 : }
869 : if (close(tdb->fd) != 0)
870 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
871 : tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
872 : if (tdb->fd == -1) {
873 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
874 : goto fail;
875 : }
876 : /*
877 : * We only use st.st_dev and st.st_ino from the raw fstat()
878 : * call, everything else needs to use tdb_fstat() in order
879 : * to skip tdb->hdr_ofs!
880 : */
881 : if (fstat(tdb->fd, &st) != 0) {
882 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
883 : goto fail;
884 : }
885 : if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
886 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n"));
887 : goto fail;
888 : }
889 : ZERO_STRUCT(st);
890 :
891 : /*
892 : * We had tdb_mmap(tdb) here before,
893 : * but we need to use tdb_fstat(),
894 : * which is triggered from tdb_oob() before calling tdb_mmap().
895 : * As this skips tdb->hdr_ofs.
896 : */
897 : tdb->map_size = 0;
898 : if (tdb_oob(tdb, 0, 1, 0) != 0) {
899 : goto fail;
900 : }
901 : #endif /* fake pread or pwrite */
902 :
903 : /* We may still think we hold the active lock. */
904 552523 : tdb->num_lockrecs = 0;
905 552523 : SAFE_FREE(tdb->lockrecs);
906 552523 : tdb->lockrecs_array_length = 0;
907 :
908 552523 : if (active_lock && tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
909 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
910 0 : goto fail;
911 : }
912 :
913 552523 : return 0;
914 :
915 1 : fail:
916 1 : tdb_close(tdb);
917 1 : return -1;
918 : }
919 :
920 : /* reopen a tdb - this can be used after a fork to ensure that we have an independent
921 : seek pointer from our parent and to re-establish locks */
922 175613 : _PUBLIC_ int tdb_reopen(struct tdb_context *tdb)
923 : {
924 : bool active_lock;
925 175613 : active_lock = (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING));
926 :
927 175613 : return tdb_reopen_internal(tdb, active_lock);
928 : }
929 :
930 : /* reopen all tdb's */
931 37941 : _PUBLIC_ int tdb_reopen_all(int parent_longlived)
932 : {
933 : struct tdb_context *tdb;
934 :
935 414852 : for (tdb=tdbs; tdb; tdb = tdb->next) {
936 : bool active_lock;
937 :
938 376911 : active_lock =
939 376911 : (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING));
940 :
941 : /*
942 : * If the parent is longlived (ie. a
943 : * parent daemon architecture), we know
944 : * it will keep it's active lock on a
945 : * tdb opened with CLEAR_IF_FIRST. Thus
946 : * for child processes we don't have to
947 : * add an active lock. This is essential
948 : * to improve performance on systems that
949 : * keep POSIX locks as a non-scalable data
950 : * structure in the kernel.
951 : */
952 376911 : if (parent_longlived) {
953 : /* Ensure no clear-if-first. */
954 359072 : active_lock = false;
955 : }
956 :
957 376911 : if (tdb_reopen_internal(tdb, active_lock) != 0)
958 0 : return -1;
959 : }
960 :
961 37941 : return 0;
962 : }
|