Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: Assigning to a ztie'd hash



This could use a valgrind pass, and I'm not sure I put the signal queuing
in the best places, and there's probably some other misc. cleanup (more
UNUSED() wrappers?), but I think this addresses the issue with assigning
to the whole hash.

I'm wondering about getstrvalue()+strlen() and the possibility of having
embedded '\0' bytes in the values from the source hashtable, but this
matches what's used in gdbmsetfn().


diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index a83e32a..2e2bd3a 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);



Messages sorted by: Reverse Date, Date, Thread, Author