/* Copyright (c) 2008-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file prqdbe.c Database backend module. This file contains the functions to store key/value pairs in different database types. */ /** Inside the prqdbe module. */ #define PRQDBE_C 1 #include "prqd.h" #line 51 "prqdbe.ctr" /** Names and abbreviations for database types. */ static char *db_type_names[] = { "b$db", "g$dbm", "n$dbm", NULL }; #if USE_DB_H /** Open a Berkeley DB file. @param pj Pointer to prqd job structure. @return 1 on success, 0 on error. */ int prqdbe_bdb_open DK_P1(PJ *,pj) { int back = 0; u_int32_t flags; DB *dbp; if(db_create(&((pj->dbbe).c.bdb.dbp), NULL, 0) == 0) { flags = DB_CREATE; dbp = (pj->dbbe).c.bdb.dbp; if(dbp->open(dbp, NULL, (pj->dbbe).c.bdb.fn, NULL, DB_BTREE, flags, 0) == 0) { back = 1; } else { pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(69)); } } else { pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(70), (pj->dbbe).c.bdb.fn); } return back; } #endif #if USE_GDBM_H /** Open a GDBM database file. @param pj Pointer to prqd job structure. @return 1 on success, 0 on error. */ int prqdbe_gdbm_open DK_P1(PJ *,pj) { int back = 0; if((pj->dbbe).c.gdbm.fn) { (pj->dbbe).c.gdbm.myfn = dkstr_dup((pj->dbbe).c.gdbm.fn); if((pj->dbbe).c.gdbm.myfn) { back = 1; } else { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(42)); } } return back; } #endif #if USE_NDBM_H /** Open NDBM database file. @param pj Pointer to prqd job structure. @return 1 on success, 0 on error. */ int prqdbe_ndbm_open DK_P1(PJ *,pj) { int back = 0; (pj->dbbe).c.ndbm.db = NULL; (pj->dbbe).c.ndbm.db = dbm_open((pj->dbbe).c.ndbm.fn, (O_RDWR | O_CREAT), 0660); if((pj->dbbe).c.ndbm.db) { back = 1; } else { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(70), (pj->dbbe).c.ndbm.fn); } return back; } #endif /** Open a database file. @param pj Pointer to prqd job structure. @return 1 on success, 0 on error. */ int prqdbe_open DK_P1(PJ *,pj) { int back = 0; char *dn, *p1, *p2; if((pj->prqdc)->dbname) { dn = (pj->prqdc)->dbname; p1 = dkstr_chr(dn, ':'); if(p1) { *p1 = '\0'; p2 = p1; p2++; p2 = dkstr_start(p2, NULL); if(p2) { (pj->dbbe).tp = dkstr_array_abbr(db_type_names, (pj->prqdc)->dbname, '$', 0); if((pj->dbbe).tp > -1) { (pj->dbbe).tp += 1; switch((pj->dbbe).tp) { #if USE_DB_H case DATABASE_TYPE_BDB: { (pj->dbbe).c.bdb.fn = p2; (pj->dbbe).c.bdb.dbp = NULL; back = prqdbe_bdb_open(pj); } break; #else case DATABASE_TYPE_BDB: { pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); } break; #endif #if USE_GDBM_H case DATABASE_TYPE_GDBM: { (pj->dbbe).c.gdbm.fn = p2; back = prqdbe_gdbm_open(pj); } break; #else case DATABASE_TYPE_GDBM: { pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); } break; #endif #if USE_NDBM_H case DATABASE_TYPE_NDBM: { (pj->dbbe).c.ndbm.fn = p2; back = prqdbe_ndbm_open(pj); } break; #else case DATABASE_TYPE_NDBM: { pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); } break; #endif default: { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(74), (pj->prqdc)->dbname); pj->e1 = 1; } break; } } else { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(74), (pj->prqdc)->dbname); pj->e1 = 1; } } else { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(73)); pj->e1 = 1; } *p1 = ':'; } else { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(72)); pj->e1 =1; } } else { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(71)); pj->e1 = 1; } return back; } #if USE_DB_H /** Store key/value pair in Berkeley DB. @param pj Pointer to prqd job structure. @param k Key string. @param v Value string. @return 1 on success, 0 on error. */ static int prqdbe_bdb_store DK_P3(PJ *,pj, char *,k, char *,v) { int back = 0; DBT kd, vd; if((pj->dbbe).c.bdb.dbp) { kd.data = k; kd.size = 1 + strlen(k); vd.data = v; vd.size = 1 + strlen(v); if(((pj->dbbe).c.bdb.dbp)->put((pj->dbbe).c.bdb.dbp,NULL,&kd,&vd,0) == 0) { back = 1; } } return back; } #endif #if USE_GDBM_H /** Store key/value pair in GDBM database. @param pj Pointer to prqd job structure. @param k Key string. @param v Value string. @return 1 on success, 0 on error. */ static int prqdbe_gdbm_store DK_P3(PJ *,pj, char *,k, char *,v) { int back = 0, ret = 1; datum kd, kv; GDBM_FILE gdbmf; if((pj->dbbe).c.gdbm.myfn) { gdbmf = gdbm_open((pj->dbbe).c.gdbm.myfn, 512, GDBM_WRCREAT, 0660, NULL); if(gdbmf) { kd.dptr = k; kd.dsize = 1 + strlen(k); kv.dptr = v; kd.dsize = 1 + strlen(v); ret = gdbm_store(gdbmf, kd, kv, GDBM_INSERT); if(ret == 0) { back = 1; } else { kd.dptr = k; kd.dsize = 1 + strlen(k); kv.dptr = v; kd.dsize = 1 + strlen(v); ret = gdbm_store(gdbmf, kd, kv, GDBM_REPLACE); if(ret == 0) { back = 1; } } gdbm_close(gdbmf); } else { /* ERROR: Failed to open gdbm database */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(70), (pj->dbbe).c.gdbm.myfn); } } else { /* ERROR: No file name */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(73)); } return back; } #endif #if USE_NDBM_H /** Store key/value pair in NDBM database. @param pj Pointer to prqd job structure. @param k Key string. @param v Value string. @return 1 on success, 0 on error. */ static int prqdbe_ndbm_store DK_P3(PJ *,pj, char *,k, char *,v) { int back = 0, i = 0; datum kd, vd; if( (pj->dbbe).c.ndbm.db ) { kd.dptr = k; kd.dsize = 1 + strlen(k); vd.dptr = v; vd.dsize = 1 + strlen(v); i = dbm_store((pj->dbbe).c.ndbm.db, kd, vd, DBM_INSERT); if(i == 0) { back = 1; } else { kd.dptr = k; kd.dsize = 1 + strlen(k); vd.dptr = v; vd.dsize = 1 + strlen(v); if(dbm_store((pj->dbbe).c.ndbm.db, kd, vd, DBM_REPLACE) == 0) { back = 1; } } } } #endif /** Store key/value pair in database. @param pj Pointer to prqd job structure. @param k Key string. @param v Value string. @return 1 on success, 0 on error. */ int prqdbe_store DK_P3(PJ *,pj, char *,k, char *,v) { int back = 0; if((pj) && (k) && (v)) { prqdlog(pj, PRQD_PRIO_INFO, prqd_get_kw(27), k, v); switch((pj->dbbe).tp) { case DATABASE_TYPE_BDB: { #if USE_DB_H back = prqdbe_bdb_store(pj, k, v); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; case DATABASE_TYPE_GDBM: { #if USE_GDBM_H back = prqdbe_gdbm_store(pj, k, v); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; case DATABASE_TYPE_NDBM: { #if USE_NDBM_H back = prqdbe_ndbm_store(pj, k, v); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; } if(!back) { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(35), k, v); } } return back; } #if USE_DB_H /** Retrieve entry from Berkeley DB. @param pj Pointer to prqd job structure. @param k Key string. @param v Pointer to buffer for value. @param sz Size of v in bytes. @return Number of bytes retrieved. */ static size_t prqdbe_bdb_fetch DK_P4(PJ *,pj, char *,k, char *,v, size_t,sz) { size_t back = 0; DBT kd, vd; DK_MEMRES(v,sz); if((pj->dbbe).c.bdb.dbp) { DK_MEMRES(&kd,sizeof(DBT)); DK_MEMRES(&vd,sizeof(DBT)); kd.data = k; kd.size = 1 + strlen(k); if(((pj->dbbe).c.bdb.dbp)->get((pj->dbbe).c.bdb.dbp,NULL,&kd,&vd,0) == 0) { if(vd.data) { if(vd.size > 0) { back = vd.size; if(back >= sz) { back = sz - 1; } DK_MEMCPY(v,vd.data,back); v[back] = '\0'; if(v[back - 1] == '\0') { back--; } } } } } return back; } #endif #if USE_GDBM_H /** Retrieve entry from GDBM database. @param pj Pointer to prqd job structure. @param k Key string. @param v Pointer to buffer for value. @param sz Size of v in bytes. @return Number of bytes retrieved. */ static size_t prqdbe_gdbm_fetch DK_P4(PJ *,pj, char *,k, char *,v, size_t,sz) { size_t back = 0; datum kd, vd; GDBM_FILE gdbmf; if((pj->dbbe).c.gdbm.myfn) { gdbmf = gdbm_open((pj->dbbe).c.gdbm.myfn, 512, GDBM_READER, 0660, NULL); if(gdbmf) { kd.dptr = k; kd.dsize = 1 + strlen(k); vd = gdbm_fetch(gdbmf, kd); if(vd.dptr) { if(vd.dsize > 0) { back = vd.dsize; if(back >= sz) back = sz - 1; DK_MEMCPY(v,vd.dptr,back); v[back] = '\0'; if(v[back - 1] == '\0') { back--; } } free(vd.dptr); } gdbm_close(gdbmf); } else { /* ERROR: Failed to open gdbm database */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(70), (pj->dbbe).c.gdbm.myfn); } } else { /* ERROR: No file name */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(73)); } return back; } #endif #if USE_NDBM_H /** Retrieve entry from NDBM database. @param pj Pointer to prqd job structure. @param k Key string. @param v Pointer to buffer for value. @param sz Size of v in bytes. @return Number of bytes retrieved. */ static size_t prqdbe_ndbm_fetch DK_P4(PJ *,pj, char *,k, char *,v, size_t,sz) { size_t back = 0; int i; datum kd, vd; DK_MEMRES(v,sz); if( (pj->dbbe).c.ndbm.db ) { DK_MEMRES(&kd,sizeof(datum)); DK_MEMRES(&vd, sizeof(datum)); kd.dptr = k; kd.dsize = 1 + strlen(k); vd = dbm_fetch( (pj->dbbe).c.ndbm.db, kd); if(vd.dptr) { if(vd.dsize > 0) { back = vd.dsize; if(back >= sz) { back = sz - 1; } DK_MEMCPY(v,vd.dptr,back); v[back] = '\0'; if(v[back - 1] == '\0') { back--; } } } } return back; } #endif /** Retrieve entry from database. @param pj Pointer to prqd job structure. @param k Key string. @param v Pointer to buffer for value. @param sz Size of v in bytes. @return Number of bytes retrieved. */ size_t prqdbe_fetch DK_P4(PJ *,pj, char *,k, char *,v, size_t,sz) { int back = 0; if((pj) && (k) && (v)) { switch((pj->dbbe).tp) { case DATABASE_TYPE_BDB: { #if USE_DB_H back = prqdbe_bdb_fetch(pj, k, v, sz); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; case DATABASE_TYPE_GDBM: { #if USE_GDBM_H back = prqdbe_gdbm_fetch(pj, k, v, sz); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; case DATABASE_TYPE_NDBM: { #if USE_NDBM_H back = prqdbe_ndbm_fetch(pj, k, v, sz); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; } if(back) { prqdlog(pj, PRQD_PRIO_DEBUG, prqd_get_kw(28), k, v); } else { prqdlog(pj, PRQD_PRIO_DEBUG, prqd_get_kw(29), k); } } return back; } #if USE_DB_H /** Close Berkeley database. @param pj Pointer to prqd job structure. */ void prqdbe_bdb_close DK_P1(PJ *,pj) { if((pj->dbbe).c.bdb.dbp) { ((pj->dbbe).c.bdb.dbp)->close((pj->dbbe).c.bdb.dbp, 0); (pj->dbbe).c.bdb.dbp = NULL; } } #endif #if USE_GDBM_H /** Close GDBM database. @param pj Pointer to prqd job structure. */ void prqdbe_gdbm_close DK_P1(PJ *,pj) { char *x; if((pj->dbbe).c.gdbm.myfn) { x = (pj->dbbe).c.gdbm.myfn; dk_delete(x); (pj->dbbe).c.gdbm.myfn = NULL; } } #endif #if USE_NDBM_H /** Close NDBM database. @param pj Pointer to prqd job structure. */ void prqdbe_ndbm_close DK_P1(PJ *,pj) { if((pj->dbbe).c.ndbm.db) { dbm_close((pj->dbbe).c.ndbm.db); (pj->dbbe).c.ndbm.db = NULL; } } #endif /** Close database. @param pj Pointer to prqd job structure. */ void prqdbe_close DK_P1(PJ *,pj) { switch((pj->dbbe).tp) { case DATABASE_TYPE_BDB: { #if USE_DB_H prqdbe_bdb_close(pj); #else pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); #endif } break; case DATABASE_TYPE_GDBM: { #if USE_GDBM_H prqdbe_gdbm_close(pj); #else pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); #endif } break; case DATABASE_TYPE_NDBM: { #if USE_NDBM_H prqdbe_ndbm_close(pj); #else pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); #endif } break; } } /** Change file ownership. @param pj Pointer to prqd job structure. @param fn File name. @param u New owners UID. @param g New group ID for file. */ static void change_file_ownership DK_P4(PJ *,pj, char *,fn, uid_t,u, gid_t,g) { if(fn) { if(chown(fn, u, g)) { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(75), fn, (unsigned long)u, (unsigned long)g); } if(chmod(fn, 0660)) { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(76), fn); } } } /** File name suffixes for NDBM files. */ static char *ndbm_file_suffixes[] = { ".dir", ".pag", NULL }; /** Change ownership for database file. @param pj Pointer to prqd job structure. @param u New owners UID. @param g New file group ID. */ void prqdbe_change_ownership DK_P3(PJ *,pj, uid_t,u, gid_t,g) { char *p2; size_t sz; switch((pj->dbbe).tp) { case DATABASE_TYPE_BDB: { change_file_ownership(pj, (pj->dbbe).c.bdb.fn, u, g); } break; case DATABASE_TYPE_GDBM: { change_file_ownership(pj, (pj->dbbe).c.gdbm.fn, u, g); } break; case DATABASE_TYPE_NDBM: { sz = 5 + strlen((pj->dbbe).c.ndbm.fn); p2 = dk_new(char,sz); if(p2) { strcpy(p2, (pj->dbbe).c.ndbm.fn); strcat(p2, ndbm_file_suffixes[1]); change_file_ownership(pj, p2, u, g); strcpy(p2, (pj->dbbe).c.ndbm.fn); strcat(p2, ndbm_file_suffixes[0]); change_file_ownership(pj, p2, u, g); dk_delete(p2); } else { prqdlog(pj,PRQD_PRIO_ERROR,prqd_get_kw(42)); } } break; } } #if USE_DB_H /** Traverse Berkeley database. @param pj Pointer to prqd job structure. @param f Traversal function. @return 1 on success, 0 on error. */ static int prqdbe_bdb_traverse DK_P2(PJ *,pj, PRQD_TRAVERSE_FCT *,f) { int back = 0, cc = 0; DB *db; DBT kd, vd; DBC *cursorp = NULL; int ret, act; char keybuffer[PRQD_DBENTRY_SIZE], valbuffer[PRQD_DBENTRY_SIZE]; char kb2[PRQD_DBENTRY_SIZE], vb2[PRQD_DBENTRY_SIZE]; size_t sz; db = (pj->dbbe).c.bdb.dbp; if(db) { DK_MEMRES(&kd,sizeof(DBT)); DK_MEMRES(&vd,sizeof(DBT)); ret = db->cursor(db, NULL, &cursorp, 0); if(ret == 0) { if(cursorp) { ret = cursorp->c_get(cursorp, &kd, &vd, DB_FIRST); if(ret == 0) { cc = back = 1; if((kd.data) && (kd.size > 0) && (vd.data) && (vd.size > 0)) { if(f) { sz = kd.size; if(sz >= sizeof(keybuffer)) { sz = sizeof(keybuffer) - 1; } DK_MEMCPY(keybuffer,kd.data,sz); keybuffer[sz] = '\0'; sz = vd.size; if(sz >= sizeof(valbuffer)) { sz = sizeof(valbuffer) - 1 ; } DK_MEMCPY(valbuffer,vd.data,sz); valbuffer[sz] = '\0'; act = (*f)(pj, keybuffer, valbuffer); if(act == 0) { back = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(77), kb2, vb2); } else { if(act < 0) { back = cc = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(78), kb2, vb2); } } } } } while(cc) { ret = cursorp->c_get(cursorp, &kd, &vd, DB_NEXT); if(ret == 0) { cc = 1; if((kd.data) && (kd.size > 0) && (vd.data) && (vd.size > 0)) { if(f) { sz = kd.size; if(sz >= sizeof(keybuffer)) { sz = sizeof(keybuffer) - 1; } DK_MEMCPY(keybuffer,kd.data,sz); keybuffer[sz] = '\0'; sz = vd.size; if(sz >= sizeof(valbuffer)) { sz = sizeof(valbuffer) - 1 ; } DK_MEMCPY(valbuffer,vd.data,sz); valbuffer[sz] = '\0'; act = (*f)(pj, keybuffer, valbuffer); if(act == 0) { back = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(77), kb2, vb2); } else { if(act < 0) { back = cc = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(78), kb2, vb2); } } } } } else { cc = 0; } } cursorp->c_close(cursorp); cursorp = NULL; } } } return back; } #endif #if USE_GDBM_H /** Traverse GDBM database. @param pj Pointer to prqd job structure. @param f Traversal function. @return 1 on success, 0 on error. */ static int prqdbe_gdbm_traverse DK_P2(PJ *,pj, PRQD_TRAVERSE_FCT *,f) { int back = 0, can_run = 0, is_first = 0, cc = 1, act = 1; datum kd, vd, nk; char keybuffer[PRQD_DBENTRY_SIZE], valbuffer[PRQD_DBENTRY_SIZE]; char kb2[PRQD_DBENTRY_SIZE], vb2[PRQD_DBENTRY_SIZE]; size_t sz; GDBM_FILE gdbmf; if((pj->dbbe).c.gdbm.myfn) { gdbmf = gdbm_open((pj->dbbe).c.gdbm.myfn, 512, GDBM_READER, 0660, NULL); if(gdbmf) { cc = 1; is_first = 1; back = 1; while(cc) { can_run = 0; if(is_first) { is_first = 0; DK_MEMRES(&kd,sizeof(datum)); kd = gdbm_firstkey(gdbmf); if(kd.dptr) { can_run = 1; } else { cc = 0; } } else { DK_MEMRES(&nk,sizeof(datum)); nk = gdbm_nextkey(gdbmf, kd); if(kd.dptr) { free(kd.dptr); kd.dptr = NULL; } kd = nk; DK_MEMRES(&nk,sizeof(datum)); if(kd.dptr) { can_run = 1; } else { cc = 0; } } if(can_run) { vd = gdbm_fetch(gdbmf, kd); if((kd.dptr) && (kd.dsize > 0) && (vd.dptr) && (vd.dsize > 0)) { sz = kd.dsize; if(sz >= sizeof(keybuffer)) { sz = sizeof(keybuffer) - 1; } DK_MEMCPY(keybuffer,kd.dptr,sz); keybuffer[sz] = '\0'; sz = vd.dsize; if(sz >= sizeof(valbuffer)) { sz = sizeof(valbuffer) - 1; } DK_MEMCPY(valbuffer,vd.dptr,sz); valbuffer[sz] = '\0'; act = 1; if(f) { act = (*f)(pj, keybuffer, valbuffer); } if(act == 0) { back = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(77), kb2, vb2); } else { if(act < 0) { back = cc = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(78), kb2, vb2); } } } if(vd.dptr) { free(vd.dptr); vd.dptr = NULL; } } } if(kd.dptr) { free(kd.dptr); kd.dptr = NULL; } gdbm_close(gdbmf); } else { /* ERROR: Failed to open gdbm database */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(70), (pj->dbbe).c.gdbm.myfn); } } else { /* ERROR: No name */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(73)); } return back; } #endif #if USE_NDBM_H /** Traverse NDBM database. @param pj Pointer to prqd job structure. @param f Traversal function. @return 1 on success, 0 on error. */ static int prqdbe_ndbm_traverse DK_P2(PJ *,pj, PRQD_TRAVERSE_FCT *,f) { int back = 0, cc = 0, act = 0; datum kd, vd; char keybuffer[PRQD_DBENTRY_SIZE], valbuffer[PRQD_DBENTRY_SIZE]; char kb2[PRQD_DBENTRY_SIZE], vb2[PRQD_DBENTRY_SIZE]; size_t sz; cc = 1; back = 1; for( kd = dbm_firstkey((pj->dbbe).c.ndbm.db); (kd.dptr != NULL) && (cc != 0); kd = dbm_nextkey((pj->dbbe).c.ndbm.db) ) { vd = dbm_fetch((pj->dbbe).c.ndbm.db, kd); if((kd.dptr) && (kd.dsize > 0) && (vd.dptr) && (vd.dsize > 0)) { sz = kd.dsize; if(sz >= sizeof(keybuffer)) { sz = sizeof(keybuffer) - 1; } DK_MEMCPY(keybuffer,kd.dptr,sz); keybuffer[sz] = '\0'; sz = vd.dsize; if(sz >= sizeof(valbuffer)) { sz = sizeof(valbuffer) - 1; } DK_MEMCPY(valbuffer,vd.dptr,sz); valbuffer[sz] = '\0'; act = 1; if(f) { act = (*f)(pj, keybuffer, valbuffer); } if(act == 0) { back = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(77), kb2, vb2); } else { if(act < 0) { back = cc = 0; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(78), kb2, vb2); } } } } return back; } #endif /** Traverse database. @param pj Pointer to prqd job structure. @param f Traversal function. @return 1 on success, 0 on error. */ int prqdbe_traverse DK_P2(PJ *,pj, PRQD_TRAVERSE_FCT *,f) { int back = 0; switch((pj->dbbe).tp) { case DATABASE_TYPE_BDB: { #if USE_DB_H back = prqdbe_bdb_traverse(pj, f); #else pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); #endif } break; case DATABASE_TYPE_GDBM: { #if USE_GDBM_H back = prqdbe_gdbm_traverse(pj, f); #else pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); #endif } break; case DATABASE_TYPE_NDBM: { #if USE_NDBM_H back = prqdbe_ndbm_traverse(pj, f); #else pj->e1 = 1; prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); #endif } break; } return back; } #if USE_DB_H /** Delete entry from Berkeley database. @param pj Pointer to prqd job structure. @param k Key of entry to delete. @return 1 on success, 0 on error. */ static int prqdbe_bdb_delete DK_P2(PJ *,pj, char *,k) { int back = 0, ret = 0; DB *db; DBT kd; if((pj->dbbe).c.bdb.dbp) { db = (pj->dbbe).c.bdb.dbp; kd.data = k; kd.size = 1 + strlen(k); ret = db->del(db, NULL, &kd, 0); if(ret == 0) { back = 1; } } return back; } #endif #if USE_NDBM_H /** Delete entry from NDBM database. @param pj Pointer to prqd job structure. @param k Key of entry to delete. @return 1 on success, 0 on error. */ static int prqdbe_ndbm_delete DK_P2(PJ *,pj, char *,k) { int back = 0; datum kd; kd.dptr = k; kd.dsize = 1 + strlen(k); if(dbm_delete((pj->dbbe).c.ndbm.db, kd) == 0) { back = 1; } return back; } #endif #if USE_GDBM_H /** Delete entry from GDBM database. @param pj Pointer to prqd job structure. @param k Key of entry to delete. @return 1 on success, 0 on error. */ static int prqdbe_gdbm_delete DK_P2(PJ *,pj, char *,k) { int back = 0; datum kd; GDBM_FILE gdbmf; if((pj->dbbe).c.gdbm.myfn) { gdbmf = gdbm_open((pj->dbbe).c.gdbm.myfn, 512, GDBM_WRCREAT, 0660, NULL); if(gdbmf) { kd.dptr = k; kd.dsize = 1 + strlen(k); if(gdbm_delete(gdbmf, kd) == 0) { back = 1; } gdbm_close(gdbmf); } else { /* ERROR: Failed to open gdbm database */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(70), (pj->dbbe).c.gdbm.myfn); } } else { /* ERROR: No filename */ prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(73)); } return back; } #endif /** Delete entry from database. @param pj Pointer to prqd job structure. @param k Key of entry to delete. @return 1 on success, 0 on error. */ int prqdbe_delete DK_P2(PJ *,pj, char *,k) { int back = 0; prqdlog(pj, PRQD_PRIO_INFO, prqd_get_kw(84), k); switch((pj->dbbe).tp) { case DATABASE_TYPE_BDB: { #if USE_DB_H back = prqdbe_bdb_delete(pj, k); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; case DATABASE_TYPE_GDBM: { #if USE_GDBM_H back = prqdbe_gdbm_delete(pj, k); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; case DATABASE_TYPE_NDBM: { #if USE_NDBM_H back = prqdbe_ndbm_delete(pj, k); #else prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(68)); pj->e1 = 1; #endif } break; } if(!back) { prqdlog(pj, PRQD_PRIO_ERROR, prqd_get_kw(67), k); } return back; }