smdb.c revision 64562
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 11static char id[] = "@(#)$Id: smdb.c,v 8.37.4.1 2000/05/25 18:56:09 gshapiro Exp $"; 12#endif /* ! lint */ 13 14#include <fcntl.h> 15#include <stdlib.h> 16#include <unistd.h> 17 18 19#include <sendmail/sendmail.h> 20#include <libsmdb/smdb.h> 21 22/* 23** SMDB_MALLOC_DATABASE -- Allocates a database structure. 24** 25** Parameters: 26** None 27** 28** Returns: 29** An pointer to an allocated SMDB_DATABASE structure or 30** NULL if it couldn't allocate the memory. 31*/ 32 33SMDB_DATABASE * 34smdb_malloc_database() 35{ 36 SMDB_DATABASE *db; 37 38 db = (SMDB_DATABASE *) malloc(sizeof(SMDB_DATABASE)); 39 40 if (db != NULL) 41 memset(db, '\0', sizeof(SMDB_DATABASE)); 42 43 return db; 44} 45 46 47/* 48** SMDB_FREE_DATABASE -- Unallocates a database structure. 49** 50** Parameters: 51** database -- a SMDB_DATABASE pointer to deallocate. 52** 53** Returns: 54** None 55*/ 56 57void 58smdb_free_database(database) 59 SMDB_DATABASE *database; 60{ 61 if (database != NULL) 62 free(database); 63} 64 65 66/* 67** SMDB_OPEN_DATABASE -- Opens a database. 68** 69** This opens a database. If type is SMDB_DEFAULT it tries to 70** use a DB1 or DB2 hash. If that isn't available, it will try 71** to use NDBM. If a specific type is given it will try to open 72** a database of that type. 73** 74** Parameters: 75** database -- An pointer to a SMDB_DATABASE pointer where the 76** opened database will be stored. This should 77** be unallocated. 78** db_name -- The name of the database to open. Do not include 79** the file name extension. 80** mode -- The mode to set on the database file or files. 81** mode_mask -- Mode bits that must match on an opened database. 82** sff -- Flags to safefile. 83** type -- The type of database to open. Supported types 84** vary depending on what was compiled in. 85** user_info -- Information on the user to use for file 86** permissions. 87** params -- Params specific to the database being opened. 88** Only supports some DB hash options right now 89** (see smdb_db_open() for details). 90** 91** Returns: 92** SMDBE_OK -- Success. 93** Anything else is an error. Look up more info about the 94** error in the comments for the specific open() used. 95*/ 96 97int 98smdb_open_database(database, db_name, mode, mode_mask, sff, type, user_info, 99 params) 100 SMDB_DATABASE **database; 101 char *db_name; 102 int mode; 103 int mode_mask; 104 long sff; 105 SMDB_DBTYPE type; 106 SMDB_USER_INFO *user_info; 107 SMDB_DBPARAMS *params; 108{ 109 int result; 110 bool type_was_default = FALSE; 111 112 if (type == SMDB_TYPE_DEFAULT) 113 { 114 type_was_default = TRUE; 115#ifdef NEWDB 116 type = SMDB_TYPE_HASH; 117#else /* NEWDB */ 118# ifdef NDBM 119 type = SMDB_TYPE_NDBM; 120# endif /* NDBM */ 121#endif /* NEWDB */ 122 } 123 124 if (type == SMDB_TYPE_DEFAULT) 125 return SMDBE_UNKNOWN_DB_TYPE; 126 127 if ((strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) || 128 (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)) 129 { 130#ifdef NEWDB 131 result = smdb_db_open(database, db_name, mode, mode_mask, sff, 132 type, user_info, params); 133# ifdef NDBM 134 if (result == ENOENT && type_was_default) 135 type = SMDB_TYPE_NDBM; 136 else 137# endif /* NDBM */ 138 return result; 139#else /* NEWDB */ 140 return SMDBE_UNSUPPORTED_DB_TYPE; 141#endif /* NEWDB */ 142 } 143 144 if (strncmp(type, SMDB_TYPE_NDBM, SMDB_TYPE_NDBM_LEN) == 0) 145 { 146#ifdef NDBM 147 result = smdb_ndbm_open(database, db_name, mode, mode_mask, 148 sff, type, user_info, params); 149 return result; 150#else /* NDBM */ 151 return SMDBE_UNSUPPORTED_DB_TYPE; 152#endif /* NDBM */ 153 } 154 155 return SMDBE_UNKNOWN_DB_TYPE; 156} 157 158/* 159** SMDB_ADD_EXTENSION -- Adds an extension to a file name. 160** 161** Just adds a . followed by a string to a db_name if there 162** is room and the db_name does not already have that extension. 163** 164** Parameters: 165** full_name -- The final file name. 166** max_full_name_len -- The max length for full_name. 167** db_name -- The name of the db. 168** extension -- The extension to add. 169** 170** Returns: 171** SMDBE_OK -- Success. 172** Anything else is an error. Look up more info about the 173** error in the comments for the specific open() used. 174*/ 175 176int 177smdb_add_extension(full_name, max_full_name_len, db_name, extension) 178 char *full_name; 179 int max_full_name_len; 180 char *db_name; 181 char *extension; 182{ 183 int extension_len; 184 int db_name_len; 185 186 if (full_name == NULL || db_name == NULL || extension == NULL) 187 return SMDBE_INVALID_PARAMETER; 188 189 extension_len = strlen(extension); 190 db_name_len = strlen(db_name); 191 192 if (extension_len + db_name_len + 2 > max_full_name_len) 193 return SMDBE_DB_NAME_TOO_LONG; 194 195 if (db_name_len < extension_len + 1 || 196 db_name[db_name_len - extension_len - 1] != '.' || 197 strcmp(&db_name[db_name_len - extension_len], extension) != 0) 198 snprintf(full_name, max_full_name_len, "%s.%s", db_name, 199 extension); 200 else 201 (void) strlcpy(full_name, db_name, max_full_name_len); 202 203 return SMDBE_OK; 204} 205 206/* 207** SMDB_LOCK_FILE -- Locks the database file. 208** 209** Locks the actual database file. 210** 211** Parameters: 212** lock_fd -- The resulting descriptor for the locked file. 213** db_name -- The name of the database without extension. 214** mode -- The open mode. 215** sff -- Flags to safefile. 216** extension -- The extension for the file. 217** 218** Returns: 219** SMDBE_OK -- Success, otherwise errno. 220*/ 221 222int 223smdb_lock_file(lock_fd, db_name, mode, sff, extension) 224 int *lock_fd; 225 char *db_name; 226 int mode; 227 long sff; 228 char *extension; 229{ 230 int result; 231 char file_name[SMDB_MAX_NAME_LEN]; 232 233 result = smdb_add_extension(file_name, SMDB_MAX_NAME_LEN, db_name, 234 extension); 235 if (result != SMDBE_OK) 236 return result; 237 238 *lock_fd = safeopen(file_name, mode & ~O_TRUNC, 0644, sff); 239 if (*lock_fd < 0) 240 return errno; 241 242 return SMDBE_OK; 243} 244 245/* 246** SMDB_UNLOCK_FILE -- Unlocks a file 247** 248** Unlocks a file. 249** 250** Parameters: 251** lock_fd -- The descriptor for the locked file. 252** 253** Returns: 254** SMDBE_OK -- Success, otherwise errno. 255*/ 256 257int 258smdb_unlock_file(lock_fd) 259 int lock_fd; 260{ 261 int result; 262 263 result = close(lock_fd); 264 if (result != 0) 265 return errno; 266 267 return SMDBE_OK; 268} 269 270/* 271** SMDB_SETUP_FILE -- Gets db file ready for use. 272** 273** Makes sure permissions on file are safe and creates it if it 274** doesn't exist. 275** 276** Parameters: 277** db_name -- The name of the database without extension. 278** extension -- The extension. 279** sff -- Flags to safefile. 280** mode_mask -- Mode bits that must match. 281** user_info -- Information on the user to use for file 282** permissions. 283** stat_info -- A place to put the stat info for the file. 284** Returns: 285** SMDBE_OK -- Success, otherwise errno. 286*/ 287 288int 289smdb_setup_file(db_name, extension, mode_mask, sff, user_info, stat_info) 290 char *db_name; 291 char *extension; 292 int mode_mask; 293 long sff; 294 SMDB_USER_INFO *user_info; 295 struct stat *stat_info; 296{ 297 int st; 298 int result; 299 char db_file_name[SMDB_MAX_NAME_LEN]; 300 301 result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, db_name, 302 extension); 303 if (result != SMDBE_OK) 304 return result; 305 306 st = safefile(db_file_name, user_info->smdbu_id, 307 user_info->smdbu_group_id, user_info->smdbu_name, 308 sff, mode_mask, stat_info); 309 if (st != 0) 310 return st; 311 312 return SMDBE_OK; 313} 314 315/* 316** SMDB_FILECHANGED -- Checks to see if a file changed. 317** 318** Compares the passed in stat_info with a current stat on 319** the passed in file descriptor. Check filechanged for 320** return values. 321** 322** Parameters: 323** db_name -- The name of the database without extension. 324** extension -- The extension. 325** db_fd -- A file descriptor for the database file. 326** stat_info -- An old stat_info. 327** Returns: 328** SMDBE_OK -- Success, otherwise errno. 329*/ 330 331int 332smdb_filechanged(db_name, extension, db_fd, stat_info) 333 char *db_name; 334 char *extension; 335 int db_fd; 336 struct stat *stat_info; 337{ 338 int result; 339 char db_file_name[SMDB_MAX_NAME_LEN]; 340 341 result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, db_name, 342 extension); 343 if (result != SMDBE_OK) 344 return result; 345 346 result = filechanged(db_file_name, db_fd, stat_info); 347 348 return result; 349} 350/* 351** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types. 352** 353** Parameters: 354** None 355** 356** Returns: 357** None 358*/ 359 360void 361smdb_print_available_types() 362{ 363#ifdef NDBM 364 printf("dbm\n"); 365#endif /* NDBM */ 366#ifdef NEWDB 367 printf("hash\n"); 368 printf("btree\n"); 369#endif /* NEWDB */ 370} 371/* 372** SMDB_DB_DEFINITION -- Given a database type, return database definition 373** 374** Reads though a structure making an association with the database 375** type and the required cpp define from sendmail/README. 376** List size is dynamic and must be NULL terminated. 377** 378** Parameters: 379** type -- The name of the database type. 380** 381** Returns: 382** definition for type, otherwise NULL. 383*/ 384 385typedef struct 386{ 387 SMDB_DBTYPE type; 388 char *dbdef; 389} dbtype; 390 391static dbtype DatabaseDefs[] = 392{ 393 { SMDB_TYPE_HASH, "NEWDB" }, 394 { SMDB_TYPE_BTREE, "NEWDB" }, 395 { SMDB_TYPE_NDBM, "NDBM" }, 396 { NULL, "OOPS" } 397}; 398 399char * 400smdb_db_definition(type) 401 SMDB_DBTYPE type; 402{ 403 dbtype *ptr = DatabaseDefs; 404 405 while (ptr != NULL && ptr->type != NULL) 406 { 407 if (strcmp(type, ptr->type) == 0) 408 return ptr->dbdef; 409 ptr++; 410 } 411 return NULL; 412} 413