1/* 2 * db_gdbm.c - bindings for gdbm 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 2008 Clint Adams 7 * All rights reserved. 8 * 9 * Permission is hereby granted, without written agreement and without 10 * license or royalty fees, to use, copy, modify, and distribute this 11 * software and to distribute modified versions of this software for any 12 * purpose, provided that the above copyright notice and the following 13 * two paragraphs appear in all copies of this software. 14 * 15 * In no event shall Clint Adams or the Zsh Development 16 * Group be liable to any party for direct, indirect, special, incidental, or 17 * consequential damages arising out of the use of this software and its 18 * documentation, even if Peter Stephenson, Sven Wischnowsky and the Zsh 19 * Development Group have been advised of the possibility of such damage. 20 * 21 * Clint Adams and the Zsh Development Group 22 * specifically disclaim any warranties, including, but not limited to, the 23 * implied warranties of merchantability and fitness for a particular purpose. 24 * The software provided hereunder is on an "as is" basis, and Peter 25 * Stephenson, Sven Wischnowsky and the Zsh Development Group have no 26 * obligation to provide maintenance, support, updates, enhancements, or 27 * modifications. 28 * 29 */ 30 31#include "db_gdbm.mdh" 32#include "db_gdbm.pro" 33 34/* 35 * Make sure we have all the bits I'm using for memory mapping, otherwise 36 * I don't know what I'm doing. 37 */ 38#if defined(HAVE_GDBM_H) && defined(HAVE_GDBM_OPEN) 39 40#include <gdbm.h> 41 42#if 0 /* what is this for? */ 43static char *backtype = "db/gdbm"; 44#endif 45 46static const struct gsu_scalar gdbm_gsu = 47{ gdbmgetfn, gdbmsetfn, gdbmunsetfn }; 48 49static struct builtin bintab[] = { 50 BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:", NULL), 51 BUILTIN("zuntie", 0, bin_zuntie, 1, -1, 0, NULL, NULL), 52}; 53 54/**/ 55static int 56bin_ztie(char *nam, char **args, Options ops, UNUSED(int func)) 57{ 58 char *resource_name, *pmname; 59 GDBM_FILE dbf = NULL; 60 Param tied_param; 61 62 if(!OPT_ISSET(ops,'d')) { 63 zwarnnam(nam, "you must pass `-d db/gdbm' to ztie", NULL); 64 return 1; 65 } 66 if(!OPT_ISSET(ops,'f')) { 67 zwarnnam(nam, "you must pass `-f' with a filename to ztie", NULL); 68 return 1; 69 } 70 71 /* Here should be a lookup of the backend type against 72 * a registry. 73 */ 74 75 pmname = ztrdup(*args); 76 77 resource_name = OPT_ARG(ops, 'f'); 78 79 if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys, 0))) { 80 zwarnnam(nam, "cannot create the requested parameter name", NULL); 81 return 1; 82 } 83 84 dbf = gdbm_open(resource_name, 0, GDBM_WRCREAT | GDBM_SYNC, 0666, 0); 85 if(!dbf) { 86 zwarnnam(nam, "error opening database file %s", resource_name); 87 return 1; 88 } 89 90 tied_param->u.hash->tmpdata = (void *)dbf; 91 92 return 0; 93} 94 95/**/ 96static int 97bin_zuntie(char *nam, char **args, Options ops, UNUSED(int func)) 98{ 99 Param pm; 100 GDBM_FILE dbf; 101 102 pm = (Param) paramtab->getnode(paramtab, args[0]); 103 if(!pm) { 104 zwarnnam(nam, "cannot untie %s", args[0]); 105 return 1; 106 } 107 108 dbf = (GDBM_FILE)(pm->u.hash->tmpdata); 109 gdbm_close(dbf); 110/* free(pm->u.hash->tmpdata); */ 111 paramtab->removenode(paramtab, pm->node.nam); 112 113 return 0; 114} 115 116/**/ 117static char * 118gdbmgetfn(Param pm) 119{ 120 datum key, content; 121 int ret; 122 GDBM_FILE dbf; 123 124 key.dptr = pm->node.nam; 125 key.dsize = strlen(key.dptr) + 1; 126 127 dbf = (GDBM_FILE)(pm->u.hash->tmpdata); 128 ret = gdbm_exists(dbf, key); 129 if(ret) { 130 content = gdbm_fetch(dbf, key); 131 } else { 132 content.dptr = dupstring(""); 133 } 134 135 return content.dptr; 136} 137 138/**/ 139static void 140gdbmsetfn(Param pm, char *val) 141{ 142 datum key, content; 143 GDBM_FILE dbf; 144 145 key.dptr = pm->node.nam; 146 key.dsize = strlen(key.dptr) + 1; 147 content.dptr = val; 148 content.dsize = strlen(content.dptr) + 1; 149 150 dbf = (GDBM_FILE)(pm->u.hash->tmpdata); 151 (void)gdbm_store(dbf, key, content, GDBM_REPLACE); 152} 153 154/**/ 155static void 156gdbmunsetfn(Param pm, int um) 157{ 158 datum key; 159 GDBM_FILE dbf; 160 161 key.dptr = pm->node.nam; 162 key.dsize = strlen(key.dptr) + 1; 163 164 dbf = (GDBM_FILE)(pm->u.hash->tmpdata); 165 (void)gdbm_delete(dbf, key); 166} 167 168/**/ 169static HashNode 170getgdbmnode(HashTable ht, const char *name) 171{ 172 int len; 173 char *nameu; 174 Param pm = NULL; 175 176 nameu = dupstring(name); 177 unmetafy(nameu, &len); 178 179 pm = (Param) hcalloc(sizeof(struct param)); 180 pm->node.nam = nameu; 181 pm->node.flags = PM_SCALAR; 182 pm->gsu.s = &gdbm_gsu; 183 pm->u.hash = ht; 184 185 return &pm->node; 186} 187 188/**/ 189static void 190scangdbmkeys(HashTable ht, ScanFunc func, int flags) 191{ 192 Param pm = NULL; 193 datum key, content; 194 GDBM_FILE dbf; 195 196 dbf = (GDBM_FILE)(ht->tmpdata); 197 198 pm = (Param) hcalloc(sizeof(struct param)); 199 200 pm->node.flags = PM_SCALAR; 201 pm->gsu.s = &nullsetscalar_gsu; 202 203 key = gdbm_firstkey(dbf); 204 205 while(key.dptr) { 206 content = gdbm_fetch(dbf, key); 207 208 pm->node.nam = key.dptr; 209 pm->u.str = content.dptr; 210 pm->gsu.s = &nullsetscalar_gsu; 211 212 func(&pm->node, flags); 213 214 key = gdbm_nextkey(dbf, key); 215 } 216 217} 218 219#else 220# error no gdbm 221#endif /* have gdbm */ 222 223static struct features module_features = { 224 bintab, sizeof(bintab)/sizeof(*bintab), 225 NULL, 0, 226 NULL, 0, 227 NULL, 0, 228 0 229}; 230 231/**/ 232int 233setup_(UNUSED(Module m)) 234{ 235 return 0; 236} 237 238/**/ 239int 240features_(Module m, char ***features) 241{ 242 *features = featuresarray(m, &module_features); 243 return 0; 244} 245 246/**/ 247int 248enables_(Module m, int **enables) 249{ 250 return handlefeatures(m, &module_features, enables); 251} 252 253/**/ 254int 255boot_(UNUSED(Module m)) 256{ 257 return 0; 258} 259 260/**/ 261int 262cleanup_(UNUSED(Module m)) 263{ 264 return setfeatureenables(m, &module_features, NULL); 265} 266 267/**/ 268int 269finish_(UNUSED(Module m)) 270{ 271 return 0; 272} 273