~ubuntu-branches/ubuntu/natty/evolution-data-server/natty

« back to all changes in this revision

Viewing changes to libdb/db/db_open.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*-
2
 
 * See the file LICENSE for redistribution information.
3
 
 *
4
 
 * Copyright (c) 1996-2002
5
 
 *      Sleepycat Software.  All rights reserved.
6
 
 */
7
 
 
8
 
#include "db_config.h"
9
 
 
10
 
#ifndef lint
11
 
static const char revid[] = "$Id$";
12
 
#endif /* not lint */
13
 
 
14
 
#ifndef NO_SYSTEM_INCLUDES
15
 
#include <sys/types.h>
16
 
 
17
 
#include <stddef.h>
18
 
#include <stdlib.h>
19
 
#include <string.h>
20
 
#endif
21
 
 
22
 
#include "db_int.h"
23
 
#include "dbinc/db_page.h"
24
 
#include "dbinc/db_shash.h"
25
 
#include "dbinc/db_swap.h"
26
 
#include "dbinc/btree.h"
27
 
#include "dbinc/crypto.h"
28
 
#include "dbinc/hmac.h"
29
 
#include "dbinc/fop.h"
30
 
#include "dbinc/hash.h"
31
 
#include "dbinc/lock.h"
32
 
#include "dbinc/log.h"
33
 
#include "dbinc/qam.h"
34
 
#include "dbinc/txn.h"
35
 
 
36
 
static int __db_openchk __P((DB *,
37
 
    DB_TXN *, const char *, const char *, DBTYPE, u_int32_t));
38
 
 
39
 
/*
40
 
 * __db_open --
41
 
 *      Main library interface to the DB access methods.
42
 
 *
43
 
 * PUBLIC: int __db_open __P((DB *, DB_TXN *,
44
 
 * PUBLIC:     const char *, const char *, DBTYPE, u_int32_t, int));
45
 
 */
46
 
int
47
 
__db_open(dbp, txn, name, subdb, type, flags, mode)
48
 
        DB *dbp;
49
 
        DB_TXN *txn;
50
 
        const char *name, *subdb;
51
 
        DBTYPE type;
52
 
        u_int32_t flags;
53
 
        int mode;
54
 
{
55
 
        DB_ENV *dbenv;
56
 
        int remove_master, remove_me, ret, t_ret, txn_local;
57
 
 
58
 
        dbenv = dbp->dbenv;
59
 
        remove_me = remove_master = txn_local = 0;
60
 
 
61
 
        PANIC_CHECK(dbenv);
62
 
 
63
 
        if ((ret = __db_openchk(dbp, txn, name, subdb, type, flags)) != 0)
64
 
                return (ret);
65
 
 
66
 
        /*
67
 
         * Create local transaction as necessary, check for consistent
68
 
         * transaction usage.
69
 
         */
70
 
        if (IS_AUTO_COMMIT(dbenv, txn, flags)) {
71
 
                if ((ret = __db_txn_auto(dbp, &txn)) != 0)
72
 
                        return (ret);
73
 
                txn_local = 1;
74
 
        } else
75
 
                if (txn != NULL && !TXN_ON(dbenv))
76
 
                        return (__db_not_txn_env(dbenv));
77
 
 
78
 
        /*
79
 
         * If the environment was configured with threads, the DB handle
80
 
         * must also be free-threaded, so we force the DB_THREAD flag on.
81
 
         * (See SR #2033 for why this is a requirement--recovery needs
82
 
         * to be able to grab a dbp using __db_fileid_to_dbp, and it has
83
 
         * no way of knowing which dbp goes with which thread, so whichever
84
 
         * one it finds has to be usable in any of them.)
85
 
         */
86
 
        if (F_ISSET(dbenv, DB_ENV_THREAD))
87
 
                LF_SET(DB_THREAD);
88
 
 
89
 
        /* Convert any DB->open flags. */
90
 
        if (LF_ISSET(DB_RDONLY))
91
 
                F_SET(dbp, DB_AM_RDONLY);
92
 
        if (LF_ISSET(DB_DIRTY_READ))
93
 
                F_SET(dbp, DB_AM_DIRTY);
94
 
 
95
 
        /* Fill in the type. */
96
 
        dbp->type = type;
97
 
 
98
 
        /*
99
 
         * If we're opening a subdatabase, we have to open (and potentially
100
 
         * create) the main database, and then get (and potentially store)
101
 
         * our base page number in that database.  Then, we can finally open
102
 
         * the subdatabase.
103
 
         */
104
 
        if ((ret = __db_dbopen(
105
 
            dbp, txn, name, subdb, flags, mode, PGNO_BASE_MD)) != 0)
106
 
                goto err;
107
 
 
108
 
        /*
109
 
         * You can open the database that describes the subdatabases in the
110
 
         * rest of the file read-only.  The content of each key's data is
111
 
         * unspecified and applications should never be adding new records
112
 
         * or updating existing records.  However, during recovery, we need
113
 
         * to open these databases R/W so we can redo/undo changes in them.
114
 
         * Likewise, we need to open master databases read/write during
115
 
         * rename and remove so we can be sure they're fully sync'ed, so
116
 
         * we provide an override flag for the purpose.
117
 
         */
118
 
        if (subdb == NULL && !IS_RECOVERING(dbenv) && !LF_ISSET(DB_RDONLY) &&
119
 
            !LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) {
120
 
                __db_err(dbenv,
121
 
    "files containing multiple databases may only be opened read-only");
122
 
                ret = EINVAL;
123
 
                goto err;
124
 
        }
125
 
 
126
 
err:    /* If we were successful, don't discard the file on close. */
127
 
        if (ret == 0)
128
 
                /* If we were successful, don't discard the file on close. */
129
 
                F_CLR(dbp, DB_AM_DISCARD | DB_AM_CREATED | DB_AM_CREATED_MSTR);
130
 
        else {
131
 
                /*
132
 
                 * If we are not transactional, we need to remove the
133
 
                 * databases/subdatabases.  If we are transactional, then
134
 
                 * the abort of the child transaction should take care of
135
 
                 * cleaning them up.
136
 
                 */
137
 
                remove_me = txn == NULL && F_ISSET(dbp, DB_AM_CREATED);
138
 
                remove_master = txn == NULL && F_ISSET(dbp, DB_AM_CREATED_MSTR);
139
 
 
140
 
                /*
141
 
                 * If we had an error, it may have happened before or after
142
 
                 * we actually logged the open.  If it happened before, then
143
 
                 * abort won't know anything about it and won't close or
144
 
                 * refresh the dbp, so we need to do it explicitly.
145
 
                 */
146
 
                (void)__db_refresh(dbp, txn, DB_NOSYNC);
147
 
        }
148
 
 
149
 
        /* Remove anyone we created. */
150
 
        if (remove_master || (subdb == NULL && remove_me))
151
 
                /* Remove file. */
152
 
                (void)dbenv->dbremove(dbenv, txn, name, NULL, 0);
153
 
        else if (remove_me)
154
 
                /* Remove subdatabase. */
155
 
                (void)dbenv->dbremove(dbenv, txn, name, subdb, 0);
156
 
 
157
 
        /* Commit for DB_AUTO_COMMIT. */
158
 
        if (txn_local) {
159
 
                if (ret == 0)
160
 
                        ret = txn->commit(txn, 0);
161
 
                else
162
 
                        if ((t_ret = txn->abort(txn)) != 0)
163
 
                                ret = __db_panic(dbenv, t_ret);
164
 
        }
165
 
 
166
 
        return (ret);
167
 
}
168
 
 
169
 
/*
170
 
 * __db_dbopen --
171
 
 *      Open a database.  This routine  gets called in three different ways.
172
 
 * 1. It can be called to open a file/database.  In this case, subdb will
173
 
 *    be NULL and meta_pgno will be PGNO_BASE_MD.
174
 
 * 2. It can be called to open a subdatabase during normal operation.  In
175
 
 *    this case, name and subname will both be non-NULL and meta_pgno will
176
 
 *    be PGNO_BAS_MD (also PGNO_INVALID).
177
 
 * 3. It can be called during recovery to open a subdatabase in which case
178
 
 *    name will be non-NULL, subname mqy be NULL and meta-pgno will be
179
 
 *    a valid pgno (i.e., not PGNO_BASE_MD).
180
 
 *
181
 
 * PUBLIC: int __db_dbopen __P((DB *, DB_TXN *,
182
 
 * PUBLIC:     const char *, const char *, u_int32_t, int, db_pgno_t));
183
 
 */
184
 
int
185
 
__db_dbopen(dbp, txn, name, subdb, flags, mode, meta_pgno)
186
 
        DB *dbp;
187
 
        DB_TXN *txn;
188
 
        const char *name, *subdb;
189
 
        u_int32_t flags;
190
 
        int mode;
191
 
        db_pgno_t meta_pgno;
192
 
{
193
 
        DB_ENV *dbenv;
194
 
        int ret;
195
 
        u_int32_t id;
196
 
 
197
 
        dbenv = dbp->dbenv;
198
 
        id = TXN_INVALID;
199
 
        if (txn != NULL)
200
 
                F_SET(dbp, DB_AM_TXN);
201
 
 
202
 
        DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, name);
203
 
        /*
204
 
         * If name is NULL, it's always a create, so make sure that we
205
 
         * have a type specified.  It would be nice if this checking
206
 
         * were done in __db_open where most of the interface checking
207
 
         * is done, but this interface (__db_dbopen) is used by the
208
 
         * recovery and limbo system, so we need to safeguard this
209
 
         * interface as well.
210
 
         */
211
 
        if (name == NULL) {
212
 
                F_SET(dbp, DB_AM_INMEM);
213
 
 
214
 
                if (dbp->type == DB_UNKNOWN) {
215
 
                        __db_err(dbenv,
216
 
                            "DBTYPE of unknown without existing file");
217
 
                        return (EINVAL);
218
 
                }
219
 
 
220
 
                if (dbp->pgsize == 0)
221
 
                        dbp->pgsize = DB_DEF_IOSIZE;
222
 
 
223
 
                /*
224
 
                 * If the file is a temporary file and we're doing locking,
225
 
                 * then we have to create a unique file ID.  We can't use our
226
 
                 * normal dev/inode pair (or whatever this OS uses in place of
227
 
                 * dev/inode pairs) because no backing file will be created
228
 
                 * until the mpool cache is filled forcing the buffers to disk.
229
 
                 * Grab a random locker ID to use as a file ID.  The created
230
 
                 * ID must never match a potential real file ID -- we know it
231
 
                 * won't because real file IDs contain a time stamp after the
232
 
                 * dev/inode pair, and we're simply storing a 4-byte value.
233
 
                 *
234
 
                 * !!!
235
 
                 * Store the locker in the file id structure -- we can get it
236
 
                 * from there as necessary, and it saves having two copies.
237
 
                 */
238
 
                if (LOCKING_ON(dbenv) && (ret = dbenv->lock_id(dbenv,
239
 
                    (u_int32_t *)dbp->fileid)) != 0)
240
 
                        return (ret);
241
 
        } else if (subdb == NULL && meta_pgno == PGNO_BASE_MD) {
242
 
                /* Open/create the underlying file.  Acquire locks. */
243
 
                if ((ret =
244
 
                    __fop_file_setup(dbp, txn, name, mode, flags, &id)) != 0)
245
 
                        return (ret);
246
 
        } else {
247
 
                if ((ret = __fop_subdb_setup(dbp,
248
 
                    txn, name, subdb, mode, flags)) != 0)
249
 
                        return (ret);
250
 
                meta_pgno = dbp->meta_pgno;
251
 
        }
252
 
 
253
 
        /*
254
 
         * If we created the file, set the truncate flag for the mpool.  This
255
 
         * isn't for anything we've done, it's protection against stupid user
256
 
         * tricks: if the user deleted a file behind Berkeley DB's back, we
257
 
         * may still have pages in the mpool that match the file's "unique" ID.
258
 
         *
259
 
         * Note that if we're opening a subdatabase, we don't want to set
260
 
         * the TRUNCATE flag even if we just created the file--we already
261
 
         * opened and updated the master using access method interfaces,
262
 
         * so we don't want to get rid of any pages that are in the mpool.
263
 
         * If we created the file when we opened the master, we already hit
264
 
         * this check in a non-subdb context then.
265
 
         */
266
 
        if (subdb == NULL && F_ISSET(dbp, DB_AM_CREATED))
267
 
                LF_SET(DB_TRUNCATE);
268
 
 
269
 
        /* Set up the underlying environment. */
270
 
        if ((ret = __db_dbenv_setup(dbp, txn, name, id, flags)) != 0)
271
 
                return (ret);
272
 
 
273
 
        /*
274
 
         * Set the open flag.  We use it to mean that the dbp has gone
275
 
         * through mpf setup, including dbreg_register.  Also, below,
276
 
         * the underlying access method open functions may want to do
277
 
         * things like acquire cursors, so the open flag has to be set
278
 
         * before calling them.
279
 
         */
280
 
        F_SET(dbp, DB_AM_OPEN_CALLED);
281
 
 
282
 
        /*
283
 
         * For unnamed files, we need to actually create the file now
284
 
         * that the mpool is open.
285
 
         */
286
 
        if (name == NULL && (ret = __db_new_file(dbp, txn, NULL, NULL)) != 0)
287
 
                return (ret);
288
 
 
289
 
        switch (dbp->type) {
290
 
        case DB_BTREE:
291
 
                ret = __bam_open(dbp, txn, name, meta_pgno, flags);
292
 
                break;
293
 
        case DB_HASH:
294
 
                ret = __ham_open(dbp, txn, name, meta_pgno, flags);
295
 
                break;
296
 
        case DB_RECNO:
297
 
                ret = __ram_open(dbp, txn, name, meta_pgno, flags);
298
 
                break;
299
 
        case DB_QUEUE:
300
 
                ret = __qam_open(dbp, txn, name, meta_pgno, mode, flags);
301
 
                break;
302
 
        case DB_UNKNOWN:
303
 
                return (__db_unknown_type(dbenv, "__db_dbopen", dbp->type));
304
 
        }
305
 
        if (ret != 0)
306
 
                goto err;
307
 
 
308
 
        DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, name);
309
 
 
310
 
        /*
311
 
         * Unnamed files don't need handle locks, so we only have to check
312
 
         * for a handle lock downgrade or lockevent in the case of named
313
 
         * files.
314
 
         */
315
 
        if (!F_ISSET(dbp, DB_AM_RECOVER) &&
316
 
            name != NULL && LOCK_ISSET(dbp->handle_lock)) {
317
 
                if (txn != NULL) {
318
 
                        ret = __txn_lockevent(dbenv,
319
 
                            txn, dbp, &dbp->handle_lock, dbp->lid);
320
 
                } else if (LOCKING_ON(dbenv))
321
 
                        /* Trade write handle lock for read handle lock. */
322
 
                        ret = __lock_downgrade(dbenv,
323
 
                            &dbp->handle_lock, DB_LOCK_READ, 0);
324
 
        }
325
 
DB_TEST_RECOVERY_LABEL
326
 
err:
327
 
        return (ret);
328
 
}
329
 
 
330
 
/*
331
 
 * __db_new_file --
332
 
 *      Create a new database file.
333
 
 *
334
 
 * PUBLIC: int __db_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
335
 
 */
336
 
int
337
 
__db_new_file(dbp, txn, fhp, name)
338
 
        DB *dbp;
339
 
        DB_TXN *txn;
340
 
        DB_FH *fhp;
341
 
        const char *name;
342
 
{
343
 
        int ret;
344
 
 
345
 
        switch (dbp->type) {
346
 
        case DB_BTREE:
347
 
        case DB_RECNO:
348
 
                ret = __bam_new_file(dbp, txn, fhp, name);
349
 
                break;
350
 
        case DB_HASH:
351
 
                ret = __ham_new_file(dbp, txn, fhp, name);
352
 
                break;
353
 
        case DB_QUEUE:
354
 
                ret = __qam_new_file(dbp, txn, fhp, name);
355
 
                break;
356
 
        default:
357
 
                __db_err(dbp->dbenv,
358
 
                    "%s: Invalid type %d specified", name, dbp->type);
359
 
                ret = EINVAL;
360
 
                break;
361
 
        }
362
 
 
363
 
        DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOGMETA, ret, name);
364
 
        /* Sync the file in preparation for moving it into place. */
365
 
        if (ret == 0 && fhp != NULL)
366
 
                ret = __os_fsync(dbp->dbenv, fhp);
367
 
 
368
 
        DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, name);
369
 
 
370
 
DB_TEST_RECOVERY_LABEL
371
 
        return (ret);
372
 
}
373
 
 
374
 
/*
375
 
 * __db_init_subdb --
376
 
 *      Initialize the dbp for a subdb.
377
 
 *
378
 
 * PUBLIC: int __db_init_subdb __P((DB *, DB *, const char *, DB_TXN *));
379
 
 */
380
 
int
381
 
__db_init_subdb(mdbp, dbp, name, txn)
382
 
        DB *mdbp, *dbp;
383
 
        const char *name;
384
 
        DB_TXN *txn;
385
 
{
386
 
        DBMETA *meta;
387
 
        DB_MPOOLFILE *mpf;
388
 
        int ret, t_ret;
389
 
 
390
 
        ret = 0;
391
 
        if (!F_ISSET(dbp, DB_AM_CREATED)) {
392
 
                /* Subdb exists; read meta-data page and initialize. */
393
 
                mpf = mdbp->mpf;
394
 
                if  ((ret = mpf->get(mpf, &dbp->meta_pgno, 0, &meta)) != 0)
395
 
                        goto err;
396
 
                ret = __db_meta_setup(mdbp->dbenv, dbp, name, meta, 0, 0);
397
 
                if ((t_ret = mpf->put(mpf, meta, 0)) != 0 && ret == 0)
398
 
                        ret = t_ret;
399
 
                /*
400
 
                 * If __db_meta_setup found that the meta-page hadn't
401
 
                 * been written out during recovery, we can just return.
402
 
                 */
403
 
                if (ret == ENOENT)
404
 
                        ret = 0;
405
 
                goto err;
406
 
        }
407
 
 
408
 
        /* Handle the create case here. */
409
 
        switch (dbp->type) {
410
 
        case DB_BTREE:
411
 
        case DB_RECNO:
412
 
                ret = __bam_new_subdb(mdbp, dbp, txn);
413
 
                break;
414
 
        case DB_HASH:
415
 
                ret = __ham_new_subdb(mdbp, dbp, txn);
416
 
                break;
417
 
        case DB_QUEUE:
418
 
                ret = EINVAL;
419
 
                break;
420
 
        default:
421
 
                __db_err(dbp->dbenv,
422
 
                    "Invalid subdatabase type %d specified", dbp->type);
423
 
                return (EINVAL);
424
 
        }
425
 
 
426
 
err:    return (ret);
427
 
}
428
 
 
429
 
/*
430
 
 * __db_chk_meta --
431
 
 *      Take a buffer containing a meta-data page and check it for a checksum
432
 
 *      (and verify the checksum if necessary) and possibly decrypt it.
433
 
 *
434
 
 *      Return 0 on success, >0 (errno) on error, -1 on checksum mismatch.
435
 
 *
436
 
 * PUBLIC: int __db_chk_meta __P((DB_ENV *, DB *, DBMETA *, int));
437
 
 */
438
 
int
439
 
__db_chk_meta(dbenv, dbp, meta, do_metachk)
440
 
        DB_ENV *dbenv;
441
 
        DB *dbp;
442
 
        DBMETA *meta;
443
 
        int do_metachk;
444
 
{
445
 
        int is_hmac, ret;
446
 
        u_int8_t *chksum;
447
 
 
448
 
        ret = 0;
449
 
 
450
 
        if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) {
451
 
                if (dbp != NULL)
452
 
                        F_SET(dbp, DB_AM_CHKSUM);
453
 
 
454
 
                is_hmac = meta->encrypt_alg == 0 ? 0 : 1;
455
 
                chksum = ((BTMETA *)meta)->chksum;
456
 
                if (do_metachk && ((ret = __db_check_chksum(dbenv,
457
 
                    (DB_CIPHER *)dbenv->crypto_handle, chksum, meta,
458
 
                    DBMETASIZE, is_hmac)) != 0))
459
 
                        return (ret);
460
 
        }
461
 
 
462
 
#ifdef HAVE_CRYPTO
463
 
        ret = __crypto_decrypt_meta(dbenv, dbp, (u_int8_t *)meta, do_metachk);
464
 
#endif
465
 
        return (ret);
466
 
}
467
 
 
468
 
/*
469
 
 * __db_meta_setup --
470
 
 *
471
 
 * Take a buffer containing a meta-data page and figure out if it's
472
 
 * valid, and if so, initialize the dbp from the meta-data page.
473
 
 *
474
 
 * PUBLIC: int __db_meta_setup __P((DB_ENV *,
475
 
 * PUBLIC:     DB *, const char *, DBMETA *, u_int32_t, int));
476
 
 */
477
 
int
478
 
__db_meta_setup(dbenv, dbp, name, meta, oflags, do_metachk)
479
 
        DB_ENV *dbenv;
480
 
        DB *dbp;
481
 
        const char *name;
482
 
        DBMETA *meta;
483
 
        u_int32_t oflags;
484
 
        int do_metachk;
485
 
{
486
 
        u_int32_t flags, magic;
487
 
        int ret;
488
 
 
489
 
        ret = 0;
490
 
 
491
 
        /*
492
 
         * Figure out what access method we're dealing with, and then
493
 
         * call access method specific code to check error conditions
494
 
         * based on conflicts between the found file and application
495
 
         * arguments.  A found file overrides some user information --
496
 
         * we don't consider it an error, for example, if the user set
497
 
         * an expected byte order and the found file doesn't match it.
498
 
         */
499
 
        F_CLR(dbp, DB_AM_SWAP);
500
 
        magic = meta->magic;
501
 
 
502
 
swap_retry:
503
 
        switch (magic) {
504
 
        case DB_BTREEMAGIC:
505
 
        case DB_HASHMAGIC:
506
 
        case DB_QAMMAGIC:
507
 
        case DB_RENAMEMAGIC:
508
 
                break;
509
 
        case 0:
510
 
                /*
511
 
                 * The only time this should be 0 is if we're in the
512
 
                 * midst of opening a subdb during recovery and that
513
 
                 * subdatabase had its meta-data page allocated, but
514
 
                 * not yet initialized.
515
 
                 */
516
 
                if (F_ISSET(dbp, DB_AM_SUBDB) && ((IS_RECOVERING(dbenv) &&
517
 
                    F_ISSET((DB_LOG *) dbenv->lg_handle, DBLOG_FORCE_OPEN)) ||
518
 
                    meta->pgno != PGNO_INVALID))
519
 
                        return (ENOENT);
520
 
 
521
 
                goto bad_format;
522
 
        default:
523
 
                if (F_ISSET(dbp, DB_AM_SWAP))
524
 
                        goto bad_format;
525
 
 
526
 
                M_32_SWAP(magic);
527
 
                F_SET(dbp, DB_AM_SWAP);
528
 
                goto swap_retry;
529
 
        }
530
 
 
531
 
        /*
532
 
         * We can only check the meta page if we are sure we have a meta page.
533
 
         * If it is random data, then this check can fail.  So only now can we
534
 
         * checksum and decrypt.  Don't distinguish between configuration and
535
 
         * checksum match errors here, because we haven't opened the database
536
 
         * and even a checksum error isn't a reason to panic the environment.
537
 
         */
538
 
        if ((ret = __db_chk_meta(dbenv, dbp, meta, do_metachk)) != 0) {
539
 
                if (ret == -1)
540
 
                        __db_err(dbenv,
541
 
                            "%s: metadata page checksum error", name);
542
 
                goto bad_format;
543
 
        }
544
 
 
545
 
        switch (magic) {
546
 
        case DB_BTREEMAGIC:
547
 
                flags = meta->flags;
548
 
                if (F_ISSET(dbp, DB_AM_SWAP))
549
 
                        M_32_SWAP(flags);
550
 
                if (LF_ISSET(BTM_RECNO))
551
 
                        dbp->type = DB_RECNO;
552
 
                else
553
 
                        dbp->type = DB_BTREE;
554
 
                if ((oflags & DB_TRUNCATE) == 0 && (ret =
555
 
                    __bam_metachk(dbp, name, (BTMETA *)meta)) != 0)
556
 
                        return (ret);
557
 
                break;
558
 
        case DB_HASHMAGIC:
559
 
                dbp->type = DB_HASH;
560
 
                if ((oflags & DB_TRUNCATE) == 0 && (ret =
561
 
                    __ham_metachk(dbp, name, (HMETA *)meta)) != 0)
562
 
                        return (ret);
563
 
                break;
564
 
        case DB_QAMMAGIC:
565
 
                dbp->type = DB_QUEUE;
566
 
                if ((oflags & DB_TRUNCATE) == 0 && (ret =
567
 
                    __qam_metachk(dbp, name, (QMETA *)meta)) != 0)
568
 
                        return (ret);
569
 
                break;
570
 
        case DB_RENAMEMAGIC:
571
 
                F_SET(dbp, DB_AM_IN_RENAME);
572
 
                break;
573
 
        }
574
 
        return (0);
575
 
 
576
 
bad_format:
577
 
        __db_err(dbenv, "%s: unexpected file type or format", name);
578
 
        return (ret == 0 ? EINVAL : ret);
579
 
}
580
 
 
581
 
/*
582
 
 * __db_openchk --
583
 
 *      Interface error checking for open calls.
584
 
 */
585
 
static int
586
 
__db_openchk(dbp, txn, name, subdb, type, flags)
587
 
        DB *dbp;
588
 
        DB_TXN *txn;
589
 
        const char *name, *subdb;
590
 
        DBTYPE type;
591
 
        u_int32_t flags;
592
 
{
593
 
        DB_ENV *dbenv;
594
 
        int ret;
595
 
        u_int32_t ok_flags;
596
 
 
597
 
        dbenv = dbp->dbenv;
598
 
 
599
 
        /* Validate arguments. */
600
 
#define OKFLAGS                                                         \
601
 
    (DB_AUTO_COMMIT | DB_CREATE | DB_DIRTY_READ | DB_EXCL |             \
602
 
     DB_FCNTL_LOCKING | DB_NOMMAP | DB_RDONLY | DB_RDWRMASTER |         \
603
 
     DB_THREAD | DB_TRUNCATE | DB_WRITEOPEN)
604
 
        if ((ret = __db_fchk(dbenv, "DB->open", flags, OKFLAGS)) != 0)
605
 
                return (ret);
606
 
        if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE))
607
 
                return (__db_ferr(dbenv, "DB->open", 1));
608
 
        if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE))
609
 
                return (__db_ferr(dbenv, "DB->open", 1));
610
 
 
611
 
#ifdef  HAVE_VXWORKS
612
 
        if (LF_ISSET(DB_TRUNCATE)) {
613
 
                __db_err(dbenv, "DB_TRUNCATE unsupported in VxWorks");
614
 
                return (__db_eopnotsup(dbenv));
615
 
        }
616
 
#endif
617
 
        switch (type) {
618
 
        case DB_UNKNOWN:
619
 
                if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) {
620
 
                        __db_err(dbenv,
621
 
            "%s: DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE",
622
 
                            name);
623
 
                        return (EINVAL);
624
 
                }
625
 
                ok_flags = 0;
626
 
                break;
627
 
        case DB_BTREE:
628
 
                ok_flags = DB_OK_BTREE;
629
 
                break;
630
 
        case DB_HASH:
631
 
                ok_flags = DB_OK_HASH;
632
 
                break;
633
 
        case DB_QUEUE:
634
 
                ok_flags = DB_OK_QUEUE;
635
 
                break;
636
 
        case DB_RECNO:
637
 
                ok_flags = DB_OK_RECNO;
638
 
                break;
639
 
        default:
640
 
                __db_err(dbenv, "unknown type: %lu", (u_long)type);
641
 
                return (EINVAL);
642
 
        }
643
 
        if (ok_flags)
644
 
                DB_ILLEGAL_METHOD(dbp, ok_flags);
645
 
 
646
 
        /* The environment may have been created, but never opened. */
647
 
        if (!F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_OPEN_CALLED)) {
648
 
                __db_err(dbenv, "environment not yet opened");
649
 
                return (EINVAL);
650
 
        }
651
 
 
652
 
        /*
653
 
         * Historically, you could pass in an environment that didn't have a
654
 
         * mpool, and DB would create a private one behind the scenes.  This
655
 
         * no longer works.
656
 
         */
657
 
        if (!F_ISSET(dbenv, DB_ENV_DBLOCAL) && !MPOOL_ON(dbenv)) {
658
 
                __db_err(dbenv, "environment did not include a memory pool");
659
 
                return (EINVAL);
660
 
        }
661
 
 
662
 
        /*
663
 
         * You can't specify threads during DB->open if subsystems in the
664
 
         * environment weren't configured with them.
665
 
         */
666
 
        if (LF_ISSET(DB_THREAD) &&
667
 
            !F_ISSET(dbenv, DB_ENV_DBLOCAL | DB_ENV_THREAD)) {
668
 
                __db_err(dbenv, "environment not created using DB_THREAD");
669
 
                return (EINVAL);
670
 
        }
671
 
 
672
 
        /* DB_TRUNCATE is not transaction recoverable. */
673
 
        if (LF_ISSET(DB_TRUNCATE) && txn != NULL) {
674
 
                __db_err(dbenv,
675
 
                    "DB_TRUNCATE illegal with transaction specified");
676
 
                return (EINVAL);
677
 
        }
678
 
 
679
 
        /* Subdatabase checks. */
680
 
        if (subdb != NULL) {
681
 
                /* Subdatabases must be created in named files. */
682
 
                if (name == NULL) {
683
 
                        __db_err(dbenv,
684
 
                    "multiple databases cannot be created in temporary files");
685
 
                        return (EINVAL);
686
 
                }
687
 
 
688
 
                /* Truncate is a physical file operation */
689
 
                if (LF_ISSET(DB_TRUNCATE)) {
690
 
                        __db_err(dbenv,
691
 
                            "DB_TRUNCATE illegal with multiple databases");
692
 
                        return (EINVAL);
693
 
                }
694
 
 
695
 
                /* QAM can't be done as a subdatabase. */
696
 
                if (type == DB_QUEUE) {
697
 
                        __db_err(dbenv, "Queue databases must be one-per-file");
698
 
                        return (EINVAL);
699
 
                }
700
 
        }
701
 
 
702
 
        return (0);
703
 
}