Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: Assigning to a ztie'd hash
- X-seq: zsh-workers 34447
- From: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: PATCH: Assigning to a ztie'd hash
- Date: Sun, 01 Feb 2015 18:34:59 -0800
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
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