1 /* 2 ** Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. 3 ** All rights reserved. 4 ** 5 ** By using this file, you agree to the terms and conditions set 6 ** forth in the LICENSE file which can be found at the top level of 7 ** the sendmail distribution. 8 */ 9 10 #ifndef lint 11 static char id[] = "@(#)$Id: smdb1.c,v 8.43.4.1 2000/08/24 17:08:00 gshapiro Exp $"; 12 #endif /* ! lint */ 13 14 #include <unistd.h> 15 #include <stdlib.h> 16 #include <fcntl.h> 17 18 #include <sendmail/sendmail.h> 19 #include <libsmdb/smdb.h> 20 21 #if (DB_VERSION_MAJOR == 1) 22 23 # define SMDB1_FILE_EXTENSION "db" 24 25 struct smdb_db1_struct 26 { 27 DB *smdb1_db; 28 int smdb1_lock_fd; 29 bool smdb1_cursor_in_use; 30 }; 31 typedef struct smdb_db1_struct SMDB_DB1_DATABASE; 32 33 struct smdb_db1_cursor 34 { 35 SMDB_DB1_DATABASE *db; 36 }; 37 typedef struct smdb_db1_cursor SMDB_DB1_CURSOR; 38 39 /* 40 ** SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type. 41 ** 42 ** Parameters: 43 ** type -- The type to translate. 44 ** 45 ** Returns: 46 ** The DB1 type that corresponsds to the passed in SMDB type. 47 ** Returns -1 if there is no equivalent type. 48 ** 49 */ 50 51 DBTYPE 52 smdb_type_to_db1_type(type) 53 SMDB_DBTYPE type; 54 { 55 if (type == SMDB_TYPE_DEFAULT) 56 return DB_HASH; 57 58 if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) 59 return DB_HASH; 60 61 if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0) 62 return DB_BTREE; 63 64 /* Should never get here thanks to test in smdb_db_open() */ 65 return DB_HASH; 66 } 67 68 69 /* 70 ** SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags. 71 ** 72 ** Parameters: 73 ** flags -- The flags to translate. 74 ** 75 ** Returns: 76 ** The db1 flags that are equivalent to the smdb flags. 77 ** 78 ** Notes: 79 ** Any invalid flags are ignored. 80 ** 81 */ 82 83 u_int 84 smdb_put_flags_to_db1_flags(flags) 85 SMDB_FLAG flags; 86 { 87 int return_flags; 88 89 return_flags = 0; 90 91 if (bitset(SMDBF_NO_OVERWRITE, flags)) 92 return_flags |= R_NOOVERWRITE; 93 94 return return_flags; 95 } 96 97 /* 98 ** SMDB_CURSOR_GET_FLAGS_TO_SMDB1 99 ** 100 ** Parameters: 101 ** flags -- The flags to translate. 102 ** 103 ** Returns: 104 ** The db1 flags that are equivalent to the smdb flags. 105 ** 106 ** Notes: 107 ** Returns -1 if we don't support the flag. 108 ** 109 */ 110 111 int 112 smdb_cursor_get_flags_to_smdb1(flags) 113 SMDB_FLAG flags; 114 { 115 switch(flags) 116 { 117 case SMDB_CURSOR_GET_FIRST: 118 return R_FIRST; 119 120 case SMDB_CURSOR_GET_LAST: 121 return R_LAST; 122 123 case SMDB_CURSOR_GET_NEXT: 124 return R_NEXT; 125 126 case SMDB_CURSOR_GET_RANGE: 127 return R_CURSOR; 128 129 default: 130 return -1; 131 } 132 } 133 134 SMDB_DB1_DATABASE * 135 smdb1_malloc_database() 136 { 137 SMDB_DB1_DATABASE *db1; 138 139 db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE)); 140 141 if (db1 != NULL) 142 { 143 db1->smdb1_lock_fd = -1; 144 db1->smdb1_cursor_in_use = FALSE; 145 } 146 147 return db1; 148 } 149 150 /* 151 ** The rest of these function correspond to the interface laid out 152 ** in smdb.h. 153 */ 154 155 int 156 smdb1_close(database) 157 SMDB_DATABASE *database; 158 { 159 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; 160 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 161 162 if (db1->smdb1_lock_fd != -1) 163 (void) close(db1->smdb1_lock_fd); 164 165 free(db1); 166 database->smdb_impl = NULL; 167 168 return db->close(db); 169 } 170 171 int 172 smdb1_del(database, key, flags) 173 SMDB_DATABASE *database; 174 SMDB_DBENT *key; 175 u_int flags; 176 { 177 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 178 179 return db->del(db, &key->db, flags); 180 } 181 182 int 183 smdb1_fd(database, fd) 184 SMDB_DATABASE *database; 185 int *fd; 186 { 187 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 188 189 *fd = db->fd(db); 190 if (*fd == -1) 191 return errno; 192 193 return SMDBE_OK; 194 } 195 196 int 197 smdb1_lockfd(database) 198 SMDB_DATABASE *database; 199 { 200 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; 201 202 return db1->smdb1_lock_fd; 203 } 204 205 206 int 207 smdb1_get(database, key, data, flags) 208 SMDB_DATABASE *database; 209 SMDB_DBENT *key; 210 SMDB_DBENT *data; 211 u_int flags; 212 { 213 int result; 214 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 215 216 result = db->get(db, &key->db, &data->db, flags); 217 if (result != 0) 218 { 219 if (result == 1) 220 return SMDBE_NOT_FOUND; 221 return errno; 222 } 223 return SMDBE_OK; 224 } 225 226 int 227 smdb1_put(database, key, data, flags) 228 SMDB_DATABASE *database; 229 SMDB_DBENT *key; 230 SMDB_DBENT *data; 231 u_int flags; 232 { 233 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 234 235 return db->put(db, &key->db, &data->db, 236 smdb_put_flags_to_db1_flags(flags)); 237 } 238 239 int 240 smdb1_set_owner(database, uid, gid) 241 SMDB_DATABASE *database; 242 uid_t uid; 243 gid_t gid; 244 { 245 # if HASFCHOWN 246 int fd; 247 int result; 248 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 249 250 fd = db->fd(db); 251 if (fd == -1) 252 return errno; 253 254 result = fchown(fd, uid, gid); 255 if (result < 0) 256 return errno; 257 # endif /* HASFCHOWN */ 258 259 return SMDBE_OK; 260 } 261 262 int 263 smdb1_sync(database, flags) 264 SMDB_DATABASE *database; 265 u_int flags; 266 { 267 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 268 269 return db->sync(db, flags); 270 } 271 272 int 273 smdb1_cursor_close(cursor) 274 SMDB_CURSOR *cursor; 275 { 276 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; 277 SMDB_DB1_DATABASE *db1 = db1_cursor->db; 278 279 if (!db1->smdb1_cursor_in_use) 280 return SMDBE_NOT_A_VALID_CURSOR; 281 282 db1->smdb1_cursor_in_use = FALSE; 283 free(cursor); 284 285 return SMDBE_OK; 286 } 287 288 int 289 smdb1_cursor_del(cursor, flags) 290 SMDB_CURSOR *cursor; 291 u_int flags; 292 { 293 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; 294 SMDB_DB1_DATABASE *db1 = db1_cursor->db; 295 DB *db = db1->smdb1_db; 296 297 return db->del(db, NULL, R_CURSOR); 298 } 299 300 int 301 smdb1_cursor_get(cursor, key, value, flags) 302 SMDB_CURSOR *cursor; 303 SMDB_DBENT *key; 304 SMDB_DBENT *value; 305 SMDB_FLAG flags; 306 { 307 int db1_flags; 308 int result; 309 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; 310 SMDB_DB1_DATABASE *db1 = db1_cursor->db; 311 DB *db = db1->smdb1_db; 312 313 db1_flags = smdb_cursor_get_flags_to_smdb1(flags); 314 result = db->seq(db, &key->db, &value->db, db1_flags); 315 if (result == -1) 316 return errno; 317 if (result == 1) 318 return SMDBE_LAST_ENTRY; 319 return SMDBE_OK; 320 } 321 322 int 323 smdb1_cursor_put(cursor, key, value, flags) 324 SMDB_CURSOR *cursor; 325 SMDB_DBENT *key; 326 SMDB_DBENT *value; 327 SMDB_FLAG flags; 328 { 329 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; 330 SMDB_DB1_DATABASE *db1 = db1_cursor->db; 331 DB *db = db1->smdb1_db; 332 333 return db->put(db, &key->db, &value->db, R_CURSOR); 334 } 335 336 int 337 smdb1_cursor(database, cursor, flags) 338 SMDB_DATABASE *database; 339 SMDB_CURSOR **cursor; 340 u_int flags; 341 { 342 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; 343 SMDB_CURSOR *cur; 344 SMDB_DB1_CURSOR *db1_cursor; 345 346 if (db1->smdb1_cursor_in_use) 347 return SMDBE_ONLY_SUPPORTS_ONE_CURSOR; 348 349 db1->smdb1_cursor_in_use = TRUE; 350 db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR)); 351 db1_cursor->db = db1; 352 353 cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR)); 354 355 if (cur == NULL) 356 return SMDBE_MALLOC; 357 358 cur->smdbc_impl = db1_cursor; 359 cur->smdbc_close = smdb1_cursor_close; 360 cur->smdbc_del = smdb1_cursor_del; 361 cur->smdbc_get = smdb1_cursor_get; 362 cur->smdbc_put = smdb1_cursor_put; 363 *cursor = cur; 364 365 return SMDBE_OK; 366 } 367 368 /* 369 ** SMDB_DB_OPEN -- Opens a db1 database. 370 ** 371 ** Parameters: 372 ** database -- An unallocated database pointer to a pointer. 373 ** db_name -- The name of the database without extension. 374 ** mode -- File permisions on the database if created. 375 ** mode_mask -- Mode bits that must match on an existing database. 376 ** sff -- Flags for safefile. 377 ** type -- The type of database to open 378 ** See smdb_type_to_db1_type for valid types. 379 ** user_info -- Information on the user to use for file 380 ** permissions. 381 ** db_params -- 382 ** An SMDB_DBPARAMS struct including params. These 383 ** are processed according to the type of the 384 ** database. Currently supported params (only for 385 ** HASH type) are: 386 ** num_elements 387 ** cache_size 388 ** 389 ** Returns: 390 ** SMDBE_OK -- Success, otherwise errno. 391 */ 392 393 int 394 smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, 395 db_params) 396 SMDB_DATABASE **database; 397 char *db_name; 398 int mode; 399 int mode_mask; 400 long sff; 401 SMDB_DBTYPE type; 402 SMDB_USER_INFO *user_info; 403 SMDB_DBPARAMS *db_params; 404 { 405 int db_fd; 406 int lock_fd; 407 int result; 408 void *params; 409 SMDB_DATABASE *smdb_db; 410 SMDB_DB1_DATABASE *db1; 411 DB *db; 412 HASHINFO hash_info; 413 BTREEINFO btree_info; 414 DBTYPE db_type; 415 struct stat stat_info; 416 char db_file_name[SMDB_MAX_NAME_LEN]; 417 418 if (type == NULL || 419 (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 && 420 strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0)) 421 return SMDBE_UNKNOWN_DB_TYPE; 422 423 result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, 424 db_name, SMDB1_FILE_EXTENSION); 425 if (result != SMDBE_OK) 426 return result; 427 428 result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask, 429 sff, user_info, &stat_info); 430 if (result != SMDBE_OK) 431 return result; 432 433 lock_fd = -1; 434 # if O_EXLOCK 435 mode |= O_EXLOCK; 436 # else /* O_EXLOCK */ 437 result = smdb_lock_file(&lock_fd, db_name, mode, sff, 438 SMDB1_FILE_EXTENSION); 439 if (result != SMDBE_OK) 440 return result; 441 # endif /* O_EXLOCK */ 442 443 *database = NULL; 444 445 smdb_db = smdb_malloc_database(); 446 db1 = smdb1_malloc_database(); 447 if (smdb_db == NULL || db1 == NULL) 448 return SMDBE_MALLOC; 449 db1->smdb1_lock_fd = lock_fd; 450 451 params = NULL; 452 if (db_params != NULL && 453 (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0)) 454 { 455 memset(&hash_info, '\0', sizeof hash_info); 456 hash_info.nelem = db_params->smdbp_num_elements; 457 hash_info.cachesize = db_params->smdbp_cache_size; 458 params = &hash_info; 459 } 460 461 if (db_params != NULL && 462 (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0)) 463 { 464 memset(&btree_info, '\0', sizeof btree_info); 465 btree_info.cachesize = db_params->smdbp_cache_size; 466 if (db_params->smdbp_allow_dup) 467 btree_info.flags |= R_DUP; 468 params = &btree_info; 469 } 470 471 db_type = smdb_type_to_db1_type(type); 472 db = dbopen(db_file_name, mode, 0644, db_type, params); 473 if (db != NULL) 474 { 475 db_fd = db->fd(db); 476 result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd, 477 &stat_info); 478 } 479 else 480 { 481 if (errno == 0) 482 result = SMDBE_BAD_OPEN; 483 else 484 result = errno; 485 } 486 487 if (result == SMDBE_OK) 488 { 489 /* Everything is ok. Setup driver */ 490 db1->smdb1_db = db; 491 492 smdb_db->smdb_close = smdb1_close; 493 smdb_db->smdb_del = smdb1_del; 494 smdb_db->smdb_fd = smdb1_fd; 495 smdb_db->smdb_lockfd = smdb1_lockfd; 496 smdb_db->smdb_get = smdb1_get; 497 smdb_db->smdb_put = smdb1_put; 498 smdb_db->smdb_set_owner = smdb1_set_owner; 499 smdb_db->smdb_sync = smdb1_sync; 500 smdb_db->smdb_cursor = smdb1_cursor; 501 smdb_db->smdb_impl = db1; 502 503 *database = smdb_db; 504 return SMDBE_OK; 505 } 506 507 if (db != NULL) 508 (void) db->close(db); 509 510 /* Error opening database */ 511 (void) smdb_unlock_file(db1->smdb1_lock_fd); 512 free(db1); 513 smdb_free_database(smdb_db); 514 515 return result; 516 } 517 518 #endif /* (DB_VERSION_MAJOR == 1) */ 519