LCOV - code coverage report
Current view: top level - lib/tdb/common - tdb_private.h (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 4 4 100.0 %
Date: 2024-04-21 15:09:00 Functions: 1 1 100.0 %

          Line data    Source code
       1             : #ifndef TDB_PRIVATE_H
       2             : #define TDB_PRIVATE_H
       3             :  /*
       4             :    Unix SMB/CIFS implementation.
       5             : 
       6             :    trivial database library - private includes
       7             : 
       8             :    Copyright (C) Andrew Tridgell              2005
       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 "replace.h"
      29             : #include "system/filesys.h"
      30             : #include "system/time.h"
      31             : #include "system/shmem.h"
      32             : #include "system/select.h"
      33             : #include "system/wait.h"
      34             : #include "tdb.h"
      35             : 
      36             : /* #define TDB_TRACE 1 */
      37             : #ifndef HAVE_GETPAGESIZE
      38             : #define getpagesize() 0x2000
      39             : #endif
      40             : 
      41             : typedef uint32_t tdb_len_t;
      42             : typedef uint32_t tdb_off_t;
      43             : 
      44             : #ifndef offsetof
      45             : #define offsetof(t,f) ((unsigned int)&((t *)0)->f)
      46             : #endif
      47             : 
      48             : #define TDB_MAGIC_FOOD "TDB file\n"
      49             : #define TDB_VERSION (0x26011967 + 6)
      50             : #define TDB_MAGIC (0x26011999U)
      51             : #define TDB_FREE_MAGIC (~TDB_MAGIC)
      52             : #define TDB_DEAD_MAGIC (0xFEE1DEAD)
      53             : #define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
      54             : #define TDB_RECOVERY_INVALID_MAGIC (0x0)
      55             : #define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U)
      56             : #define TDB_FEATURE_FLAG_MAGIC (0xbad1a52U)
      57             : #define TDB_ALIGNMENT 4
      58             : #define DEFAULT_HASH_SIZE 131
      59             : #define FREELIST_TOP (sizeof(struct tdb_header))
      60             : #define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
      61             : #define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24))
      62             : #define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
      63             : #define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
      64             : #define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t))
      65             : #define TDB_HASHTABLE_SIZE(tdb) ((tdb->hash_size+1)*sizeof(tdb_off_t))
      66             : #define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + sizeof(tdb_off_t))
      67             : #define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start)
      68             : #define TDB_SEQNUM_OFS    offsetof(struct tdb_header, sequence_number)
      69             : #define TDB_PAD_BYTE 0x42
      70             : #define TDB_PAD_U32  0x42424242
      71             : 
      72             : #define TDB_FEATURE_FLAG_MUTEX 0x00000001
      73             : 
      74             : #define TDB_SUPPORTED_FEATURE_FLAGS ( \
      75             :         TDB_FEATURE_FLAG_MUTEX | \
      76             :         0)
      77             : 
      78             : /* NB assumes there is a local variable called "tdb" that is the
      79             :  * current context, also takes doubly-parenthesized print-style
      80             :  * argument. */
      81             : #define TDB_LOG(x) tdb->log.log_fn x
      82             : 
      83             : #ifdef TDB_TRACE
      84             : void tdb_trace(struct tdb_context *tdb, const char *op);
      85             : void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op);
      86             : void tdb_trace_open(struct tdb_context *tdb, const char *op,
      87             :                     unsigned hash_size, unsigned tdb_flags, unsigned open_flags);
      88             : void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret);
      89             : void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret);
      90             : void tdb_trace_1rec(struct tdb_context *tdb, const char *op,
      91             :                     TDB_DATA rec);
      92             : void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op,
      93             :                         TDB_DATA rec, int ret);
      94             : void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op,
      95             :                            TDB_DATA rec, TDB_DATA ret);
      96             : void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
      97             :                              TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
      98             :                              int ret);
      99             : void tdb_trace_1plusn_rec_flag_ret(struct tdb_context *tdb, const char *op,
     100             :                                    TDB_DATA rec,
     101             :                                    const TDB_DATA *recs, int num_recs,
     102             :                                    unsigned flag, int ret);
     103             : void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
     104             :                            TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret);
     105             : #else
     106             : #define tdb_trace(tdb, op)
     107             : #define tdb_trace_seqnum(tdb, seqnum, op)
     108             : #define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags)
     109             : #define tdb_trace_ret(tdb, op, ret)
     110             : #define tdb_trace_retrec(tdb, op, ret)
     111             : #define tdb_trace_1rec(tdb, op, rec)
     112             : #define tdb_trace_1rec_ret(tdb, op, rec, ret)
     113             : #define tdb_trace_1rec_retrec(tdb, op, rec, ret)
     114             : #define tdb_trace_2rec_flag_ret(tdb, op, rec1, rec2, flag, ret)
     115             : #define tdb_trace_1plusn_rec_flag_ret(tdb, op, rec, recs, num_recs, flag, ret);
     116             : #define tdb_trace_2rec_retrec(tdb, op, rec1, rec2, ret)
     117             : #endif /* !TDB_TRACE */
     118             : 
     119             : /* lock offsets */
     120             : #define OPEN_LOCK        0
     121             : #define ACTIVE_LOCK      4
     122             : #define TRANSACTION_LOCK 8
     123             : 
     124             : /* free memory if the pointer is valid and zero the pointer */
     125             : #ifndef SAFE_FREE
     126             : #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
     127             : #endif
     128             : 
     129             : /*
     130             :  * Note: the BUCKET macro is broken as it returns an unexpected result when
     131             :  * called as BUCKET(-1) for the freelist:
     132             :  *
     133             :  * -1 is sign converted to an unsigned int 4294967295 and then the modulo
     134             :  * tdb->hashtable_size is computed. So with a hashtable_size of 10 the result
     135             :  * is
     136             :  *
     137             :  *   4294967295 % hashtable_size = 5.
     138             :  *
     139             :  * where it should be -1 (C uses symmetric modulo).
     140             :  *
     141             :  * As all callers will lock the same wrong list consistently locking is still
     142             :  * consistent. We can not change this without an incompatible on-disk format
     143             :  * change, otherwise different tdb versions would use incompatible locking.
     144             :  */
     145             : #define BUCKET(hash) ((hash) % tdb->hash_size)
     146             : 
     147             : #define DOCONV() (tdb->flags & TDB_CONVERT)
     148             : #define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x)
     149             : 
     150             : 
     151             : /* the body of the database is made of one tdb_record for the free space
     152             :    plus a separate data list for each hash value */
     153             : struct tdb_record {
     154             :         tdb_off_t next; /* offset of the next record in the list */
     155             :         tdb_len_t rec_len; /* total byte length of record */
     156             :         tdb_len_t key_len; /* byte length of key */
     157             :         tdb_len_t data_len; /* byte length of data */
     158             :         uint32_t full_hash; /* the full 32 bit hash of the key */
     159             :         uint32_t magic;   /* try to catch errors */
     160             :         /* the following union is implied:
     161             :                 union {
     162             :                         char record[rec_len];
     163             :                         struct {
     164             :                                 char key[key_len];
     165             :                                 char data[data_len];
     166             :                         }
     167             :                         uint32_t totalsize; (tailer)
     168             :                 }
     169             :         */
     170             : };
     171             : 
     172             : 
     173             : /* this is stored at the front of every database */
     174             : struct tdb_header {
     175             :         char magic_food[32]; /* for /etc/magic */
     176             :         uint32_t version; /* version of the code */
     177             :         uint32_t hash_size; /* number of hash entries */
     178             :         tdb_off_t rwlocks; /* obsolete - kept to detect old formats */
     179             :         tdb_off_t recovery_start; /* offset of transaction recovery region */
     180             :         tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */
     181             :         uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */
     182             :         uint32_t magic2_hash; /* hash of TDB_MAGIC. */
     183             :         uint32_t feature_flags;
     184             :         tdb_len_t mutex_size; /* set if TDB_FEATURE_FLAG_MUTEX is set */
     185             :         tdb_off_t reserved[25];
     186             : };
     187             : 
     188             : struct tdb_lock_type {
     189             :         uint32_t off;
     190             :         uint32_t count;
     191             :         uint32_t ltype;
     192             : };
     193             : 
     194             : struct tdb_chainwalk_ctx {
     195             :         tdb_off_t slow_ptr;
     196             :         bool slow_chase;
     197             : };
     198             : 
     199             : struct tdb_traverse_lock {
     200             :         struct tdb_traverse_lock *next;
     201             :         uint32_t off;
     202             :         uint32_t list;
     203             :         int lock_rw;
     204             : };
     205             : 
     206             : void tdb_chainwalk_init(struct tdb_chainwalk_ctx *ctx, tdb_off_t ptr);
     207             : bool tdb_chainwalk_check(struct tdb_context *tdb,
     208             :                          struct tdb_chainwalk_ctx *ctx,
     209             :                          tdb_off_t next_ptr);
     210             : 
     211             : enum tdb_lock_flags {
     212             :         /* WAIT == F_SETLKW, NOWAIT == F_SETLK */
     213             :         TDB_LOCK_NOWAIT = 0,
     214             :         TDB_LOCK_WAIT = 1,
     215             :         /* If set, don't log an error on failure. */
     216             :         TDB_LOCK_PROBE = 2,
     217             :         /* If set, don't actually lock at all. */
     218             :         TDB_LOCK_MARK_ONLY = 4,
     219             : };
     220             : 
     221             : struct tdb_methods {
     222             :         int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int );
     223             :         int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t);
     224             :         void (*next_hash_chain)(struct tdb_context *, uint32_t *);
     225             :         int (*tdb_oob)(struct tdb_context *, tdb_off_t , tdb_len_t, int );
     226             :         int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t );
     227             : };
     228             : 
     229             : struct tdb_mutexes;
     230             : 
     231             : struct tdb_context {
     232             :         char *name; /* the name of the database */
     233             :         void *map_ptr; /* where it is currently mapped */
     234             :         int fd; /* open file descriptor for the database */
     235             :         tdb_len_t map_size; /* how much space has been mapped */
     236             :         int read_only; /* opened read-only */
     237             :         int traverse_read; /* read-only traversal */
     238             :         int traverse_write; /* read-write traversal */
     239             :         struct tdb_lock_type allrecord_lock; /* .offset == upgradable */
     240             :         int num_lockrecs;
     241             :         struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */
     242             :         int lockrecs_array_length;
     243             : 
     244             :         tdb_off_t hdr_ofs; /* this is 0 or header.mutex_size */
     245             :         struct tdb_mutexes *mutexes; /* mmap of the mutex area */
     246             : 
     247             :         enum TDB_ERROR ecode; /* error code for last tdb error */
     248             :         uint32_t hash_size;
     249             :         uint32_t feature_flags;
     250             :         uint32_t flags; /* the flags passed to tdb_open */
     251             :         struct tdb_traverse_lock travlocks; /* current traversal locks */
     252             :         struct tdb_context *next; /* all tdbs to avoid multiple opens */
     253             :         dev_t device;   /* uniquely identifies this tdb */
     254             :         ino_t inode;    /* uniquely identifies this tdb */
     255             :         struct tdb_logging_context log;
     256             :         unsigned int (*hash_fn)(TDB_DATA *key);
     257             :         int open_flags; /* flags used in the open - needed by reopen */
     258             :         const struct tdb_methods *methods;
     259             :         struct tdb_transaction *transaction;
     260             :         int page_size;
     261             :         int max_dead_records;
     262             : #ifdef TDB_TRACE
     263             :         int tracefd;
     264             : #endif
     265             :         volatile sig_atomic_t *interrupt_sig_ptr;
     266             : };
     267             : 
     268             : 
     269             : /*
     270             :   internal prototypes
     271             : */
     272             : int tdb_munmap(struct tdb_context *tdb);
     273             : int tdb_mmap(struct tdb_context *tdb);
     274             : int tdb_lock(struct tdb_context *tdb, int list, int ltype);
     275             : int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype);
     276             : int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
     277             :                   enum tdb_lock_flags flags);
     278             : int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
     279             :                     bool mark_lock);
     280             : int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
     281             : int tdb_brlock(struct tdb_context *tdb,
     282             :                int rw_type, tdb_off_t offset, size_t len,
     283             :                enum tdb_lock_flags flags);
     284             : int tdb_brunlock(struct tdb_context *tdb,
     285             :                  int rw_type, tdb_off_t offset, size_t len);
     286             : bool tdb_have_extra_locks(struct tdb_context *tdb);
     287             : void tdb_release_transaction_locks(struct tdb_context *tdb);
     288             : int tdb_transaction_lock(struct tdb_context *tdb, int ltype,
     289             :                          enum tdb_lock_flags lockflags);
     290             : int tdb_transaction_unlock(struct tdb_context *tdb, int ltype);
     291             : int tdb_recovery_area(struct tdb_context *tdb,
     292             :                       const struct tdb_methods *methods,
     293             :                       tdb_off_t *recovery_offset,
     294             :                       struct tdb_record *rec);
     295             : int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
     296             :                        enum tdb_lock_flags flags, bool upgradable);
     297             : int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock);
     298             : int tdb_allrecord_upgrade(struct tdb_context *tdb);
     299             : int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
     300             : int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
     301             : int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
     302             : int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
     303             : void *tdb_convert(void *buf, uint32_t size);
     304             : int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
     305             : tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length,
     306             :                        struct tdb_record *rec);
     307             : 
     308             : int _tdb_oob(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe);
     309             : 
     310 26041384063 : static inline int tdb_oob(
     311             :         struct tdb_context *tdb, tdb_off_t off, tdb_len_t len, int probe)
     312             : {
     313 25238730198 :         if (likely((off + len >= off) && (off + len <= tdb->map_size))) {
     314 24504300453 :                 return 0;
     315             :         }
     316     7067594 :         return _tdb_oob(tdb, off, len, probe);
     317             : }
     318             : 
     319             : 
     320             : int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
     321             : int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
     322             : int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
     323             : int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
     324             : bool tdb_needs_recovery(struct tdb_context *tdb);
     325             : int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
     326             : int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
     327             : unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
     328             : int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
     329             :                    tdb_off_t offset, tdb_len_t len,
     330             :                    int (*parser)(TDB_DATA key, TDB_DATA data,
     331             :                                  void *private_data),
     332             :                    void *private_data);
     333             : tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
     334             :                            struct tdb_record *rec);
     335             : tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
     336             :                         struct tdb_record *r, tdb_len_t length,
     337             :                         tdb_off_t *p_last_ptr);
     338             : int tdb_trim_dead(struct tdb_context *tdb, uint32_t hash);
     339             : void tdb_io_init(struct tdb_context *tdb);
     340             : int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
     341             : tdb_off_t tdb_expand_adjust(tdb_off_t map_size, tdb_off_t size, int page_size);
     342             : int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
     343             :                       struct tdb_record *rec);
     344             : bool tdb_write_all(int fd, const void *buf, size_t count);
     345             : int tdb_transaction_recover(struct tdb_context *tdb);
     346             : void tdb_header_hash(struct tdb_context *tdb,
     347             :                      uint32_t *magic1_hash, uint32_t *magic2_hash);
     348             : unsigned int tdb_old_hash(TDB_DATA *key);
     349             : size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off);
     350             : bool tdb_add_off_t(tdb_off_t a, tdb_off_t b, tdb_off_t *pret);
     351             : 
     352             : /* tdb_off_t and tdb_len_t right now are both uint32_t */
     353             : #define tdb_add_len_t tdb_add_off_t
     354             : 
     355             : size_t tdb_mutex_size(struct tdb_context *tdb);
     356             : bool tdb_have_mutexes(struct tdb_context *tdb);
     357             : int tdb_mutex_init(struct tdb_context *tdb);
     358             : int tdb_mutex_mmap(struct tdb_context *tdb);
     359             : int tdb_mutex_munmap(struct tdb_context *tdb);
     360             : bool tdb_mutex_lock(struct tdb_context *tdb, int rw, off_t off, off_t len,
     361             :                     bool waitflag, int *pret);
     362             : bool tdb_mutex_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len,
     363             :                       int *pret);
     364             : int tdb_mutex_allrecord_lock(struct tdb_context *tdb, int ltype,
     365             :                              enum tdb_lock_flags flags);
     366             : int tdb_mutex_allrecord_unlock(struct tdb_context *tdb);
     367             : int tdb_mutex_allrecord_upgrade(struct tdb_context *tdb);
     368             : void tdb_mutex_allrecord_downgrade(struct tdb_context *tdb);
     369             : 
     370             : #endif /* TDB_PRIVATE_H */

Generated by: LCOV version 1.14