|
@@ -130,6 +130,9 @@ struct delayed_set_stat
|
|
|
|
|
|
static struct delayed_set_stat *delayed_set_stat_head;
|
|
|
|
|
|
+/* Table of delayed stat updates hashed by path; null if none. */
|
|
|
+static Hash_table *delayed_set_stat_table;
|
|
|
+
|
|
|
/* A link whose creation we have delayed. */
|
|
|
struct delayed_link
|
|
|
{
|
|
@@ -214,6 +217,20 @@ dl_compare (void const *a, void const *b)
|
|
|
return (da->dev == db->dev) & (da->ino == db->ino);
|
|
|
}
|
|
|
|
|
|
+static size_t
|
|
|
+ds_hash (void const *entry, size_t table_size)
|
|
|
+{
|
|
|
+ struct delayed_set_stat const *ds = entry;
|
|
|
+ return hash_string (ds->file_name, table_size);
|
|
|
+}
|
|
|
+
|
|
|
+static bool
|
|
|
+ds_compare (void const *a, void const *b)
|
|
|
+{
|
|
|
+ struct delayed_set_stat const *dsa = a, *dsb = b;
|
|
|
+ return strcmp (dsa->file_name, dsb->file_name) == 0;
|
|
|
+}
|
|
|
+
|
|
|
/* Set up to extract files. */
|
|
|
void
|
|
|
extr_init (void)
|
|
@@ -513,11 +530,14 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
|
|
|
size_t file_name_len = strlen (file_name);
|
|
|
struct delayed_set_stat *data;
|
|
|
|
|
|
- for (data = delayed_set_stat_head; data; data = data->next)
|
|
|
- if (strcmp (data->file_name, file_name) == 0)
|
|
|
- break;
|
|
|
+ if (! (delayed_set_stat_table
|
|
|
+ || (delayed_set_stat_table = hash_initialize (0, 0, ds_hash,
|
|
|
+ ds_compare, NULL))))
|
|
|
+ xalloc_die ();
|
|
|
+
|
|
|
+ const struct delayed_set_stat key = { .file_name = (char*) file_name };
|
|
|
|
|
|
- if (data)
|
|
|
+ if ((data = hash_lookup (delayed_set_stat_table, &key)) != NULL)
|
|
|
{
|
|
|
if (data->interdir)
|
|
|
{
|
|
@@ -541,6 +561,8 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
|
|
|
delayed_set_stat_head = data;
|
|
|
data->file_name_len = file_name_len;
|
|
|
data->file_name = xstrdup (file_name);
|
|
|
+ if (! hash_insert (delayed_set_stat_table, data))
|
|
|
+ xalloc_die ();
|
|
|
data->after_links = false;
|
|
|
if (st)
|
|
|
{
|
|
@@ -652,6 +674,7 @@ remove_delayed_set_stat (const char *fname)
|
|
|
if (chdir_current == data->change_dir
|
|
|
&& strcmp (data->file_name, fname) == 0)
|
|
|
{
|
|
|
+ hash_remove (delayed_set_stat_table, data);
|
|
|
free_delayed_set_stat (data);
|
|
|
if (prev)
|
|
|
prev->next = next;
|
|
@@ -1000,6 +1023,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
|
|
|
}
|
|
|
|
|
|
delayed_set_stat_head = data->next;
|
|
|
+ hash_remove (delayed_set_stat_table, data);
|
|
|
free_delayed_set_stat (data);
|
|
|
}
|
|
|
}
|
|
@@ -1962,6 +1986,13 @@ extract_finish (void)
|
|
|
/* Finally, fix the status of directories that are ancestors
|
|
|
of delayed links. */
|
|
|
apply_nonancestor_delayed_set_stat ("", 1);
|
|
|
+
|
|
|
+ /* This table should be empty after apply_nonancestor_delayed_set_stat */
|
|
|
+ if (delayed_set_stat_table != NULL)
|
|
|
+ {
|
|
|
+ hash_free (delayed_set_stat_table);
|
|
|
+ delayed_set_stat_table = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
bool
|