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