1 /* 2 Unix SMB/CIFS implementation. 3 4 trivial database library - private includes 5 6 Copyright (C) Andrew Tridgell 2005 7 8 ** NOTE! The following LGPL license applies to the tdb 9 ** library. This does NOT imply that all of Samba is released 10 ** under the LGPL 11 12 This library is free software; you can redistribute it and/or 13 modify it under the terms of the GNU Lesser General Public 14 License as published by the Free Software Foundation; either 15 version 3 of the License, or (at your option) any later version. 16 17 This library is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Lesser General Public License for more details. 21 22 You should have received a copy of the GNU Lesser General Public 23 License along with this library; if not, see <http://www.gnu.org/licenses/>. 24*/ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif /* HAVE_CONFIG_H */ 29 30#include <unistd.h> 31#include <stdint.h> 32#include <stdbool.h> 33#include <sys/stat.h> 34#include <fcntl.h> 35#include <sys/select.h> 36#include <sys/mman.h> 37#include <sys/time.h> 38#include <time.h> 39#include <utime.h> 40#include <sys/wait.h> 41#include <string.h> 42#include <stdlib.h> 43#include <limits.h> 44#include <stdio.h> 45#include <errno.h> 46#include <sys/param.h> 47#include <stddef.h> 48 49#ifndef __STRING 50#define __STRING(x) #x 51#endif 52 53#ifndef __STRINGSTRING 54#define __STRINGSTRING(x) __STRING(x) 55#endif 56 57#ifndef __LINESTR__ 58#define __LINESTR__ __STRINGSTRING(__LINE__) 59#endif 60 61#ifndef __location__ 62#define __location__ __FILE__ ":" __LINESTR__ 63#endif 64 65#include <atalk/util.h> 66#include "atalk/tdb.h" 67 68/* #define TDB_TRACE 1 */ 69#ifndef HAVE_GETPAGESIZE 70#define getpagesize() 0x2000 71#endif 72 73typedef uint32_t tdb_len_t; 74typedef uint32_t tdb_off_t; 75 76#define TDB_MAGIC_FOOD "TDB file\n" 77#define TDB_VERSION (0x26011967 + 6) 78#define TDB_MAGIC (0x26011999U) 79#define TDB_FREE_MAGIC (~TDB_MAGIC) 80#define TDB_DEAD_MAGIC (0xFEE1DEAD) 81#define TDB_RECOVERY_MAGIC (0xf53bc0e7U) 82#define TDB_ALIGNMENT 4 83#define DEFAULT_HASH_SIZE 131 84#define FREELIST_TOP (sizeof(struct tdb_header)) 85#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) 86#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) 87#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) 88#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) 89#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) 90#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t)) 91#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + sizeof(tdb_off_t)) 92#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start) 93#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number) 94#define TDB_PAD_BYTE 0x42 95#define TDB_PAD_U32 0x42424242 96 97/* NB assumes there is a local variable called "tdb" that is the 98 * current context, also takes doubly-parenthesized print-style 99 * argument. */ 100#define TDB_LOG(x) tdb->log.log_fn x 101 102#ifdef TDB_TRACE 103void tdb_trace(struct tdb_context *tdb, const char *op); 104void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op); 105void tdb_trace_open(struct tdb_context *tdb, const char *op, 106 unsigned hash_size, unsigned tdb_flags, unsigned open_flags); 107void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret); 108void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret); 109void tdb_trace_1rec(struct tdb_context *tdb, const char *op, 110 TDB_DATA rec); 111void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op, 112 TDB_DATA rec, int ret); 113void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op, 114 TDB_DATA rec, TDB_DATA ret); 115void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op, 116 TDB_DATA rec1, TDB_DATA rec2, unsigned flag, 117 int ret); 118void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op, 119 TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret); 120#else 121#define tdb_trace(tdb, op) 122#define tdb_trace_seqnum(tdb, seqnum, op) 123#define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags) 124#define tdb_trace_ret(tdb, op, ret) 125#define tdb_trace_retrec(tdb, op, ret) 126#define tdb_trace_1rec(tdb, op, rec) 127#define tdb_trace_1rec_ret(tdb, op, rec, ret) 128#define tdb_trace_1rec_retrec(tdb, op, rec, ret) 129#define tdb_trace_2rec_flag_ret(tdb, op, rec1, rec2, flag, ret) 130#define tdb_trace_2rec_retrec(tdb, op, rec1, rec2, ret) 131#endif /* !TDB_TRACE */ 132 133/* lock offsets */ 134#define GLOBAL_LOCK 0 135#define ACTIVE_LOCK 4 136#define TRANSACTION_LOCK 8 137 138/* free memory if the pointer is valid and zero the pointer */ 139#ifndef SAFE_FREE 140#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) 141#endif 142 143#define BUCKET(hash) ((hash) % tdb->header.hash_size) 144 145#define DOCONV() (tdb->flags & TDB_CONVERT) 146#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x) 147 148 149/* the body of the database is made of one tdb_record for the free space 150 plus a separate data list for each hash value */ 151struct tdb_record { 152 tdb_off_t next; /* offset of the next record in the list */ 153 tdb_len_t rec_len; /* total byte length of record */ 154 tdb_len_t key_len; /* byte length of key */ 155 tdb_len_t data_len; /* byte length of data */ 156 uint32_t full_hash; /* the full 32 bit hash of the key */ 157 uint32_t magic; /* try to catch errors */ 158 /* the following union is implied: 159 union { 160 char record[rec_len]; 161 struct { 162 char key[key_len]; 163 char data[data_len]; 164 } 165 uint32_t totalsize; (tailer) 166 } 167 */ 168}; 169 170 171/* this is stored at the front of every database */ 172struct tdb_header { 173 char magic_food[32]; /* for /etc/magic */ 174 uint32_t version; /* version of the code */ 175 uint32_t hash_size; /* number of hash entries */ 176 tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ 177 tdb_off_t recovery_start; /* offset of transaction recovery region */ 178 tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ 179 tdb_off_t reserved[29]; 180}; 181 182struct tdb_lock_type { 183 int list; 184 uint32_t count; 185 uint32_t ltype; 186}; 187 188struct tdb_traverse_lock { 189 struct tdb_traverse_lock *next; 190 uint32_t off; 191 uint32_t hash; 192 int lock_rw; 193}; 194 195 196struct tdb_methods { 197 int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int ); 198 int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t); 199 void (*next_hash_chain)(struct tdb_context *, uint32_t *); 200 int (*tdb_oob)(struct tdb_context *, tdb_off_t , int ); 201 int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); 202 int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t); 203}; 204 205struct tdb_context { 206 char *name; /* the name of the database */ 207 void *map_ptr; /* where it is currently mapped */ 208 int fd; /* open file descriptor for the database */ 209 tdb_len_t map_size; /* how much space has been mapped */ 210 int read_only; /* opened read-only */ 211 int traverse_read; /* read-only traversal */ 212 int traverse_write; /* read-write traversal */ 213 struct tdb_lock_type global_lock; 214 int num_lockrecs; 215 struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */ 216 enum TDB_ERROR ecode; /* error code for last tdb error */ 217 struct tdb_header header; /* a cached copy of the header */ 218 uint32_t flags; /* the flags passed to tdb_open */ 219 struct tdb_traverse_lock travlocks; /* current traversal locks */ 220 struct tdb_context *next; /* all tdbs to avoid multiple opens */ 221 dev_t device; /* uniquely identifies this tdb */ 222 ino_t inode; /* uniquely identifies this tdb */ 223 struct tdb_logging_context log; 224 unsigned int (*hash_fn)(TDB_DATA *key); 225 int open_flags; /* flags used in the open - needed by reopen */ 226 unsigned int num_locks; /* number of chain locks held */ 227 const struct tdb_methods *methods; 228 struct tdb_transaction *transaction; 229 int page_size; 230 int max_dead_records; 231 int transaction_lock_count; 232#ifdef TDB_TRACE 233 int tracefd; 234#endif 235 volatile sig_atomic_t *interrupt_sig_ptr; 236}; 237 238 239/* 240 internal prototypes 241*/ 242int tdb_munmap(struct tdb_context *tdb); 243void tdb_mmap(struct tdb_context *tdb); 244int tdb_lock(struct tdb_context *tdb, int list, int ltype); 245int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); 246int tdb_unlock(struct tdb_context *tdb, int list, int ltype); 247int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); 248int tdb_transaction_lock(struct tdb_context *tdb, int ltype); 249int tdb_transaction_unlock(struct tdb_context *tdb); 250int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len); 251int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); 252int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); 253int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); 254int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); 255void *tdb_convert(void *buf, uint32_t size); 256int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); 257tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec); 258int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); 259int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); 260int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); 261int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); 262int _tdb_transaction_cancel(struct tdb_context *tdb); 263int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); 264int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec); 265int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct tdb_record *rec); 266unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); 267int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, 268 tdb_off_t offset, tdb_len_t len, 269 int (*parser)(TDB_DATA key, TDB_DATA data, 270 void *private_data), 271 void *private_data); 272tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype, 273 struct tdb_record *rec); 274void tdb_io_init(struct tdb_context *tdb); 275int tdb_expand(struct tdb_context *tdb, tdb_off_t size); 276int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, 277 struct tdb_record *rec); 278 279 280