164562Sgshapiro/* 2261363Sgshapiro** Copyright (c) 1999-2002 Proofpoint, Inc. and its suppliers. 364562Sgshapiro** All rights reserved. 464562Sgshapiro** 564562Sgshapiro** By using this file, you agree to the terms and conditions set 664562Sgshapiro** forth in the LICENSE file which can be found at the top level of 764562Sgshapiro** the sendmail distribution. 864562Sgshapiro*/ 964562Sgshapiro 1090792Sgshapiro#include <sm/gen.h> 11266692SgshapiroSM_RCSID("@(#)$Id: smndbm.c,v 8.55 2013-11-22 20:51:49 ca Exp $") 1264562Sgshapiro 1364562Sgshapiro#include <fcntl.h> 1464562Sgshapiro#include <stdlib.h> 1564562Sgshapiro#include <unistd.h> 1664562Sgshapiro 1764562Sgshapiro#include <sendmail/sendmail.h> 1864562Sgshapiro#include <libsmdb/smdb.h> 1964562Sgshapiro 2064562Sgshapiro#ifdef NDBM 2164562Sgshapiro 2264562Sgshapiro# define SMNDB_DIR_FILE_EXTENSION "dir" 2364562Sgshapiro# define SMNDB_PAG_FILE_EXTENSION "pag" 2464562Sgshapiro 2564562Sgshapirostruct smdb_dbm_database_struct 2664562Sgshapiro{ 2764562Sgshapiro DBM *smndbm_dbm; 2864562Sgshapiro int smndbm_lock_fd; 2964562Sgshapiro bool smndbm_cursor_in_use; 3064562Sgshapiro}; 3164562Sgshapirotypedef struct smdb_dbm_database_struct SMDB_DBM_DATABASE; 3264562Sgshapiro 3364562Sgshapirostruct smdb_dbm_cursor_struct 3464562Sgshapiro{ 3564562Sgshapiro SMDB_DBM_DATABASE *smndbmc_db; 3664562Sgshapiro datum smndbmc_current_key; 3764562Sgshapiro}; 3864562Sgshapirotypedef struct smdb_dbm_cursor_struct SMDB_DBM_CURSOR; 3964562Sgshapiro 4090792Sgshapiro/* 4164562Sgshapiro** SMDB_PUT_FLAGS_TO_NDBM_FLAGS -- Translates smdb put flags to ndbm put flags. 4264562Sgshapiro** 4364562Sgshapiro** Parameters: 4464562Sgshapiro** flags -- The flags to translate. 4564562Sgshapiro** 4664562Sgshapiro** Returns: 4764562Sgshapiro** The ndbm flags that are equivalent to the smdb flags. 4864562Sgshapiro** 4964562Sgshapiro** Notes: 5064562Sgshapiro** Any invalid flags are ignored. 5164562Sgshapiro** 5264562Sgshapiro*/ 5364562Sgshapiro 5464562Sgshapiroint 5564562Sgshapirosmdb_put_flags_to_ndbm_flags(flags) 5664562Sgshapiro SMDB_FLAG flags; 5764562Sgshapiro{ 5864562Sgshapiro int return_flags; 5964562Sgshapiro 6064562Sgshapiro return_flags = 0; 6164562Sgshapiro if (bitset(SMDBF_NO_OVERWRITE, flags)) 6264562Sgshapiro return_flags = DBM_INSERT; 6364562Sgshapiro else 6464562Sgshapiro return_flags = DBM_REPLACE; 6564562Sgshapiro 6664562Sgshapiro return return_flags; 6764562Sgshapiro} 6864562Sgshapiro 6990792Sgshapiro/* 7090792Sgshapiro** Except for smdb_ndbm_open, the rest of these function correspond to the 7190792Sgshapiro** interface laid out in smdb.h. 7264562Sgshapiro*/ 7364562Sgshapiro 7464562SgshapiroSMDB_DBM_DATABASE * 7564562Sgshapirosmdbm_malloc_database() 7664562Sgshapiro{ 7764562Sgshapiro SMDB_DBM_DATABASE *db; 7864562Sgshapiro 7964562Sgshapiro db = (SMDB_DBM_DATABASE *) malloc(sizeof(SMDB_DBM_DATABASE)); 8064562Sgshapiro if (db != NULL) 8164562Sgshapiro { 8264562Sgshapiro db->smndbm_dbm = NULL; 8364562Sgshapiro db->smndbm_lock_fd = -1; 8490792Sgshapiro db->smndbm_cursor_in_use = false; 8564562Sgshapiro } 8664562Sgshapiro 8764562Sgshapiro return db; 8864562Sgshapiro} 8964562Sgshapiro 9064562Sgshapiroint 9164562Sgshapirosmdbm_close(database) 9264562Sgshapiro SMDB_DATABASE *database; 9364562Sgshapiro{ 9464562Sgshapiro SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl; 9564562Sgshapiro DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; 9664562Sgshapiro 9764562Sgshapiro dbm_close(dbm); 9864562Sgshapiro if (db->smndbm_lock_fd != -1) 9964562Sgshapiro close(db->smndbm_lock_fd); 10064562Sgshapiro 10164562Sgshapiro free(db); 10264562Sgshapiro database->smdb_impl = NULL; 10364562Sgshapiro 10464562Sgshapiro return SMDBE_OK; 10564562Sgshapiro} 10664562Sgshapiro 10764562Sgshapiroint 10864562Sgshapirosmdbm_del(database, key, flags) 10964562Sgshapiro SMDB_DATABASE *database; 11064562Sgshapiro SMDB_DBENT *key; 11190792Sgshapiro unsigned int flags; 11264562Sgshapiro{ 11364562Sgshapiro int result; 11464562Sgshapiro DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; 11571345Sgshapiro datum dbkey; 11664562Sgshapiro 11790792Sgshapiro (void) memset(&dbkey, '\0', sizeof dbkey); 11871345Sgshapiro dbkey.dptr = key->data; 11971345Sgshapiro dbkey.dsize = key->size; 12071345Sgshapiro 12164562Sgshapiro errno = 0; 12271345Sgshapiro result = dbm_delete(dbm, dbkey); 12364562Sgshapiro if (result != 0) 12464562Sgshapiro { 12564562Sgshapiro int save_errno = errno; 12664562Sgshapiro 12764562Sgshapiro if (dbm_error(dbm)) 12864562Sgshapiro return SMDBE_IO_ERROR; 12964562Sgshapiro 13064562Sgshapiro if (save_errno != 0) 13164562Sgshapiro return save_errno; 13264562Sgshapiro 13364562Sgshapiro return SMDBE_NOT_FOUND; 13464562Sgshapiro } 13564562Sgshapiro return SMDBE_OK; 13664562Sgshapiro} 13764562Sgshapiro 13864562Sgshapiroint 13964562Sgshapirosmdbm_fd(database, fd) 14064562Sgshapiro SMDB_DATABASE *database; 14164562Sgshapiro int *fd; 14264562Sgshapiro{ 14364562Sgshapiro DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; 14464562Sgshapiro 14564562Sgshapiro *fd = dbm_dirfno(dbm); 14664562Sgshapiro if (*fd <= 0) 14764562Sgshapiro return EINVAL; 14864562Sgshapiro 14964562Sgshapiro return SMDBE_OK; 15064562Sgshapiro} 15164562Sgshapiro 15264562Sgshapiroint 15366494Sgshapirosmdbm_lockfd(database) 15466494Sgshapiro SMDB_DATABASE *database; 15566494Sgshapiro{ 15666494Sgshapiro SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl; 15766494Sgshapiro 15866494Sgshapiro return db->smndbm_lock_fd; 15966494Sgshapiro} 16066494Sgshapiro 16166494Sgshapiroint 16264562Sgshapirosmdbm_get(database, key, data, flags) 16364562Sgshapiro SMDB_DATABASE *database; 16464562Sgshapiro SMDB_DBENT *key; 16564562Sgshapiro SMDB_DBENT *data; 16690792Sgshapiro unsigned int flags; 16764562Sgshapiro{ 16864562Sgshapiro DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; 16971345Sgshapiro datum dbkey, dbdata; 17064562Sgshapiro 17190792Sgshapiro (void) memset(&dbkey, '\0', sizeof dbkey); 17290792Sgshapiro (void) memset(&dbdata, '\0', sizeof dbdata); 17371345Sgshapiro dbkey.dptr = key->data; 17471345Sgshapiro dbkey.dsize = key->size; 17571345Sgshapiro 17664562Sgshapiro errno = 0; 17771345Sgshapiro dbdata = dbm_fetch(dbm, dbkey); 17871345Sgshapiro if (dbdata.dptr == NULL) 17964562Sgshapiro { 18064562Sgshapiro int save_errno = errno; 18164562Sgshapiro 18264562Sgshapiro if (dbm_error(dbm)) 18364562Sgshapiro return SMDBE_IO_ERROR; 18464562Sgshapiro 18564562Sgshapiro if (save_errno != 0) 18664562Sgshapiro return save_errno; 18764562Sgshapiro 18864562Sgshapiro return SMDBE_NOT_FOUND; 18964562Sgshapiro } 19071345Sgshapiro data->data = dbdata.dptr; 19171345Sgshapiro data->size = dbdata.dsize; 19264562Sgshapiro return SMDBE_OK; 19364562Sgshapiro} 19464562Sgshapiro 19564562Sgshapiroint 19664562Sgshapirosmdbm_put(database, key, data, flags) 19764562Sgshapiro SMDB_DATABASE *database; 19864562Sgshapiro SMDB_DBENT *key; 19964562Sgshapiro SMDB_DBENT *data; 20090792Sgshapiro unsigned int flags; 20164562Sgshapiro{ 20264562Sgshapiro int result; 20364562Sgshapiro int save_errno; 20464562Sgshapiro DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; 20571345Sgshapiro datum dbkey, dbdata; 20664562Sgshapiro 20790792Sgshapiro (void) memset(&dbkey, '\0', sizeof dbkey); 20890792Sgshapiro (void) memset(&dbdata, '\0', sizeof dbdata); 20971345Sgshapiro dbkey.dptr = key->data; 21071345Sgshapiro dbkey.dsize = key->size; 21171345Sgshapiro dbdata.dptr = data->data; 21271345Sgshapiro dbdata.dsize = data->size; 21371345Sgshapiro 21464562Sgshapiro errno = 0; 21571345Sgshapiro result = dbm_store(dbm, dbkey, dbdata, 21664562Sgshapiro smdb_put_flags_to_ndbm_flags(flags)); 21764562Sgshapiro switch (result) 21864562Sgshapiro { 21964562Sgshapiro case 1: 22064562Sgshapiro return SMDBE_DUPLICATE; 22164562Sgshapiro 22264562Sgshapiro case 0: 22364562Sgshapiro return SMDBE_OK; 22464562Sgshapiro 22564562Sgshapiro default: 22664562Sgshapiro save_errno = errno; 22764562Sgshapiro 22864562Sgshapiro if (dbm_error(dbm)) 22964562Sgshapiro return SMDBE_IO_ERROR; 23064562Sgshapiro 23164562Sgshapiro if (save_errno != 0) 23264562Sgshapiro return save_errno; 23364562Sgshapiro 23464562Sgshapiro return SMDBE_IO_ERROR; 23564562Sgshapiro } 23664562Sgshapiro /* NOTREACHED */ 23764562Sgshapiro} 23864562Sgshapiro 23964562Sgshapiroint 24064562Sgshapirosmndbm_set_owner(database, uid, gid) 24164562Sgshapiro SMDB_DATABASE *database; 24264562Sgshapiro uid_t uid; 24364562Sgshapiro gid_t gid; 24464562Sgshapiro{ 24564562Sgshapiro# if HASFCHOWN 24664562Sgshapiro int fd; 24764562Sgshapiro int result; 24864562Sgshapiro DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; 24964562Sgshapiro 25064562Sgshapiro fd = dbm_dirfno(dbm); 25164562Sgshapiro if (fd <= 0) 25264562Sgshapiro return EINVAL; 25364562Sgshapiro 25464562Sgshapiro result = fchown(fd, uid, gid); 25564562Sgshapiro if (result < 0) 25664562Sgshapiro return errno; 25764562Sgshapiro 25864562Sgshapiro fd = dbm_pagfno(dbm); 25964562Sgshapiro if (fd <= 0) 26064562Sgshapiro return EINVAL; 26164562Sgshapiro 26264562Sgshapiro result = fchown(fd, uid, gid); 26364562Sgshapiro if (result < 0) 26464562Sgshapiro return errno; 26564562Sgshapiro# endif /* HASFCHOWN */ 26664562Sgshapiro 26764562Sgshapiro return SMDBE_OK; 26864562Sgshapiro} 26964562Sgshapiro 27064562Sgshapiroint 27164562Sgshapirosmdbm_sync(database, flags) 27264562Sgshapiro SMDB_DATABASE *database; 27390792Sgshapiro unsigned int flags; 27464562Sgshapiro{ 27564562Sgshapiro return SMDBE_UNSUPPORTED; 27664562Sgshapiro} 27764562Sgshapiro 27864562Sgshapiroint 27964562Sgshapirosmdbm_cursor_close(cursor) 28064562Sgshapiro SMDB_CURSOR *cursor; 28164562Sgshapiro{ 28264562Sgshapiro SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; 28364562Sgshapiro SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; 28464562Sgshapiro 28564562Sgshapiro if (!db->smndbm_cursor_in_use) 28664562Sgshapiro return SMDBE_NOT_A_VALID_CURSOR; 28764562Sgshapiro 28890792Sgshapiro db->smndbm_cursor_in_use = false; 28964562Sgshapiro free(dbm_cursor); 29064562Sgshapiro free(cursor); 29164562Sgshapiro 29264562Sgshapiro return SMDBE_OK; 29364562Sgshapiro} 29464562Sgshapiro 29564562Sgshapiroint 29664562Sgshapirosmdbm_cursor_del(cursor, flags) 29764562Sgshapiro SMDB_CURSOR *cursor; 29890792Sgshapiro unsigned int flags; 29964562Sgshapiro{ 30064562Sgshapiro int result; 30164562Sgshapiro SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; 30264562Sgshapiro SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; 30364562Sgshapiro DBM *dbm = db->smndbm_dbm; 30464562Sgshapiro 30564562Sgshapiro errno = 0; 30664562Sgshapiro result = dbm_delete(dbm, dbm_cursor->smndbmc_current_key); 30764562Sgshapiro if (result != 0) 30864562Sgshapiro { 30964562Sgshapiro int save_errno = errno; 31064562Sgshapiro 31164562Sgshapiro if (dbm_error(dbm)) 31264562Sgshapiro return SMDBE_IO_ERROR; 31364562Sgshapiro 31464562Sgshapiro if (save_errno != 0) 31564562Sgshapiro return save_errno; 31664562Sgshapiro 31764562Sgshapiro return SMDBE_NOT_FOUND; 31864562Sgshapiro } 31964562Sgshapiro return SMDBE_OK; 32064562Sgshapiro} 32164562Sgshapiro 32264562Sgshapiroint 32364562Sgshapirosmdbm_cursor_get(cursor, key, value, flags) 32464562Sgshapiro SMDB_CURSOR *cursor; 32564562Sgshapiro SMDB_DBENT *key; 32664562Sgshapiro SMDB_DBENT *value; 32764562Sgshapiro SMDB_FLAG flags; 32864562Sgshapiro{ 32964562Sgshapiro SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; 33064562Sgshapiro SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; 33164562Sgshapiro DBM *dbm = db->smndbm_dbm; 33271345Sgshapiro datum dbkey, dbdata; 33364562Sgshapiro 33490792Sgshapiro (void) memset(&dbkey, '\0', sizeof dbkey); 33590792Sgshapiro (void) memset(&dbdata, '\0', sizeof dbdata); 33671345Sgshapiro 33764562Sgshapiro if (flags == SMDB_CURSOR_GET_RANGE) 33864562Sgshapiro return SMDBE_UNSUPPORTED; 33964562Sgshapiro 34064562Sgshapiro if (dbm_cursor->smndbmc_current_key.dptr == NULL) 34164562Sgshapiro { 34264562Sgshapiro dbm_cursor->smndbmc_current_key = dbm_firstkey(dbm); 34364562Sgshapiro if (dbm_cursor->smndbmc_current_key.dptr == NULL) 34464562Sgshapiro { 34564562Sgshapiro if (dbm_error(dbm)) 34664562Sgshapiro return SMDBE_IO_ERROR; 34764562Sgshapiro return SMDBE_LAST_ENTRY; 34864562Sgshapiro } 34964562Sgshapiro } 35064562Sgshapiro else 35164562Sgshapiro { 35264562Sgshapiro dbm_cursor->smndbmc_current_key = dbm_nextkey(dbm); 35364562Sgshapiro if (dbm_cursor->smndbmc_current_key.dptr == NULL) 35464562Sgshapiro { 35564562Sgshapiro if (dbm_error(dbm)) 35664562Sgshapiro return SMDBE_IO_ERROR; 35764562Sgshapiro return SMDBE_LAST_ENTRY; 35864562Sgshapiro } 35964562Sgshapiro } 36064562Sgshapiro 36164562Sgshapiro errno = 0; 36271345Sgshapiro dbdata = dbm_fetch(dbm, dbm_cursor->smndbmc_current_key); 36371345Sgshapiro if (dbdata.dptr == NULL) 36464562Sgshapiro { 36564562Sgshapiro int save_errno = errno; 36664562Sgshapiro 36764562Sgshapiro if (dbm_error(dbm)) 36864562Sgshapiro return SMDBE_IO_ERROR; 36964562Sgshapiro 37064562Sgshapiro if (save_errno != 0) 37164562Sgshapiro return save_errno; 37264562Sgshapiro 37364562Sgshapiro return SMDBE_NOT_FOUND; 37464562Sgshapiro } 37571345Sgshapiro value->data = dbdata.dptr; 37671345Sgshapiro value->size = dbdata.dsize; 37771345Sgshapiro key->data = dbm_cursor->smndbmc_current_key.dptr; 37871345Sgshapiro key->size = dbm_cursor->smndbmc_current_key.dsize; 37964562Sgshapiro 38064562Sgshapiro return SMDBE_OK; 38164562Sgshapiro} 38264562Sgshapiro 38364562Sgshapiroint 38464562Sgshapirosmdbm_cursor_put(cursor, key, value, flags) 38564562Sgshapiro SMDB_CURSOR *cursor; 38664562Sgshapiro SMDB_DBENT *key; 38764562Sgshapiro SMDB_DBENT *value; 38864562Sgshapiro SMDB_FLAG flags; 38964562Sgshapiro{ 39064562Sgshapiro int result; 39164562Sgshapiro int save_errno; 39264562Sgshapiro SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; 39364562Sgshapiro SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; 39464562Sgshapiro DBM *dbm = db->smndbm_dbm; 39571345Sgshapiro datum dbdata; 39664562Sgshapiro 39790792Sgshapiro (void) memset(&dbdata, '\0', sizeof dbdata); 39871345Sgshapiro dbdata.dptr = value->data; 39971345Sgshapiro dbdata.dsize = value->size; 40071345Sgshapiro 40164562Sgshapiro errno = 0; 40271345Sgshapiro result = dbm_store(dbm, dbm_cursor->smndbmc_current_key, dbdata, 40364562Sgshapiro smdb_put_flags_to_ndbm_flags(flags)); 40464562Sgshapiro switch (result) 40564562Sgshapiro { 40664562Sgshapiro case 1: 40764562Sgshapiro return SMDBE_DUPLICATE; 40864562Sgshapiro 40964562Sgshapiro case 0: 41064562Sgshapiro return SMDBE_OK; 41164562Sgshapiro 41264562Sgshapiro default: 41364562Sgshapiro save_errno = errno; 41464562Sgshapiro 41564562Sgshapiro if (dbm_error(dbm)) 41664562Sgshapiro return SMDBE_IO_ERROR; 41764562Sgshapiro 41864562Sgshapiro if (save_errno != 0) 41964562Sgshapiro return save_errno; 42064562Sgshapiro 42164562Sgshapiro return SMDBE_IO_ERROR; 42264562Sgshapiro } 42364562Sgshapiro /* NOTREACHED */ 42464562Sgshapiro} 42564562Sgshapiro 42664562Sgshapiroint 42764562Sgshapirosmdbm_cursor(database, cursor, flags) 42864562Sgshapiro SMDB_DATABASE *database; 42964562Sgshapiro SMDB_CURSOR **cursor; 43064562Sgshapiro SMDB_FLAG flags; 43164562Sgshapiro{ 43264562Sgshapiro SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl; 43364562Sgshapiro SMDB_CURSOR *cur; 43464562Sgshapiro SMDB_DBM_CURSOR *dbm_cursor; 43564562Sgshapiro 43664562Sgshapiro if (db->smndbm_cursor_in_use) 43764562Sgshapiro return SMDBE_ONLY_SUPPORTS_ONE_CURSOR; 43864562Sgshapiro 43990792Sgshapiro db->smndbm_cursor_in_use = true; 44064562Sgshapiro dbm_cursor = (SMDB_DBM_CURSOR *) malloc(sizeof(SMDB_DBM_CURSOR)); 441261363Sgshapiro if (dbm_cursor == NULL) 442261363Sgshapiro return SMDBE_MALLOC; 44364562Sgshapiro dbm_cursor->smndbmc_db = db; 44464562Sgshapiro dbm_cursor->smndbmc_current_key.dptr = NULL; 44564562Sgshapiro dbm_cursor->smndbmc_current_key.dsize = 0; 44664562Sgshapiro 44764562Sgshapiro cur = (SMDB_CURSOR*) malloc(sizeof(SMDB_CURSOR)); 44864562Sgshapiro if (cur == NULL) 449261363Sgshapiro { 450261363Sgshapiro free(dbm_cursor); 45164562Sgshapiro return SMDBE_MALLOC; 452261363Sgshapiro } 45364562Sgshapiro 45464562Sgshapiro cur->smdbc_impl = dbm_cursor; 45564562Sgshapiro cur->smdbc_close = smdbm_cursor_close; 45664562Sgshapiro cur->smdbc_del = smdbm_cursor_del; 45764562Sgshapiro cur->smdbc_get = smdbm_cursor_get; 45864562Sgshapiro cur->smdbc_put = smdbm_cursor_put; 45964562Sgshapiro *cursor = cur; 46064562Sgshapiro 46164562Sgshapiro return SMDBE_OK; 46264562Sgshapiro} 46390792Sgshapiro/* 46464562Sgshapiro** SMDB_NDBM_OPEN -- Opens a ndbm database. 46564562Sgshapiro** 46664562Sgshapiro** Parameters: 46764562Sgshapiro** database -- An unallocated database pointer to a pointer. 46864562Sgshapiro** db_name -- The name of the database without extension. 46964562Sgshapiro** mode -- File permisions on a created database. 47064562Sgshapiro** mode_mask -- Mode bits that much match on an opened database. 47164562Sgshapiro** sff -- Flags to safefile. 47264562Sgshapiro** type -- The type of database to open. 47364562Sgshapiro** Only SMDB_NDBM is supported. 47464562Sgshapiro** user_info -- Information on the user to use for file 47564562Sgshapiro** permissions. 47690792Sgshapiro** db_params -- No params are supported. 47764562Sgshapiro** 47864562Sgshapiro** Returns: 47964562Sgshapiro** SMDBE_OK -- Success, otherwise errno: 48064562Sgshapiro** SMDBE_MALLOC -- Cannot allocate memory. 48164562Sgshapiro** SMDBE_UNSUPPORTED -- The type is not supported. 48264562Sgshapiro** SMDBE_GDBM_IS_BAD -- We have detected GDBM and we don't 48364562Sgshapiro** like it. 48464562Sgshapiro** SMDBE_BAD_OPEN -- dbm_open failed and errno was not set. 48564562Sgshapiro** Anything else: errno 48664562Sgshapiro*/ 48764562Sgshapiro 48864562Sgshapiroint 48964562Sgshapirosmdb_ndbm_open(database, db_name, mode, mode_mask, sff, type, user_info, 49064562Sgshapiro db_params) 49164562Sgshapiro SMDB_DATABASE **database; 49264562Sgshapiro char *db_name; 49364562Sgshapiro int mode; 49464562Sgshapiro int mode_mask; 49564562Sgshapiro long sff; 49664562Sgshapiro SMDB_DBTYPE type; 49764562Sgshapiro SMDB_USER_INFO *user_info; 49864562Sgshapiro SMDB_DBPARAMS *db_params; 49964562Sgshapiro{ 50094334Sgshapiro bool lockcreated = false; 50164562Sgshapiro int result; 50264562Sgshapiro int lock_fd; 50364562Sgshapiro SMDB_DATABASE *smdb_db; 50464562Sgshapiro SMDB_DBM_DATABASE *db; 50564562Sgshapiro DBM *dbm = NULL; 50664562Sgshapiro struct stat dir_stat_info; 50764562Sgshapiro struct stat pag_stat_info; 50864562Sgshapiro 50964562Sgshapiro result = SMDBE_OK; 51064562Sgshapiro *database = NULL; 51164562Sgshapiro 51264562Sgshapiro if (type == NULL) 51364562Sgshapiro return SMDBE_UNKNOWN_DB_TYPE; 51464562Sgshapiro 51564562Sgshapiro result = smdb_setup_file(db_name, SMNDB_DIR_FILE_EXTENSION, mode_mask, 51664562Sgshapiro sff, user_info, &dir_stat_info); 51764562Sgshapiro if (result != SMDBE_OK) 51864562Sgshapiro return result; 51964562Sgshapiro 52064562Sgshapiro result = smdb_setup_file(db_name, SMNDB_PAG_FILE_EXTENSION, mode_mask, 52164562Sgshapiro sff, user_info, &pag_stat_info); 52264562Sgshapiro if (result != SMDBE_OK) 52364562Sgshapiro return result; 52464562Sgshapiro 52594334Sgshapiro if ((dir_stat_info.st_mode == ST_MODE_NOFILE || 52694334Sgshapiro pag_stat_info.st_mode == ST_MODE_NOFILE) && 52794334Sgshapiro bitset(mode, O_CREAT)) 52894334Sgshapiro lockcreated = true; 52994334Sgshapiro 53064562Sgshapiro lock_fd = -1; 53164562Sgshapiro result = smdb_lock_file(&lock_fd, db_name, mode, sff, 53264562Sgshapiro SMNDB_DIR_FILE_EXTENSION); 53364562Sgshapiro if (result != SMDBE_OK) 53464562Sgshapiro return result; 53564562Sgshapiro 53694334Sgshapiro if (lockcreated) 53794334Sgshapiro { 53894334Sgshapiro int pag_fd; 53994334Sgshapiro 54094334Sgshapiro /* Need to pre-open the .pag file as well with O_EXCL */ 54194334Sgshapiro result = smdb_lock_file(&pag_fd, db_name, mode, sff, 54294334Sgshapiro SMNDB_PAG_FILE_EXTENSION); 54394334Sgshapiro if (result != SMDBE_OK) 54494334Sgshapiro { 54594334Sgshapiro (void) close(lock_fd); 54694334Sgshapiro return result; 54794334Sgshapiro } 54894334Sgshapiro (void) close(pag_fd); 54994334Sgshapiro 55094334Sgshapiro mode |= O_TRUNC; 55194334Sgshapiro mode &= ~(O_CREAT|O_EXCL); 55294334Sgshapiro } 55394334Sgshapiro 55464562Sgshapiro smdb_db = smdb_malloc_database(); 55564562Sgshapiro if (smdb_db == NULL) 55664562Sgshapiro result = SMDBE_MALLOC; 55764562Sgshapiro 55864562Sgshapiro db = smdbm_malloc_database(); 55964562Sgshapiro if (db == NULL) 56064562Sgshapiro result = SMDBE_MALLOC; 56164562Sgshapiro 56264562Sgshapiro /* Try to open database */ 56364562Sgshapiro if (result == SMDBE_OK) 56464562Sgshapiro { 56564562Sgshapiro db->smndbm_lock_fd = lock_fd; 56664562Sgshapiro 56764562Sgshapiro errno = 0; 56898121Sgshapiro dbm = dbm_open(db_name, mode, DBMMODE); 56964562Sgshapiro if (dbm == NULL) 57064562Sgshapiro { 57164562Sgshapiro if (errno == 0) 57264562Sgshapiro result = SMDBE_BAD_OPEN; 57364562Sgshapiro else 57464562Sgshapiro result = errno; 57564562Sgshapiro } 57664562Sgshapiro db->smndbm_dbm = dbm; 57764562Sgshapiro } 57864562Sgshapiro 57964562Sgshapiro /* Check for GDBM */ 58064562Sgshapiro if (result == SMDBE_OK) 58164562Sgshapiro { 58264562Sgshapiro if (dbm_dirfno(dbm) == dbm_pagfno(dbm)) 58364562Sgshapiro result = SMDBE_GDBM_IS_BAD; 58464562Sgshapiro } 58564562Sgshapiro 58664562Sgshapiro /* Check for filechanged */ 58764562Sgshapiro if (result == SMDBE_OK) 58864562Sgshapiro { 58964562Sgshapiro result = smdb_filechanged(db_name, SMNDB_DIR_FILE_EXTENSION, 59064562Sgshapiro dbm_dirfno(dbm), &dir_stat_info); 59164562Sgshapiro if (result == SMDBE_OK) 59264562Sgshapiro { 59364562Sgshapiro result = smdb_filechanged(db_name, 59464562Sgshapiro SMNDB_PAG_FILE_EXTENSION, 59564562Sgshapiro dbm_pagfno(dbm), 59664562Sgshapiro &pag_stat_info); 59764562Sgshapiro } 59864562Sgshapiro } 59964562Sgshapiro 60064562Sgshapiro /* XXX Got to get fchown stuff in here */ 60164562Sgshapiro 60264562Sgshapiro /* Setup driver if everything is ok */ 60364562Sgshapiro if (result == SMDBE_OK) 60464562Sgshapiro { 60564562Sgshapiro *database = smdb_db; 60664562Sgshapiro 60764562Sgshapiro smdb_db->smdb_close = smdbm_close; 60864562Sgshapiro smdb_db->smdb_del = smdbm_del; 60964562Sgshapiro smdb_db->smdb_fd = smdbm_fd; 61066494Sgshapiro smdb_db->smdb_lockfd = smdbm_lockfd; 61164562Sgshapiro smdb_db->smdb_get = smdbm_get; 61264562Sgshapiro smdb_db->smdb_put = smdbm_put; 61364562Sgshapiro smdb_db->smdb_set_owner = smndbm_set_owner; 61464562Sgshapiro smdb_db->smdb_sync = smdbm_sync; 61564562Sgshapiro smdb_db->smdb_cursor = smdbm_cursor; 61664562Sgshapiro 61764562Sgshapiro smdb_db->smdb_impl = db; 61864562Sgshapiro 61964562Sgshapiro return SMDBE_OK; 62064562Sgshapiro } 62164562Sgshapiro 62264562Sgshapiro /* If we're here, something bad happened, clean up */ 62364562Sgshapiro if (dbm != NULL) 62464562Sgshapiro dbm_close(dbm); 62564562Sgshapiro 62664562Sgshapiro smdb_unlock_file(db->smndbm_lock_fd); 62764562Sgshapiro free(db); 62864562Sgshapiro smdb_free_database(smdb_db); 62964562Sgshapiro 63064562Sgshapiro return result; 63164562Sgshapiro} 63264562Sgshapiro#endif /* NDBM */ 633