smdb1.c revision 261363
1246074Sgabor/*
2246074Sgabor** Copyright (c) 1999-2002, 2004, 2009 Proofpoint, Inc. and its suppliers.
3246074Sgabor**	All rights reserved.
4246074Sgabor**
5246074Sgabor** By using this file, you agree to the terms and conditions set
6246074Sgabor** forth in the LICENSE file which can be found at the top level of
7246074Sgabor** the sendmail distribution.
8246074Sgabor*/
9246074Sgabor
10246074Sgabor#include <sm/gen.h>
11246074SgaborSM_RCSID("@(#)$Id: smdb1.c,v 8.63 2013/11/22 20:51:49 ca Exp $")
12246074Sgabor
13246074Sgabor#include <unistd.h>
14246074Sgabor#include <stdlib.h>
15246074Sgabor#include <fcntl.h>
16246074Sgabor
17246074Sgabor#include <sendmail/sendmail.h>
18246074Sgabor#include <libsmdb/smdb.h>
19246074Sgabor
20246074Sgabor#if (DB_VERSION_MAJOR == 1)
21246074Sgabor
22246074Sgabor# define SMDB1_FILE_EXTENSION "db"
23246074Sgabor
24246074Sgaborstruct smdb_db1_struct
25246074Sgabor{
26246091Sdelphij	DB	*smdb1_db;
27246091Sdelphij	int	smdb1_lock_fd;
28246074Sgabor	bool	smdb1_cursor_in_use;
29246074Sgabor};
30246074Sgabortypedef struct smdb_db1_struct SMDB_DB1_DATABASE;
31246074Sgabor
32246074Sgaborstruct smdb_db1_cursor
33246074Sgabor{
34285976Sdelphij	SMDB_DB1_DATABASE	*db;
35246074Sgabor};
36246074Sgabortypedef struct smdb_db1_cursor SMDB_DB1_CURSOR;
37285976Sdelphij
38246074Sgaborstatic DBTYPE		smdb_type_to_db1_type __P((SMDB_DBTYPE));
39287223Sdelphijstatic unsigned int	smdb_put_flags_to_db1_flags __P((SMDB_FLAG));
40287223Sdelphijstatic int		smdb_cursor_get_flags_to_smdb1 __P((SMDB_FLAG));
41246074Sgaborstatic SMDB_DB1_DATABASE *smdb1_malloc_database __P((void));
42287223Sdelphijstatic int		smdb1_close __P((SMDB_DATABASE *));
43246074Sgaborstatic int		smdb1_del __P((SMDB_DATABASE *, SMDB_DBENT *, unsigned int));
44246074Sgaborstatic int		smdb1_fd __P((SMDB_DATABASE *, int *));
45246074Sgaborstatic int		smdb1_lockfd __P((SMDB_DATABASE *));
46246074Sgaborstatic int		smdb1_get __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
47246074Sgaborstatic int		smdb1_put __P((SMDB_DATABASE *, SMDB_DBENT *, SMDB_DBENT *, unsigned int));
48246074Sgaborstatic int		smdb1_set_owner __P((SMDB_DATABASE *, uid_t, gid_t));
49246074Sgaborstatic int		smdb1_sync __P((SMDB_DATABASE *, unsigned int));
50246074Sgaborstatic int		smdb1_cursor_close __P((SMDB_CURSOR *));
51246074Sgaborstatic int		smdb1_cursor_del __P((SMDB_CURSOR *, unsigned int));
52246074Sgaborstatic int		smdb1_cursor_get __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
53246074Sgaborstatic int		smdb1_cursor_put __P((SMDB_CURSOR *, SMDB_DBENT *, SMDB_DBENT *, SMDB_FLAG));
54246074Sgaborstatic int		smdb1_cursor __P((SMDB_DATABASE *, SMDB_CURSOR **, unsigned int));
55246074Sgabor
56246074Sgabor/*
57246074Sgabor**  SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type.
58246074Sgabor**
59246074Sgabor**	Parameters:
60246074Sgabor**		type -- The type to translate.
61246074Sgabor**
62246074Sgabor**	Returns:
63246074Sgabor**		The DB1 type that corresponsds to the passed in SMDB type.
64246074Sgabor**		Returns -1 if there is no equivalent type.
65246074Sgabor**
66246074Sgabor*/
67246074Sgabor
68246074Sgaborstatic DBTYPE
69246074Sgaborsmdb_type_to_db1_type(type)
70246074Sgabor	SMDB_DBTYPE type;
71246074Sgabor{
72246074Sgabor	if (type == SMDB_TYPE_DEFAULT)
73246074Sgabor		return DB_HASH;
74246074Sgabor
75246074Sgabor	if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
76246074Sgabor		return DB_HASH;
77246074Sgabor
78246074Sgabor	if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
79246074Sgabor		return DB_BTREE;
80246074Sgabor
81246074Sgabor	/* Should never get here thanks to test in smdb_db_open() */
82246074Sgabor	return DB_HASH;
83246074Sgabor}
84246074Sgabor/*
85246074Sgabor**  SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags.
86246074Sgabor**
87246074Sgabor**	Parameters:
88246074Sgabor**		flags -- The flags to translate.
89246074Sgabor**
90246074Sgabor**	Returns:
91246074Sgabor**		The db1 flags that are equivalent to the smdb flags.
92246074Sgabor**
93246074Sgabor**	Notes:
94246074Sgabor**		Any invalid flags are ignored.
95246074Sgabor**
96246074Sgabor*/
97246074Sgabor
98246074Sgaborstatic unsigned int
99246074Sgaborsmdb_put_flags_to_db1_flags(flags)
100246074Sgabor	SMDB_FLAG flags;
101246074Sgabor{
102246074Sgabor	int return_flags;
103246074Sgabor
104246074Sgabor	return_flags = 0;
105246074Sgabor
106246074Sgabor	if (bitset(SMDBF_NO_OVERWRITE, flags))
107246074Sgabor		return_flags |= R_NOOVERWRITE;
108246074Sgabor
109246074Sgabor	return return_flags;
110246074Sgabor}
111246074Sgabor/*
112246074Sgabor**  SMDB_CURSOR_GET_FLAGS_TO_SMDB1
113246074Sgabor**
114246074Sgabor**	Parameters:
115246074Sgabor**		flags -- The flags to translate.
116246074Sgabor**
117246074Sgabor**	Returns:
118246074Sgabor**		The db1 flags that are equivalent to the smdb flags.
119246074Sgabor**
120246074Sgabor**	Notes:
121246074Sgabor**		Returns -1 if we don't support the flag.
122246074Sgabor**
123246074Sgabor*/
124246074Sgabor
125246074Sgaborstatic int
126246074Sgaborsmdb_cursor_get_flags_to_smdb1(flags)
127246074Sgabor	SMDB_FLAG flags;
128246074Sgabor{
129246074Sgabor	switch(flags)
130246074Sgabor	{
131246074Sgabor		case SMDB_CURSOR_GET_FIRST:
132246074Sgabor			return R_FIRST;
133246074Sgabor
134246074Sgabor		case SMDB_CURSOR_GET_LAST:
135246074Sgabor			return R_LAST;
136246074Sgabor
137246074Sgabor		case SMDB_CURSOR_GET_NEXT:
138246074Sgabor			return R_NEXT;
139287223Sdelphij
140246074Sgabor		case SMDB_CURSOR_GET_RANGE:
141246074Sgabor			return R_CURSOR;
142246074Sgabor
143246074Sgabor		default:
144246074Sgabor			return -1;
145285976Sdelphij	}
146246074Sgabor}
147246074Sgabor
148246074Sgabor/*
149246074Sgabor**  The rest of these functions correspond to the interface laid out in smdb.h.
150246074Sgabor*/
151246074Sgabor
152246074Sgaborstatic SMDB_DB1_DATABASE *
153246074Sgaborsmdb1_malloc_database()
154246074Sgabor{
155246074Sgabor	SMDB_DB1_DATABASE *db1;
156246074Sgabor
157246074Sgabor	db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE));
158246074Sgabor
159246074Sgabor	if (db1 != NULL)
160246074Sgabor	{
161246074Sgabor		db1->smdb1_lock_fd = -1;
162246074Sgabor		db1->smdb1_cursor_in_use = false;
163246074Sgabor	}
164246074Sgabor
165246074Sgabor	return db1;
166246074Sgabor}
167246074Sgabor
168246074Sgaborstatic int
169246074Sgaborsmdb1_close(database)
170246074Sgabor	SMDB_DATABASE *database;
171246074Sgabor{
172246074Sgabor	int result;
173285976Sdelphij	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
174285976Sdelphij	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
175246074Sgabor
176246074Sgabor	result = db->close(db);
177246074Sgabor	if (db1->smdb1_lock_fd != -1)
178246074Sgabor		(void) close(db1->smdb1_lock_fd);
179246074Sgabor
180285976Sdelphij	free(db1);
181246074Sgabor	database->smdb_impl = NULL;
182287223Sdelphij
183287223Sdelphij	return result;
184287223Sdelphij}
185246074Sgabor
186246074Sgaborstatic int
187246074Sgaborsmdb1_del(database, key, flags)
188246074Sgabor	SMDB_DATABASE *database;
189246074Sgabor	SMDB_DBENT *key;
190285976Sdelphij	unsigned int flags;
191246074Sgabor{
192246074Sgabor	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
193246074Sgabor	DBT dbkey;
194287223Sdelphij
195287223Sdelphij	(void) memset(&dbkey, '\0', sizeof dbkey);
196246074Sgabor	dbkey.data = key->data;
197285976Sdelphij	dbkey.size = key->size;
198246074Sgabor	return db->del(db, &dbkey, flags);
199246074Sgabor}
200246074Sgabor
201246074Sgaborstatic int
202246074Sgaborsmdb1_fd(database, fd)
203285976Sdelphij	SMDB_DATABASE *database;
204285976Sdelphij	int *fd;
205285976Sdelphij{
206246074Sgabor	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
207246074Sgabor
208246074Sgabor	*fd = db->fd(db);
209246074Sgabor	if (*fd == -1)
210285976Sdelphij		return errno;
211285976Sdelphij
212246074Sgabor	return SMDBE_OK;
213246074Sgabor}
214246074Sgabor
215246074Sgaborstatic int
216246074Sgaborsmdb1_lockfd(database)
217246074Sgabor	SMDB_DATABASE *database;
218246074Sgabor{
219285976Sdelphij	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
220285976Sdelphij
221287223Sdelphij	return db1->smdb1_lock_fd;
222287223Sdelphij}
223287223Sdelphij
224287223Sdelphij
225287223Sdelphijstatic int
226287223Sdelphijsmdb1_get(database, key, data, flags)
227287223Sdelphij	SMDB_DATABASE *database;
228287223Sdelphij	SMDB_DBENT *key;
229287223Sdelphij	SMDB_DBENT *data;
230287223Sdelphij	unsigned int flags;
231287223Sdelphij{
232287223Sdelphij	int result;
233287223Sdelphij	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
234287223Sdelphij	DBT dbkey, dbdata;
235287223Sdelphij
236246074Sgabor	(void) memset(&dbdata, '\0', sizeof dbdata);
237285976Sdelphij	(void) memset(&dbkey, '\0', sizeof dbkey);
238246074Sgabor	dbkey.data = key->data;
239285976Sdelphij	dbkey.size = key->size;
240285976Sdelphij
241285976Sdelphij	result = db->get(db, &dbkey, &dbdata, flags);
242287223Sdelphij	if (result != 0)
243287223Sdelphij	{
244287223Sdelphij		if (result == 1)
245287223Sdelphij			return SMDBE_NOT_FOUND;
246287223Sdelphij		return errno;
247287223Sdelphij	}
248287223Sdelphij	data->data = dbdata.data;
249287223Sdelphij	data->size = dbdata.size;
250287223Sdelphij	return SMDBE_OK;
251287223Sdelphij}
252287223Sdelphij
253287223Sdelphijstatic int
254285976Sdelphijsmdb1_put(database, key, data, flags)
255285976Sdelphij	SMDB_DATABASE *database;
256246074Sgabor	SMDB_DBENT *key;
257285976Sdelphij	SMDB_DBENT *data;
258285976Sdelphij	unsigned int flags;
259246074Sgabor{
260285976Sdelphij	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
261246074Sgabor	DBT dbkey, dbdata;
262246074Sgabor
263246074Sgabor	(void) memset(&dbdata, '\0', sizeof dbdata);
264246074Sgabor	(void) memset(&dbkey, '\0', sizeof dbkey);
265246074Sgabor	dbkey.data = key->data;
266246074Sgabor	dbkey.size = key->size;
267246074Sgabor	dbdata.data = data->data;
268246074Sgabor	dbdata.size = data->size;
269246074Sgabor
270246074Sgabor	return db->put(db, &dbkey, &dbdata,
271246074Sgabor		       smdb_put_flags_to_db1_flags(flags));
272246074Sgabor}
273246074Sgabor
274246074Sgaborstatic int
275246074Sgaborsmdb1_set_owner(database, uid, gid)
276246074Sgabor	SMDB_DATABASE *database;
277246074Sgabor	uid_t uid;
278246074Sgabor	gid_t gid;
279246074Sgabor{
280246074Sgabor# if HASFCHOWN
281246074Sgabor	int fd;
282246074Sgabor	int result;
283246074Sgabor	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
284246074Sgabor
285246074Sgabor	fd = db->fd(db);
286246074Sgabor	if (fd == -1)
287246074Sgabor		return errno;
288246074Sgabor
289246074Sgabor	result = fchown(fd, uid, gid);
290246074Sgabor	if (result < 0)
291246074Sgabor		return errno;
292246074Sgabor# endif /* HASFCHOWN */
293246074Sgabor
294246074Sgabor	return SMDBE_OK;
295246074Sgabor}
296246074Sgabor
297246074Sgaborstatic int
298246074Sgaborsmdb1_sync(database, flags)
299246074Sgabor	SMDB_DATABASE *database;
300246074Sgabor	unsigned int flags;
301246074Sgabor{
302246074Sgabor	DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db;
303246074Sgabor
304246074Sgabor	return db->sync(db, flags);
305246074Sgabor}
306246074Sgabor
307246074Sgaborstatic int
308246074Sgaborsmdb1_cursor_close(cursor)
309246074Sgabor	SMDB_CURSOR *cursor;
310246074Sgabor{
311246074Sgabor	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
312246074Sgabor	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
313246074Sgabor
314246074Sgabor	if (!db1->smdb1_cursor_in_use)
315246074Sgabor		return SMDBE_NOT_A_VALID_CURSOR;
316246074Sgabor
317246074Sgabor	db1->smdb1_cursor_in_use = false;
318246074Sgabor	free(cursor);
319246074Sgabor
320246074Sgabor	return SMDBE_OK;
321246074Sgabor}
322246074Sgabor
323246074Sgaborstatic int
324246074Sgaborsmdb1_cursor_del(cursor, flags)
325246074Sgabor	SMDB_CURSOR *cursor;
326246074Sgabor	unsigned int flags;
327246074Sgabor{
328246074Sgabor	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
329246074Sgabor	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
330246074Sgabor	DB *db = db1->smdb1_db;
331246074Sgabor
332246074Sgabor	return db->del(db, NULL, R_CURSOR);
333246074Sgabor}
334246074Sgabor
335246074Sgaborstatic int
336246074Sgaborsmdb1_cursor_get(cursor, key, value, flags)
337246074Sgabor	SMDB_CURSOR *cursor;
338246074Sgabor	SMDB_DBENT *key;
339246074Sgabor	SMDB_DBENT *value;
340246074Sgabor	SMDB_FLAG flags;
341246074Sgabor{
342246074Sgabor	int db1_flags;
343246074Sgabor	int result;
344246074Sgabor	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
345246074Sgabor	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
346246074Sgabor	DB *db = db1->smdb1_db;
347246074Sgabor	DBT dbkey, dbdata;
348246074Sgabor
349246074Sgabor	(void) memset(&dbdata, '\0', sizeof dbdata);
350246074Sgabor	(void) memset(&dbkey, '\0', sizeof dbkey);
351246074Sgabor
352246074Sgabor	db1_flags = smdb_cursor_get_flags_to_smdb1(flags);
353246074Sgabor	result = db->seq(db, &dbkey, &dbdata, db1_flags);
354246074Sgabor	if (result == -1)
355246074Sgabor		return errno;
356246074Sgabor	if (result == 1)
357246074Sgabor		return SMDBE_LAST_ENTRY;
358246074Sgabor	value->data = dbdata.data;
359246074Sgabor	value->size = dbdata.size;
360246074Sgabor	key->data = dbkey.data;
361246074Sgabor	key->size = dbkey.size;
362246074Sgabor	return SMDBE_OK;
363246074Sgabor}
364246074Sgabor
365246074Sgaborstatic int
366246074Sgaborsmdb1_cursor_put(cursor, key, value, flags)
367246074Sgabor	SMDB_CURSOR *cursor;
368246074Sgabor	SMDB_DBENT *key;
369246074Sgabor	SMDB_DBENT *value;
370246074Sgabor	SMDB_FLAG flags;
371246074Sgabor{
372246074Sgabor	SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl;
373246074Sgabor	SMDB_DB1_DATABASE *db1 = db1_cursor->db;
374246074Sgabor	DB *db = db1->smdb1_db;
375246074Sgabor	DBT dbkey, dbdata;
376246074Sgabor
377246074Sgabor	(void) memset(&dbdata, '\0', sizeof dbdata);
378246074Sgabor	(void) memset(&dbkey, '\0', sizeof dbkey);
379246074Sgabor	dbkey.data = key->data;
380246074Sgabor	dbkey.size = key->size;
381246074Sgabor	dbdata.data = value->data;
382246074Sgabor	dbdata.size = value->size;
383246074Sgabor
384246074Sgabor	return db->put(db, &dbkey, &dbdata, R_CURSOR);
385246074Sgabor}
386246074Sgabor
387246074Sgaborstatic int
388246074Sgaborsmdb1_cursor(database, cursor, flags)
389246074Sgabor	SMDB_DATABASE *database;
390246074Sgabor	SMDB_CURSOR **cursor;
391246074Sgabor	unsigned int flags;
392246074Sgabor{
393246074Sgabor	SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl;
394246074Sgabor	SMDB_CURSOR *cur;
395246074Sgabor	SMDB_DB1_CURSOR *db1_cursor;
396246074Sgabor
397246074Sgabor	if (db1->smdb1_cursor_in_use)
398246074Sgabor		return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
399246074Sgabor
400246074Sgabor	db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR));
401246074Sgabor	if (db1_cursor == NULL)
402246074Sgabor		return SMDBE_MALLOC;
403246074Sgabor
404246074Sgabor	cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
405246074Sgabor	if (cur == NULL)
406246074Sgabor	{
407246074Sgabor		free(db1_cursor);
408246074Sgabor		return SMDBE_MALLOC;
409246074Sgabor	}
410246074Sgabor
411246074Sgabor	db1->smdb1_cursor_in_use = true;
412246074Sgabor	db1_cursor->db = db1;
413246074Sgabor	cur->smdbc_impl = db1_cursor;
414246074Sgabor	cur->smdbc_close = smdb1_cursor_close;
415246074Sgabor	cur->smdbc_del = smdb1_cursor_del;
416246074Sgabor	cur->smdbc_get = smdb1_cursor_get;
417246074Sgabor	cur->smdbc_put = smdb1_cursor_put;
418246074Sgabor	*cursor = cur;
419246074Sgabor
420246074Sgabor	return SMDBE_OK;
421246074Sgabor}
422246074Sgabor/*
423246074Sgabor**  SMDB_DB_OPEN -- Opens a db1 database.
424246074Sgabor**
425246074Sgabor**	Parameters:
426246074Sgabor**		database -- An unallocated database pointer to a pointer.
427246074Sgabor**		db_name -- The name of the database without extension.
428246074Sgabor**		mode -- File permisions on the database if created.
429246074Sgabor**		mode_mask -- Mode bits that must match on an existing database.
430246074Sgabor**		sff -- Flags for safefile.
431246074Sgabor**		type -- The type of database to open
432246074Sgabor**			See smdb_type_to_db1_type for valid types.
433246074Sgabor**		user_info -- Information on the user to use for file
434246074Sgabor**			    permissions.
435246074Sgabor**		db_params --
436246074Sgabor**			An SMDB_DBPARAMS struct including params. These
437246074Sgabor**			are processed according to the type of the
438246074Sgabor**			database. Currently supported params (only for
439246074Sgabor**			HASH type) are:
440246074Sgabor**			   num_elements
441246074Sgabor**			   cache_size
442246074Sgabor**
443246074Sgabor**	Returns:
444246074Sgabor**		SMDBE_OK -- Success, otherwise errno.
445246074Sgabor*/
446246074Sgabor
447246074Sgaborint
448246074Sgaborsmdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info,
449246074Sgabor	     db_params)
450246074Sgabor	SMDB_DATABASE **database;
451246074Sgabor	char *db_name;
452246074Sgabor	int mode;
453246074Sgabor	int mode_mask;
454246074Sgabor	long sff;
455246074Sgabor	SMDB_DBTYPE type;
456246074Sgabor	SMDB_USER_INFO *user_info;
457246074Sgabor	SMDB_DBPARAMS *db_params;
458246074Sgabor{
459246074Sgabor	bool lockcreated = false;
460246074Sgabor	int db_fd;
461246074Sgabor	int lock_fd;
462246074Sgabor	int result;
463246074Sgabor	void *params;
464246074Sgabor	SMDB_DATABASE *smdb_db;
465246074Sgabor	SMDB_DB1_DATABASE *db1;
466246074Sgabor	DB *db;
467246074Sgabor	HASHINFO hash_info;
468246074Sgabor	BTREEINFO btree_info;
469246074Sgabor	DBTYPE db_type;
470246074Sgabor	struct stat stat_info;
471246074Sgabor	char db_file_name[MAXPATHLEN];
472246074Sgabor
473246074Sgabor	if (type == NULL ||
474246074Sgabor	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 &&
475246074Sgabor	     strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0))
476246074Sgabor		return SMDBE_UNKNOWN_DB_TYPE;
477246074Sgabor
478246074Sgabor	result = smdb_add_extension(db_file_name, sizeof db_file_name,
479246074Sgabor				    db_name, SMDB1_FILE_EXTENSION);
480246074Sgabor	if (result != SMDBE_OK)
481246074Sgabor		return result;
482246074Sgabor
483246074Sgabor	result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask,
484246074Sgabor				 sff, user_info, &stat_info);
485246074Sgabor	if (result != SMDBE_OK)
486246074Sgabor		return result;
487246074Sgabor
488246074Sgabor	if (stat_info.st_mode == ST_MODE_NOFILE &&
489246074Sgabor	    bitset(mode, O_CREAT))
490246074Sgabor		lockcreated = true;
491246074Sgabor
492246074Sgabor	lock_fd = -1;
493246074Sgabor	result = smdb_lock_file(&lock_fd, db_name, mode, sff,
494246074Sgabor				SMDB1_FILE_EXTENSION);
495246074Sgabor	if (result != SMDBE_OK)
496246074Sgabor		return result;
497246074Sgabor
498246074Sgabor	if (lockcreated)
499246074Sgabor	{
500246074Sgabor		mode |= O_TRUNC;
501246074Sgabor		mode &= ~(O_CREAT|O_EXCL);
502246074Sgabor	}
503246074Sgabor
504246074Sgabor	*database = NULL;
505
506	smdb_db = smdb_malloc_database();
507	db1 = smdb1_malloc_database();
508	if (smdb_db == NULL || db1 == NULL)
509	{
510		(void) smdb_unlock_file(lock_fd);
511		smdb_free_database(smdb_db);
512		free(db1);
513		return SMDBE_MALLOC;
514	}
515	db1->smdb1_lock_fd = lock_fd;
516
517	params = NULL;
518	if (db_params != NULL &&
519	    (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0))
520	{
521		(void) memset(&hash_info, '\0', sizeof hash_info);
522		hash_info.nelem = db_params->smdbp_num_elements;
523		hash_info.cachesize = db_params->smdbp_cache_size;
524		params = &hash_info;
525	}
526
527	if (db_params != NULL &&
528	    (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0))
529	{
530		(void) memset(&btree_info, '\0', sizeof btree_info);
531		btree_info.cachesize = db_params->smdbp_cache_size;
532		if (db_params->smdbp_allow_dup)
533			btree_info.flags |= R_DUP;
534		params = &btree_info;
535	}
536
537	db_type = smdb_type_to_db1_type(type);
538	db = dbopen(db_file_name, mode, DBMMODE, db_type, params);
539	if (db != NULL)
540	{
541		db_fd = db->fd(db);
542		result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd,
543					  &stat_info);
544	}
545	else
546	{
547		if (errno == 0)
548			result = SMDBE_BAD_OPEN;
549		else
550			result = errno;
551	}
552
553	if (result == SMDBE_OK)
554	{
555		/* Everything is ok. Setup driver */
556		db1->smdb1_db = db;
557
558		smdb_db->smdb_close = smdb1_close;
559		smdb_db->smdb_del = smdb1_del;
560		smdb_db->smdb_fd = smdb1_fd;
561		smdb_db->smdb_lockfd = smdb1_lockfd;
562		smdb_db->smdb_get = smdb1_get;
563		smdb_db->smdb_put = smdb1_put;
564		smdb_db->smdb_set_owner = smdb1_set_owner;
565		smdb_db->smdb_sync = smdb1_sync;
566		smdb_db->smdb_cursor = smdb1_cursor;
567		smdb_db->smdb_impl = db1;
568
569		*database = smdb_db;
570		return SMDBE_OK;
571	}
572
573	if (db != NULL)
574		(void) db->close(db);
575
576	/* Error opening database */
577	(void) smdb_unlock_file(db1->smdb1_lock_fd);
578	free(db1);
579	smdb_free_database(smdb_db);
580
581	return result;
582}
583
584#endif /* (DB_VERSION_MAJOR == 1) */
585