1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate ** Copyright (c) 1999-2002 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: smndbm.c,v 8.52 2002/05/21 22:30:30 gshapiro 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 #include <sendmail/sendmail.h>
20*0Sstevel@tonic-gate #include <libsmdb/smdb.h>
21*0Sstevel@tonic-gate
22*0Sstevel@tonic-gate #ifdef NDBM
23*0Sstevel@tonic-gate
24*0Sstevel@tonic-gate # define SMNDB_DIR_FILE_EXTENSION "dir"
25*0Sstevel@tonic-gate # define SMNDB_PAG_FILE_EXTENSION "pag"
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate struct smdb_dbm_database_struct
28*0Sstevel@tonic-gate {
29*0Sstevel@tonic-gate DBM *smndbm_dbm;
30*0Sstevel@tonic-gate int smndbm_lock_fd;
31*0Sstevel@tonic-gate bool smndbm_cursor_in_use;
32*0Sstevel@tonic-gate };
33*0Sstevel@tonic-gate typedef struct smdb_dbm_database_struct SMDB_DBM_DATABASE;
34*0Sstevel@tonic-gate
35*0Sstevel@tonic-gate struct smdb_dbm_cursor_struct
36*0Sstevel@tonic-gate {
37*0Sstevel@tonic-gate SMDB_DBM_DATABASE *smndbmc_db;
38*0Sstevel@tonic-gate datum smndbmc_current_key;
39*0Sstevel@tonic-gate };
40*0Sstevel@tonic-gate typedef struct smdb_dbm_cursor_struct SMDB_DBM_CURSOR;
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate /*
43*0Sstevel@tonic-gate ** SMDB_PUT_FLAGS_TO_NDBM_FLAGS -- Translates smdb put flags to ndbm put flags.
44*0Sstevel@tonic-gate **
45*0Sstevel@tonic-gate ** Parameters:
46*0Sstevel@tonic-gate ** flags -- The flags to translate.
47*0Sstevel@tonic-gate **
48*0Sstevel@tonic-gate ** Returns:
49*0Sstevel@tonic-gate ** The ndbm flags that are equivalent to the smdb flags.
50*0Sstevel@tonic-gate **
51*0Sstevel@tonic-gate ** Notes:
52*0Sstevel@tonic-gate ** Any invalid flags are ignored.
53*0Sstevel@tonic-gate **
54*0Sstevel@tonic-gate */
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate int
smdb_put_flags_to_ndbm_flags(flags)57*0Sstevel@tonic-gate smdb_put_flags_to_ndbm_flags(flags)
58*0Sstevel@tonic-gate SMDB_FLAG flags;
59*0Sstevel@tonic-gate {
60*0Sstevel@tonic-gate int return_flags;
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate return_flags = 0;
63*0Sstevel@tonic-gate if (bitset(SMDBF_NO_OVERWRITE, flags))
64*0Sstevel@tonic-gate return_flags = DBM_INSERT;
65*0Sstevel@tonic-gate else
66*0Sstevel@tonic-gate return_flags = DBM_REPLACE;
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate return return_flags;
69*0Sstevel@tonic-gate }
70*0Sstevel@tonic-gate
71*0Sstevel@tonic-gate /*
72*0Sstevel@tonic-gate ** Except for smdb_ndbm_open, the rest of these function correspond to the
73*0Sstevel@tonic-gate ** interface laid out in smdb.h.
74*0Sstevel@tonic-gate */
75*0Sstevel@tonic-gate
76*0Sstevel@tonic-gate SMDB_DBM_DATABASE *
smdbm_malloc_database()77*0Sstevel@tonic-gate smdbm_malloc_database()
78*0Sstevel@tonic-gate {
79*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db;
80*0Sstevel@tonic-gate
81*0Sstevel@tonic-gate db = (SMDB_DBM_DATABASE *) malloc(sizeof(SMDB_DBM_DATABASE));
82*0Sstevel@tonic-gate if (db != NULL)
83*0Sstevel@tonic-gate {
84*0Sstevel@tonic-gate db->smndbm_dbm = NULL;
85*0Sstevel@tonic-gate db->smndbm_lock_fd = -1;
86*0Sstevel@tonic-gate db->smndbm_cursor_in_use = false;
87*0Sstevel@tonic-gate }
88*0Sstevel@tonic-gate
89*0Sstevel@tonic-gate return db;
90*0Sstevel@tonic-gate }
91*0Sstevel@tonic-gate
92*0Sstevel@tonic-gate int
smdbm_close(database)93*0Sstevel@tonic-gate smdbm_close(database)
94*0Sstevel@tonic-gate SMDB_DATABASE *database;
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl;
97*0Sstevel@tonic-gate DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm;
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gate dbm_close(dbm);
100*0Sstevel@tonic-gate if (db->smndbm_lock_fd != -1)
101*0Sstevel@tonic-gate close(db->smndbm_lock_fd);
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate free(db);
104*0Sstevel@tonic-gate database->smdb_impl = NULL;
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gate return SMDBE_OK;
107*0Sstevel@tonic-gate }
108*0Sstevel@tonic-gate
109*0Sstevel@tonic-gate int
smdbm_del(database,key,flags)110*0Sstevel@tonic-gate smdbm_del(database, key, flags)
111*0Sstevel@tonic-gate SMDB_DATABASE *database;
112*0Sstevel@tonic-gate SMDB_DBENT *key;
113*0Sstevel@tonic-gate unsigned int flags;
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate int result;
116*0Sstevel@tonic-gate DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm;
117*0Sstevel@tonic-gate datum dbkey;
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
120*0Sstevel@tonic-gate dbkey.dptr = key->data;
121*0Sstevel@tonic-gate dbkey.dsize = key->size;
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate errno = 0;
124*0Sstevel@tonic-gate result = dbm_delete(dbm, dbkey);
125*0Sstevel@tonic-gate if (result != 0)
126*0Sstevel@tonic-gate {
127*0Sstevel@tonic-gate int save_errno = errno;
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gate if (dbm_error(dbm))
130*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
131*0Sstevel@tonic-gate
132*0Sstevel@tonic-gate if (save_errno != 0)
133*0Sstevel@tonic-gate return save_errno;
134*0Sstevel@tonic-gate
135*0Sstevel@tonic-gate return SMDBE_NOT_FOUND;
136*0Sstevel@tonic-gate }
137*0Sstevel@tonic-gate return SMDBE_OK;
138*0Sstevel@tonic-gate }
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate int
smdbm_fd(database,fd)141*0Sstevel@tonic-gate smdbm_fd(database, fd)
142*0Sstevel@tonic-gate SMDB_DATABASE *database;
143*0Sstevel@tonic-gate int *fd;
144*0Sstevel@tonic-gate {
145*0Sstevel@tonic-gate DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm;
146*0Sstevel@tonic-gate
147*0Sstevel@tonic-gate *fd = dbm_dirfno(dbm);
148*0Sstevel@tonic-gate if (*fd <= 0)
149*0Sstevel@tonic-gate return EINVAL;
150*0Sstevel@tonic-gate
151*0Sstevel@tonic-gate return SMDBE_OK;
152*0Sstevel@tonic-gate }
153*0Sstevel@tonic-gate
154*0Sstevel@tonic-gate int
smdbm_lockfd(database)155*0Sstevel@tonic-gate smdbm_lockfd(database)
156*0Sstevel@tonic-gate SMDB_DATABASE *database;
157*0Sstevel@tonic-gate {
158*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl;
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate return db->smndbm_lock_fd;
161*0Sstevel@tonic-gate }
162*0Sstevel@tonic-gate
163*0Sstevel@tonic-gate int
smdbm_get(database,key,data,flags)164*0Sstevel@tonic-gate smdbm_get(database, key, data, flags)
165*0Sstevel@tonic-gate SMDB_DATABASE *database;
166*0Sstevel@tonic-gate SMDB_DBENT *key;
167*0Sstevel@tonic-gate SMDB_DBENT *data;
168*0Sstevel@tonic-gate unsigned int flags;
169*0Sstevel@tonic-gate {
170*0Sstevel@tonic-gate DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm;
171*0Sstevel@tonic-gate datum dbkey, dbdata;
172*0Sstevel@tonic-gate
173*0Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
174*0Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
175*0Sstevel@tonic-gate dbkey.dptr = key->data;
176*0Sstevel@tonic-gate dbkey.dsize = key->size;
177*0Sstevel@tonic-gate
178*0Sstevel@tonic-gate errno = 0;
179*0Sstevel@tonic-gate dbdata = dbm_fetch(dbm, dbkey);
180*0Sstevel@tonic-gate if (dbdata.dptr == NULL)
181*0Sstevel@tonic-gate {
182*0Sstevel@tonic-gate int save_errno = errno;
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate if (dbm_error(dbm))
185*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate if (save_errno != 0)
188*0Sstevel@tonic-gate return save_errno;
189*0Sstevel@tonic-gate
190*0Sstevel@tonic-gate return SMDBE_NOT_FOUND;
191*0Sstevel@tonic-gate }
192*0Sstevel@tonic-gate data->data = dbdata.dptr;
193*0Sstevel@tonic-gate data->size = dbdata.dsize;
194*0Sstevel@tonic-gate return SMDBE_OK;
195*0Sstevel@tonic-gate }
196*0Sstevel@tonic-gate
197*0Sstevel@tonic-gate int
smdbm_put(database,key,data,flags)198*0Sstevel@tonic-gate smdbm_put(database, key, data, flags)
199*0Sstevel@tonic-gate SMDB_DATABASE *database;
200*0Sstevel@tonic-gate SMDB_DBENT *key;
201*0Sstevel@tonic-gate SMDB_DBENT *data;
202*0Sstevel@tonic-gate unsigned int flags;
203*0Sstevel@tonic-gate {
204*0Sstevel@tonic-gate int result;
205*0Sstevel@tonic-gate int save_errno;
206*0Sstevel@tonic-gate DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm;
207*0Sstevel@tonic-gate datum dbkey, dbdata;
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
210*0Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
211*0Sstevel@tonic-gate dbkey.dptr = key->data;
212*0Sstevel@tonic-gate dbkey.dsize = key->size;
213*0Sstevel@tonic-gate dbdata.dptr = data->data;
214*0Sstevel@tonic-gate dbdata.dsize = data->size;
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gate errno = 0;
217*0Sstevel@tonic-gate result = dbm_store(dbm, dbkey, dbdata,
218*0Sstevel@tonic-gate smdb_put_flags_to_ndbm_flags(flags));
219*0Sstevel@tonic-gate switch (result)
220*0Sstevel@tonic-gate {
221*0Sstevel@tonic-gate case 1:
222*0Sstevel@tonic-gate return SMDBE_DUPLICATE;
223*0Sstevel@tonic-gate
224*0Sstevel@tonic-gate case 0:
225*0Sstevel@tonic-gate return SMDBE_OK;
226*0Sstevel@tonic-gate
227*0Sstevel@tonic-gate default:
228*0Sstevel@tonic-gate save_errno = errno;
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate if (dbm_error(dbm))
231*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
232*0Sstevel@tonic-gate
233*0Sstevel@tonic-gate if (save_errno != 0)
234*0Sstevel@tonic-gate return save_errno;
235*0Sstevel@tonic-gate
236*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
237*0Sstevel@tonic-gate }
238*0Sstevel@tonic-gate /* NOTREACHED */
239*0Sstevel@tonic-gate }
240*0Sstevel@tonic-gate
241*0Sstevel@tonic-gate int
smndbm_set_owner(database,uid,gid)242*0Sstevel@tonic-gate smndbm_set_owner(database, uid, gid)
243*0Sstevel@tonic-gate SMDB_DATABASE *database;
244*0Sstevel@tonic-gate uid_t uid;
245*0Sstevel@tonic-gate gid_t gid;
246*0Sstevel@tonic-gate {
247*0Sstevel@tonic-gate # if HASFCHOWN
248*0Sstevel@tonic-gate int fd;
249*0Sstevel@tonic-gate int result;
250*0Sstevel@tonic-gate DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm;
251*0Sstevel@tonic-gate
252*0Sstevel@tonic-gate fd = dbm_dirfno(dbm);
253*0Sstevel@tonic-gate if (fd <= 0)
254*0Sstevel@tonic-gate return EINVAL;
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gate result = fchown(fd, uid, gid);
257*0Sstevel@tonic-gate if (result < 0)
258*0Sstevel@tonic-gate return errno;
259*0Sstevel@tonic-gate
260*0Sstevel@tonic-gate fd = dbm_pagfno(dbm);
261*0Sstevel@tonic-gate if (fd <= 0)
262*0Sstevel@tonic-gate return EINVAL;
263*0Sstevel@tonic-gate
264*0Sstevel@tonic-gate result = fchown(fd, uid, gid);
265*0Sstevel@tonic-gate if (result < 0)
266*0Sstevel@tonic-gate return errno;
267*0Sstevel@tonic-gate # endif /* HASFCHOWN */
268*0Sstevel@tonic-gate
269*0Sstevel@tonic-gate return SMDBE_OK;
270*0Sstevel@tonic-gate }
271*0Sstevel@tonic-gate
272*0Sstevel@tonic-gate int
smdbm_sync(database,flags)273*0Sstevel@tonic-gate smdbm_sync(database, flags)
274*0Sstevel@tonic-gate SMDB_DATABASE *database;
275*0Sstevel@tonic-gate unsigned int flags;
276*0Sstevel@tonic-gate {
277*0Sstevel@tonic-gate return SMDBE_UNSUPPORTED;
278*0Sstevel@tonic-gate }
279*0Sstevel@tonic-gate
280*0Sstevel@tonic-gate int
smdbm_cursor_close(cursor)281*0Sstevel@tonic-gate smdbm_cursor_close(cursor)
282*0Sstevel@tonic-gate SMDB_CURSOR *cursor;
283*0Sstevel@tonic-gate {
284*0Sstevel@tonic-gate SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl;
285*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db;
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate if (!db->smndbm_cursor_in_use)
288*0Sstevel@tonic-gate return SMDBE_NOT_A_VALID_CURSOR;
289*0Sstevel@tonic-gate
290*0Sstevel@tonic-gate db->smndbm_cursor_in_use = false;
291*0Sstevel@tonic-gate free(dbm_cursor);
292*0Sstevel@tonic-gate free(cursor);
293*0Sstevel@tonic-gate
294*0Sstevel@tonic-gate return SMDBE_OK;
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate
297*0Sstevel@tonic-gate int
smdbm_cursor_del(cursor,flags)298*0Sstevel@tonic-gate smdbm_cursor_del(cursor, flags)
299*0Sstevel@tonic-gate SMDB_CURSOR *cursor;
300*0Sstevel@tonic-gate unsigned int flags;
301*0Sstevel@tonic-gate {
302*0Sstevel@tonic-gate int result;
303*0Sstevel@tonic-gate SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl;
304*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db;
305*0Sstevel@tonic-gate DBM *dbm = db->smndbm_dbm;
306*0Sstevel@tonic-gate
307*0Sstevel@tonic-gate errno = 0;
308*0Sstevel@tonic-gate result = dbm_delete(dbm, dbm_cursor->smndbmc_current_key);
309*0Sstevel@tonic-gate if (result != 0)
310*0Sstevel@tonic-gate {
311*0Sstevel@tonic-gate int save_errno = errno;
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gate if (dbm_error(dbm))
314*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate if (save_errno != 0)
317*0Sstevel@tonic-gate return save_errno;
318*0Sstevel@tonic-gate
319*0Sstevel@tonic-gate return SMDBE_NOT_FOUND;
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate return SMDBE_OK;
322*0Sstevel@tonic-gate }
323*0Sstevel@tonic-gate
324*0Sstevel@tonic-gate int
smdbm_cursor_get(cursor,key,value,flags)325*0Sstevel@tonic-gate smdbm_cursor_get(cursor, key, value, flags)
326*0Sstevel@tonic-gate SMDB_CURSOR *cursor;
327*0Sstevel@tonic-gate SMDB_DBENT *key;
328*0Sstevel@tonic-gate SMDB_DBENT *value;
329*0Sstevel@tonic-gate SMDB_FLAG flags;
330*0Sstevel@tonic-gate {
331*0Sstevel@tonic-gate SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl;
332*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db;
333*0Sstevel@tonic-gate DBM *dbm = db->smndbm_dbm;
334*0Sstevel@tonic-gate datum dbkey, dbdata;
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate (void) memset(&dbkey, '\0', sizeof dbkey);
337*0Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
338*0Sstevel@tonic-gate
339*0Sstevel@tonic-gate if (flags == SMDB_CURSOR_GET_RANGE)
340*0Sstevel@tonic-gate return SMDBE_UNSUPPORTED;
341*0Sstevel@tonic-gate
342*0Sstevel@tonic-gate if (dbm_cursor->smndbmc_current_key.dptr == NULL)
343*0Sstevel@tonic-gate {
344*0Sstevel@tonic-gate dbm_cursor->smndbmc_current_key = dbm_firstkey(dbm);
345*0Sstevel@tonic-gate if (dbm_cursor->smndbmc_current_key.dptr == NULL)
346*0Sstevel@tonic-gate {
347*0Sstevel@tonic-gate if (dbm_error(dbm))
348*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
349*0Sstevel@tonic-gate return SMDBE_LAST_ENTRY;
350*0Sstevel@tonic-gate }
351*0Sstevel@tonic-gate }
352*0Sstevel@tonic-gate else
353*0Sstevel@tonic-gate {
354*0Sstevel@tonic-gate dbm_cursor->smndbmc_current_key = dbm_nextkey(dbm);
355*0Sstevel@tonic-gate if (dbm_cursor->smndbmc_current_key.dptr == NULL)
356*0Sstevel@tonic-gate {
357*0Sstevel@tonic-gate if (dbm_error(dbm))
358*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
359*0Sstevel@tonic-gate return SMDBE_LAST_ENTRY;
360*0Sstevel@tonic-gate }
361*0Sstevel@tonic-gate }
362*0Sstevel@tonic-gate
363*0Sstevel@tonic-gate errno = 0;
364*0Sstevel@tonic-gate dbdata = dbm_fetch(dbm, dbm_cursor->smndbmc_current_key);
365*0Sstevel@tonic-gate if (dbdata.dptr == NULL)
366*0Sstevel@tonic-gate {
367*0Sstevel@tonic-gate int save_errno = errno;
368*0Sstevel@tonic-gate
369*0Sstevel@tonic-gate if (dbm_error(dbm))
370*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
371*0Sstevel@tonic-gate
372*0Sstevel@tonic-gate if (save_errno != 0)
373*0Sstevel@tonic-gate return save_errno;
374*0Sstevel@tonic-gate
375*0Sstevel@tonic-gate return SMDBE_NOT_FOUND;
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate value->data = dbdata.dptr;
378*0Sstevel@tonic-gate value->size = dbdata.dsize;
379*0Sstevel@tonic-gate key->data = dbm_cursor->smndbmc_current_key.dptr;
380*0Sstevel@tonic-gate key->size = dbm_cursor->smndbmc_current_key.dsize;
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gate return SMDBE_OK;
383*0Sstevel@tonic-gate }
384*0Sstevel@tonic-gate
385*0Sstevel@tonic-gate int
smdbm_cursor_put(cursor,key,value,flags)386*0Sstevel@tonic-gate smdbm_cursor_put(cursor, key, value, flags)
387*0Sstevel@tonic-gate SMDB_CURSOR *cursor;
388*0Sstevel@tonic-gate SMDB_DBENT *key;
389*0Sstevel@tonic-gate SMDB_DBENT *value;
390*0Sstevel@tonic-gate SMDB_FLAG flags;
391*0Sstevel@tonic-gate {
392*0Sstevel@tonic-gate int result;
393*0Sstevel@tonic-gate int save_errno;
394*0Sstevel@tonic-gate SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl;
395*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db;
396*0Sstevel@tonic-gate DBM *dbm = db->smndbm_dbm;
397*0Sstevel@tonic-gate datum dbdata;
398*0Sstevel@tonic-gate
399*0Sstevel@tonic-gate (void) memset(&dbdata, '\0', sizeof dbdata);
400*0Sstevel@tonic-gate dbdata.dptr = value->data;
401*0Sstevel@tonic-gate dbdata.dsize = value->size;
402*0Sstevel@tonic-gate
403*0Sstevel@tonic-gate errno = 0;
404*0Sstevel@tonic-gate result = dbm_store(dbm, dbm_cursor->smndbmc_current_key, dbdata,
405*0Sstevel@tonic-gate smdb_put_flags_to_ndbm_flags(flags));
406*0Sstevel@tonic-gate switch (result)
407*0Sstevel@tonic-gate {
408*0Sstevel@tonic-gate case 1:
409*0Sstevel@tonic-gate return SMDBE_DUPLICATE;
410*0Sstevel@tonic-gate
411*0Sstevel@tonic-gate case 0:
412*0Sstevel@tonic-gate return SMDBE_OK;
413*0Sstevel@tonic-gate
414*0Sstevel@tonic-gate default:
415*0Sstevel@tonic-gate save_errno = errno;
416*0Sstevel@tonic-gate
417*0Sstevel@tonic-gate if (dbm_error(dbm))
418*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
419*0Sstevel@tonic-gate
420*0Sstevel@tonic-gate if (save_errno != 0)
421*0Sstevel@tonic-gate return save_errno;
422*0Sstevel@tonic-gate
423*0Sstevel@tonic-gate return SMDBE_IO_ERROR;
424*0Sstevel@tonic-gate }
425*0Sstevel@tonic-gate /* NOTREACHED */
426*0Sstevel@tonic-gate }
427*0Sstevel@tonic-gate
428*0Sstevel@tonic-gate int
smdbm_cursor(database,cursor,flags)429*0Sstevel@tonic-gate smdbm_cursor(database, cursor, flags)
430*0Sstevel@tonic-gate SMDB_DATABASE *database;
431*0Sstevel@tonic-gate SMDB_CURSOR **cursor;
432*0Sstevel@tonic-gate SMDB_FLAG flags;
433*0Sstevel@tonic-gate {
434*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl;
435*0Sstevel@tonic-gate SMDB_CURSOR *cur;
436*0Sstevel@tonic-gate SMDB_DBM_CURSOR *dbm_cursor;
437*0Sstevel@tonic-gate
438*0Sstevel@tonic-gate if (db->smndbm_cursor_in_use)
439*0Sstevel@tonic-gate return SMDBE_ONLY_SUPPORTS_ONE_CURSOR;
440*0Sstevel@tonic-gate
441*0Sstevel@tonic-gate db->smndbm_cursor_in_use = true;
442*0Sstevel@tonic-gate dbm_cursor = (SMDB_DBM_CURSOR *) malloc(sizeof(SMDB_DBM_CURSOR));
443*0Sstevel@tonic-gate dbm_cursor->smndbmc_db = db;
444*0Sstevel@tonic-gate dbm_cursor->smndbmc_current_key.dptr = NULL;
445*0Sstevel@tonic-gate dbm_cursor->smndbmc_current_key.dsize = 0;
446*0Sstevel@tonic-gate
447*0Sstevel@tonic-gate cur = (SMDB_CURSOR*) malloc(sizeof(SMDB_CURSOR));
448*0Sstevel@tonic-gate if (cur == NULL)
449*0Sstevel@tonic-gate return SMDBE_MALLOC;
450*0Sstevel@tonic-gate
451*0Sstevel@tonic-gate cur->smdbc_impl = dbm_cursor;
452*0Sstevel@tonic-gate cur->smdbc_close = smdbm_cursor_close;
453*0Sstevel@tonic-gate cur->smdbc_del = smdbm_cursor_del;
454*0Sstevel@tonic-gate cur->smdbc_get = smdbm_cursor_get;
455*0Sstevel@tonic-gate cur->smdbc_put = smdbm_cursor_put;
456*0Sstevel@tonic-gate *cursor = cur;
457*0Sstevel@tonic-gate
458*0Sstevel@tonic-gate return SMDBE_OK;
459*0Sstevel@tonic-gate }
460*0Sstevel@tonic-gate /*
461*0Sstevel@tonic-gate ** SMDB_NDBM_OPEN -- Opens a ndbm database.
462*0Sstevel@tonic-gate **
463*0Sstevel@tonic-gate ** Parameters:
464*0Sstevel@tonic-gate ** database -- An unallocated database pointer to a pointer.
465*0Sstevel@tonic-gate ** db_name -- The name of the database without extension.
466*0Sstevel@tonic-gate ** mode -- File permisions on a created database.
467*0Sstevel@tonic-gate ** mode_mask -- Mode bits that much match on an opened database.
468*0Sstevel@tonic-gate ** sff -- Flags to safefile.
469*0Sstevel@tonic-gate ** type -- The type of database to open.
470*0Sstevel@tonic-gate ** Only SMDB_NDBM is supported.
471*0Sstevel@tonic-gate ** user_info -- Information on the user to use for file
472*0Sstevel@tonic-gate ** permissions.
473*0Sstevel@tonic-gate ** db_params -- No params are supported.
474*0Sstevel@tonic-gate **
475*0Sstevel@tonic-gate ** Returns:
476*0Sstevel@tonic-gate ** SMDBE_OK -- Success, otherwise errno:
477*0Sstevel@tonic-gate ** SMDBE_MALLOC -- Cannot allocate memory.
478*0Sstevel@tonic-gate ** SMDBE_UNSUPPORTED -- The type is not supported.
479*0Sstevel@tonic-gate ** SMDBE_GDBM_IS_BAD -- We have detected GDBM and we don't
480*0Sstevel@tonic-gate ** like it.
481*0Sstevel@tonic-gate ** SMDBE_BAD_OPEN -- dbm_open failed and errno was not set.
482*0Sstevel@tonic-gate ** Anything else: errno
483*0Sstevel@tonic-gate */
484*0Sstevel@tonic-gate
485*0Sstevel@tonic-gate int
smdb_ndbm_open(database,db_name,mode,mode_mask,sff,type,user_info,db_params)486*0Sstevel@tonic-gate smdb_ndbm_open(database, db_name, mode, mode_mask, sff, type, user_info,
487*0Sstevel@tonic-gate db_params)
488*0Sstevel@tonic-gate SMDB_DATABASE **database;
489*0Sstevel@tonic-gate char *db_name;
490*0Sstevel@tonic-gate int mode;
491*0Sstevel@tonic-gate int mode_mask;
492*0Sstevel@tonic-gate long sff;
493*0Sstevel@tonic-gate SMDB_DBTYPE type;
494*0Sstevel@tonic-gate SMDB_USER_INFO *user_info;
495*0Sstevel@tonic-gate SMDB_DBPARAMS *db_params;
496*0Sstevel@tonic-gate {
497*0Sstevel@tonic-gate bool lockcreated = false;
498*0Sstevel@tonic-gate int result;
499*0Sstevel@tonic-gate int lock_fd;
500*0Sstevel@tonic-gate SMDB_DATABASE *smdb_db;
501*0Sstevel@tonic-gate SMDB_DBM_DATABASE *db;
502*0Sstevel@tonic-gate DBM *dbm = NULL;
503*0Sstevel@tonic-gate struct stat dir_stat_info;
504*0Sstevel@tonic-gate struct stat pag_stat_info;
505*0Sstevel@tonic-gate
506*0Sstevel@tonic-gate result = SMDBE_OK;
507*0Sstevel@tonic-gate *database = NULL;
508*0Sstevel@tonic-gate
509*0Sstevel@tonic-gate if (type == NULL)
510*0Sstevel@tonic-gate return SMDBE_UNKNOWN_DB_TYPE;
511*0Sstevel@tonic-gate
512*0Sstevel@tonic-gate result = smdb_setup_file(db_name, SMNDB_DIR_FILE_EXTENSION, mode_mask,
513*0Sstevel@tonic-gate sff, user_info, &dir_stat_info);
514*0Sstevel@tonic-gate if (result != SMDBE_OK)
515*0Sstevel@tonic-gate return result;
516*0Sstevel@tonic-gate
517*0Sstevel@tonic-gate result = smdb_setup_file(db_name, SMNDB_PAG_FILE_EXTENSION, mode_mask,
518*0Sstevel@tonic-gate sff, user_info, &pag_stat_info);
519*0Sstevel@tonic-gate if (result != SMDBE_OK)
520*0Sstevel@tonic-gate return result;
521*0Sstevel@tonic-gate
522*0Sstevel@tonic-gate if ((dir_stat_info.st_mode == ST_MODE_NOFILE ||
523*0Sstevel@tonic-gate pag_stat_info.st_mode == ST_MODE_NOFILE) &&
524*0Sstevel@tonic-gate bitset(mode, O_CREAT))
525*0Sstevel@tonic-gate lockcreated = true;
526*0Sstevel@tonic-gate
527*0Sstevel@tonic-gate lock_fd = -1;
528*0Sstevel@tonic-gate result = smdb_lock_file(&lock_fd, db_name, mode, sff,
529*0Sstevel@tonic-gate SMNDB_DIR_FILE_EXTENSION);
530*0Sstevel@tonic-gate if (result != SMDBE_OK)
531*0Sstevel@tonic-gate return result;
532*0Sstevel@tonic-gate
533*0Sstevel@tonic-gate if (lockcreated)
534*0Sstevel@tonic-gate {
535*0Sstevel@tonic-gate int pag_fd;
536*0Sstevel@tonic-gate
537*0Sstevel@tonic-gate /* Need to pre-open the .pag file as well with O_EXCL */
538*0Sstevel@tonic-gate result = smdb_lock_file(&pag_fd, db_name, mode, sff,
539*0Sstevel@tonic-gate SMNDB_PAG_FILE_EXTENSION);
540*0Sstevel@tonic-gate if (result != SMDBE_OK)
541*0Sstevel@tonic-gate {
542*0Sstevel@tonic-gate (void) close(lock_fd);
543*0Sstevel@tonic-gate return result;
544*0Sstevel@tonic-gate }
545*0Sstevel@tonic-gate (void) close(pag_fd);
546*0Sstevel@tonic-gate
547*0Sstevel@tonic-gate mode |= O_TRUNC;
548*0Sstevel@tonic-gate mode &= ~(O_CREAT|O_EXCL);
549*0Sstevel@tonic-gate }
550*0Sstevel@tonic-gate
551*0Sstevel@tonic-gate smdb_db = smdb_malloc_database();
552*0Sstevel@tonic-gate if (smdb_db == NULL)
553*0Sstevel@tonic-gate result = SMDBE_MALLOC;
554*0Sstevel@tonic-gate
555*0Sstevel@tonic-gate db = smdbm_malloc_database();
556*0Sstevel@tonic-gate if (db == NULL)
557*0Sstevel@tonic-gate result = SMDBE_MALLOC;
558*0Sstevel@tonic-gate
559*0Sstevel@tonic-gate /* Try to open database */
560*0Sstevel@tonic-gate if (result == SMDBE_OK)
561*0Sstevel@tonic-gate {
562*0Sstevel@tonic-gate db->smndbm_lock_fd = lock_fd;
563*0Sstevel@tonic-gate
564*0Sstevel@tonic-gate errno = 0;
565*0Sstevel@tonic-gate dbm = dbm_open(db_name, mode, DBMMODE);
566*0Sstevel@tonic-gate if (dbm == NULL)
567*0Sstevel@tonic-gate {
568*0Sstevel@tonic-gate if (errno == 0)
569*0Sstevel@tonic-gate result = SMDBE_BAD_OPEN;
570*0Sstevel@tonic-gate else
571*0Sstevel@tonic-gate result = errno;
572*0Sstevel@tonic-gate }
573*0Sstevel@tonic-gate db->smndbm_dbm = dbm;
574*0Sstevel@tonic-gate }
575*0Sstevel@tonic-gate
576*0Sstevel@tonic-gate /* Check for GDBM */
577*0Sstevel@tonic-gate if (result == SMDBE_OK)
578*0Sstevel@tonic-gate {
579*0Sstevel@tonic-gate if (dbm_dirfno(dbm) == dbm_pagfno(dbm))
580*0Sstevel@tonic-gate result = SMDBE_GDBM_IS_BAD;
581*0Sstevel@tonic-gate }
582*0Sstevel@tonic-gate
583*0Sstevel@tonic-gate /* Check for filechanged */
584*0Sstevel@tonic-gate if (result == SMDBE_OK)
585*0Sstevel@tonic-gate {
586*0Sstevel@tonic-gate result = smdb_filechanged(db_name, SMNDB_DIR_FILE_EXTENSION,
587*0Sstevel@tonic-gate dbm_dirfno(dbm), &dir_stat_info);
588*0Sstevel@tonic-gate if (result == SMDBE_OK)
589*0Sstevel@tonic-gate {
590*0Sstevel@tonic-gate result = smdb_filechanged(db_name,
591*0Sstevel@tonic-gate SMNDB_PAG_FILE_EXTENSION,
592*0Sstevel@tonic-gate dbm_pagfno(dbm),
593*0Sstevel@tonic-gate &pag_stat_info);
594*0Sstevel@tonic-gate }
595*0Sstevel@tonic-gate }
596*0Sstevel@tonic-gate
597*0Sstevel@tonic-gate /* XXX Got to get fchown stuff in here */
598*0Sstevel@tonic-gate
599*0Sstevel@tonic-gate /* Setup driver if everything is ok */
600*0Sstevel@tonic-gate if (result == SMDBE_OK)
601*0Sstevel@tonic-gate {
602*0Sstevel@tonic-gate *database = smdb_db;
603*0Sstevel@tonic-gate
604*0Sstevel@tonic-gate smdb_db->smdb_close = smdbm_close;
605*0Sstevel@tonic-gate smdb_db->smdb_del = smdbm_del;
606*0Sstevel@tonic-gate smdb_db->smdb_fd = smdbm_fd;
607*0Sstevel@tonic-gate smdb_db->smdb_lockfd = smdbm_lockfd;
608*0Sstevel@tonic-gate smdb_db->smdb_get = smdbm_get;
609*0Sstevel@tonic-gate smdb_db->smdb_put = smdbm_put;
610*0Sstevel@tonic-gate smdb_db->smdb_set_owner = smndbm_set_owner;
611*0Sstevel@tonic-gate smdb_db->smdb_sync = smdbm_sync;
612*0Sstevel@tonic-gate smdb_db->smdb_cursor = smdbm_cursor;
613*0Sstevel@tonic-gate
614*0Sstevel@tonic-gate smdb_db->smdb_impl = db;
615*0Sstevel@tonic-gate
616*0Sstevel@tonic-gate return SMDBE_OK;
617*0Sstevel@tonic-gate }
618*0Sstevel@tonic-gate
619*0Sstevel@tonic-gate /* If we're here, something bad happened, clean up */
620*0Sstevel@tonic-gate if (dbm != NULL)
621*0Sstevel@tonic-gate dbm_close(dbm);
622*0Sstevel@tonic-gate
623*0Sstevel@tonic-gate smdb_unlock_file(db->smndbm_lock_fd);
624*0Sstevel@tonic-gate free(db);
625*0Sstevel@tonic-gate smdb_free_database(smdb_db);
626*0Sstevel@tonic-gate
627*0Sstevel@tonic-gate return result;
628*0Sstevel@tonic-gate }
629*0Sstevel@tonic-gate #endif /* NDBM */
630