xref: /freebsd/contrib/sendmail/libsmdb/smdb.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
106f25ae9SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro ** Copyright (c) 1999-2002 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro **	All rights reserved.
406f25ae9SGregory Neil Shapiro **
506f25ae9SGregory Neil Shapiro ** By using this file, you agree to the terms and conditions set
606f25ae9SGregory Neil Shapiro ** forth in the LICENSE file which can be found at the top level of
706f25ae9SGregory Neil Shapiro ** the sendmail distribution.
806f25ae9SGregory Neil Shapiro */
906f25ae9SGregory Neil Shapiro 
1040266059SGregory Neil Shapiro #include <sm/gen.h>
114313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: smdb.c,v 8.59 2013-11-22 20:51:49 ca Exp $")
1206f25ae9SGregory Neil Shapiro 
1306f25ae9SGregory Neil Shapiro #include <fcntl.h>
1406f25ae9SGregory Neil Shapiro #include <stdlib.h>
1506f25ae9SGregory Neil Shapiro #include <unistd.h>
1606f25ae9SGregory Neil Shapiro 
1706f25ae9SGregory Neil Shapiro 
1806f25ae9SGregory Neil Shapiro #include <sendmail/sendmail.h>
1906f25ae9SGregory Neil Shapiro #include <libsmdb/smdb.h>
2006f25ae9SGregory Neil Shapiro 
21b6bacd31SGregory Neil Shapiro static bool	smdb_lockfile __P((int, int));
22b6bacd31SGregory Neil Shapiro 
2340266059SGregory Neil Shapiro /*
2406f25ae9SGregory Neil Shapiro **  SMDB_MALLOC_DATABASE -- Allocates a database structure.
2506f25ae9SGregory Neil Shapiro **
2606f25ae9SGregory Neil Shapiro **	Parameters:
2706f25ae9SGregory Neil Shapiro **		None
2806f25ae9SGregory Neil Shapiro **
2906f25ae9SGregory Neil Shapiro **	Returns:
305b0945b5SGregory Neil Shapiro **		A pointer to an allocated SMDB_DATABASE structure or
3106f25ae9SGregory Neil Shapiro **		NULL if it couldn't allocate the memory.
3206f25ae9SGregory Neil Shapiro */
3306f25ae9SGregory Neil Shapiro 
3406f25ae9SGregory Neil Shapiro SMDB_DATABASE *
smdb_malloc_database()3506f25ae9SGregory Neil Shapiro smdb_malloc_database()
3606f25ae9SGregory Neil Shapiro {
3706f25ae9SGregory Neil Shapiro 	SMDB_DATABASE *db;
3806f25ae9SGregory Neil Shapiro 
3906f25ae9SGregory Neil Shapiro 	db = (SMDB_DATABASE *) malloc(sizeof(SMDB_DATABASE));
4006f25ae9SGregory Neil Shapiro 
4106f25ae9SGregory Neil Shapiro 	if (db != NULL)
4240266059SGregory Neil Shapiro 		(void) memset(db, '\0', sizeof(SMDB_DATABASE));
4306f25ae9SGregory Neil Shapiro 
4406f25ae9SGregory Neil Shapiro 	return db;
4506f25ae9SGregory Neil Shapiro }
4606f25ae9SGregory Neil Shapiro 
4740266059SGregory Neil Shapiro /*
4806f25ae9SGregory Neil Shapiro **  SMDB_FREE_DATABASE -- Unallocates a database structure.
4906f25ae9SGregory Neil Shapiro **
5006f25ae9SGregory Neil Shapiro **	Parameters:
5106f25ae9SGregory Neil Shapiro **		database -- a SMDB_DATABASE pointer to deallocate.
5206f25ae9SGregory Neil Shapiro **
5306f25ae9SGregory Neil Shapiro **	Returns:
5406f25ae9SGregory Neil Shapiro **		None
5506f25ae9SGregory Neil Shapiro */
5606f25ae9SGregory Neil Shapiro 
5706f25ae9SGregory Neil Shapiro void
smdb_free_database(database)5806f25ae9SGregory Neil Shapiro smdb_free_database(database)
5906f25ae9SGregory Neil Shapiro 	SMDB_DATABASE *database;
6006f25ae9SGregory Neil Shapiro {
6106f25ae9SGregory Neil Shapiro 	if (database != NULL)
6206f25ae9SGregory Neil Shapiro 		free(database);
6306f25ae9SGregory Neil Shapiro }
645b0945b5SGregory Neil Shapiro 
6540266059SGregory Neil Shapiro /*
6642e5d165SGregory Neil Shapiro **  SMDB_LOCKFILE -- lock a file using flock or (shudder) fcntl locking
6742e5d165SGregory Neil Shapiro **
6842e5d165SGregory Neil Shapiro **	Parameters:
6942e5d165SGregory Neil Shapiro **		fd -- the file descriptor of the file.
7042e5d165SGregory Neil Shapiro **		type -- type of the lock.  Bits can be:
7142e5d165SGregory Neil Shapiro **			LOCK_EX -- exclusive lock.
7242e5d165SGregory Neil Shapiro **			LOCK_NB -- non-blocking.
7342e5d165SGregory Neil Shapiro **
7442e5d165SGregory Neil Shapiro **	Returns:
7540266059SGregory Neil Shapiro **		true if the lock was acquired.
7640266059SGregory Neil Shapiro **		false otherwise.
7742e5d165SGregory Neil Shapiro */
7842e5d165SGregory Neil Shapiro 
7942e5d165SGregory Neil Shapiro static bool
smdb_lockfile(fd,type)8042e5d165SGregory Neil Shapiro smdb_lockfile(fd, type)
8142e5d165SGregory Neil Shapiro 	int fd;
8242e5d165SGregory Neil Shapiro 	int type;
8342e5d165SGregory Neil Shapiro {
8442e5d165SGregory Neil Shapiro 	int i;
8542e5d165SGregory Neil Shapiro 	int save_errno;
8642e5d165SGregory Neil Shapiro #if !HASFLOCK
8742e5d165SGregory Neil Shapiro 	int action;
8842e5d165SGregory Neil Shapiro 	struct flock lfd;
8942e5d165SGregory Neil Shapiro 
9040266059SGregory Neil Shapiro 	(void) memset(&lfd, '\0', sizeof lfd);
9142e5d165SGregory Neil Shapiro 	if (bitset(LOCK_UN, type))
9242e5d165SGregory Neil Shapiro 		lfd.l_type = F_UNLCK;
9342e5d165SGregory Neil Shapiro 	else if (bitset(LOCK_EX, type))
9442e5d165SGregory Neil Shapiro 		lfd.l_type = F_WRLCK;
9542e5d165SGregory Neil Shapiro 	else
9642e5d165SGregory Neil Shapiro 		lfd.l_type = F_RDLCK;
9742e5d165SGregory Neil Shapiro 
9842e5d165SGregory Neil Shapiro 	if (bitset(LOCK_NB, type))
9942e5d165SGregory Neil Shapiro 		action = F_SETLK;
10042e5d165SGregory Neil Shapiro 	else
10142e5d165SGregory Neil Shapiro 		action = F_SETLKW;
10242e5d165SGregory Neil Shapiro 
10342e5d165SGregory Neil Shapiro 	while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
10442e5d165SGregory Neil Shapiro 		continue;
10542e5d165SGregory Neil Shapiro 	if (i >= 0)
10640266059SGregory Neil Shapiro 		return true;
10742e5d165SGregory Neil Shapiro 	save_errno = errno;
10842e5d165SGregory Neil Shapiro 
10942e5d165SGregory Neil Shapiro 	/*
11042e5d165SGregory Neil Shapiro 	**  On SunOS, if you are testing using -oQ/tmp/mqueue or
11142e5d165SGregory Neil Shapiro 	**  -oA/tmp/aliases or anything like that, and /tmp is mounted
11242e5d165SGregory Neil Shapiro 	**  as type "tmp" (that is, served from swap space), the
11342e5d165SGregory Neil Shapiro 	**  previous fcntl will fail with "Invalid argument" errors.
11442e5d165SGregory Neil Shapiro 	**  Since this is fairly common during testing, we will assume
11542e5d165SGregory Neil Shapiro 	**  that this indicates that the lock is successfully grabbed.
11642e5d165SGregory Neil Shapiro 	*/
11742e5d165SGregory Neil Shapiro 
11842e5d165SGregory Neil Shapiro 	if (save_errno == EINVAL)
11940266059SGregory Neil Shapiro 		return true;
12042e5d165SGregory Neil Shapiro 
12142e5d165SGregory Neil Shapiro 	if (!bitset(LOCK_NB, type) ||
12242e5d165SGregory Neil Shapiro 	    (save_errno != EACCES && save_errno != EAGAIN))
12342e5d165SGregory Neil Shapiro 	{
12442e5d165SGregory Neil Shapiro # if 0
125605302a5SGregory Neil Shapiro 		int omode = fcntl(fd, F_GETFL, NULL);
126605302a5SGregory Neil Shapiro 		int euid = (int) geteuid();
127605302a5SGregory Neil Shapiro 
12842e5d165SGregory Neil Shapiro 		syslog(LOG_ERR, "cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
129605302a5SGregory Neil Shapiro 		       filename, ext, fd, type, omode, euid);
13042e5d165SGregory Neil Shapiro # endif /* 0 */
131605302a5SGregory Neil Shapiro 		errno = save_errno;
13240266059SGregory Neil Shapiro 		return false;
13342e5d165SGregory Neil Shapiro 	}
13442e5d165SGregory Neil Shapiro #else /* !HASFLOCK */
13542e5d165SGregory Neil Shapiro 
13642e5d165SGregory Neil Shapiro 	while ((i = flock(fd, type)) < 0 && errno == EINTR)
13742e5d165SGregory Neil Shapiro 		continue;
13842e5d165SGregory Neil Shapiro 	if (i >= 0)
13940266059SGregory Neil Shapiro 		return true;
14042e5d165SGregory Neil Shapiro 	save_errno = errno;
14142e5d165SGregory Neil Shapiro 
14242e5d165SGregory Neil Shapiro 	if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK)
14342e5d165SGregory Neil Shapiro 	{
14442e5d165SGregory Neil Shapiro # if 0
145605302a5SGregory Neil Shapiro 		int omode = fcntl(fd, F_GETFL, NULL);
146605302a5SGregory Neil Shapiro 		int euid = (int) geteuid();
147605302a5SGregory Neil Shapiro 
14842e5d165SGregory Neil Shapiro 		syslog(LOG_ERR, "cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
149605302a5SGregory Neil Shapiro 		       filename, ext, fd, type, omode, euid);
15042e5d165SGregory Neil Shapiro # endif /* 0 */
151605302a5SGregory Neil Shapiro 		errno = save_errno;
15240266059SGregory Neil Shapiro 		return false;
15342e5d165SGregory Neil Shapiro 	}
15442e5d165SGregory Neil Shapiro #endif /* !HASFLOCK */
15542e5d165SGregory Neil Shapiro 	errno = save_errno;
15640266059SGregory Neil Shapiro 	return false;
15742e5d165SGregory Neil Shapiro }
1585b0945b5SGregory Neil Shapiro 
15940266059SGregory Neil Shapiro /*
16006f25ae9SGregory Neil Shapiro **  SMDB_OPEN_DATABASE -- Opens a database.
16106f25ae9SGregory Neil Shapiro **
16206f25ae9SGregory Neil Shapiro **	This opens a database. If type is SMDB_DEFAULT it tries to
1635b0945b5SGregory Neil Shapiro **	use available DB types.  If a specific type is given it will
1645b0945b5SGregory Neil Shapiro **	try to open a database of that type.
16506f25ae9SGregory Neil Shapiro **
16606f25ae9SGregory Neil Shapiro **	Parameters:
1675b0945b5SGregory Neil Shapiro **		database -- A pointer to a SMDB_DATABASE pointer where the
16806f25ae9SGregory Neil Shapiro **			   opened database will be stored. This should
16906f25ae9SGregory Neil Shapiro **			   be unallocated.
17006f25ae9SGregory Neil Shapiro **		db_name -- The name of the database to open. Do not include
17106f25ae9SGregory Neil Shapiro **			  the file name extension.
17206f25ae9SGregory Neil Shapiro **		mode -- The mode to set on the database file or files.
17306f25ae9SGregory Neil Shapiro **		mode_mask -- Mode bits that must match on an opened database.
17406f25ae9SGregory Neil Shapiro **		sff -- Flags to safefile.
17506f25ae9SGregory Neil Shapiro **		type -- The type of database to open. Supported types
17606f25ae9SGregory Neil Shapiro **		       vary depending on what was compiled in.
17706f25ae9SGregory Neil Shapiro **		user_info -- Information on the user to use for file
17806f25ae9SGregory Neil Shapiro **			    permissions.
17906f25ae9SGregory Neil Shapiro **		params -- Params specific to the database being opened.
18006f25ae9SGregory Neil Shapiro **			 Only supports some DB hash options right now
18106f25ae9SGregory Neil Shapiro **			 (see smdb_db_open() for details).
18206f25ae9SGregory Neil Shapiro **
18306f25ae9SGregory Neil Shapiro **	Returns:
18406f25ae9SGregory Neil Shapiro **		SMDBE_OK -- Success.
18506f25ae9SGregory Neil Shapiro **		Anything else is an error. Look up more info about the
18606f25ae9SGregory Neil Shapiro **		error in the comments for the specific open() used.
18706f25ae9SGregory Neil Shapiro */
18806f25ae9SGregory Neil Shapiro 
1895b0945b5SGregory Neil Shapiro struct type2func_s
1905b0945b5SGregory Neil Shapiro {
1915b0945b5SGregory Neil Shapiro 	const char	*t2f_type;
1925b0945b5SGregory Neil Shapiro 	smdb_open_func	*t2f_open_fun;
1935b0945b5SGregory Neil Shapiro };
1945b0945b5SGregory Neil Shapiro typedef struct type2func_s type2func_t;
1955b0945b5SGregory Neil Shapiro static type2func_t type2func[] = {
1965b0945b5SGregory Neil Shapiro 	{ SMDB_TYPE_HASH, smdb_db_open	},
1975b0945b5SGregory Neil Shapiro 	{ SMDB_TYPE_BTREE, smdb_db_open	},
1985b0945b5SGregory Neil Shapiro 	{ SMDB_TYPE_NDBM, smdb_ndbm_open},
1995b0945b5SGregory Neil Shapiro 	{ SMDB_TYPE_CDB, smdb_cdb_open },
2005b0945b5SGregory Neil Shapiro 	{ NULL, NULL }
2015b0945b5SGregory Neil Shapiro };
2025b0945b5SGregory Neil Shapiro 
20306f25ae9SGregory Neil Shapiro int
smdb_open_database(database,db_name,mode,mode_mask,sff,type,user_info,params)20406f25ae9SGregory Neil Shapiro smdb_open_database(database, db_name, mode, mode_mask, sff, type, user_info,
20506f25ae9SGregory Neil Shapiro 		   params)
20606f25ae9SGregory Neil Shapiro 	SMDB_DATABASE **database;
20706f25ae9SGregory Neil Shapiro 	char *db_name;
20806f25ae9SGregory Neil Shapiro 	int mode;
20906f25ae9SGregory Neil Shapiro 	int mode_mask;
21006f25ae9SGregory Neil Shapiro 	long sff;
21106f25ae9SGregory Neil Shapiro 	SMDB_DBTYPE type;
21206f25ae9SGregory Neil Shapiro 	SMDB_USER_INFO *user_info;
21306f25ae9SGregory Neil Shapiro 	SMDB_DBPARAMS *params;
21406f25ae9SGregory Neil Shapiro {
2155b0945b5SGregory Neil Shapiro 	bool type_was_default;
2165b0945b5SGregory Neil Shapiro 	int result, i;
2175b0945b5SGregory Neil Shapiro 	const char *smdb_type;
2185b0945b5SGregory Neil Shapiro 	smdb_open_func *smdb_open_fun;
21906f25ae9SGregory Neil Shapiro 
2205b0945b5SGregory Neil Shapiro 	result = SMDBE_UNSUPPORTED_DB_TYPE;
2215b0945b5SGregory Neil Shapiro 	type_was_default = SMDB_IS_TYPE_DEFAULT(type);
2225b0945b5SGregory Neil Shapiro 	for (i = 0; (smdb_type = type2func[i].t2f_type) != NULL; i++)
22306f25ae9SGregory Neil Shapiro 	{
2245b0945b5SGregory Neil Shapiro 		if (!type_was_default && strcmp(type, smdb_type) != 0)
2255b0945b5SGregory Neil Shapiro 			continue;
2265b0945b5SGregory Neil Shapiro 		smdb_open_fun = type2func[i].t2f_open_fun;
2275b0945b5SGregory Neil Shapiro 		if (smdb_open_fun == NULL)
22806f25ae9SGregory Neil Shapiro 		{
2295b0945b5SGregory Neil Shapiro 			if (type_was_default)
2305b0945b5SGregory Neil Shapiro 				continue;
23106f25ae9SGregory Neil Shapiro 			else
23206f25ae9SGregory Neil Shapiro 				return SMDBE_UNSUPPORTED_DB_TYPE;
23306f25ae9SGregory Neil Shapiro 		}
2345b0945b5SGregory Neil Shapiro 		result = (*smdb_open_fun)(database, db_name, mode, mode_mask, sff,
2355b0945b5SGregory Neil Shapiro 					(char *)smdb_type, user_info, params);
2365b0945b5SGregory Neil Shapiro 		if (!((result == ENOENT
2375b0945b5SGregory Neil Shapiro 			|| result == EINVAL
2385b0945b5SGregory Neil Shapiro #ifdef EFTYPE
2395b0945b5SGregory Neil Shapiro 			|| result == EFTYPE
2405b0945b5SGregory Neil Shapiro #endif
2415b0945b5SGregory Neil Shapiro 		       )
2425b0945b5SGregory Neil Shapiro 		    && type_was_default))
2435b0945b5SGregory Neil Shapiro 			goto ret;
24406f25ae9SGregory Neil Shapiro 	}
24506f25ae9SGregory Neil Shapiro 	return SMDBE_UNKNOWN_DB_TYPE;
2465b0945b5SGregory Neil Shapiro 
2475b0945b5SGregory Neil Shapiro   ret:
2485b0945b5SGregory Neil Shapiro 	return result;
24906f25ae9SGregory Neil Shapiro }
2505b0945b5SGregory Neil Shapiro 
25140266059SGregory Neil Shapiro /*
25206f25ae9SGregory Neil Shapiro **  SMDB_ADD_EXTENSION -- Adds an extension to a file name.
25306f25ae9SGregory Neil Shapiro **
25406f25ae9SGregory Neil Shapiro **	Just adds a . followed by a string to a db_name if there
25506f25ae9SGregory Neil Shapiro **	is room and the db_name does not already have that extension.
25606f25ae9SGregory Neil Shapiro **
25706f25ae9SGregory Neil Shapiro **	Parameters:
25806f25ae9SGregory Neil Shapiro **		full_name -- The final file name.
25906f25ae9SGregory Neil Shapiro **		max_full_name_len -- The max length for full_name.
26006f25ae9SGregory Neil Shapiro **		db_name -- The name of the db.
26106f25ae9SGregory Neil Shapiro **		extension -- The extension to add.
26206f25ae9SGregory Neil Shapiro **
26306f25ae9SGregory Neil Shapiro **	Returns:
26406f25ae9SGregory Neil Shapiro **		SMDBE_OK -- Success.
26506f25ae9SGregory Neil Shapiro **		Anything else is an error. Look up more info about the
26606f25ae9SGregory Neil Shapiro **		error in the comments for the specific open() used.
26706f25ae9SGregory Neil Shapiro */
26806f25ae9SGregory Neil Shapiro 
26906f25ae9SGregory Neil Shapiro int
smdb_add_extension(full_name,max_full_name_len,db_name,extension)27006f25ae9SGregory Neil Shapiro smdb_add_extension(full_name, max_full_name_len, db_name, extension)
27106f25ae9SGregory Neil Shapiro 	char *full_name;
27206f25ae9SGregory Neil Shapiro 	int max_full_name_len;
27306f25ae9SGregory Neil Shapiro 	char *db_name;
27406f25ae9SGregory Neil Shapiro 	char *extension;
27506f25ae9SGregory Neil Shapiro {
27606f25ae9SGregory Neil Shapiro 	int extension_len;
27706f25ae9SGregory Neil Shapiro 	int db_name_len;
27806f25ae9SGregory Neil Shapiro 
27906f25ae9SGregory Neil Shapiro 	if (full_name == NULL || db_name == NULL || extension == NULL)
28006f25ae9SGregory Neil Shapiro 		return SMDBE_INVALID_PARAMETER;
28106f25ae9SGregory Neil Shapiro 
28206f25ae9SGregory Neil Shapiro 	extension_len = strlen(extension);
28306f25ae9SGregory Neil Shapiro 	db_name_len = strlen(db_name);
28406f25ae9SGregory Neil Shapiro 
28506f25ae9SGregory Neil Shapiro 	if (extension_len + db_name_len + 2 > max_full_name_len)
28606f25ae9SGregory Neil Shapiro 		return SMDBE_DB_NAME_TOO_LONG;
28706f25ae9SGregory Neil Shapiro 
28806f25ae9SGregory Neil Shapiro 	if (db_name_len < extension_len + 1 ||
28906f25ae9SGregory Neil Shapiro 	    db_name[db_name_len - extension_len - 1] != '.' ||
29006f25ae9SGregory Neil Shapiro 	    strcmp(&db_name[db_name_len - extension_len], extension) != 0)
29140266059SGregory Neil Shapiro 		(void) sm_snprintf(full_name, max_full_name_len, "%s.%s",
29240266059SGregory Neil Shapiro 				   db_name, extension);
29306f25ae9SGregory Neil Shapiro 	else
29440266059SGregory Neil Shapiro 		(void) sm_strlcpy(full_name, db_name, max_full_name_len);
29506f25ae9SGregory Neil Shapiro 
29606f25ae9SGregory Neil Shapiro 	return SMDBE_OK;
29706f25ae9SGregory Neil Shapiro }
29840266059SGregory Neil Shapiro /*
29906f25ae9SGregory Neil Shapiro **  SMDB_LOCK_FILE -- Locks the database file.
30006f25ae9SGregory Neil Shapiro **
30106f25ae9SGregory Neil Shapiro **	Locks the actual database file.
30206f25ae9SGregory Neil Shapiro **
30306f25ae9SGregory Neil Shapiro **	Parameters:
30406f25ae9SGregory Neil Shapiro **		lock_fd -- The resulting descriptor for the locked file.
30506f25ae9SGregory Neil Shapiro **		db_name -- The name of the database without extension.
30606f25ae9SGregory Neil Shapiro **		mode -- The open mode.
30706f25ae9SGregory Neil Shapiro **		sff -- Flags to safefile.
30806f25ae9SGregory Neil Shapiro **		extension -- The extension for the file.
30906f25ae9SGregory Neil Shapiro **
31006f25ae9SGregory Neil Shapiro **	Returns:
31106f25ae9SGregory Neil Shapiro **		SMDBE_OK -- Success, otherwise errno.
31206f25ae9SGregory Neil Shapiro */
31306f25ae9SGregory Neil Shapiro 
31406f25ae9SGregory Neil Shapiro int
smdb_lock_file(lock_fd,db_name,mode,sff,extension)31506f25ae9SGregory Neil Shapiro smdb_lock_file(lock_fd, db_name, mode, sff, extension)
31606f25ae9SGregory Neil Shapiro 	int *lock_fd;
31706f25ae9SGregory Neil Shapiro 	char *db_name;
31806f25ae9SGregory Neil Shapiro 	int mode;
31906f25ae9SGregory Neil Shapiro 	long sff;
32006f25ae9SGregory Neil Shapiro 	char *extension;
32106f25ae9SGregory Neil Shapiro {
32206f25ae9SGregory Neil Shapiro 	int result;
32394c01205SGregory Neil Shapiro 	char file_name[MAXPATHLEN];
32406f25ae9SGregory Neil Shapiro 
32594c01205SGregory Neil Shapiro 	result = smdb_add_extension(file_name, sizeof file_name, db_name,
32606f25ae9SGregory Neil Shapiro 				    extension);
32706f25ae9SGregory Neil Shapiro 	if (result != SMDBE_OK)
32806f25ae9SGregory Neil Shapiro 		return result;
32906f25ae9SGregory Neil Shapiro 
33094c01205SGregory Neil Shapiro 	*lock_fd = safeopen(file_name, mode & ~O_TRUNC, DBMMODE, sff);
33106f25ae9SGregory Neil Shapiro 	if (*lock_fd < 0)
33206f25ae9SGregory Neil Shapiro 		return errno;
33306f25ae9SGregory Neil Shapiro 
33406f25ae9SGregory Neil Shapiro 	return SMDBE_OK;
33506f25ae9SGregory Neil Shapiro }
336*d39bd2c1SGregory Neil Shapiro 
33740266059SGregory Neil Shapiro /*
338*d39bd2c1SGregory Neil Shapiro **  SMDB_UNLOCK_FILE -- Unlocks a file - via close()
33906f25ae9SGregory Neil Shapiro **
34006f25ae9SGregory Neil Shapiro **	Parameters:
34106f25ae9SGregory Neil Shapiro **		lock_fd -- The descriptor for the locked file.
34206f25ae9SGregory Neil Shapiro **
34306f25ae9SGregory Neil Shapiro **	Returns:
34406f25ae9SGregory Neil Shapiro **		SMDBE_OK -- Success, otherwise errno.
34506f25ae9SGregory Neil Shapiro */
34606f25ae9SGregory Neil Shapiro 
34706f25ae9SGregory Neil Shapiro int
smdb_unlock_file(lock_fd)34806f25ae9SGregory Neil Shapiro smdb_unlock_file(lock_fd)
34906f25ae9SGregory Neil Shapiro 	int lock_fd;
35006f25ae9SGregory Neil Shapiro {
35106f25ae9SGregory Neil Shapiro 	int result;
35206f25ae9SGregory Neil Shapiro 
35306f25ae9SGregory Neil Shapiro 	result = close(lock_fd);
35406f25ae9SGregory Neil Shapiro 	if (result != 0)
35506f25ae9SGregory Neil Shapiro 		return errno;
35606f25ae9SGregory Neil Shapiro 
35706f25ae9SGregory Neil Shapiro 	return SMDBE_OK;
35806f25ae9SGregory Neil Shapiro }
35940266059SGregory Neil Shapiro /*
36042e5d165SGregory Neil Shapiro **  SMDB_LOCK_MAP -- Locks a database.
36142e5d165SGregory Neil Shapiro **
36242e5d165SGregory Neil Shapiro **	Parameters:
36342e5d165SGregory Neil Shapiro **		database -- database description.
36442e5d165SGregory Neil Shapiro **		type -- type of the lock.  Bits can be:
36542e5d165SGregory Neil Shapiro **			LOCK_EX -- exclusive lock.
36642e5d165SGregory Neil Shapiro **			LOCK_NB -- non-blocking.
36742e5d165SGregory Neil Shapiro **
36842e5d165SGregory Neil Shapiro **	Returns:
36942e5d165SGregory Neil Shapiro **		SMDBE_OK -- Success, otherwise errno.
37042e5d165SGregory Neil Shapiro */
37142e5d165SGregory Neil Shapiro 
37242e5d165SGregory Neil Shapiro int
smdb_lock_map(database,type)37342e5d165SGregory Neil Shapiro smdb_lock_map(database, type)
37442e5d165SGregory Neil Shapiro 	SMDB_DATABASE *database;
37542e5d165SGregory Neil Shapiro 	int type;
37642e5d165SGregory Neil Shapiro {
37742e5d165SGregory Neil Shapiro 	int fd;
37842e5d165SGregory Neil Shapiro 
37942e5d165SGregory Neil Shapiro 	fd = database->smdb_lockfd(database);
38042e5d165SGregory Neil Shapiro 	if (fd < 0)
38142e5d165SGregory Neil Shapiro 		return SMDBE_NOT_FOUND;
38242e5d165SGregory Neil Shapiro 	if (!smdb_lockfile(fd, type))
38342e5d165SGregory Neil Shapiro 		return SMDBE_LOCK_NOT_GRANTED;
38442e5d165SGregory Neil Shapiro 	return SMDBE_OK;
38542e5d165SGregory Neil Shapiro }
38640266059SGregory Neil Shapiro /*
38742e5d165SGregory Neil Shapiro **  SMDB_UNLOCK_MAP -- Unlocks a database
38842e5d165SGregory Neil Shapiro **
38942e5d165SGregory Neil Shapiro **	Parameters:
39042e5d165SGregory Neil Shapiro **		database -- database description.
39142e5d165SGregory Neil Shapiro **
39242e5d165SGregory Neil Shapiro **	Returns:
39342e5d165SGregory Neil Shapiro **		SMDBE_OK -- Success, otherwise errno.
39442e5d165SGregory Neil Shapiro */
39542e5d165SGregory Neil Shapiro 
39642e5d165SGregory Neil Shapiro int
smdb_unlock_map(database)39742e5d165SGregory Neil Shapiro smdb_unlock_map(database)
39842e5d165SGregory Neil Shapiro 	SMDB_DATABASE *database;
39942e5d165SGregory Neil Shapiro {
40042e5d165SGregory Neil Shapiro 	int fd;
40142e5d165SGregory Neil Shapiro 
40242e5d165SGregory Neil Shapiro 	fd = database->smdb_lockfd(database);
40342e5d165SGregory Neil Shapiro 	if (fd < 0)
40442e5d165SGregory Neil Shapiro 		return SMDBE_NOT_FOUND;
40542e5d165SGregory Neil Shapiro 	if (!smdb_lockfile(fd, LOCK_UN))
40642e5d165SGregory Neil Shapiro 		return SMDBE_LOCK_NOT_HELD;
40742e5d165SGregory Neil Shapiro 	return SMDBE_OK;
40842e5d165SGregory Neil Shapiro }
40940266059SGregory Neil Shapiro /*
41006f25ae9SGregory Neil Shapiro **  SMDB_SETUP_FILE -- Gets db file ready for use.
41106f25ae9SGregory Neil Shapiro **
41206f25ae9SGregory Neil Shapiro **	Makes sure permissions on file are safe and creates it if it
41306f25ae9SGregory Neil Shapiro **	doesn't exist.
41406f25ae9SGregory Neil Shapiro **
41506f25ae9SGregory Neil Shapiro **	Parameters:
41606f25ae9SGregory Neil Shapiro **		db_name -- The name of the database without extension.
41706f25ae9SGregory Neil Shapiro **		extension -- The extension.
41806f25ae9SGregory Neil Shapiro **		sff -- Flags to safefile.
41906f25ae9SGregory Neil Shapiro **		mode_mask -- Mode bits that must match.
42006f25ae9SGregory Neil Shapiro **		user_info -- Information on the user to use for file
42106f25ae9SGregory Neil Shapiro **			    permissions.
42206f25ae9SGregory Neil Shapiro **		stat_info -- A place to put the stat info for the file.
42306f25ae9SGregory Neil Shapiro **	Returns:
42406f25ae9SGregory Neil Shapiro **		SMDBE_OK -- Success, otherwise errno.
42506f25ae9SGregory Neil Shapiro */
42606f25ae9SGregory Neil Shapiro 
42706f25ae9SGregory Neil Shapiro int
smdb_setup_file(db_name,extension,mode_mask,sff,user_info,stat_info)42806f25ae9SGregory Neil Shapiro smdb_setup_file(db_name, extension, mode_mask, sff, user_info, stat_info)
42906f25ae9SGregory Neil Shapiro 	char *db_name;
43006f25ae9SGregory Neil Shapiro 	char *extension;
43106f25ae9SGregory Neil Shapiro 	int mode_mask;
43206f25ae9SGregory Neil Shapiro 	long sff;
43306f25ae9SGregory Neil Shapiro 	SMDB_USER_INFO *user_info;
43406f25ae9SGregory Neil Shapiro 	struct stat *stat_info;
43506f25ae9SGregory Neil Shapiro {
43606f25ae9SGregory Neil Shapiro 	int st;
43706f25ae9SGregory Neil Shapiro 	int result;
43894c01205SGregory Neil Shapiro 	char db_file_name[MAXPATHLEN];
43906f25ae9SGregory Neil Shapiro 
44094c01205SGregory Neil Shapiro 	result = smdb_add_extension(db_file_name, sizeof db_file_name, db_name,
44106f25ae9SGregory Neil Shapiro 				    extension);
44206f25ae9SGregory Neil Shapiro 	if (result != SMDBE_OK)
44306f25ae9SGregory Neil Shapiro 		return result;
44406f25ae9SGregory Neil Shapiro 
44506f25ae9SGregory Neil Shapiro 	st = safefile(db_file_name, user_info->smdbu_id,
44606f25ae9SGregory Neil Shapiro 		      user_info->smdbu_group_id, user_info->smdbu_name,
44706f25ae9SGregory Neil Shapiro 		      sff, mode_mask, stat_info);
44806f25ae9SGregory Neil Shapiro 	if (st != 0)
44906f25ae9SGregory Neil Shapiro 		return st;
45006f25ae9SGregory Neil Shapiro 
45106f25ae9SGregory Neil Shapiro 	return SMDBE_OK;
45206f25ae9SGregory Neil Shapiro }
45340266059SGregory Neil Shapiro /*
45406f25ae9SGregory Neil Shapiro **  SMDB_FILECHANGED -- Checks to see if a file changed.
45506f25ae9SGregory Neil Shapiro **
45606f25ae9SGregory Neil Shapiro **	Compares the passed in stat_info with a current stat on
45706f25ae9SGregory Neil Shapiro **	the passed in file descriptor. Check filechanged for
45806f25ae9SGregory Neil Shapiro **	return values.
45906f25ae9SGregory Neil Shapiro **
46006f25ae9SGregory Neil Shapiro **	Parameters:
46106f25ae9SGregory Neil Shapiro **		db_name -- The name of the database without extension.
46206f25ae9SGregory Neil Shapiro **		extension -- The extension.
46306f25ae9SGregory Neil Shapiro **		db_fd -- A file descriptor for the database file.
46406f25ae9SGregory Neil Shapiro **		stat_info -- An old stat_info.
46506f25ae9SGregory Neil Shapiro **	Returns:
46606f25ae9SGregory Neil Shapiro **		SMDBE_OK -- Success, otherwise errno.
46706f25ae9SGregory Neil Shapiro */
46806f25ae9SGregory Neil Shapiro 
46906f25ae9SGregory Neil Shapiro int
smdb_filechanged(db_name,extension,db_fd,stat_info)47006f25ae9SGregory Neil Shapiro smdb_filechanged(db_name, extension, db_fd, stat_info)
47106f25ae9SGregory Neil Shapiro 	char *db_name;
47206f25ae9SGregory Neil Shapiro 	char *extension;
47306f25ae9SGregory Neil Shapiro 	int db_fd;
47406f25ae9SGregory Neil Shapiro 	struct stat *stat_info;
47506f25ae9SGregory Neil Shapiro {
47606f25ae9SGregory Neil Shapiro 	int result;
47794c01205SGregory Neil Shapiro 	char db_file_name[MAXPATHLEN];
47806f25ae9SGregory Neil Shapiro 
47994c01205SGregory Neil Shapiro 	result = smdb_add_extension(db_file_name, sizeof db_file_name, db_name,
48006f25ae9SGregory Neil Shapiro 				    extension);
48106f25ae9SGregory Neil Shapiro 	if (result != SMDBE_OK)
48206f25ae9SGregory Neil Shapiro 		return result;
48340266059SGregory Neil Shapiro 	return filechanged(db_file_name, db_fd, stat_info);
48406f25ae9SGregory Neil Shapiro }
4855b0945b5SGregory Neil Shapiro 
48640266059SGregory Neil Shapiro /*
48706f25ae9SGregory Neil Shapiro **  SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types.
48806f25ae9SGregory Neil Shapiro **
48906f25ae9SGregory Neil Shapiro **	Parameters:
490*d39bd2c1SGregory Neil Shapiro **		ext - also show extension?
49106f25ae9SGregory Neil Shapiro **
49206f25ae9SGregory Neil Shapiro **	Returns:
49306f25ae9SGregory Neil Shapiro **		None
49406f25ae9SGregory Neil Shapiro */
49506f25ae9SGregory Neil Shapiro 
49606f25ae9SGregory Neil Shapiro void
smdb_print_available_types(ext)4975b0945b5SGregory Neil Shapiro smdb_print_available_types(ext)
4985b0945b5SGregory Neil Shapiro 	bool ext;
49906f25ae9SGregory Neil Shapiro {
5005b0945b5SGregory Neil Shapiro # define PEXT1	((ext) ? ":" : "")
5015b0945b5SGregory Neil Shapiro # define PEXT2(x)	((ext) ? x : "")
5025b0945b5SGregory Neil Shapiro 
5035b0945b5SGregory Neil Shapiro #if NDBM
5045b0945b5SGregory Neil Shapiro 	printf("%s%s%s\n", SMDB_TYPE_NDBM, PEXT1, PEXT2(SMNDB_DIR_FILE_EXTENSION));
5055b0945b5SGregory Neil Shapiro #endif
5065b0945b5SGregory Neil Shapiro #if NEWDB
5075b0945b5SGregory Neil Shapiro /* # if SMDB1_FILE_EXTENSION == SMDB2_FILE_EXTENSION */
5085b0945b5SGregory Neil Shapiro 	printf("%s%s%s\n", SMDB_TYPE_HASH, PEXT1, PEXT2(SMDB1_FILE_EXTENSION));
5095b0945b5SGregory Neil Shapiro 	printf("%s%s%s\n", SMDB_TYPE_BTREE, PEXT1, PEXT2(SMDB1_FILE_EXTENSION));
5105b0945b5SGregory Neil Shapiro #endif
5115b0945b5SGregory Neil Shapiro #if CDB
5125b0945b5SGregory Neil Shapiro 	printf("%s%s%s\n", SMDB_TYPE_CDB, PEXT1, PEXT2(SMCDB_FILE_EXTENSION));
5135b0945b5SGregory Neil Shapiro #endif
5145b0945b5SGregory Neil Shapiro #ifdef SMDB_TYPE_IMPL
5155b0945b5SGregory Neil Shapiro 	printf("%s%s%s\n", SMDB_TYPE_IMPL, PEXT1, "");
5165b0945b5SGregory Neil Shapiro #endif
51706f25ae9SGregory Neil Shapiro }
5185b0945b5SGregory Neil Shapiro 
5195b0945b5SGregory Neil Shapiro /*
5205b0945b5SGregory Neil Shapiro **  SMDB_IS_DB_TYPE -- Does a name match an available DB type?
5215b0945b5SGregory Neil Shapiro **
5225b0945b5SGregory Neil Shapiro **	Parameters:
5235b0945b5SGregory Neil Shapiro **		type -- The name of the database type.
5245b0945b5SGregory Neil Shapiro **
5255b0945b5SGregory Neil Shapiro **	Returns:
5265b0945b5SGregory Neil Shapiro **		true iff match
5275b0945b5SGregory Neil Shapiro */
5285b0945b5SGregory Neil Shapiro 
5295b0945b5SGregory Neil Shapiro bool
smdb_is_db_type(db_type)5305b0945b5SGregory Neil Shapiro smdb_is_db_type(db_type)
5315b0945b5SGregory Neil Shapiro 	const char *db_type;
5325b0945b5SGregory Neil Shapiro {
5335b0945b5SGregory Neil Shapiro #if NDBM
5345b0945b5SGregory Neil Shapiro 	if (strcmp(db_type, SMDB_TYPE_NDBM) == 0)
5355b0945b5SGregory Neil Shapiro 		return true;
5365b0945b5SGregory Neil Shapiro #endif
5375b0945b5SGregory Neil Shapiro #if NEWDB
5385b0945b5SGregory Neil Shapiro 	if (strcmp(db_type, SMDB_TYPE_HASH) == 0)
5395b0945b5SGregory Neil Shapiro 		return true;
5405b0945b5SGregory Neil Shapiro 	if (strcmp(db_type, SMDB_TYPE_BTREE) == 0)
5415b0945b5SGregory Neil Shapiro 		return true;
5425b0945b5SGregory Neil Shapiro #endif
5435b0945b5SGregory Neil Shapiro #if CDB
5445b0945b5SGregory Neil Shapiro 	if (strcmp(db_type, SMDB_TYPE_CDB) == 0)
5455b0945b5SGregory Neil Shapiro 		return true;
5465b0945b5SGregory Neil Shapiro #endif
5475b0945b5SGregory Neil Shapiro 	return false;
5485b0945b5SGregory Neil Shapiro }
5495b0945b5SGregory Neil Shapiro 
5505b0945b5SGregory Neil Shapiro 
55140266059SGregory Neil Shapiro /*
55206f25ae9SGregory Neil Shapiro **  SMDB_DB_DEFINITION -- Given a database type, return database definition
55306f25ae9SGregory Neil Shapiro **
55406f25ae9SGregory Neil Shapiro **	Reads though a structure making an association with the database
55506f25ae9SGregory Neil Shapiro **	type and the required cpp define from sendmail/README.
55606f25ae9SGregory Neil Shapiro **	List size is dynamic and must be NULL terminated.
55706f25ae9SGregory Neil Shapiro **
55806f25ae9SGregory Neil Shapiro **	Parameters:
55906f25ae9SGregory Neil Shapiro **		type -- The name of the database type.
56006f25ae9SGregory Neil Shapiro **
56106f25ae9SGregory Neil Shapiro **	Returns:
56206f25ae9SGregory Neil Shapiro **		definition for type, otherwise NULL.
56306f25ae9SGregory Neil Shapiro */
56406f25ae9SGregory Neil Shapiro 
56506f25ae9SGregory Neil Shapiro typedef struct
56606f25ae9SGregory Neil Shapiro {
56706f25ae9SGregory Neil Shapiro 	SMDB_DBTYPE type;
56806f25ae9SGregory Neil Shapiro 	char *dbdef;
56906f25ae9SGregory Neil Shapiro } dbtype;
57006f25ae9SGregory Neil Shapiro 
57106f25ae9SGregory Neil Shapiro static dbtype DatabaseDefs[] =
57206f25ae9SGregory Neil Shapiro {
57306f25ae9SGregory Neil Shapiro 	{ SMDB_TYPE_HASH,	"NEWDB" },
57406f25ae9SGregory Neil Shapiro 	{ SMDB_TYPE_BTREE,	"NEWDB" },
57506f25ae9SGregory Neil Shapiro 	{ SMDB_TYPE_NDBM,	"NDBM"	},
5765b0945b5SGregory Neil Shapiro 	{ SMDB_TYPE_CDB,	"CDB"	},
57706f25ae9SGregory Neil Shapiro 	{ NULL,			"OOPS"	}
57806f25ae9SGregory Neil Shapiro };
57906f25ae9SGregory Neil Shapiro 
58006f25ae9SGregory Neil Shapiro char *
smdb_db_definition(type)58106f25ae9SGregory Neil Shapiro smdb_db_definition(type)
58206f25ae9SGregory Neil Shapiro 	SMDB_DBTYPE type;
58306f25ae9SGregory Neil Shapiro {
58406f25ae9SGregory Neil Shapiro 	dbtype *ptr = DatabaseDefs;
58506f25ae9SGregory Neil Shapiro 
58606f25ae9SGregory Neil Shapiro 	while (ptr != NULL && ptr->type != NULL)
58706f25ae9SGregory Neil Shapiro 	{
58806f25ae9SGregory Neil Shapiro 		if (strcmp(type, ptr->type) == 0)
58906f25ae9SGregory Neil Shapiro 			return ptr->dbdef;
59006f25ae9SGregory Neil Shapiro 		ptr++;
59106f25ae9SGregory Neil Shapiro 	}
59206f25ae9SGregory Neil Shapiro 	return NULL;
59306f25ae9SGregory Neil Shapiro }
594