smdb.c revision 285303
144743Smarkm/* 244743Smarkm** Copyright (c) 1999-2002 Proofpoint, Inc. and its suppliers. 344743Smarkm** All rights reserved. 444743Smarkm** 544743Smarkm** By using this file, you agree to the terms and conditions set 644743Smarkm** forth in the LICENSE file which can be found at the top level of 744743Smarkm** the sendmail distribution. 844743Smarkm*/ 944743Smarkm 1044743Smarkm#include <sm/gen.h> 1144743SmarkmSM_RCSID("@(#)$Id: smdb.c,v 8.59 2013-11-22 20:51:49 ca Exp $") 1244743Smarkm 1344743Smarkm#include <fcntl.h> 1444743Smarkm#include <stdlib.h> 1544743Smarkm#include <unistd.h> 1644743Smarkm 1744743Smarkm 1844743Smarkm#include <sendmail/sendmail.h> 1944743Smarkm#include <libsmdb/smdb.h> 2044743Smarkm 2144743Smarkmstatic bool smdb_lockfile __P((int, int)); 2244743Smarkm 2344743Smarkm/* 2444743Smarkm** SMDB_MALLOC_DATABASE -- Allocates a database structure. 2544743Smarkm** 2644743Smarkm** Parameters: 2744743Smarkm** None 2844743Smarkm** 2944743Smarkm** Returns: 3044743Smarkm** An pointer to an allocated SMDB_DATABASE structure or 3144743Smarkm** NULL if it couldn't allocate the memory. 3244743Smarkm*/ 3344743Smarkm 3444743SmarkmSMDB_DATABASE * 3544743Smarkmsmdb_malloc_database() 3644743Smarkm{ 3744743Smarkm SMDB_DATABASE *db; 3844743Smarkm 3944743Smarkm db = (SMDB_DATABASE *) malloc(sizeof(SMDB_DATABASE)); 4044743Smarkm 4144743Smarkm if (db != NULL) 4244743Smarkm (void) memset(db, '\0', sizeof(SMDB_DATABASE)); 4344743Smarkm 4444743Smarkm return db; 4544743Smarkm} 4644743Smarkm 4744743Smarkm 4844743Smarkm/* 4944743Smarkm** SMDB_FREE_DATABASE -- Unallocates a database structure. 5044743Smarkm** 5144743Smarkm** Parameters: 5244743Smarkm** database -- a SMDB_DATABASE pointer to deallocate. 5344743Smarkm** 5444743Smarkm** Returns: 5544743Smarkm** None 5644743Smarkm*/ 5744743Smarkm 5844743Smarkmvoid 5944743Smarkmsmdb_free_database(database) 6044743Smarkm SMDB_DATABASE *database; 6144743Smarkm{ 6244743Smarkm if (database != NULL) 6344743Smarkm free(database); 6444743Smarkm} 6544743Smarkm/* 6644743Smarkm** SMDB_LOCKFILE -- lock a file using flock or (shudder) fcntl locking 6744743Smarkm** 6844743Smarkm** Parameters: 6944743Smarkm** fd -- the file descriptor of the file. 7044743Smarkm** type -- type of the lock. Bits can be: 7144743Smarkm** LOCK_EX -- exclusive lock. 7244743Smarkm** LOCK_NB -- non-blocking. 7344743Smarkm** 7444743Smarkm** Returns: 7544743Smarkm** true if the lock was acquired. 7644743Smarkm** false otherwise. 7744743Smarkm*/ 7844743Smarkm 7944743Smarkmstatic bool 8044743Smarkmsmdb_lockfile(fd, type) 8144743Smarkm int fd; 8244743Smarkm int type; 8344743Smarkm{ 8444743Smarkm int i; 8544743Smarkm int save_errno; 8644743Smarkm#if !HASFLOCK 8744743Smarkm int action; 8844743Smarkm struct flock lfd; 8944743Smarkm 9044743Smarkm (void) memset(&lfd, '\0', sizeof lfd); 9144743Smarkm if (bitset(LOCK_UN, type)) 9244743Smarkm lfd.l_type = F_UNLCK; 9344743Smarkm else if (bitset(LOCK_EX, type)) 9444743Smarkm lfd.l_type = F_WRLCK; 9544743Smarkm else 9644743Smarkm lfd.l_type = F_RDLCK; 9744743Smarkm 9844743Smarkm if (bitset(LOCK_NB, type)) 9944743Smarkm action = F_SETLK; 10044743Smarkm else 10144743Smarkm action = F_SETLKW; 10244743Smarkm 10344743Smarkm while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR) 10444743Smarkm continue; 10544743Smarkm if (i >= 0) 10644743Smarkm return true; 10744743Smarkm save_errno = errno; 10844743Smarkm 10944743Smarkm /* 11044743Smarkm ** On SunOS, if you are testing using -oQ/tmp/mqueue or 11144743Smarkm ** -oA/tmp/aliases or anything like that, and /tmp is mounted 11244743Smarkm ** as type "tmp" (that is, served from swap space), the 11344743Smarkm ** previous fcntl will fail with "Invalid argument" errors. 11444743Smarkm ** Since this is fairly common during testing, we will assume 11544743Smarkm ** that this indicates that the lock is successfully grabbed. 11644743Smarkm */ 11744743Smarkm 11844743Smarkm if (save_errno == EINVAL) 11944743Smarkm return true; 12044743Smarkm 12144743Smarkm if (!bitset(LOCK_NB, type) || 12244743Smarkm (save_errno != EACCES && save_errno != EAGAIN)) 12344743Smarkm { 12444743Smarkm# if 0 12544743Smarkm int omode = fcntl(fd, F_GETFL, NULL); 12644743Smarkm int euid = (int) geteuid(); 12744743Smarkm 12844743Smarkm syslog(LOG_ERR, "cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", 12944743Smarkm filename, ext, fd, type, omode, euid); 13044743Smarkm# endif /* 0 */ 13144743Smarkm errno = save_errno; 13244743Smarkm return false; 13344743Smarkm } 13444743Smarkm#else /* !HASFLOCK */ 13544743Smarkm 13644743Smarkm while ((i = flock(fd, type)) < 0 && errno == EINTR) 137 continue; 138 if (i >= 0) 139 return true; 140 save_errno = errno; 141 142 if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK) 143 { 144# if 0 145 int omode = fcntl(fd, F_GETFL, NULL); 146 int euid = (int) geteuid(); 147 148 syslog(LOG_ERR, "cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", 149 filename, ext, fd, type, omode, euid); 150# endif /* 0 */ 151 errno = save_errno; 152 return false; 153 } 154#endif /* !HASFLOCK */ 155 errno = save_errno; 156 return false; 157} 158/* 159** SMDB_OPEN_DATABASE -- Opens a database. 160** 161** This opens a database. If type is SMDB_DEFAULT it tries to 162** use a DB1 or DB2 hash. If that isn't available, it will try 163** to use NDBM. If a specific type is given it will try to open 164** a database of that type. 165** 166** Parameters: 167** database -- An pointer to a SMDB_DATABASE pointer where the 168** opened database will be stored. This should 169** be unallocated. 170** db_name -- The name of the database to open. Do not include 171** the file name extension. 172** mode -- The mode to set on the database file or files. 173** mode_mask -- Mode bits that must match on an opened database. 174** sff -- Flags to safefile. 175** type -- The type of database to open. Supported types 176** vary depending on what was compiled in. 177** user_info -- Information on the user to use for file 178** permissions. 179** params -- Params specific to the database being opened. 180** Only supports some DB hash options right now 181** (see smdb_db_open() for details). 182** 183** Returns: 184** SMDBE_OK -- Success. 185** Anything else is an error. Look up more info about the 186** error in the comments for the specific open() used. 187*/ 188 189int 190smdb_open_database(database, db_name, mode, mode_mask, sff, type, user_info, 191 params) 192 SMDB_DATABASE **database; 193 char *db_name; 194 int mode; 195 int mode_mask; 196 long sff; 197 SMDB_DBTYPE type; 198 SMDB_USER_INFO *user_info; 199 SMDB_DBPARAMS *params; 200{ 201#if defined(NEWDB) && defined(NDBM) 202 bool type_was_default = false; 203#endif 204 205 if (type == SMDB_TYPE_DEFAULT) 206 { 207#ifdef NEWDB 208# ifdef NDBM 209 type_was_default = true; 210# endif 211 type = SMDB_TYPE_HASH; 212#else /* NEWDB */ 213# ifdef NDBM 214 type = SMDB_TYPE_NDBM; 215# endif /* NDBM */ 216#endif /* NEWDB */ 217 } 218 219 if (type == SMDB_TYPE_DEFAULT) 220 return SMDBE_UNKNOWN_DB_TYPE; 221 222 if ((strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) || 223 (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)) 224 { 225#ifdef NEWDB 226 int result; 227 228 result = smdb_db_open(database, db_name, mode, mode_mask, sff, 229 type, user_info, params); 230# ifdef NDBM 231 if (result == ENOENT && type_was_default) 232 type = SMDB_TYPE_NDBM; 233 else 234# endif /* NDBM */ 235 return result; 236#else /* NEWDB */ 237 return SMDBE_UNSUPPORTED_DB_TYPE; 238#endif /* NEWDB */ 239 } 240 241 if (strncmp(type, SMDB_TYPE_NDBM, SMDB_TYPE_NDBM_LEN) == 0) 242 { 243#ifdef NDBM 244 int result; 245 246 result = smdb_ndbm_open(database, db_name, mode, mode_mask, 247 sff, type, user_info, params); 248 return result; 249#else /* NDBM */ 250 return SMDBE_UNSUPPORTED_DB_TYPE; 251#endif /* NDBM */ 252 } 253 254 return SMDBE_UNKNOWN_DB_TYPE; 255} 256/* 257** SMDB_ADD_EXTENSION -- Adds an extension to a file name. 258** 259** Just adds a . followed by a string to a db_name if there 260** is room and the db_name does not already have that extension. 261** 262** Parameters: 263** full_name -- The final file name. 264** max_full_name_len -- The max length for full_name. 265** db_name -- The name of the db. 266** extension -- The extension to add. 267** 268** Returns: 269** SMDBE_OK -- Success. 270** Anything else is an error. Look up more info about the 271** error in the comments for the specific open() used. 272*/ 273 274int 275smdb_add_extension(full_name, max_full_name_len, db_name, extension) 276 char *full_name; 277 int max_full_name_len; 278 char *db_name; 279 char *extension; 280{ 281 int extension_len; 282 int db_name_len; 283 284 if (full_name == NULL || db_name == NULL || extension == NULL) 285 return SMDBE_INVALID_PARAMETER; 286 287 extension_len = strlen(extension); 288 db_name_len = strlen(db_name); 289 290 if (extension_len + db_name_len + 2 > max_full_name_len) 291 return SMDBE_DB_NAME_TOO_LONG; 292 293 if (db_name_len < extension_len + 1 || 294 db_name[db_name_len - extension_len - 1] != '.' || 295 strcmp(&db_name[db_name_len - extension_len], extension) != 0) 296 (void) sm_snprintf(full_name, max_full_name_len, "%s.%s", 297 db_name, extension); 298 else 299 (void) sm_strlcpy(full_name, db_name, max_full_name_len); 300 301 return SMDBE_OK; 302} 303/* 304** SMDB_LOCK_FILE -- Locks the database file. 305** 306** Locks the actual database file. 307** 308** Parameters: 309** lock_fd -- The resulting descriptor for the locked file. 310** db_name -- The name of the database without extension. 311** mode -- The open mode. 312** sff -- Flags to safefile. 313** extension -- The extension for the file. 314** 315** Returns: 316** SMDBE_OK -- Success, otherwise errno. 317*/ 318 319int 320smdb_lock_file(lock_fd, db_name, mode, sff, extension) 321 int *lock_fd; 322 char *db_name; 323 int mode; 324 long sff; 325 char *extension; 326{ 327 int result; 328 char file_name[MAXPATHLEN]; 329 330 result = smdb_add_extension(file_name, sizeof file_name, db_name, 331 extension); 332 if (result != SMDBE_OK) 333 return result; 334 335 *lock_fd = safeopen(file_name, mode & ~O_TRUNC, DBMMODE, sff); 336 if (*lock_fd < 0) 337 return errno; 338 339 return SMDBE_OK; 340} 341/* 342** SMDB_UNLOCK_FILE -- Unlocks a file 343** 344** Unlocks a file. 345** 346** Parameters: 347** lock_fd -- The descriptor for the locked file. 348** 349** Returns: 350** SMDBE_OK -- Success, otherwise errno. 351*/ 352 353int 354smdb_unlock_file(lock_fd) 355 int lock_fd; 356{ 357 int result; 358 359 result = close(lock_fd); 360 if (result != 0) 361 return errno; 362 363 return SMDBE_OK; 364} 365/* 366** SMDB_LOCK_MAP -- Locks a database. 367** 368** Parameters: 369** database -- database description. 370** type -- type of the lock. Bits can be: 371** LOCK_EX -- exclusive lock. 372** LOCK_NB -- non-blocking. 373** 374** Returns: 375** SMDBE_OK -- Success, otherwise errno. 376*/ 377 378int 379smdb_lock_map(database, type) 380 SMDB_DATABASE *database; 381 int type; 382{ 383 int fd; 384 385 fd = database->smdb_lockfd(database); 386 if (fd < 0) 387 return SMDBE_NOT_FOUND; 388 if (!smdb_lockfile(fd, type)) 389 return SMDBE_LOCK_NOT_GRANTED; 390 return SMDBE_OK; 391} 392/* 393** SMDB_UNLOCK_MAP -- Unlocks a database 394** 395** Parameters: 396** database -- database description. 397** 398** Returns: 399** SMDBE_OK -- Success, otherwise errno. 400*/ 401 402int 403smdb_unlock_map(database) 404 SMDB_DATABASE *database; 405{ 406 int fd; 407 408 fd = database->smdb_lockfd(database); 409 if (fd < 0) 410 return SMDBE_NOT_FOUND; 411 if (!smdb_lockfile(fd, LOCK_UN)) 412 return SMDBE_LOCK_NOT_HELD; 413 return SMDBE_OK; 414} 415/* 416** SMDB_SETUP_FILE -- Gets db file ready for use. 417** 418** Makes sure permissions on file are safe and creates it if it 419** doesn't exist. 420** 421** Parameters: 422** db_name -- The name of the database without extension. 423** extension -- The extension. 424** sff -- Flags to safefile. 425** mode_mask -- Mode bits that must match. 426** user_info -- Information on the user to use for file 427** permissions. 428** stat_info -- A place to put the stat info for the file. 429** Returns: 430** SMDBE_OK -- Success, otherwise errno. 431*/ 432 433int 434smdb_setup_file(db_name, extension, mode_mask, sff, user_info, stat_info) 435 char *db_name; 436 char *extension; 437 int mode_mask; 438 long sff; 439 SMDB_USER_INFO *user_info; 440 struct stat *stat_info; 441{ 442 int st; 443 int result; 444 char db_file_name[MAXPATHLEN]; 445 446 result = smdb_add_extension(db_file_name, sizeof db_file_name, db_name, 447 extension); 448 if (result != SMDBE_OK) 449 return result; 450 451 st = safefile(db_file_name, user_info->smdbu_id, 452 user_info->smdbu_group_id, user_info->smdbu_name, 453 sff, mode_mask, stat_info); 454 if (st != 0) 455 return st; 456 457 return SMDBE_OK; 458} 459/* 460** SMDB_FILECHANGED -- Checks to see if a file changed. 461** 462** Compares the passed in stat_info with a current stat on 463** the passed in file descriptor. Check filechanged for 464** return values. 465** 466** Parameters: 467** db_name -- The name of the database without extension. 468** extension -- The extension. 469** db_fd -- A file descriptor for the database file. 470** stat_info -- An old stat_info. 471** Returns: 472** SMDBE_OK -- Success, otherwise errno. 473*/ 474 475int 476smdb_filechanged(db_name, extension, db_fd, stat_info) 477 char *db_name; 478 char *extension; 479 int db_fd; 480 struct stat *stat_info; 481{ 482 int result; 483 char db_file_name[MAXPATHLEN]; 484 485 result = smdb_add_extension(db_file_name, sizeof db_file_name, db_name, 486 extension); 487 if (result != SMDBE_OK) 488 return result; 489 return filechanged(db_file_name, db_fd, stat_info); 490} 491/* 492** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types. 493** 494** Parameters: 495** None 496** 497** Returns: 498** None 499*/ 500 501void 502smdb_print_available_types() 503{ 504#ifdef NDBM 505 printf("dbm\n"); 506#endif /* NDBM */ 507#ifdef NEWDB 508 printf("hash\n"); 509 printf("btree\n"); 510#endif /* NEWDB */ 511} 512/* 513** SMDB_DB_DEFINITION -- Given a database type, return database definition 514** 515** Reads though a structure making an association with the database 516** type and the required cpp define from sendmail/README. 517** List size is dynamic and must be NULL terminated. 518** 519** Parameters: 520** type -- The name of the database type. 521** 522** Returns: 523** definition for type, otherwise NULL. 524*/ 525 526typedef struct 527{ 528 SMDB_DBTYPE type; 529 char *dbdef; 530} dbtype; 531 532static dbtype DatabaseDefs[] = 533{ 534 { SMDB_TYPE_HASH, "NEWDB" }, 535 { SMDB_TYPE_BTREE, "NEWDB" }, 536 { SMDB_TYPE_NDBM, "NDBM" }, 537 { NULL, "OOPS" } 538}; 539 540char * 541smdb_db_definition(type) 542 SMDB_DBTYPE type; 543{ 544 dbtype *ptr = DatabaseDefs; 545 546 while (ptr != NULL && ptr->type != NULL) 547 { 548 if (strcmp(type, ptr->type) == 0) 549 return ptr->dbdef; 550 ptr++; 551 } 552 return NULL; 553} 554