1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate ** Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
3*0Sstevel@tonic-gate **	All rights reserved.
4*0Sstevel@tonic-gate **
5*0Sstevel@tonic-gate ** By using this file, you agree to the terms and conditions set
6*0Sstevel@tonic-gate ** forth in the LICENSE file which can be found at the top level of
7*0Sstevel@tonic-gate ** the sendmail distribution.
8*0Sstevel@tonic-gate */
9*0Sstevel@tonic-gate 
10*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
11*0Sstevel@tonic-gate 
12*0Sstevel@tonic-gate #include <sm/gen.h>
13*0Sstevel@tonic-gate SM_RCSID("@(#)$Id: smdb2.c,v 8.72.2.7 2003/06/24 17:16:10 ca Exp $")
14*0Sstevel@tonic-gate 
15*0Sstevel@tonic-gate #include <fcntl.h>
16*0Sstevel@tonic-gate #include <stdlib.h>
17*0Sstevel@tonic-gate #include <unistd.h>
18*0Sstevel@tonic-gate 
19*0Sstevel@tonic-gate 
20*0Sstevel@tonic-gate #include <sendmail/sendmail.h>
21*0Sstevel@tonic-gate #include <libsmdb/smdb.h>
22*0Sstevel@tonic-gate 
23*0Sstevel@tonic-gate #if (DB_VERSION_MAJOR >= 2)
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate # define SMDB2_FILE_EXTENSION "db"
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate struct smdb_db2_database
28*0Sstevel@tonic-gate {
29*0Sstevel@tonic-gate 	DB	*smdb2_db;
30*0Sstevel@tonic-gate 	int	smdb2_lock_fd;
31*0Sstevel@tonic-gate };
32*0Sstevel@tonic-gate typedef struct smdb_db2_database SMDB_DB2_DATABASE;
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate /*
35*0Sstevel@tonic-gate **  SMDB_TYPE_TO_DB2_TYPE -- Translates smdb database type to db2 type.
36*0Sstevel@tonic-gate **
37*0Sstevel@tonic-gate **	Parameters:
38*0Sstevel@tonic-gate **		type -- The type to translate.
39*0Sstevel@tonic-gate **
40*0Sstevel@tonic-gate **	Returns:
41*0Sstevel@tonic-gate **		The DB2 type that corresponsds to the passed in SMDB type.
42*0Sstevel@tonic-gate **		Returns -1 if there is no equivalent type.
43*0Sstevel@tonic-gate **
44*0Sstevel@tonic-gate */
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate DBTYPE
47*0Sstevel@tonic-gate smdb_type_to_db2_type(type)
48*0Sstevel@tonic-gate 	SMDB_DBTYPE type;
49*0Sstevel@tonic-gate {
50*0Sstevel@tonic-gate 	if (type == SMDB_TYPE_DEFAULT)
51*0Sstevel@tonic-gate 		return DB_HASH;
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate 	if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
54*0Sstevel@tonic-gate 		return DB_HASH;
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
57*0Sstevel@tonic-gate 		return DB_BTREE;
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	return DB_UNKNOWN;
60*0Sstevel@tonic-gate }
61*0Sstevel@tonic-gate /*
62*0Sstevel@tonic-gate **  DB2_ERROR_TO_SMDB -- Translates db2 errors to smdbe errors
63*0Sstevel@tonic-gate **
64*0Sstevel@tonic-gate **	Parameters:
65*0Sstevel@tonic-gate **		error -- The error to translate.
66*0Sstevel@tonic-gate **
67*0Sstevel@tonic-gate **	Returns:
68*0Sstevel@tonic-gate **		The SMDBE error corresponding to the db2 error.
69*0Sstevel@tonic-gate **		If we don't have a corresponding error, it returs errno.
70*0Sstevel@tonic-gate **
71*0Sstevel@tonic-gate */
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate int
74*0Sstevel@tonic-gate db2_error_to_smdb(error)
75*0Sstevel@tonic-gate 	int error;
76*0Sstevel@tonic-gate {
77*0Sstevel@tonic-gate 	int result;
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	switch (error)
80*0Sstevel@tonic-gate 	{
81*0Sstevel@tonic-gate # ifdef DB_INCOMPLETE
82*0Sstevel@tonic-gate 		case DB_INCOMPLETE:
83*0Sstevel@tonic-gate 			result = SMDBE_INCOMPLETE;
84*0Sstevel@tonic-gate 			break;
85*0Sstevel@tonic-gate # endif /* DB_INCOMPLETE */
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate # ifdef DB_NOTFOUND
88*0Sstevel@tonic-gate 		case DB_NOTFOUND:
89*0Sstevel@tonic-gate 			result = SMDBE_NOT_FOUND;
90*0Sstevel@tonic-gate 			break;
91*0Sstevel@tonic-gate # endif /* DB_NOTFOUND */
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate # ifdef DB_KEYEMPTY
94*0Sstevel@tonic-gate 		case DB_KEYEMPTY:
95*0Sstevel@tonic-gate 			result = SMDBE_KEY_EMPTY;
96*0Sstevel@tonic-gate 			break;
97*0Sstevel@tonic-gate # endif /* DB_KEYEMPTY */
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate # ifdef DB_KEYEXIST
100*0Sstevel@tonic-gate 		case DB_KEYEXIST:
101*0Sstevel@tonic-gate 			result = SMDBE_KEY_EXIST;
102*0Sstevel@tonic-gate 			break;
103*0Sstevel@tonic-gate # endif /* DB_KEYEXIST */
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate # ifdef DB_LOCK_DEADLOCK
106*0Sstevel@tonic-gate 		case DB_LOCK_DEADLOCK:
107*0Sstevel@tonic-gate 			result = SMDBE_LOCK_DEADLOCK;
108*0Sstevel@tonic-gate 			break;
109*0Sstevel@tonic-gate # endif /* DB_LOCK_DEADLOCK */
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate # ifdef DB_LOCK_NOTGRANTED
112*0Sstevel@tonic-gate 		case DB_LOCK_NOTGRANTED:
113*0Sstevel@tonic-gate 			result = SMDBE_LOCK_NOT_GRANTED;
114*0Sstevel@tonic-gate 			break;
115*0Sstevel@tonic-gate # endif /* DB_LOCK_NOTGRANTED */
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate # ifdef DB_LOCK_NOTHELD
118*0Sstevel@tonic-gate 		case DB_LOCK_NOTHELD:
119*0Sstevel@tonic-gate 			result = SMDBE_LOCK_NOT_HELD;
120*0Sstevel@tonic-gate 			break;
121*0Sstevel@tonic-gate # endif /* DB_LOCK_NOTHELD */
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate # ifdef DB_RUNRECOVERY
124*0Sstevel@tonic-gate 		case DB_RUNRECOVERY:
125*0Sstevel@tonic-gate 			result = SMDBE_RUN_RECOVERY;
126*0Sstevel@tonic-gate 			break;
127*0Sstevel@tonic-gate # endif /* DB_RUNRECOVERY */
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate # ifdef DB_OLD_VERSION
130*0Sstevel@tonic-gate 		case DB_OLD_VERSION:
131*0Sstevel@tonic-gate 			result = SMDBE_OLD_VERSION;
132*0Sstevel@tonic-gate 			break;
133*0Sstevel@tonic-gate # endif /* DB_OLD_VERSION */
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 		case 0:
136*0Sstevel@tonic-gate 			result = SMDBE_OK;
137*0Sstevel@tonic-gate 			break;
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 		default:
140*0Sstevel@tonic-gate 			result = error;
141*0Sstevel@tonic-gate 	}
142*0Sstevel@tonic-gate 	return result;
143*0Sstevel@tonic-gate }
144*0Sstevel@tonic-gate /*
145*0Sstevel@tonic-gate **  SMDB_PUT_FLAGS_TO_DB2_FLAGS -- Translates smdb put flags to db2 put flags.
146*0Sstevel@tonic-gate **
147*0Sstevel@tonic-gate **	Parameters:
148*0Sstevel@tonic-gate **		flags -- The flags to translate.
149*0Sstevel@tonic-gate **
150*0Sstevel@tonic-gate **	Returns:
151*0Sstevel@tonic-gate **		The db2 flags that are equivalent to the smdb flags.
152*0Sstevel@tonic-gate **
153*0Sstevel@tonic-gate **	Notes:
154*0Sstevel@tonic-gate **		Any invalid flags are ignored.
155*0Sstevel@tonic-gate **
156*0Sstevel@tonic-gate */
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate unsigned int
159*0Sstevel@tonic-gate smdb_put_flags_to_db2_flags(flags)
160*0Sstevel@tonic-gate 	SMDB_FLAG flags;
161*0Sstevel@tonic-gate {
162*0Sstevel@tonic-gate 	int return_flags;
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	return_flags = 0;
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	if (bitset(SMDBF_NO_OVERWRITE, flags))
167*0Sstevel@tonic-gate 		return_flags |= DB_NOOVERWRITE;
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	return return_flags;
170*0Sstevel@tonic-gate }
171*0Sstevel@tonic-gate /*
172*0Sstevel@tonic-gate **  SMDB_CURSOR_GET_FLAGS_TO_DB2 -- Translates smdb cursor get flags to db2
173*0Sstevel@tonic-gate **	getflags.
174*0Sstevel@tonic-gate **
175*0Sstevel@tonic-gate **	Parameters:
176*0Sstevel@tonic-gate **		flags -- The flags to translate.
177*0Sstevel@tonic-gate **
178*0Sstevel@tonic-gate **	Returns:
179*0Sstevel@tonic-gate **		The db2 flags that are equivalent to the smdb flags.
180*0Sstevel@tonic-gate **
181*0Sstevel@tonic-gate **	Notes:
182*0Sstevel@tonic-gate **		-1 is returned if flag is unknown.
183*0Sstevel@tonic-gate **
184*0Sstevel@tonic-gate */
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate int
187*0Sstevel@tonic-gate smdb_cursor_get_flags_to_db2(flags)
188*0Sstevel@tonic-gate 	SMDB_FLAG flags;
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate 	switch (flags)
191*0Sstevel@tonic-gate 	{
192*0Sstevel@tonic-gate 		case SMDB_CURSOR_GET_FIRST:
193*0Sstevel@tonic-gate 			return DB_FIRST;
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 		case SMDB_CURSOR_GET_LAST:
196*0Sstevel@tonic-gate 			return DB_LAST;
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 		case SMDB_CURSOR_GET_NEXT:
199*0Sstevel@tonic-gate 			return DB_NEXT;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 		case SMDB_CURSOR_GET_RANGE:
202*0Sstevel@tonic-gate 			return DB_SET_RANGE;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 		default:
205*0Sstevel@tonic-gate 			return -1;
206*0Sstevel@tonic-gate 	}
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate /*
210*0Sstevel@tonic-gate **  Except for smdb_db_open, the rest of these functions correspond to the
211*0Sstevel@tonic-gate **  interface laid out in smdb.h.
212*0Sstevel@tonic-gate */
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate SMDB_DB2_DATABASE *
215*0Sstevel@tonic-gate smdb2_malloc_database()
216*0Sstevel@tonic-gate {
217*0Sstevel@tonic-gate 	SMDB_DB2_DATABASE *db2;
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 	db2 = (SMDB_DB2_DATABASE *) malloc(sizeof(SMDB_DB2_DATABASE));
220*0Sstevel@tonic-gate 	if (db2 != NULL)
221*0Sstevel@tonic-gate 		db2->smdb2_lock_fd = -1;
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 	return db2;
224*0Sstevel@tonic-gate }
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate int
227*0Sstevel@tonic-gate smdb2_close(database)
228*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
229*0Sstevel@tonic-gate {
230*0Sstevel@tonic-gate 	int result;
231*0Sstevel@tonic-gate 	SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl;
232*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 	result = db2_error_to_smdb(db->close(db, 0));
235*0Sstevel@tonic-gate 	if (db2->smdb2_lock_fd != -1)
236*0Sstevel@tonic-gate 		close(db2->smdb2_lock_fd);
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	free(db2);
239*0Sstevel@tonic-gate 	database->smdb_impl = NULL;
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 	return result;
242*0Sstevel@tonic-gate }
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate int
245*0Sstevel@tonic-gate smdb2_del(database, key, flags)
246*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
247*0Sstevel@tonic-gate 	SMDB_DBENT *key;
248*0Sstevel@tonic-gate 	unsigned int flags;
249*0Sstevel@tonic-gate {
250*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
251*0Sstevel@tonic-gate 	DBT dbkey;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
254*0Sstevel@tonic-gate 	dbkey.data = key->data;
255*0Sstevel@tonic-gate 	dbkey.size = key->size;
256*0Sstevel@tonic-gate 	return db2_error_to_smdb(db->del(db, NULL, &dbkey, flags));
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate int
260*0Sstevel@tonic-gate smdb2_fd(database, fd)
261*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
262*0Sstevel@tonic-gate 	int *fd;
263*0Sstevel@tonic-gate {
264*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	return db2_error_to_smdb(db->fd(db, fd));
267*0Sstevel@tonic-gate }
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate int
270*0Sstevel@tonic-gate smdb2_lockfd(database)
271*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
272*0Sstevel@tonic-gate {
273*0Sstevel@tonic-gate 	SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl;
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	return db2->smdb2_lock_fd;
276*0Sstevel@tonic-gate }
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate int
279*0Sstevel@tonic-gate smdb2_get(database, key, data, flags)
280*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
281*0Sstevel@tonic-gate 	SMDB_DBENT *key;
282*0Sstevel@tonic-gate 	SMDB_DBENT *data;
283*0Sstevel@tonic-gate 	unsigned int flags;
284*0Sstevel@tonic-gate {
285*0Sstevel@tonic-gate 	int result;
286*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
287*0Sstevel@tonic-gate 	DBT dbkey, dbdata;
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
290*0Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
291*0Sstevel@tonic-gate 	dbkey.data = key->data;
292*0Sstevel@tonic-gate 	dbkey.size = key->size;
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 	result = db->get(db, NULL, &dbkey, &dbdata, flags);
295*0Sstevel@tonic-gate 	data->data = dbdata.data;
296*0Sstevel@tonic-gate 	data->size = dbdata.size;
297*0Sstevel@tonic-gate 	return db2_error_to_smdb(result);
298*0Sstevel@tonic-gate }
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate int
301*0Sstevel@tonic-gate smdb2_put(database, key, data, flags)
302*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
303*0Sstevel@tonic-gate 	SMDB_DBENT *key;
304*0Sstevel@tonic-gate 	SMDB_DBENT *data;
305*0Sstevel@tonic-gate 	unsigned int flags;
306*0Sstevel@tonic-gate {
307*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
308*0Sstevel@tonic-gate 	DBT dbkey, dbdata;
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
311*0Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
312*0Sstevel@tonic-gate 	dbkey.data = key->data;
313*0Sstevel@tonic-gate 	dbkey.size = key->size;
314*0Sstevel@tonic-gate 	dbdata.data = data->data;
315*0Sstevel@tonic-gate 	dbdata.size = data->size;
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	return db2_error_to_smdb(db->put(db, NULL, &dbkey, &dbdata,
318*0Sstevel@tonic-gate 					 smdb_put_flags_to_db2_flags(flags)));
319*0Sstevel@tonic-gate }
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate int
323*0Sstevel@tonic-gate smdb2_set_owner(database, uid, gid)
324*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
325*0Sstevel@tonic-gate 	uid_t uid;
326*0Sstevel@tonic-gate 	gid_t gid;
327*0Sstevel@tonic-gate {
328*0Sstevel@tonic-gate # if HASFCHOWN
329*0Sstevel@tonic-gate 	int fd;
330*0Sstevel@tonic-gate 	int result;
331*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
332*0Sstevel@tonic-gate 
333*0Sstevel@tonic-gate 	result = db->fd(db, &fd);
334*0Sstevel@tonic-gate 	if (result != 0)
335*0Sstevel@tonic-gate 		return result;
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	result = fchown(fd, uid, gid);
338*0Sstevel@tonic-gate 	if (result < 0)
339*0Sstevel@tonic-gate 		return errno;
340*0Sstevel@tonic-gate # endif /* HASFCHOWN */
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	return SMDBE_OK;
343*0Sstevel@tonic-gate }
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate int
346*0Sstevel@tonic-gate smdb2_sync(database, flags)
347*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
348*0Sstevel@tonic-gate 	unsigned int flags;
349*0Sstevel@tonic-gate {
350*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 	return db2_error_to_smdb(db->sync(db, flags));
353*0Sstevel@tonic-gate }
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate int
356*0Sstevel@tonic-gate smdb2_cursor_close(cursor)
357*0Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
358*0Sstevel@tonic-gate {
359*0Sstevel@tonic-gate 	int ret;
360*0Sstevel@tonic-gate 	DBC *dbc = (DBC *) cursor->smdbc_impl;
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	ret = db2_error_to_smdb(dbc->c_close(dbc));
363*0Sstevel@tonic-gate 	free(cursor);
364*0Sstevel@tonic-gate 	return ret;
365*0Sstevel@tonic-gate }
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate int
368*0Sstevel@tonic-gate smdb2_cursor_del(cursor, flags)
369*0Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
370*0Sstevel@tonic-gate 	SMDB_FLAG flags;
371*0Sstevel@tonic-gate {
372*0Sstevel@tonic-gate 	DBC *dbc = (DBC *) cursor->smdbc_impl;
373*0Sstevel@tonic-gate 
374*0Sstevel@tonic-gate 	return db2_error_to_smdb(dbc->c_del(dbc, 0));
375*0Sstevel@tonic-gate }
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate int
378*0Sstevel@tonic-gate smdb2_cursor_get(cursor, key, value, flags)
379*0Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
380*0Sstevel@tonic-gate 	SMDB_DBENT *key;
381*0Sstevel@tonic-gate 	SMDB_DBENT *value;
382*0Sstevel@tonic-gate 	SMDB_FLAG flags;
383*0Sstevel@tonic-gate {
384*0Sstevel@tonic-gate 	int db2_flags;
385*0Sstevel@tonic-gate 	int result;
386*0Sstevel@tonic-gate 	DBC *dbc = (DBC *) cursor->smdbc_impl;
387*0Sstevel@tonic-gate 	DBT dbkey, dbdata;
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
390*0Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
391*0Sstevel@tonic-gate 
392*0Sstevel@tonic-gate 	db2_flags = smdb_cursor_get_flags_to_db2(flags);
393*0Sstevel@tonic-gate 	result = dbc->c_get(dbc, &dbkey, &dbdata, db2_flags);
394*0Sstevel@tonic-gate 	if (result == DB_NOTFOUND)
395*0Sstevel@tonic-gate 		return SMDBE_LAST_ENTRY;
396*0Sstevel@tonic-gate 	key->data = dbkey.data;
397*0Sstevel@tonic-gate 	key->size = dbkey.size;
398*0Sstevel@tonic-gate 	value->data = dbdata.data;
399*0Sstevel@tonic-gate 	value->size = dbdata.size;
400*0Sstevel@tonic-gate 	return db2_error_to_smdb(result);
401*0Sstevel@tonic-gate }
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate int
404*0Sstevel@tonic-gate smdb2_cursor_put(cursor, key, value, flags)
405*0Sstevel@tonic-gate 	SMDB_CURSOR *cursor;
406*0Sstevel@tonic-gate 	SMDB_DBENT *key;
407*0Sstevel@tonic-gate 	SMDB_DBENT *value;
408*0Sstevel@tonic-gate 	SMDB_FLAG flags;
409*0Sstevel@tonic-gate {
410*0Sstevel@tonic-gate 	DBC *dbc = (DBC *) cursor->smdbc_impl;
411*0Sstevel@tonic-gate 	DBT dbkey, dbdata;
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	(void) memset(&dbdata, '\0', sizeof dbdata);
414*0Sstevel@tonic-gate 	(void) memset(&dbkey, '\0', sizeof dbkey);
415*0Sstevel@tonic-gate 	dbkey.data = key->data;
416*0Sstevel@tonic-gate 	dbkey.size = key->size;
417*0Sstevel@tonic-gate 	dbdata.data = value->data;
418*0Sstevel@tonic-gate 	dbdata.size = value->size;
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 	return db2_error_to_smdb(dbc->c_put(dbc, &dbkey, &dbdata, 0));
421*0Sstevel@tonic-gate }
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate int
424*0Sstevel@tonic-gate smdb2_cursor(database, cursor, flags)
425*0Sstevel@tonic-gate 	SMDB_DATABASE *database;
426*0Sstevel@tonic-gate 	SMDB_CURSOR **cursor;
427*0Sstevel@tonic-gate 	SMDB_FLAG flags;
428*0Sstevel@tonic-gate {
429*0Sstevel@tonic-gate 	int result;
430*0Sstevel@tonic-gate 	DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
431*0Sstevel@tonic-gate 	DBC *db2_cursor;
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
434*0Sstevel@tonic-gate 	result = db->cursor(db, NULL, &db2_cursor, 0);
435*0Sstevel@tonic-gate # else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
436*0Sstevel@tonic-gate 	result = db->cursor(db, NULL, &db2_cursor);
437*0Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
438*0Sstevel@tonic-gate 	if (result != 0)
439*0Sstevel@tonic-gate 		return db2_error_to_smdb(result);
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 	*cursor = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
442*0Sstevel@tonic-gate 	if (*cursor == NULL)
443*0Sstevel@tonic-gate 		return SMDBE_MALLOC;
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate 	(*cursor)->smdbc_close = smdb2_cursor_close;
446*0Sstevel@tonic-gate 	(*cursor)->smdbc_del = smdb2_cursor_del;
447*0Sstevel@tonic-gate 	(*cursor)->smdbc_get = smdb2_cursor_get;
448*0Sstevel@tonic-gate 	(*cursor)->smdbc_put = smdb2_cursor_put;
449*0Sstevel@tonic-gate 	(*cursor)->smdbc_impl = db2_cursor;
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 	return SMDBE_OK;
452*0Sstevel@tonic-gate }
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2
455*0Sstevel@tonic-gate static int
456*0Sstevel@tonic-gate smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
457*0Sstevel@tonic-gate 	char *db_name;
458*0Sstevel@tonic-gate 	DBTYPE db_type;
459*0Sstevel@tonic-gate 	int db_flags;
460*0Sstevel@tonic-gate 	SMDB_DBPARAMS *db_params;
461*0Sstevel@tonic-gate 	DB **db;
462*0Sstevel@tonic-gate {
463*0Sstevel@tonic-gate 	void *params;
464*0Sstevel@tonic-gate 	DB_INFO db_info;
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 	params = NULL;
467*0Sstevel@tonic-gate 	(void) memset(&db_info, '\0', sizeof db_info);
468*0Sstevel@tonic-gate 	if (db_params != NULL)
469*0Sstevel@tonic-gate 	{
470*0Sstevel@tonic-gate 		db_info.db_cachesize = db_params->smdbp_cache_size;
471*0Sstevel@tonic-gate 		if (db_type == DB_HASH)
472*0Sstevel@tonic-gate 			db_info.h_nelem = db_params->smdbp_num_elements;
473*0Sstevel@tonic-gate 		if (db_params->smdbp_allow_dup)
474*0Sstevel@tonic-gate 			db_info.flags |= DB_DUP;
475*0Sstevel@tonic-gate 		params = &db_info;
476*0Sstevel@tonic-gate 	}
477*0Sstevel@tonic-gate 	return db_open(db_name, db_type, db_flags, DBMMODE, NULL, params, db);
478*0Sstevel@tonic-gate }
479*0Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
482*0Sstevel@tonic-gate static int
483*0Sstevel@tonic-gate smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
484*0Sstevel@tonic-gate 	char *db_name;
485*0Sstevel@tonic-gate 	DBTYPE db_type;
486*0Sstevel@tonic-gate 	int db_flags;
487*0Sstevel@tonic-gate 	SMDB_DBPARAMS *db_params;
488*0Sstevel@tonic-gate 	DB **db;
489*0Sstevel@tonic-gate {
490*0Sstevel@tonic-gate 	int result;
491*0Sstevel@tonic-gate 
492*0Sstevel@tonic-gate 	result = db_create(db, NULL, 0);
493*0Sstevel@tonic-gate 	if (result != 0 || *db == NULL)
494*0Sstevel@tonic-gate 		return result;
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate 	if (db_params != NULL)
497*0Sstevel@tonic-gate 	{
498*0Sstevel@tonic-gate 		result = (*db)->set_cachesize(*db, 0,
499*0Sstevel@tonic-gate 					      db_params->smdbp_cache_size, 0);
500*0Sstevel@tonic-gate 		if (result != 0)
501*0Sstevel@tonic-gate 		{
502*0Sstevel@tonic-gate 			(void) (*db)->close((*db), 0);
503*0Sstevel@tonic-gate 			*db = NULL;
504*0Sstevel@tonic-gate 			return db2_error_to_smdb(result);
505*0Sstevel@tonic-gate 		}
506*0Sstevel@tonic-gate 		if (db_type == DB_HASH)
507*0Sstevel@tonic-gate 		{
508*0Sstevel@tonic-gate 			result = (*db)->set_h_nelem(*db, db_params->smdbp_num_elements);
509*0Sstevel@tonic-gate 			if (result != 0)
510*0Sstevel@tonic-gate 			{
511*0Sstevel@tonic-gate 				(void) (*db)->close(*db, 0);
512*0Sstevel@tonic-gate 				*db = NULL;
513*0Sstevel@tonic-gate 				return db2_error_to_smdb(result);
514*0Sstevel@tonic-gate 			}
515*0Sstevel@tonic-gate 		}
516*0Sstevel@tonic-gate 		if (db_params->smdbp_allow_dup)
517*0Sstevel@tonic-gate 		{
518*0Sstevel@tonic-gate 			result = (*db)->set_flags(*db, DB_DUP);
519*0Sstevel@tonic-gate 			if (result != 0)
520*0Sstevel@tonic-gate 			{
521*0Sstevel@tonic-gate 				(void) (*db)->close(*db, 0);
522*0Sstevel@tonic-gate 				*db = NULL;
523*0Sstevel@tonic-gate 				return db2_error_to_smdb(result);
524*0Sstevel@tonic-gate 			}
525*0Sstevel@tonic-gate 		}
526*0Sstevel@tonic-gate 	}
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate 	result = (*db)->open(*db,
529*0Sstevel@tonic-gate 			     DBTXN	/* transaction for DB 4.1 */
530*0Sstevel@tonic-gate 			     db_name, NULL, db_type, db_flags, DBMMODE);
531*0Sstevel@tonic-gate 	if (result != 0)
532*0Sstevel@tonic-gate 	{
533*0Sstevel@tonic-gate 		(void) (*db)->close(*db, 0);
534*0Sstevel@tonic-gate 		*db = NULL;
535*0Sstevel@tonic-gate 	}
536*0Sstevel@tonic-gate 	return db2_error_to_smdb(result);
537*0Sstevel@tonic-gate }
538*0Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
539*0Sstevel@tonic-gate /*
540*0Sstevel@tonic-gate **  SMDB_DB_OPEN -- Opens a db database.
541*0Sstevel@tonic-gate **
542*0Sstevel@tonic-gate **	Parameters:
543*0Sstevel@tonic-gate **		database -- An unallocated database pointer to a pointer.
544*0Sstevel@tonic-gate **		db_name -- The name of the database without extension.
545*0Sstevel@tonic-gate **		mode -- File permisions for a created database.
546*0Sstevel@tonic-gate **		mode_mask -- Mode bits that must match on an opened database.
547*0Sstevel@tonic-gate **		sff -- Flags for safefile.
548*0Sstevel@tonic-gate **		type -- The type of database to open
549*0Sstevel@tonic-gate **			See smdb_type_to_db2_type for valid types.
550*0Sstevel@tonic-gate **		user_info -- User information for file permissions.
551*0Sstevel@tonic-gate **		db_params --
552*0Sstevel@tonic-gate **			An SMDB_DBPARAMS struct including params. These
553*0Sstevel@tonic-gate **			are processed according to the type of the
554*0Sstevel@tonic-gate **			database. Currently supported params (only for
555*0Sstevel@tonic-gate **			HASH type) are:
556*0Sstevel@tonic-gate **			   num_elements
557*0Sstevel@tonic-gate **			   cache_size
558*0Sstevel@tonic-gate **
559*0Sstevel@tonic-gate **	Returns:
560*0Sstevel@tonic-gate **		SMDBE_OK -- Success, other errno:
561*0Sstevel@tonic-gate **		SMDBE_MALLOC -- Cannot allocate memory.
562*0Sstevel@tonic-gate **		SMDBE_BAD_OPEN -- db_open didn't return an error, but
563*0Sstevel@tonic-gate **				 somehow the DB pointer is NULL.
564*0Sstevel@tonic-gate **		Anything else: translated error from db2
565*0Sstevel@tonic-gate */
566*0Sstevel@tonic-gate 
567*0Sstevel@tonic-gate int
568*0Sstevel@tonic-gate smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, db_params)
569*0Sstevel@tonic-gate 	SMDB_DATABASE **database;
570*0Sstevel@tonic-gate 	char *db_name;
571*0Sstevel@tonic-gate 	int mode;
572*0Sstevel@tonic-gate 	int mode_mask;
573*0Sstevel@tonic-gate 	long sff;
574*0Sstevel@tonic-gate 	SMDB_DBTYPE type;
575*0Sstevel@tonic-gate 	SMDB_USER_INFO *user_info;
576*0Sstevel@tonic-gate 	SMDB_DBPARAMS *db_params;
577*0Sstevel@tonic-gate {
578*0Sstevel@tonic-gate 	bool lockcreated = false;
579*0Sstevel@tonic-gate 	int result;
580*0Sstevel@tonic-gate 	int db_flags;
581*0Sstevel@tonic-gate 	int lock_fd;
582*0Sstevel@tonic-gate 	int db_fd;
583*0Sstevel@tonic-gate 	int major_v, minor_v, patch_v;
584*0Sstevel@tonic-gate 	SMDB_DATABASE *smdb_db;
585*0Sstevel@tonic-gate 	SMDB_DB2_DATABASE *db2;
586*0Sstevel@tonic-gate 	DB *db;
587*0Sstevel@tonic-gate 	DBTYPE db_type;
588*0Sstevel@tonic-gate 	struct stat stat_info;
589*0Sstevel@tonic-gate 	char db_file_name[MAXPATHLEN];
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 	(void) db_version(&major_v, &minor_v, &patch_v);
592*0Sstevel@tonic-gate 	if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR)
593*0Sstevel@tonic-gate 		return SMDBE_VERSION_MISMATCH;
594*0Sstevel@tonic-gate 
595*0Sstevel@tonic-gate 	*database = NULL;
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate 	result = smdb_add_extension(db_file_name, sizeof db_file_name,
598*0Sstevel@tonic-gate 				    db_name, SMDB2_FILE_EXTENSION);
599*0Sstevel@tonic-gate 	if (result != SMDBE_OK)
600*0Sstevel@tonic-gate 		return result;
601*0Sstevel@tonic-gate 
602*0Sstevel@tonic-gate 	result = smdb_setup_file(db_name, SMDB2_FILE_EXTENSION,
603*0Sstevel@tonic-gate 				 mode_mask, sff, user_info, &stat_info);
604*0Sstevel@tonic-gate 	if (result != SMDBE_OK)
605*0Sstevel@tonic-gate 		return result;
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate 	lock_fd = -1;
608*0Sstevel@tonic-gate 
609*0Sstevel@tonic-gate 	if (stat_info.st_mode == ST_MODE_NOFILE &&
610*0Sstevel@tonic-gate 	    bitset(mode, O_CREAT))
611*0Sstevel@tonic-gate 		lockcreated = true;
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 	result = smdb_lock_file(&lock_fd, db_name, mode, sff,
614*0Sstevel@tonic-gate 				SMDB2_FILE_EXTENSION);
615*0Sstevel@tonic-gate 	if (result != SMDBE_OK)
616*0Sstevel@tonic-gate 		return result;
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 	if (lockcreated)
619*0Sstevel@tonic-gate 	{
620*0Sstevel@tonic-gate 		mode |= O_TRUNC;
621*0Sstevel@tonic-gate 		mode &= ~(O_CREAT|O_EXCL);
622*0Sstevel@tonic-gate 	}
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate 	smdb_db = smdb_malloc_database();
625*0Sstevel@tonic-gate 	if (smdb_db == NULL)
626*0Sstevel@tonic-gate 		return SMDBE_MALLOC;
627*0Sstevel@tonic-gate 
628*0Sstevel@tonic-gate 	db2 = smdb2_malloc_database();
629*0Sstevel@tonic-gate 	if (db2 == NULL)
630*0Sstevel@tonic-gate 		return SMDBE_MALLOC;
631*0Sstevel@tonic-gate 
632*0Sstevel@tonic-gate 	db2->smdb2_lock_fd = lock_fd;
633*0Sstevel@tonic-gate 
634*0Sstevel@tonic-gate 	db_type = smdb_type_to_db2_type(type);
635*0Sstevel@tonic-gate 
636*0Sstevel@tonic-gate 	db = NULL;
637*0Sstevel@tonic-gate 
638*0Sstevel@tonic-gate 	db_flags = 0;
639*0Sstevel@tonic-gate 	if (bitset(O_CREAT, mode))
640*0Sstevel@tonic-gate 		db_flags |= DB_CREATE;
641*0Sstevel@tonic-gate 	if (bitset(O_TRUNC, mode))
642*0Sstevel@tonic-gate 		db_flags |= DB_TRUNCATE;
643*0Sstevel@tonic-gate 	if (mode == O_RDONLY)
644*0Sstevel@tonic-gate 		db_flags |= DB_RDONLY;
645*0Sstevel@tonic-gate 	SM_DB_FLAG_ADD(db_flags);
646*0Sstevel@tonic-gate 
647*0Sstevel@tonic-gate 	result = smdb_db_open_internal(db_file_name, db_type,
648*0Sstevel@tonic-gate 				       db_flags, db_params, &db);
649*0Sstevel@tonic-gate 
650*0Sstevel@tonic-gate 	if (result == 0 && db != NULL)
651*0Sstevel@tonic-gate 	{
652*0Sstevel@tonic-gate 		result = db->fd(db, &db_fd);
653*0Sstevel@tonic-gate 		if (result == 0)
654*0Sstevel@tonic-gate 			result = SMDBE_OK;
655*0Sstevel@tonic-gate 	}
656*0Sstevel@tonic-gate 	else
657*0Sstevel@tonic-gate 	{
658*0Sstevel@tonic-gate 		/* Try and narrow down on the problem */
659*0Sstevel@tonic-gate 		if (result != 0)
660*0Sstevel@tonic-gate 			result = db2_error_to_smdb(result);
661*0Sstevel@tonic-gate 		else
662*0Sstevel@tonic-gate 			result = SMDBE_BAD_OPEN;
663*0Sstevel@tonic-gate 	}
664*0Sstevel@tonic-gate 
665*0Sstevel@tonic-gate 	if (result == SMDBE_OK)
666*0Sstevel@tonic-gate 		result = smdb_filechanged(db_name, SMDB2_FILE_EXTENSION, db_fd,
667*0Sstevel@tonic-gate 					  &stat_info);
668*0Sstevel@tonic-gate 
669*0Sstevel@tonic-gate 	if (result == SMDBE_OK)
670*0Sstevel@tonic-gate 	{
671*0Sstevel@tonic-gate 		/* Everything is ok. Setup driver */
672*0Sstevel@tonic-gate 		db2->smdb2_db = db;
673*0Sstevel@tonic-gate 
674*0Sstevel@tonic-gate 		smdb_db->smdb_close = smdb2_close;
675*0Sstevel@tonic-gate 		smdb_db->smdb_del = smdb2_del;
676*0Sstevel@tonic-gate 		smdb_db->smdb_fd = smdb2_fd;
677*0Sstevel@tonic-gate 		smdb_db->smdb_lockfd = smdb2_lockfd;
678*0Sstevel@tonic-gate 		smdb_db->smdb_get = smdb2_get;
679*0Sstevel@tonic-gate 		smdb_db->smdb_put = smdb2_put;
680*0Sstevel@tonic-gate 		smdb_db->smdb_set_owner = smdb2_set_owner;
681*0Sstevel@tonic-gate 		smdb_db->smdb_sync = smdb2_sync;
682*0Sstevel@tonic-gate 		smdb_db->smdb_cursor = smdb2_cursor;
683*0Sstevel@tonic-gate 		smdb_db->smdb_impl = db2;
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate 		*database = smdb_db;
686*0Sstevel@tonic-gate 
687*0Sstevel@tonic-gate 		return SMDBE_OK;
688*0Sstevel@tonic-gate 	}
689*0Sstevel@tonic-gate 
690*0Sstevel@tonic-gate 	if (db != NULL)
691*0Sstevel@tonic-gate 		db->close(db, 0);
692*0Sstevel@tonic-gate 
693*0Sstevel@tonic-gate 	smdb_unlock_file(db2->smdb2_lock_fd);
694*0Sstevel@tonic-gate 	free(db2);
695*0Sstevel@tonic-gate 	smdb_free_database(smdb_db);
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate 	return result;
698*0Sstevel@tonic-gate }
699*0Sstevel@tonic-gate 
700*0Sstevel@tonic-gate #endif /* (DB_VERSION_MAJOR >= 2) */
701