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 7808263 : void tdb_header_hash(struct tdb_context *tdb,
35 : uint32_t *magic1_hash, uint32_t *magic2_hash)
36 : {
37 211801 : TDB_DATA hash_key;
38 7808263 : uint32_t tdb_magic = TDB_MAGIC;
39 :
40 7808263 : hash_key.dptr = discard_const_p(unsigned char, TDB_MAGIC_FOOD);
41 7808263 : hash_key.dsize = sizeof(TDB_MAGIC_FOOD);
42 7808263 : *magic1_hash = tdb->hash_fn(&hash_key);
43 :
44 7808263 : hash_key.dptr = (unsigned char *)CONVERT(tdb_magic);
45 7808263 : hash_key.dsize = sizeof(tdb_magic);
46 7808263 : *magic2_hash = tdb->hash_fn(&hash_key);
47 :
48 : /* Make sure at least one hash is non-zero! */
49 7808263 : if (*magic1_hash == 0 && *magic2_hash == 0)
50 0 : *magic1_hash = 1;
51 7808263 : }
52 :
53 : /* initialise a new database with a specified hash size */
54 6473435 : static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *header,
55 : int hash_size)
56 : {
57 181237 : struct tdb_header *newdb;
58 181237 : size_t size;
59 6473435 : int ret = -1;
60 :
61 : /* We make it up in memory, then write it out if not internal */
62 6473435 : size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
63 6473435 : 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 6473435 : newdb->version = TDB_VERSION;
70 6473435 : newdb->hash_size = hash_size;
71 :
72 6473435 : 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 6473435 : if (tdb->flags & TDB_INCOMPATIBLE_HASH)
77 6377711 : 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 6473435 : if (tdb->flags & TDB_MUTEX_LOCKING) {
85 316161 : 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 6473435 : if (newdb->feature_flags != 0) {
93 316161 : newdb->rwlocks = TDB_FEATURE_FLAG_MAGIC;
94 : }
95 :
96 : /*
97 : * It's required for some following code paths
98 : * to have the fields on 'tdb' up-to-date.
99 : *
100 : * E.g. tdb_mutex_size() requires it
101 : */
102 6473435 : tdb->feature_flags = newdb->feature_flags;
103 6473435 : tdb->hash_size = newdb->hash_size;
104 :
105 6473435 : if (tdb->flags & TDB_INTERNAL) {
106 6017663 : tdb->map_size = size;
107 6017663 : tdb->map_ptr = (char *)newdb;
108 6017663 : memcpy(header, newdb, sizeof(*header));
109 : /* Convert the `ondisk' version if asked. */
110 6017663 : CONVERT(*newdb);
111 6017663 : return 0;
112 : }
113 455772 : if (lseek(tdb->fd, 0, SEEK_SET) == -1)
114 0 : goto fail;
115 :
116 455772 : if (ftruncate(tdb->fd, 0) == -1)
117 0 : goto fail;
118 :
119 455772 : if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
120 316161 : newdb->mutex_size = tdb_mutex_size(tdb);
121 316161 : tdb->hdr_ofs = newdb->mutex_size;
122 : }
123 :
124 : /* This creates an endian-converted header, as if read from disk */
125 455772 : CONVERT(*newdb);
126 455772 : memcpy(header, newdb, sizeof(*header));
127 : /* Don't endian-convert the magic food! */
128 455772 : memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
129 :
130 455772 : if (!tdb_write_all(tdb->fd, newdb, size))
131 0 : goto fail;
132 :
133 455772 : 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 324610 : ret = ftruncate(
141 : tdb->fd,
142 316161 : newdb->mutex_size + sizeof(struct tdb_header));
143 316161 : if (ret == -1) {
144 0 : goto fail;
145 : }
146 316161 : ret = tdb_mutex_init(tdb);
147 316161 : 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 316161 : ret = lseek(tdb->fd, newdb->mutex_size, SEEK_SET);
156 316161 : if (ret == -1) {
157 0 : goto fail;
158 : }
159 316161 : if (!tdb_write_all(tdb->fd, newdb, size)) {
160 0 : goto fail;
161 : }
162 : }
163 :
164 443735 : ret = 0;
165 455772 : fail:
166 455772 : SAFE_FREE(newdb);
167 455772 : return ret;
168 : }
169 :
170 :
171 :
172 1269424 : static int tdb_already_open(dev_t device,
173 : ino_t ino)
174 : {
175 30598 : struct tdb_context *i;
176 :
177 12243669 : for (i = tdbs; i; i = i->next) {
178 10974245 : if (i->device == device && i->inode == ino) {
179 0 : return 1;
180 : }
181 : }
182 :
183 1238826 : 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 6021704 : _PUBLIC_ struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
197 : int open_flags, mode_t mode)
198 : {
199 6021704 : 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 164 : static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
205 : {
206 164 : }
207 :
208 1269454 : 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 1269454 : tdb_header_hash(tdb, m1, m2);
213 1269454 : if (header->magic1_hash == *m1 &&
214 1269345 : header->magic2_hash == *m2) {
215 1238782 : return true;
216 : }
217 :
218 : /* If they explicitly set a hash, always respect it. */
219 109 : if (!default_hash)
220 8 : return false;
221 :
222 : /* Otherwise, try the other inbuilt hash. */
223 101 : if (tdb->hash_fn == tdb_old_hash)
224 66 : tdb->hash_fn = tdb_jenkins_hash;
225 : else
226 35 : tdb->hash_fn = tdb_old_hash;
227 101 : return check_header_hash(tdb, header, false, m1, m2);
228 : }
229 :
230 356798 : static bool tdb_mutex_open_ok(struct tdb_context *tdb,
231 : const struct tdb_header *header)
232 : {
233 356798 : 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 69 : return true;
239 : }
240 :
241 356729 : if (!(tdb->flags & TDB_MUTEX_LOCKING)) {
242 24 : 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 24 : return false;
247 : }
248 :
249 356705 : 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 347401 : return true;
259 : }
260 :
261 7330024 : _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 7330024 : int orig_errno = errno;
267 7330024 : struct tdb_header header = {
268 : .version = 0,
269 : };
270 201500 : struct tdb_context *tdb;
271 201500 : struct stat st;
272 7330024 : int rev = 0;
273 7330024 : bool locked = false;
274 201500 : unsigned char *vp;
275 201500 : uint32_t vertest;
276 201500 : unsigned v;
277 201500 : const char *hash_alg;
278 201500 : uint32_t magic1, magic2;
279 201500 : int ret;
280 :
281 7330024 : if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
282 : /* Can't log this */
283 0 : errno = ENOMEM;
284 0 : goto fail;
285 : }
286 7330024 : tdb_io_init(tdb);
287 :
288 7330024 : if (tdb_flags & TDB_INTERNAL) {
289 6017664 : tdb_flags |= TDB_INCOMPATIBLE_HASH;
290 : }
291 7330024 : if (tdb_flags & TDB_MUTEX_LOCKING) {
292 356770 : tdb_flags |= TDB_INCOMPATIBLE_HASH;
293 : }
294 :
295 7330024 : tdb->fd = -1;
296 : #ifdef TDB_TRACE
297 : tdb->tracefd = -1;
298 : #endif
299 7330024 : tdb->name = NULL;
300 7330024 : tdb->map_ptr = NULL;
301 7330024 : tdb->flags = tdb_flags;
302 7330024 : tdb->open_flags = open_flags;
303 7330024 : if (log_ctx) {
304 1308320 : tdb->log = *log_ctx;
305 : } else {
306 6021704 : tdb->log.log_fn = null_log_fn;
307 6021704 : tdb->log.log_private = NULL;
308 : }
309 :
310 7330024 : if (name == NULL && (tdb_flags & TDB_INTERNAL)) {
311 6017532 : name = "__TDB_INTERNAL__";
312 : }
313 :
314 7330024 : 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 7330024 : 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 7330024 : 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 7330003 : if (tdb->flags & TDB_INCOMPATIBLE_HASH) {
342 6455561 : tdb->hash_fn = tdb_jenkins_hash;
343 : } else {
344 874442 : tdb->hash_fn = tdb_old_hash;
345 : }
346 7128503 : hash_alg = "either default";
347 : }
348 :
349 : /* cache the page size */
350 7330024 : tdb->page_size = getpagesize();
351 7330024 : if (tdb->page_size <= 0) {
352 0 : tdb->page_size = 0x2000;
353 : }
354 :
355 7330024 : tdb->max_dead_records = (tdb_flags & TDB_VOLATILE) ? 5 : 0;
356 :
357 7330024 : 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 7330024 : if (hash_size == 0)
365 706132 : hash_size = DEFAULT_HASH_SIZE;
366 7330024 : if ((open_flags & O_ACCMODE) == O_RDONLY) {
367 787 : tdb->read_only = 1;
368 : /* read only databases don't do locking or clear if first */
369 787 : tdb->flags |= TDB_NOLOCK;
370 787 : tdb->flags &= ~(TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING);
371 : }
372 :
373 7330024 : 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 7330024 : 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 356707 : 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 356706 : 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 356705 : 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 356705 : 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 7330022 : if (getenv("TDB_NO_FSYNC")) {
433 7329920 : 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 7330022 : if (!(tdb->flags & TDB_DISALLOW_NESTING)) {
441 6996845 : tdb->flags |= TDB_ALLOW_NESTING;
442 : }
443 :
444 : /* internal databases don't mmap or lock, and start off cleared */
445 7330022 : if (tdb->flags & TDB_INTERNAL) {
446 6017663 : tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
447 6017663 : tdb->flags &= ~TDB_CLEAR_IF_FIRST;
448 6017663 : 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 6017663 : tdb->hash_size = hash_size;
453 6017663 : goto internal;
454 : }
455 :
456 1344659 : if ((tdb->fd = open(name, open_flags, mode)) == -1) {
457 42876 : TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n",
458 : name, strerror(errno)));
459 42876 : goto fail; /* errno set by open(2) */
460 : }
461 :
462 : /* on exec, don't inherit the fd */
463 1269483 : v = fcntl(tdb->fd, F_GETFD, 0);
464 1269483 : fcntl(tdb->fd, F_SETFD, v | FD_CLOEXEC);
465 :
466 : /* ensure there is only one process initialising at once */
467 1269483 : 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 1269463 : if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
475 422134 : (!tdb->read_only)) {
476 422042 : ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK,
477 : TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
478 422042 : locked = (ret == 0);
479 :
480 422042 : if (locked) {
481 384000 : ret = tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0,
482 : TDB_LOCK_WAIT);
483 384000 : 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 384000 : ret = tdb_new_database(tdb, &header, hash_size);
490 384000 : 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 384000 : ret = tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0);
498 384000 : 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 384000 : ret = lseek(tdb->fd, 0, SEEK_SET);
505 384000 : 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 1269463 : errno = 0;
515 1269463 : if (read(tdb->fd, &header, sizeof(header)) != sizeof(header)
516 : /*
517 : * Call strncmp() rather than strcmp() in case header.magic_food is
518 : * not zero‐terminated. We’re still checking the full string for
519 : * equality, as tdb_header::magic_food is larger than
520 : * TDB_MAGIC_FOOD.
521 : */
522 1197687 : || strncmp(header.magic_food, TDB_MAGIC_FOOD, sizeof(header.magic_food)) != 0) {
523 143548 : if (!(open_flags & O_CREAT) ||
524 71772 : tdb_new_database(tdb, &header, hash_size) == -1) {
525 4 : if (errno == 0) {
526 4 : errno = EIO; /* ie bad format or something */
527 : }
528 4 : goto fail;
529 : }
530 71772 : rev = (tdb->flags & TDB_CONVERT);
531 1197687 : } else if (header.version != TDB_VERSION
532 20 : && !(rev = (header.version==TDB_BYTEREV(TDB_VERSION)))) {
533 : /* wrong version */
534 1 : errno = EIO;
535 1 : goto fail;
536 : }
537 1269458 : vp = (unsigned char *)&header.version;
538 1269458 : vertest = (((uint32_t)vp[0]) << 24) | (((uint32_t)vp[1]) << 16) |
539 1269458 : (((uint32_t)vp[2]) << 8) | (uint32_t)vp[3];
540 1269458 : tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
541 1269458 : if (!rev)
542 1269434 : tdb->flags &= ~TDB_CONVERT;
543 : else {
544 24 : tdb->flags |= TDB_CONVERT;
545 24 : tdb_convert(&header, sizeof(header));
546 : }
547 :
548 : /*
549 : * We only use st.st_dev and st.st_ino from the raw fstat()
550 : * call, everything else needs to use tdb_fstat() in order
551 : * to skip tdb->hdr_ofs!
552 : */
553 1269458 : if (fstat(tdb->fd, &st) == -1) {
554 0 : goto fail;
555 : }
556 1269458 : tdb->device = st.st_dev;
557 1269458 : tdb->inode = st.st_ino;
558 1269458 : ZERO_STRUCT(st);
559 :
560 1269458 : if (header.rwlocks != 0 &&
561 428651 : header.rwlocks != TDB_FEATURE_FLAG_MAGIC &&
562 80022 : header.rwlocks != TDB_HASH_RWLOCK_MAGIC) {
563 2 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
564 2 : errno = ENOSYS;
565 2 : goto fail;
566 : }
567 :
568 1269456 : if (header.hash_size == 0) {
569 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: invalid database: 0 hash_size\n"));
570 0 : errno = ENOSYS;
571 0 : goto fail;
572 : }
573 :
574 1269456 : tdb->hash_size = header.hash_size;
575 :
576 1269456 : if (header.rwlocks == TDB_FEATURE_FLAG_MAGIC) {
577 356798 : tdb->feature_flags = header.feature_flags;
578 : }
579 :
580 1269456 : if (tdb->feature_flags & ~TDB_SUPPORTED_FEATURE_FLAGS) {
581 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: unsupported "
582 : "features in tdb %s: 0x%08x (supported: 0x%08x)\n",
583 : name, (unsigned)tdb->feature_flags,
584 : (unsigned)TDB_SUPPORTED_FEATURE_FLAGS));
585 0 : errno = ENOSYS;
586 0 : goto fail;
587 : }
588 :
589 1269456 : if (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
590 356798 : if (!tdb_mutex_open_ok(tdb, &header)) {
591 24 : errno = EINVAL;
592 24 : goto fail;
593 : }
594 :
595 : /*
596 : * We need to remember the hdr_ofs
597 : * also for the TDB_NOLOCK case
598 : * if the current library doesn't support
599 : * mutex locking.
600 : */
601 356774 : tdb->hdr_ofs = header.mutex_size;
602 :
603 356774 : if ((!(tdb_flags & TDB_CLEAR_IF_FIRST)) && (!tdb->read_only)) {
604 : /*
605 : * Open an existing mutexed tdb, but without
606 : * CLEAR_IF_FIRST. We need to initialize the
607 : * mutex array and keep the CLEAR_IF_FIRST
608 : * lock locked.
609 : */
610 40561 : ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK,
611 : TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
612 40561 : locked = (ret == 0);
613 :
614 40561 : if (locked) {
615 27778 : ret = tdb_mutex_init(tdb);
616 27778 : if (ret == -1) {
617 0 : TDB_LOG((tdb,
618 : TDB_DEBUG_FATAL,
619 : "tdb_open_ex: tdb_mutex_init "
620 : "failed for ""%s: %s\n",
621 : name, strerror(errno)));
622 0 : goto fail;
623 : }
624 : }
625 : }
626 : }
627 :
628 1269432 : if ((header.magic1_hash == 0) && (header.magic2_hash == 0)) {
629 : /* older TDB without magic hash references */
630 79 : tdb->hash_fn = tdb_old_hash;
631 1269353 : } else if (!check_header_hash(tdb, &header, !hash_fn,
632 : &magic1, &magic2)) {
633 8 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
634 : "%s was not created with %s hash function we are using\n"
635 : "magic1_hash[0x%08X %s 0x%08X] "
636 : "magic2_hash[0x%08X %s 0x%08X]\n",
637 : name, hash_alg,
638 : header.magic1_hash,
639 : (header.magic1_hash == magic1) ? "==" : "!=",
640 : magic1,
641 : header.magic2_hash,
642 : (header.magic2_hash == magic2) ? "==" : "!=",
643 : magic2));
644 8 : errno = EINVAL;
645 8 : goto fail;
646 : }
647 :
648 : /* Is it already in the open list? If so, fail. */
649 1300022 : if (tdb_already_open(tdb->device, tdb->inode)) {
650 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
651 : "%s (%d,%d) is already open in this process\n",
652 : name, (int)tdb->device, (int)tdb->inode));
653 0 : errno = EBUSY;
654 0 : goto fail;
655 : }
656 :
657 : /*
658 : * We had tdb_mmap(tdb) here before,
659 : * but we need to use tdb_fstat(),
660 : * which is triggered from tdb_oob() before calling tdb_mmap().
661 : * As this skips tdb->hdr_ofs.
662 : */
663 1269424 : tdb->map_size = 0;
664 1269424 : ret = tdb_oob(tdb, 0, 1, 0);
665 1269424 : if (ret == -1) {
666 0 : errno = EIO;
667 0 : goto fail;
668 : }
669 :
670 1269424 : if (tdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
671 356774 : if (!(tdb->flags & TDB_NOLOCK)) {
672 356705 : ret = tdb_mutex_mmap(tdb);
673 356705 : if (ret != 0) {
674 0 : goto fail;
675 : }
676 : }
677 : }
678 :
679 1269424 : if (tdb->hash_size > UINT32_MAX/4) {
680 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
681 : "hash size %"PRIu32" too large\n", tdb->hash_size));
682 0 : errno = EINVAL;
683 0 : goto fail;
684 : }
685 :
686 1269424 : ret = tdb_oob(tdb, FREELIST_TOP, 4*tdb->hash_size, 1);
687 1238826 : if (ret == -1) {
688 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
689 : "hash size %"PRIu32" does not fit\n", tdb->hash_size));
690 0 : errno = EINVAL;
691 0 : goto fail;
692 : }
693 :
694 1269424 : if (locked) {
695 411778 : if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) {
696 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
697 : "failed to release ACTIVE_LOCK on %s: %s\n",
698 : name, strerror(errno)));
699 0 : goto fail;
700 : }
701 :
702 :
703 : }
704 :
705 1269424 : if (locked || (tdb_flags & TDB_CLEAR_IF_FIRST)) {
706 : /*
707 : * We always need to do this if the CLEAR_IF_FIRST
708 : * flag is set, even if we didn't get the initial
709 : * exclusive lock as we need to let all other users
710 : * know we're using it.
711 : */
712 :
713 449911 : ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT);
714 449911 : if (ret == -1) {
715 0 : goto fail;
716 : }
717 : }
718 :
719 : /* if needed, run recovery */
720 1269424 : if (tdb_transaction_recover(tdb) == -1) {
721 0 : goto fail;
722 : }
723 :
724 : #ifdef TDB_TRACE
725 : {
726 : char tracefile[strlen(name) + 32];
727 :
728 : snprintf(tracefile, sizeof(tracefile),
729 : "%s.trace.%li", name, (long)getpid());
730 : tdb->tracefd = open(tracefile, O_WRONLY|O_CREAT|O_EXCL, 0600);
731 : if (tdb->tracefd >= 0) {
732 : tdb_enable_seqnum(tdb);
733 : tdb_trace_open(tdb, "tdb_open", hash_size, tdb_flags,
734 : open_flags);
735 : } else
736 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to open trace file %s!\n", tracefile));
737 : }
738 : #endif
739 :
740 1269424 : internal:
741 : /* Internal (memory-only) databases skip all the code above to
742 : * do with disk files, and resume here by releasing their
743 : * open lock and hooking into the active list. */
744 7287087 : if (tdb_nest_unlock(tdb, OPEN_LOCK, F_WRLCK, false) == -1) {
745 0 : goto fail;
746 : }
747 7287087 : tdb->next = tdbs;
748 7287087 : tdbs = tdb;
749 7287087 : errno = orig_errno;
750 7287087 : return tdb;
751 :
752 42937 : fail:
753 42937 : { int save_errno = errno;
754 :
755 42937 : if (!tdb)
756 0 : return NULL;
757 :
758 : #ifdef TDB_TRACE
759 : close(tdb->tracefd);
760 : #endif
761 42937 : if (tdb->map_ptr) {
762 0 : if (tdb->flags & TDB_INTERNAL)
763 0 : SAFE_FREE(tdb->map_ptr);
764 : else
765 0 : tdb_munmap(tdb);
766 : }
767 42937 : if (tdb->fd != -1)
768 59 : if (close(tdb->fd) != 0)
769 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
770 42937 : SAFE_FREE(tdb->lockrecs);
771 42937 : SAFE_FREE(tdb->name);
772 42937 : SAFE_FREE(tdb);
773 42937 : errno = save_errno;
774 42937 : return NULL;
775 : }
776 : }
777 :
778 : /*
779 : * Set the maximum number of dead records per hash chain
780 : */
781 :
782 4 : _PUBLIC_ void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
783 : {
784 4 : tdb->max_dead_records = max_dead;
785 4 : }
786 :
787 : /**
788 : * Close a database.
789 : *
790 : * @returns -1 for error; 0 for success.
791 : **/
792 6733157 : _PUBLIC_ int tdb_close(struct tdb_context *tdb)
793 : {
794 185929 : struct tdb_context **i;
795 6733157 : int ret = 0;
796 :
797 6733157 : if (tdb->transaction) {
798 186 : tdb_transaction_cancel(tdb);
799 : }
800 185929 : tdb_trace(tdb, "tdb_close");
801 :
802 6733157 : if (tdb->map_ptr) {
803 6733098 : if (tdb->flags & TDB_INTERNAL)
804 6017584 : SAFE_FREE(tdb->map_ptr);
805 : else
806 715514 : tdb_munmap(tdb);
807 : }
808 :
809 6733157 : tdb_mutex_munmap(tdb);
810 :
811 6733157 : SAFE_FREE(tdb->name);
812 6733157 : if (tdb->fd != -1) {
813 715573 : ret = close(tdb->fd);
814 715573 : tdb->fd = -1;
815 : }
816 6733157 : SAFE_FREE(tdb->lockrecs);
817 :
818 : /* Remove from contexts list */
819 14538984 : for (i = &tdbs; *i; i = &(*i)->next) {
820 14538984 : if (*i == tdb) {
821 6733157 : *i = tdb->next;
822 6733157 : break;
823 : }
824 : }
825 :
826 : #ifdef TDB_TRACE
827 : close(tdb->tracefd);
828 : #endif
829 6733157 : memset(tdb, 0, sizeof(*tdb));
830 6733157 : SAFE_FREE(tdb);
831 :
832 6733157 : return ret;
833 : }
834 :
835 : /* register a logging function */
836 2 : _PUBLIC_ void tdb_set_logging_function(struct tdb_context *tdb,
837 : const struct tdb_logging_context *log_ctx)
838 : {
839 2 : tdb->log = *log_ctx;
840 2 : }
841 :
842 1025 : _PUBLIC_ void *tdb_get_logging_private(struct tdb_context *tdb)
843 : {
844 1025 : return tdb->log.log_private;
845 : }
846 :
847 1228701 : static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock)
848 : {
849 : #if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \
850 : !defined(LIBREPLACE_PWRITE_NOT_REPLACED)
851 : struct stat st;
852 : #endif
853 :
854 1228701 : if (tdb->flags & TDB_INTERNAL) {
855 0 : return 0; /* Nothing to do. */
856 : }
857 :
858 1228701 : if (tdb_have_extra_locks(tdb)) {
859 0 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
860 0 : goto fail;
861 : }
862 :
863 1228701 : if (tdb->transaction != 0) {
864 1 : TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n"));
865 1 : goto fail;
866 : }
867 :
868 : /* If we have real pread & pwrite, we can skip reopen. */
869 : #if !defined(LIBREPLACE_PREAD_NOT_REPLACED) || \
870 : !defined(LIBREPLACE_PWRITE_NOT_REPLACED)
871 : if (tdb_munmap(tdb) != 0) {
872 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
873 : goto fail;
874 : }
875 : if (close(tdb->fd) != 0)
876 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
877 : tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
878 : if (tdb->fd == -1) {
879 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
880 : goto fail;
881 : }
882 : /*
883 : * We only use st.st_dev and st.st_ino from the raw fstat()
884 : * call, everything else needs to use tdb_fstat() in order
885 : * to skip tdb->hdr_ofs!
886 : */
887 : if (fstat(tdb->fd, &st) != 0) {
888 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
889 : goto fail;
890 : }
891 : if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
892 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n"));
893 : goto fail;
894 : }
895 : ZERO_STRUCT(st);
896 :
897 : /*
898 : * We had tdb_mmap(tdb) here before,
899 : * but we need to use tdb_fstat(),
900 : * which is triggered from tdb_oob() before calling tdb_mmap().
901 : * As this skips tdb->hdr_ofs.
902 : */
903 : tdb->map_size = 0;
904 : if (tdb_oob(tdb, 0, 1, 0) != 0) {
905 : goto fail;
906 : }
907 : #endif /* fake pread or pwrite */
908 :
909 : /* We may still think we hold the active lock. */
910 1228700 : tdb->num_lockrecs = 0;
911 1228700 : SAFE_FREE(tdb->lockrecs);
912 1228700 : tdb->lockrecs_array_length = 0;
913 :
914 1228700 : if (active_lock && tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
915 0 : TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
916 0 : goto fail;
917 : }
918 :
919 1208931 : return 0;
920 :
921 1 : fail:
922 1 : tdb_close(tdb);
923 1 : return -1;
924 : }
925 :
926 : /* reopen a tdb - this can be used after a fork to ensure that we have an independent
927 : seek pointer from our parent and to re-establish locks */
928 219158 : _PUBLIC_ int tdb_reopen(struct tdb_context *tdb)
929 : {
930 1718 : bool active_lock;
931 219158 : active_lock = (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING));
932 :
933 219158 : return tdb_reopen_internal(tdb, active_lock);
934 : }
935 :
936 : /* reopen all tdb's */
937 96857 : _PUBLIC_ int tdb_reopen_all(int parent_longlived)
938 : {
939 1784 : struct tdb_context *tdb;
940 :
941 1106400 : for (tdb=tdbs; tdb; tdb = tdb->next) {
942 18052 : bool active_lock;
943 :
944 1009543 : active_lock =
945 1009543 : (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING));
946 :
947 : /*
948 : * If the parent is longlived (ie. a
949 : * parent daemon architecture), we know
950 : * it will keep it's active lock on a
951 : * tdb opened with CLEAR_IF_FIRST. Thus
952 : * for child processes we don't have to
953 : * add an active lock. This is essential
954 : * to improve performance on systems that
955 : * keep POSIX locks as a non-scalable data
956 : * structure in the kernel.
957 : */
958 1009543 : if (parent_longlived) {
959 : /* Ensure no clear-if-first. */
960 891625 : active_lock = false;
961 : }
962 :
963 1009543 : if (tdb_reopen_internal(tdb, active_lock) != 0)
964 0 : return -1;
965 : }
966 :
967 95073 : return 0;
968 : }
|