summaryrefslogtreecommitdiffstats
path: root/lib/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hash.c')
-rw-r--r--lib/hash.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/lib/hash.c b/lib/hash.c
index 918aa0d..2b123be 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -1,6 +1,6 @@
/* hash - hashing table processing.
- Copyright (C) 1998-2004, 2006-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 1998-2004, 2006-2007, 2009-2024 Free Software Foundation, Inc.
Written by Jim Meyering, 1992.
@@ -29,6 +29,7 @@
#include "bitrotate.h"
#include "xalloc-oversized.h"
+#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -499,13 +500,17 @@ compute_bucket_size (size_t candidate, const Hash_tuning *tuning)
{
float new_candidate = candidate / tuning->growth_threshold;
if ((float) SIZE_MAX <= new_candidate)
- return 0;
+ goto nomem;
candidate = new_candidate;
}
candidate = next_prime (candidate);
if (xalloc_oversized (candidate, sizeof (struct hash_entry *)))
- return 0;
+ goto nomem;
return candidate;
+
+ nomem:
+ errno = ENOMEM;
+ return 0;
}
Hash_table *
@@ -534,6 +539,7 @@ hash_initialize (size_t candidate, const Hash_tuning *tuning,
if the user provides invalid tuning options, we silently revert to
using the defaults, and ignore further request to change the tuning
options. */
+ errno = EINVAL;
goto fail;
}
@@ -607,6 +613,7 @@ hash_free (Hash_table *table)
struct hash_entry *bucket;
struct hash_entry *cursor;
struct hash_entry *next;
+ int err = errno;
/* Call the user data_freer function. */
if (table->data_freer && table->n_entries)
@@ -649,6 +656,8 @@ hash_free (Hash_table *table)
/* Free the remainder of the hash table structure. */
free (table->bucket);
free (table);
+
+ errno = err;
}
/* Insertion and deletion. */
@@ -762,8 +771,8 @@ hash_find_entry (Hash_table *table, const void *entry,
/* Internal helper, to move entries from SRC to DST. Both tables must
share the same free entry list. If SAFE, only move overflow
entries, saving bucket heads for later, so that no allocations will
- occur. Return false if the free entry list is exhausted and an
- allocation fails. */
+ occur. Return false (setting errno) if the free entry list is
+ exhausted and an allocation fails. */
static bool
transfer_entries (Hash_table *dst, Hash_table *src, bool safe)
@@ -910,12 +919,14 @@ hash_rehash (Hash_table *table, size_t candidate)
passes. Two passes give worse cache performance and takes
longer, but at this point, we're already out of memory, so slow
and safe is better than failure. */
+ int err = errno;
table->free_entry_list = new_table->free_entry_list;
if (! (transfer_entries (table, new_table, true)
&& transfer_entries (table, new_table, false)))
abort ();
/* table->n_entries already holds its value. */
free (new_table->bucket);
+ errno = err;
return false;
}
@@ -962,7 +973,10 @@ hash_insert_if_absent (Hash_table *table, void const *entry,
* tuning->growth_threshold));
if ((float) SIZE_MAX <= candidate)
- return -1;
+ {
+ errno = ENOMEM;
+ return -1;
+ }
/* If the rehash fails, arrange to return NULL. */
if (!hash_rehash (table, candidate))