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.3 2000/10/05 23:06:30 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 DBT dbkey; 179 180 memset(&dbkey, '\0', sizeof dbkey); 181 dbkey.data = key->data; 182 dbkey.size = key->size; 183 return db->del(db, &dbkey, flags); 184 } 185 186 int 187 smdb1_fd(database, fd) 188 SMDB_DATABASE *database; 189 int *fd; 190 { 191 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 192 193 *fd = db->fd(db); 194 if (*fd == -1) 195 return errno; 196 197 return SMDBE_OK; 198 } 199 200 int 201 smdb1_lockfd(database) 202 SMDB_DATABASE *database; 203 { 204 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; 205 206 return db1->smdb1_lock_fd; 207 } 208 209 210 int 211 smdb1_get(database, key, data, flags) 212 SMDB_DATABASE *database; 213 SMDB_DBENT *key; 214 SMDB_DBENT *data; 215 u_int flags; 216 { 217 int result; 218 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 219 DBT dbkey, dbdata; 220 221 memset(&dbdata, '\0', sizeof dbdata); 222 memset(&dbkey, '\0', sizeof dbkey); 223 dbkey.data = key->data; 224 dbkey.size = key->size; 225 226 result = db->get(db, &dbkey, &dbdata, flags); 227 if (result != 0) 228 { 229 if (result == 1) 230 return SMDBE_NOT_FOUND; 231 return errno; 232 } 233 data->data = dbdata.data; 234 data->size = dbdata.size; 235 return SMDBE_OK; 236 } 237 238 int 239 smdb1_put(database, key, data, flags) 240 SMDB_DATABASE *database; 241 SMDB_DBENT *key; 242 SMDB_DBENT *data; 243 u_int flags; 244 { 245 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 246 DBT dbkey, dbdata; 247 248 memset(&dbdata, '\0', sizeof dbdata); 249 memset(&dbkey, '\0', sizeof dbkey); 250 dbkey.data = key->data; 251 dbkey.size = key->size; 252 dbdata.data = data->data; 253 dbdata.size = data->size; 254 255 return db->put(db, &dbkey, &dbdata, 256 smdb_put_flags_to_db1_flags(flags)); 257 } 258 259 int 260 smdb1_set_owner(database, uid, gid) 261 SMDB_DATABASE *database; 262 uid_t uid; 263 gid_t gid; 264 { 265 # if HASFCHOWN 266 int fd; 267 int result; 268 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 269 270 fd = db->fd(db); 271 if (fd == -1) 272 return errno; 273 274 result = fchown(fd, uid, gid); 275 if (result < 0) 276 return errno; 277 # endif /* HASFCHOWN */ 278 279 return SMDBE_OK; 280 } 281 282 int 283 smdb1_sync(database, flags) 284 SMDB_DATABASE *database; 285 u_int flags; 286 { 287 DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; 288 289 return db->sync(db, flags); 290 } 291 292 int 293 smdb1_cursor_close(cursor) 294 SMDB_CURSOR *cursor; 295 { 296 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; 297 SMDB_DB1_DATABASE *db1 = db1_cursor->db; 298 299 if (!db1->smdb1_cursor_in_use) 300 return SMDBE_NOT_A_VALID_CURSOR; 301 302 db1->smdb1_cursor_in_use = FALSE; 303 free(cursor); 304 305 return SMDBE_OK; 306 } 307 308 int 309 smdb1_cursor_del(cursor, flags) 310 SMDB_CURSOR *cursor; 311 u_int flags; 312 { 313 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; 314 SMDB_DB1_DATABASE *db1 = db1_cursor->db; 315 DB *db = db1->smdb1_db; 316 317 return db->del(db, NULL, R_CURSOR); 318 } 319 320 int 321 smdb1_cursor_get(cursor, key, value, flags) 322 SMDB_CURSOR *cursor; 323 SMDB_DBENT *key; 324 SMDB_DBENT *value; 325 SMDB_FLAG flags; 326 { 327 int db1_flags; 328 int result; 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 DBT dbkey, dbdata; 333 334 memset(&dbdata, '\0', sizeof dbdata); 335 memset(&dbkey, '\0', sizeof dbkey); 336 337 db1_flags = smdb_cursor_get_flags_to_smdb1(flags); 338 result = db->seq(db, &dbkey, &dbdata, db1_flags); 339 if (result == -1) 340 return errno; 341 if (result == 1) 342 return SMDBE_LAST_ENTRY; 343 value->data = dbdata.data; 344 value->size = dbdata.size; 345 key->data = dbkey.data; 346 key->size = dbkey.size; 347 return SMDBE_OK; 348 } 349 350 int 351 smdb1_cursor_put(cursor, key, value, flags) 352 SMDB_CURSOR *cursor; 353 SMDB_DBENT *key; 354 SMDB_DBENT *value; 355 SMDB_FLAG flags; 356 { 357 SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; 358 SMDB_DB1_DATABASE *db1 = db1_cursor->db; 359 DB *db = db1->smdb1_db; 360 DBT dbkey, dbdata; 361 362 memset(&dbdata, '\0', sizeof dbdata); 363 memset(&dbkey, '\0', sizeof dbkey); 364 dbkey.data = key->data; 365 dbkey.size = key->size; 366 dbdata.data = value->data; 367 dbdata.size = value->size; 368 369 return db->put(db, &dbkey, &dbdata, R_CURSOR); 370 } 371 372 int 373 smdb1_cursor(database, cursor, flags) 374 SMDB_DATABASE *database; 375 SMDB_CURSOR **cursor; 376 u_int flags; 377 { 378 SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; 379 SMDB_CURSOR *cur; 380 SMDB_DB1_CURSOR *db1_cursor; 381 382 if (db1->smdb1_cursor_in_use) 383 return SMDBE_ONLY_SUPPORTS_ONE_CURSOR; 384 385 db1->smdb1_cursor_in_use = TRUE; 386 db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR)); 387 db1_cursor->db = db1; 388 389 cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR)); 390 391 if (cur == NULL) 392 return SMDBE_MALLOC; 393 394 cur->smdbc_impl = db1_cursor; 395 cur->smdbc_close = smdb1_cursor_close; 396 cur->smdbc_del = smdb1_cursor_del; 397 cur->smdbc_get = smdb1_cursor_get; 398 cur->smdbc_put = smdb1_cursor_put; 399 *cursor = cur; 400 401 return SMDBE_OK; 402 } 403 404 /* 405 ** SMDB_DB_OPEN -- Opens a db1 database. 406 ** 407 ** Parameters: 408 ** database -- An unallocated database pointer to a pointer. 409 ** db_name -- The name of the database without extension. 410 ** mode -- File permisions on the database if created. 411 ** mode_mask -- Mode bits that must match on an existing database. 412 ** sff -- Flags for safefile. 413 ** type -- The type of database to open 414 ** See smdb_type_to_db1_type for valid types. 415 ** user_info -- Information on the user to use for file 416 ** permissions. 417 ** db_params -- 418 ** An SMDB_DBPARAMS struct including params. These 419 ** are processed according to the type of the 420 ** database. Currently supported params (only for 421 ** HASH type) are: 422 ** num_elements 423 ** cache_size 424 ** 425 ** Returns: 426 ** SMDBE_OK -- Success, otherwise errno. 427 */ 428 429 int 430 smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, 431 db_params) 432 SMDB_DATABASE **database; 433 char *db_name; 434 int mode; 435 int mode_mask; 436 long sff; 437 SMDB_DBTYPE type; 438 SMDB_USER_INFO *user_info; 439 SMDB_DBPARAMS *db_params; 440 { 441 int db_fd; 442 int lock_fd; 443 int result; 444 void *params; 445 SMDB_DATABASE *smdb_db; 446 SMDB_DB1_DATABASE *db1; 447 DB *db; 448 HASHINFO hash_info; 449 BTREEINFO btree_info; 450 DBTYPE db_type; 451 struct stat stat_info; 452 char db_file_name[SMDB_MAX_NAME_LEN]; 453 454 if (type == NULL || 455 (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 && 456 strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0)) 457 return SMDBE_UNKNOWN_DB_TYPE; 458 459 result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, 460 db_name, SMDB1_FILE_EXTENSION); 461 if (result != SMDBE_OK) 462 return result; 463 464 result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask, 465 sff, user_info, &stat_info); 466 if (result != SMDBE_OK) 467 return result; 468 469 lock_fd = -1; 470 # if O_EXLOCK 471 mode |= O_EXLOCK; 472 # else /* O_EXLOCK */ 473 result = smdb_lock_file(&lock_fd, db_name, mode, sff, 474 SMDB1_FILE_EXTENSION); 475 if (result != SMDBE_OK) 476 return result; 477 # endif /* O_EXLOCK */ 478 479 *database = NULL; 480 481 smdb_db = smdb_malloc_database(); 482 db1 = smdb1_malloc_database(); 483 if (smdb_db == NULL || db1 == NULL) 484 return SMDBE_MALLOC; 485 db1->smdb1_lock_fd = lock_fd; 486 487 params = NULL; 488 if (db_params != NULL && 489 (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0)) 490 { 491 memset(&hash_info, '\0', sizeof hash_info); 492 hash_info.nelem = db_params->smdbp_num_elements; 493 hash_info.cachesize = db_params->smdbp_cache_size; 494 params = &hash_info; 495 } 496 497 if (db_params != NULL && 498 (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0)) 499 { 500 memset(&btree_info, '\0', sizeof btree_info); 501 btree_info.cachesize = db_params->smdbp_cache_size; 502 if (db_params->smdbp_allow_dup) 503 btree_info.flags |= R_DUP; 504 params = &btree_info; 505 } 506 507 db_type = smdb_type_to_db1_type(type); 508 db = dbopen(db_file_name, mode, 0644, db_type, params); 509 if (db != NULL) 510 { 511 db_fd = db->fd(db); 512 result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd, 513 &stat_info); 514 } 515 else 516 { 517 if (errno == 0) 518 result = SMDBE_BAD_OPEN; 519 else 520 result = errno; 521 } 522 523 if (result == SMDBE_OK) 524 { 525 /* Everything is ok. Setup driver */ 526 db1->smdb1_db = db; 527 528 smdb_db->smdb_close = smdb1_close; 529 smdb_db->smdb_del = smdb1_del; 530 smdb_db->smdb_fd = smdb1_fd; 531 smdb_db->smdb_lockfd = smdb1_lockfd; 532 smdb_db->smdb_get = smdb1_get; 533 smdb_db->smdb_put = smdb1_put; 534 smdb_db->smdb_set_owner = smdb1_set_owner; 535 smdb_db->smdb_sync = smdb1_sync; 536 smdb_db->smdb_cursor = smdb1_cursor; 537 smdb_db->smdb_impl = db1; 538 539 *database = smdb_db; 540 return SMDBE_OK; 541 } 542 543 if (db != NULL) 544 (void) db->close(db); 545 546 /* Error opening database */ 547 (void) smdb_unlock_file(db1->smdb1_lock_fd); 548 free(db1); 549 smdb_free_database(smdb_db); 550 551 return result; 552 } 553 554 #endif /* (DB_VERSION_MAJOR == 1) */ 555