about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2015-02-02 09:46:08 -0800
committerBarton E. Schaefer <schaefer@zsh.org>2015-02-02 09:46:08 -0800
commit1254538a41c45b7031030764074ae46abf4970e3 (patch)
tree4d4d1ce74ef7f4bddf2b66a65a1b00b90a643dbd /Src
parenta5333cc34431ae962265b9b10b8a6071f04c6c50 (diff)
downloadzsh-1254538a41c45b7031030764074ae46abf4970e3.tar.gz
zsh-1254538a41c45b7031030764074ae46abf4970e3.tar.xz
zsh-1254538a41c45b7031030764074ae46abf4970e3.zip
34447: fix assignment of key-value array to ztie'd parameter.
Add gdbmhashsetfn() for this purpose.  Erases and reorganizes the database
before bulk assign.
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/db_gdbm.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index a83e32a7b..2e2bd3a1e 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -45,7 +45,7 @@ static const struct gsu_scalar gdbm_gsu =
 { gdbmgetfn, gdbmsetfn, gdbmunsetfn };
 /**/
 static const struct gsu_hash gdbm_hash_gsu =
-{ hashgetfn, hashsetfn, gdbmhashunsetfn };
+{ hashgetfn, gdbmhashsetfn, gdbmhashunsetfn };
 
 static struct builtin bintab[] = {
     BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:r", NULL),
@@ -194,7 +194,7 @@ gdbmsetfn(Param pm, char *val)
 
 /**/
 static void
-gdbmunsetfn(Param pm, int um)
+gdbmunsetfn(Param pm, UNUSED(int um))
 {
     datum key;
     GDBM_FILE dbf;
@@ -232,9 +232,7 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags)
 {
     Param pm = NULL;
     datum key, content;
-    GDBM_FILE dbf;
-
-    dbf = (GDBM_FILE)(ht->tmpdata);
+    GDBM_FILE dbf = (GDBM_FILE)(ht->tmpdata);
 
     pm = (Param) hcalloc(sizeof(struct param));
 
@@ -259,6 +257,59 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags)
 
 /**/
 static void
+gdbmhashsetfn(Param pm, HashTable ht)
+{
+    int i;
+    HashNode hn;
+    GDBM_FILE dbf;
+    datum key, content;
+
+    if (!pm->u.hash || pm->u.hash == ht)
+	return;
+
+    if (!(dbf = (GDBM_FILE)(pm->u.hash->tmpdata)))
+	return;
+
+    key = gdbm_firstkey(dbf);
+    while (key.dptr) {
+	queue_signals();
+	(void)gdbm_delete(dbf, key);
+	free(key.dptr);
+	unqueue_signals();
+	key = gdbm_firstkey(dbf);
+    }
+
+    /* just deleted everything, clean up */
+    (void)gdbm_reorganize(dbf);
+
+    if (!ht)
+	return;
+
+    for (i = 0; i < ht->hsize; i++)
+	for (hn = ht->nodes[i]; hn; hn = hn->next) {
+	    struct value v;
+
+	    v.isarr = v.flags = v.start = 0;
+	    v.end = -1;
+	    v.arr = NULL;
+	    v.pm = (Param) hn;
+
+	    key.dptr = v.pm->node.nam;
+	    key.dsize = strlen(key.dptr) + 1;
+
+	    queue_signals();
+
+	    content.dptr = getstrvalue(&v);
+	    content.dsize = strlen(content.dptr) + 1;
+
+	    (void)gdbm_store(dbf, key, content, GDBM_REPLACE);	
+
+	    unqueue_signals();
+	}
+}
+
+/**/
+static void
 gdbmuntie(Param pm)
 {
     GDBM_FILE dbf = (GDBM_FILE)(pm->u.hash->tmpdata);