smdb.c revision 64562
164562Sgshapiro/* 264562Sgshapiro** Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. 364562Sgshapiro** All rights reserved. 464562Sgshapiro** 564562Sgshapiro** By using this file, you agree to the terms and conditions set 664562Sgshapiro** forth in the LICENSE file which can be found at the top level of 764562Sgshapiro** the sendmail distribution. 864562Sgshapiro*/ 964562Sgshapiro 1064562Sgshapiro#ifndef lint 1164562Sgshapirostatic char id[] = "@(#)$Id: smdb.c,v 8.37.4.1 2000/05/25 18:56:09 gshapiro Exp $"; 1264562Sgshapiro#endif /* ! lint */ 1364562Sgshapiro 1464562Sgshapiro#include <fcntl.h> 1564562Sgshapiro#include <stdlib.h> 1664562Sgshapiro#include <unistd.h> 1764562Sgshapiro 1864562Sgshapiro 1964562Sgshapiro#include <sendmail/sendmail.h> 2064562Sgshapiro#include <libsmdb/smdb.h> 2164562Sgshapiro 2264562Sgshapiro/* 2364562Sgshapiro** SMDB_MALLOC_DATABASE -- Allocates a database structure. 2464562Sgshapiro** 2564562Sgshapiro** Parameters: 2664562Sgshapiro** None 2764562Sgshapiro** 2864562Sgshapiro** Returns: 2964562Sgshapiro** An pointer to an allocated SMDB_DATABASE structure or 3064562Sgshapiro** NULL if it couldn't allocate the memory. 3164562Sgshapiro*/ 3264562Sgshapiro 3364562SgshapiroSMDB_DATABASE * 3464562Sgshapirosmdb_malloc_database() 3564562Sgshapiro{ 3664562Sgshapiro SMDB_DATABASE *db; 3764562Sgshapiro 3864562Sgshapiro db = (SMDB_DATABASE *) malloc(sizeof(SMDB_DATABASE)); 3964562Sgshapiro 4064562Sgshapiro if (db != NULL) 4164562Sgshapiro memset(db, '\0', sizeof(SMDB_DATABASE)); 4264562Sgshapiro 4364562Sgshapiro return db; 4464562Sgshapiro} 4564562Sgshapiro 4664562Sgshapiro 4764562Sgshapiro/* 4864562Sgshapiro** SMDB_FREE_DATABASE -- Unallocates a database structure. 4964562Sgshapiro** 5064562Sgshapiro** Parameters: 5164562Sgshapiro** database -- a SMDB_DATABASE pointer to deallocate. 5264562Sgshapiro** 5364562Sgshapiro** Returns: 5464562Sgshapiro** None 5564562Sgshapiro*/ 5664562Sgshapiro 5764562Sgshapirovoid 5864562Sgshapirosmdb_free_database(database) 5964562Sgshapiro SMDB_DATABASE *database; 6064562Sgshapiro{ 6164562Sgshapiro if (database != NULL) 6264562Sgshapiro free(database); 6364562Sgshapiro} 6464562Sgshapiro 6564562Sgshapiro 6664562Sgshapiro/* 6764562Sgshapiro** SMDB_OPEN_DATABASE -- Opens a database. 6864562Sgshapiro** 6964562Sgshapiro** This opens a database. If type is SMDB_DEFAULT it tries to 7064562Sgshapiro** use a DB1 or DB2 hash. If that isn't available, it will try 7164562Sgshapiro** to use NDBM. If a specific type is given it will try to open 7264562Sgshapiro** a database of that type. 7364562Sgshapiro** 7464562Sgshapiro** Parameters: 7564562Sgshapiro** database -- An pointer to a SMDB_DATABASE pointer where the 7664562Sgshapiro** opened database will be stored. This should 7764562Sgshapiro** be unallocated. 7864562Sgshapiro** db_name -- The name of the database to open. Do not include 7964562Sgshapiro** the file name extension. 8064562Sgshapiro** mode -- The mode to set on the database file or files. 8164562Sgshapiro** mode_mask -- Mode bits that must match on an opened database. 8264562Sgshapiro** sff -- Flags to safefile. 8364562Sgshapiro** type -- The type of database to open. Supported types 8464562Sgshapiro** vary depending on what was compiled in. 8564562Sgshapiro** user_info -- Information on the user to use for file 8664562Sgshapiro** permissions. 8764562Sgshapiro** params -- Params specific to the database being opened. 8864562Sgshapiro** Only supports some DB hash options right now 8964562Sgshapiro** (see smdb_db_open() for details). 9064562Sgshapiro** 9164562Sgshapiro** Returns: 9264562Sgshapiro** SMDBE_OK -- Success. 9364562Sgshapiro** Anything else is an error. Look up more info about the 9464562Sgshapiro** error in the comments for the specific open() used. 9564562Sgshapiro*/ 9664562Sgshapiro 9764562Sgshapiroint 9864562Sgshapirosmdb_open_database(database, db_name, mode, mode_mask, sff, type, user_info, 9964562Sgshapiro params) 10064562Sgshapiro SMDB_DATABASE **database; 10164562Sgshapiro char *db_name; 10264562Sgshapiro int mode; 10364562Sgshapiro int mode_mask; 10464562Sgshapiro long sff; 10564562Sgshapiro SMDB_DBTYPE type; 10664562Sgshapiro SMDB_USER_INFO *user_info; 10764562Sgshapiro SMDB_DBPARAMS *params; 10864562Sgshapiro{ 10964562Sgshapiro int result; 11064562Sgshapiro bool type_was_default = FALSE; 11164562Sgshapiro 11264562Sgshapiro if (type == SMDB_TYPE_DEFAULT) 11364562Sgshapiro { 11464562Sgshapiro type_was_default = TRUE; 11564562Sgshapiro#ifdef NEWDB 11664562Sgshapiro type = SMDB_TYPE_HASH; 11764562Sgshapiro#else /* NEWDB */ 11864562Sgshapiro# ifdef NDBM 11964562Sgshapiro type = SMDB_TYPE_NDBM; 12064562Sgshapiro# endif /* NDBM */ 12164562Sgshapiro#endif /* NEWDB */ 12264562Sgshapiro } 12364562Sgshapiro 12464562Sgshapiro if (type == SMDB_TYPE_DEFAULT) 12564562Sgshapiro return SMDBE_UNKNOWN_DB_TYPE; 12664562Sgshapiro 12764562Sgshapiro if ((strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) || 12864562Sgshapiro (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)) 12964562Sgshapiro { 13064562Sgshapiro#ifdef NEWDB 13164562Sgshapiro result = smdb_db_open(database, db_name, mode, mode_mask, sff, 13264562Sgshapiro type, user_info, params); 13364562Sgshapiro# ifdef NDBM 13464562Sgshapiro if (result == ENOENT && type_was_default) 13564562Sgshapiro type = SMDB_TYPE_NDBM; 13664562Sgshapiro else 13764562Sgshapiro# endif /* NDBM */ 13864562Sgshapiro return result; 13964562Sgshapiro#else /* NEWDB */ 14064562Sgshapiro return SMDBE_UNSUPPORTED_DB_TYPE; 14164562Sgshapiro#endif /* NEWDB */ 14264562Sgshapiro } 14364562Sgshapiro 14464562Sgshapiro if (strncmp(type, SMDB_TYPE_NDBM, SMDB_TYPE_NDBM_LEN) == 0) 14564562Sgshapiro { 14664562Sgshapiro#ifdef NDBM 14764562Sgshapiro result = smdb_ndbm_open(database, db_name, mode, mode_mask, 14864562Sgshapiro sff, type, user_info, params); 14964562Sgshapiro return result; 15064562Sgshapiro#else /* NDBM */ 15164562Sgshapiro return SMDBE_UNSUPPORTED_DB_TYPE; 15264562Sgshapiro#endif /* NDBM */ 15364562Sgshapiro } 15464562Sgshapiro 15564562Sgshapiro return SMDBE_UNKNOWN_DB_TYPE; 15664562Sgshapiro} 15764562Sgshapiro 15864562Sgshapiro/* 15964562Sgshapiro** SMDB_ADD_EXTENSION -- Adds an extension to a file name. 16064562Sgshapiro** 16164562Sgshapiro** Just adds a . followed by a string to a db_name if there 16264562Sgshapiro** is room and the db_name does not already have that extension. 16364562Sgshapiro** 16464562Sgshapiro** Parameters: 16564562Sgshapiro** full_name -- The final file name. 16664562Sgshapiro** max_full_name_len -- The max length for full_name. 16764562Sgshapiro** db_name -- The name of the db. 16864562Sgshapiro** extension -- The extension to add. 16964562Sgshapiro** 17064562Sgshapiro** Returns: 17164562Sgshapiro** SMDBE_OK -- Success. 17264562Sgshapiro** Anything else is an error. Look up more info about the 17364562Sgshapiro** error in the comments for the specific open() used. 17464562Sgshapiro*/ 17564562Sgshapiro 17664562Sgshapiroint 17764562Sgshapirosmdb_add_extension(full_name, max_full_name_len, db_name, extension) 17864562Sgshapiro char *full_name; 17964562Sgshapiro int max_full_name_len; 18064562Sgshapiro char *db_name; 18164562Sgshapiro char *extension; 18264562Sgshapiro{ 18364562Sgshapiro int extension_len; 18464562Sgshapiro int db_name_len; 18564562Sgshapiro 18664562Sgshapiro if (full_name == NULL || db_name == NULL || extension == NULL) 18764562Sgshapiro return SMDBE_INVALID_PARAMETER; 18864562Sgshapiro 18964562Sgshapiro extension_len = strlen(extension); 19064562Sgshapiro db_name_len = strlen(db_name); 19164562Sgshapiro 19264562Sgshapiro if (extension_len + db_name_len + 2 > max_full_name_len) 19364562Sgshapiro return SMDBE_DB_NAME_TOO_LONG; 19464562Sgshapiro 19564562Sgshapiro if (db_name_len < extension_len + 1 || 19664562Sgshapiro db_name[db_name_len - extension_len - 1] != '.' || 19764562Sgshapiro strcmp(&db_name[db_name_len - extension_len], extension) != 0) 19864562Sgshapiro snprintf(full_name, max_full_name_len, "%s.%s", db_name, 19964562Sgshapiro extension); 20064562Sgshapiro else 20164562Sgshapiro (void) strlcpy(full_name, db_name, max_full_name_len); 20264562Sgshapiro 20364562Sgshapiro return SMDBE_OK; 20464562Sgshapiro} 20564562Sgshapiro 20664562Sgshapiro/* 20764562Sgshapiro** SMDB_LOCK_FILE -- Locks the database file. 20864562Sgshapiro** 20964562Sgshapiro** Locks the actual database file. 21064562Sgshapiro** 21164562Sgshapiro** Parameters: 21264562Sgshapiro** lock_fd -- The resulting descriptor for the locked file. 21364562Sgshapiro** db_name -- The name of the database without extension. 21464562Sgshapiro** mode -- The open mode. 21564562Sgshapiro** sff -- Flags to safefile. 21664562Sgshapiro** extension -- The extension for the file. 21764562Sgshapiro** 21864562Sgshapiro** Returns: 21964562Sgshapiro** SMDBE_OK -- Success, otherwise errno. 22064562Sgshapiro*/ 22164562Sgshapiro 22264562Sgshapiroint 22364562Sgshapirosmdb_lock_file(lock_fd, db_name, mode, sff, extension) 22464562Sgshapiro int *lock_fd; 22564562Sgshapiro char *db_name; 22664562Sgshapiro int mode; 22764562Sgshapiro long sff; 22864562Sgshapiro char *extension; 22964562Sgshapiro{ 23064562Sgshapiro int result; 23164562Sgshapiro char file_name[SMDB_MAX_NAME_LEN]; 23264562Sgshapiro 23364562Sgshapiro result = smdb_add_extension(file_name, SMDB_MAX_NAME_LEN, db_name, 23464562Sgshapiro extension); 23564562Sgshapiro if (result != SMDBE_OK) 23664562Sgshapiro return result; 23764562Sgshapiro 23864562Sgshapiro *lock_fd = safeopen(file_name, mode & ~O_TRUNC, 0644, sff); 23964562Sgshapiro if (*lock_fd < 0) 24064562Sgshapiro return errno; 24164562Sgshapiro 24264562Sgshapiro return SMDBE_OK; 24364562Sgshapiro} 24464562Sgshapiro 24564562Sgshapiro/* 24664562Sgshapiro** SMDB_UNLOCK_FILE -- Unlocks a file 24764562Sgshapiro** 24864562Sgshapiro** Unlocks a file. 24964562Sgshapiro** 25064562Sgshapiro** Parameters: 25164562Sgshapiro** lock_fd -- The descriptor for the locked file. 25264562Sgshapiro** 25364562Sgshapiro** Returns: 25464562Sgshapiro** SMDBE_OK -- Success, otherwise errno. 25564562Sgshapiro*/ 25664562Sgshapiro 25764562Sgshapiroint 25864562Sgshapirosmdb_unlock_file(lock_fd) 25964562Sgshapiro int lock_fd; 26064562Sgshapiro{ 26164562Sgshapiro int result; 26264562Sgshapiro 26364562Sgshapiro result = close(lock_fd); 26464562Sgshapiro if (result != 0) 26564562Sgshapiro return errno; 26664562Sgshapiro 26764562Sgshapiro return SMDBE_OK; 26864562Sgshapiro} 26964562Sgshapiro 27064562Sgshapiro/* 27164562Sgshapiro** SMDB_SETUP_FILE -- Gets db file ready for use. 27264562Sgshapiro** 27364562Sgshapiro** Makes sure permissions on file are safe and creates it if it 27464562Sgshapiro** doesn't exist. 27564562Sgshapiro** 27664562Sgshapiro** Parameters: 27764562Sgshapiro** db_name -- The name of the database without extension. 27864562Sgshapiro** extension -- The extension. 27964562Sgshapiro** sff -- Flags to safefile. 28064562Sgshapiro** mode_mask -- Mode bits that must match. 28164562Sgshapiro** user_info -- Information on the user to use for file 28264562Sgshapiro** permissions. 28364562Sgshapiro** stat_info -- A place to put the stat info for the file. 28464562Sgshapiro** Returns: 28564562Sgshapiro** SMDBE_OK -- Success, otherwise errno. 28664562Sgshapiro*/ 28764562Sgshapiro 28864562Sgshapiroint 28964562Sgshapirosmdb_setup_file(db_name, extension, mode_mask, sff, user_info, stat_info) 29064562Sgshapiro char *db_name; 29164562Sgshapiro char *extension; 29264562Sgshapiro int mode_mask; 29364562Sgshapiro long sff; 29464562Sgshapiro SMDB_USER_INFO *user_info; 29564562Sgshapiro struct stat *stat_info; 29664562Sgshapiro{ 29764562Sgshapiro int st; 29864562Sgshapiro int result; 29964562Sgshapiro char db_file_name[SMDB_MAX_NAME_LEN]; 30064562Sgshapiro 30164562Sgshapiro result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, db_name, 30264562Sgshapiro extension); 30364562Sgshapiro if (result != SMDBE_OK) 30464562Sgshapiro return result; 30564562Sgshapiro 30664562Sgshapiro st = safefile(db_file_name, user_info->smdbu_id, 30764562Sgshapiro user_info->smdbu_group_id, user_info->smdbu_name, 30864562Sgshapiro sff, mode_mask, stat_info); 30964562Sgshapiro if (st != 0) 31064562Sgshapiro return st; 31164562Sgshapiro 31264562Sgshapiro return SMDBE_OK; 31364562Sgshapiro} 31464562Sgshapiro 31564562Sgshapiro/* 31664562Sgshapiro** SMDB_FILECHANGED -- Checks to see if a file changed. 31764562Sgshapiro** 31864562Sgshapiro** Compares the passed in stat_info with a current stat on 31964562Sgshapiro** the passed in file descriptor. Check filechanged for 32064562Sgshapiro** return values. 32164562Sgshapiro** 32264562Sgshapiro** Parameters: 32364562Sgshapiro** db_name -- The name of the database without extension. 32464562Sgshapiro** extension -- The extension. 32564562Sgshapiro** db_fd -- A file descriptor for the database file. 32664562Sgshapiro** stat_info -- An old stat_info. 32764562Sgshapiro** Returns: 32864562Sgshapiro** SMDBE_OK -- Success, otherwise errno. 32964562Sgshapiro*/ 33064562Sgshapiro 33164562Sgshapiroint 33264562Sgshapirosmdb_filechanged(db_name, extension, db_fd, stat_info) 33364562Sgshapiro char *db_name; 33464562Sgshapiro char *extension; 33564562Sgshapiro int db_fd; 33664562Sgshapiro struct stat *stat_info; 33764562Sgshapiro{ 33864562Sgshapiro int result; 33964562Sgshapiro char db_file_name[SMDB_MAX_NAME_LEN]; 34064562Sgshapiro 34164562Sgshapiro result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, db_name, 34264562Sgshapiro extension); 34364562Sgshapiro if (result != SMDBE_OK) 34464562Sgshapiro return result; 34564562Sgshapiro 34664562Sgshapiro result = filechanged(db_file_name, db_fd, stat_info); 34764562Sgshapiro 34864562Sgshapiro return result; 34964562Sgshapiro} 35064562Sgshapiro/* 35164562Sgshapiro** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types. 35264562Sgshapiro** 35364562Sgshapiro** Parameters: 35464562Sgshapiro** None 35564562Sgshapiro** 35664562Sgshapiro** Returns: 35764562Sgshapiro** None 35864562Sgshapiro*/ 35964562Sgshapiro 36064562Sgshapirovoid 36164562Sgshapirosmdb_print_available_types() 36264562Sgshapiro{ 36364562Sgshapiro#ifdef NDBM 36464562Sgshapiro printf("dbm\n"); 36564562Sgshapiro#endif /* NDBM */ 36664562Sgshapiro#ifdef NEWDB 36764562Sgshapiro printf("hash\n"); 36864562Sgshapiro printf("btree\n"); 36964562Sgshapiro#endif /* NEWDB */ 37064562Sgshapiro} 37164562Sgshapiro/* 37264562Sgshapiro** SMDB_DB_DEFINITION -- Given a database type, return database definition 37364562Sgshapiro** 37464562Sgshapiro** Reads though a structure making an association with the database 37564562Sgshapiro** type and the required cpp define from sendmail/README. 37664562Sgshapiro** List size is dynamic and must be NULL terminated. 37764562Sgshapiro** 37864562Sgshapiro** Parameters: 37964562Sgshapiro** type -- The name of the database type. 38064562Sgshapiro** 38164562Sgshapiro** Returns: 38264562Sgshapiro** definition for type, otherwise NULL. 38364562Sgshapiro*/ 38464562Sgshapiro 38564562Sgshapirotypedef struct 38664562Sgshapiro{ 38764562Sgshapiro SMDB_DBTYPE type; 38864562Sgshapiro char *dbdef; 38964562Sgshapiro} dbtype; 39064562Sgshapiro 39164562Sgshapirostatic dbtype DatabaseDefs[] = 39264562Sgshapiro{ 39364562Sgshapiro { SMDB_TYPE_HASH, "NEWDB" }, 39464562Sgshapiro { SMDB_TYPE_BTREE, "NEWDB" }, 39564562Sgshapiro { SMDB_TYPE_NDBM, "NDBM" }, 39664562Sgshapiro { NULL, "OOPS" } 39764562Sgshapiro}; 39864562Sgshapiro 39964562Sgshapirochar * 40064562Sgshapirosmdb_db_definition(type) 40164562Sgshapiro SMDB_DBTYPE type; 40264562Sgshapiro{ 40364562Sgshapiro dbtype *ptr = DatabaseDefs; 40464562Sgshapiro 40564562Sgshapiro while (ptr != NULL && ptr->type != NULL) 40664562Sgshapiro { 40764562Sgshapiro if (strcmp(type, ptr->type) == 0) 40864562Sgshapiro return ptr->dbdef; 40964562Sgshapiro ptr++; 41064562Sgshapiro } 41164562Sgshapiro return NULL; 41264562Sgshapiro} 413