1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-11 13:01:28 +02:00
zsh/Src/Modules/db_gdbm.c
2011-06-19 16:26:10 +00:00

272 lines
5.6 KiB
C

/*
* db_gdbm.c - bindings for gdbm
*
* This file is part of zsh, the Z shell.
*
* Copyright (c) 2008 Clint Adams
* All rights reserved.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and to distribute modified versions of this software for any
* purpose, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* In no event shall Clint Adams or the Zsh Development
* Group be liable to any party for direct, indirect, special, incidental, or
* consequential damages arising out of the use of this software and its
* documentation, even if Peter Stephenson, Sven Wischnowsky and the Zsh
* Development Group have been advised of the possibility of such damage.
*
* Clint Adams and the Zsh Development Group
* specifically disclaim any warranties, including, but not limited to, the
* implied warranties of merchantability and fitness for a particular purpose.
* The software provided hereunder is on an "as is" basis, and Peter
* Stephenson, Sven Wischnowsky and the Zsh Development Group have no
* obligation to provide maintenance, support, updates, enhancements, or
* modifications.
*
*/
#include "db_gdbm.mdh"
#include "db_gdbm.pro"
/*
* Make sure we have all the bits I'm using for memory mapping, otherwise
* I don't know what I'm doing.
*/
#if defined(HAVE_GDBM_H) && defined(HAVE_GDBM_OPEN)
#include <gdbm.h>
#if 0 /* what is this for? */
static char *backtype = "db/gdbm";
#endif
static const struct gsu_scalar gdbm_gsu =
{ gdbmgetfn, gdbmsetfn, gdbmunsetfn };
static struct builtin bintab[] = {
BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:", NULL),
BUILTIN("zuntie", 0, bin_zuntie, 1, -1, 0, NULL, NULL),
};
/**/
static int
bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
{
char *resource_name, *pmname;
GDBM_FILE dbf = NULL;
Param tied_param;
if(!OPT_ISSET(ops,'d')) {
zwarnnam(nam, "you must pass `-d db/gdbm' to ztie", NULL);
return 1;
}
if(!OPT_ISSET(ops,'f')) {
zwarnnam(nam, "you must pass `-f' with a filename to ztie", NULL);
return 1;
}
/* Here should be a lookup of the backend type against
* a registry.
*/
pmname = ztrdup(*args);
resource_name = OPT_ARG(ops, 'f');
if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys, 0))) {
zwarnnam(nam, "cannot create the requested parameter name", NULL);
return 1;
}
dbf = gdbm_open(resource_name, 0, GDBM_WRCREAT | GDBM_SYNC, 0666, 0);
if(!dbf) {
zwarnnam(nam, "error opening database file %s", resource_name);
return 1;
}
tied_param->u.hash->tmpdata = (void *)dbf;
return 0;
}
/**/
static int
bin_zuntie(char *nam, char **args, Options ops, UNUSED(int func))
{
Param pm;
GDBM_FILE dbf;
pm = (Param) paramtab->getnode(paramtab, args[0]);
if(!pm) {
zwarnnam(nam, "cannot untie %s", args[0]);
return 1;
}
dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
gdbm_close(dbf);
/* free(pm->u.hash->tmpdata); */
paramtab->removenode(paramtab, pm->node.nam);
return 0;
}
/**/
static char *
gdbmgetfn(Param pm)
{
datum key, content;
int ret;
GDBM_FILE dbf;
key.dptr = pm->node.nam;
key.dsize = strlen(key.dptr) + 1;
dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
ret = gdbm_exists(dbf, key);
if(ret) {
content = gdbm_fetch(dbf, key);
} else {
content.dptr = dupstring("");
}
return content.dptr;
}
/**/
static void
gdbmsetfn(Param pm, char *val)
{
datum key, content;
GDBM_FILE dbf;
key.dptr = pm->node.nam;
key.dsize = strlen(key.dptr) + 1;
content.dptr = val;
content.dsize = strlen(content.dptr) + 1;
dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
(void)gdbm_store(dbf, key, content, GDBM_REPLACE);
}
/**/
static void
gdbmunsetfn(Param pm, int um)
{
datum key;
GDBM_FILE dbf;
key.dptr = pm->node.nam;
key.dsize = strlen(key.dptr) + 1;
dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
(void)gdbm_delete(dbf, key);
}
/**/
static HashNode
getgdbmnode(HashTable ht, const char *name)
{
int len;
char *nameu;
Param pm = NULL;
nameu = dupstring(name);
unmetafy(nameu, &len);
pm = (Param) hcalloc(sizeof(struct param));
pm->node.nam = nameu;
pm->node.flags = PM_SCALAR;
pm->gsu.s = &gdbm_gsu;
pm->u.hash = ht;
return &pm->node;
}
/**/
static void
scangdbmkeys(HashTable ht, ScanFunc func, int flags)
{
Param pm = NULL;
datum key, content;
GDBM_FILE dbf;
dbf = (GDBM_FILE)(ht->tmpdata);
pm = (Param) hcalloc(sizeof(struct param));
pm->node.flags = PM_SCALAR;
pm->gsu.s = &nullsetscalar_gsu;
key = gdbm_firstkey(dbf);
while(key.dptr) {
content = gdbm_fetch(dbf, key);
pm->node.nam = key.dptr;
pm->u.str = content.dptr;
pm->gsu.s = &nullsetscalar_gsu;
func(&pm->node, flags);
key = gdbm_nextkey(dbf, key);
}
}
#else
# error no gdbm
#endif /* have gdbm */
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
{
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m, &module_features, enables);
}
/**/
int
boot_(UNUSED(Module m))
{
return 0;
}
/**/
int
cleanup_(UNUSED(Module m))
{
return setfeatureenables(m, &module_features, NULL);
}
/**/
int
finish_(UNUSED(Module m))
{
return 0;
}