mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-11 13:01:28 +02:00
272 lines
5.6 KiB
C
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;
|
|
}
|