diff options
Diffstat (limited to 'src/cache.c')
-rw-r--r-- | src/cache.c | 159 |
1 files changed, 107 insertions, 52 deletions
diff --git a/src/cache.c b/src/cache.c index 2825421..476d83d 100644 --- a/src/cache.c +++ b/src/cache.c @@ -92,23 +92,35 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, int insert) { struct prelink_entry e, *ent = NULL; - void **filename_slot; - void **devino_slot; + void **filename_slot, *dummy = NULL; + void **devino_slot = NULL; struct stat64 st; + char *canon_filename = NULL; e.filename = filename; - filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT); + filename_slot = htab_find_slot (prelink_filename_htab, &e, + insert ? INSERT : NO_INSERT); if (filename_slot == NULL) - goto error_out; + { + if (insert) + goto error_out; + filename_slot = &dummy; + } if (*filename_slot != NULL) return (struct prelink_entry *) *filename_slot; if (! stp) { - if (stat64 (filename, &st) < 0) + canon_filename = prelink_canonicalize (filename, &st); + if (canon_filename == NULL && stat64 (filename, &st) < 0) { error (0, errno, "Could not stat %s", filename); + if (insert) + { + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + } return NULL; } stp = &st; @@ -116,52 +128,38 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, e.dev = stp->st_dev; e.ino = stp->st_ino; - devino_slot = htab_find_slot (prelink_devino_htab, &e, INSERT); + devino_slot = htab_find_slot (prelink_devino_htab, &e, + insert ? INSERT : NO_INSERT); if (devino_slot == NULL) - goto error_out; + { + if (insert) + goto error_out; + free (canon_filename); + return NULL; + } if (*devino_slot != NULL) { - char *canon_filename; - ent = (struct prelink_entry *) *devino_slot; - canon_filename = canonicalize_file_name (filename); + if (canon_filename == NULL) + canon_filename = prelink_canonicalize (filename, NULL); if (canon_filename == NULL) { error (0, 0, "Could not canonicalize filename %s", filename); - return NULL; + goto error_out2; } if (strcmp (canon_filename, ent->canon_filename) != 0) { struct prelink_link *hardlink; - if (ent->flags & PCF_VERIFY_CANONFNAME) - { - char *canon_ent_filename - = canonicalize_file_name (ent->canon_filename); - - ent->flags &= ~PCF_VERIFY_CANONFNAME; - if (canon_ent_filename == NULL - || strcmp (canon_ent_filename, ent->canon_filename) != 0) - { - free (canon_ent_filename); - canon_ent_filename = (char *) ent->canon_filename; - ent->canon_filename = canon_filename; - free (canon_ent_filename); - return ent; - } - free (canon_ent_filename); - } - hardlink = (struct prelink_link *) malloc (sizeof (struct prelink_link)); if (hardlink == NULL) { error (0, ENOMEM, "Could not record hardlink %s to %s", canon_filename, ent->canon_filename); - free (canon_filename); - return NULL; + goto error_out2; } hardlink->canon_filename = canon_filename; @@ -174,7 +172,11 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, } if (! insert) - return NULL; + { + if (canon_filename != NULL) + free (canon_filename); + return NULL; + } ent = (struct prelink_entry *) calloc (sizeof (struct prelink_entry), 1); if (ent == NULL) @@ -184,11 +186,16 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, if (ent->filename == NULL) goto error_out; - ent->canon_filename = canonicalize_file_name (filename); + if (canon_filename != NULL) + ent->canon_filename = canon_filename; + else + ent->canon_filename = prelink_canonicalize (filename, NULL); if (ent->canon_filename == NULL) { error (0, 0, "Could not canonicalize filename %s", filename); - return NULL; + free ((char *) ent->filename); + free (ent); + goto error_out2; } ent->dev = stp->st_dev; @@ -204,6 +211,22 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, error_out: free (ent); error (0, ENOMEM, "Could not insert %s into hash table", filename); +error_out2: + if (insert) + { + if (filename_slot != NULL) + { + assert (*filename_slot == NULL); + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + } + if (devino_slot != NULL && *devino_slot == NULL) + { + *devino_slot = &dummy; + htab_clear_slot (prelink_devino_htab, devino_slot); + } + } + free (canon_filename); return NULL; } @@ -211,10 +234,11 @@ static struct prelink_entry * prelink_load_entry (const char *filename) { struct prelink_entry e, *ent = NULL; - void **filename_slot; - void **devino_slot, *dummy = NULL; + void **filename_slot, *dummy = NULL; + void **devino_slot = &dummy; struct stat64 st; uint32_t ctime = 0, mtime = 0; + char *canon_filename = NULL; e.filename = filename; filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT); @@ -224,11 +248,32 @@ prelink_load_entry (const char *filename) if (*filename_slot != NULL) return (struct prelink_entry *) *filename_slot; - if (stat64 (filename, &st) < 0) + canon_filename = prelink_canonicalize (filename, &st); + if (canon_filename == NULL) + goto error_out2; + if (strcmp (canon_filename, filename) != 0) { - e.dev = 0; - e.ino = 0; - devino_slot = &dummy; + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + + e.filename = canon_filename; + filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT); + if (filename_slot == NULL) + goto error_out; + + if (*filename_slot != NULL) + { + free (canon_filename); + return (struct prelink_entry *) *filename_slot; + } + } + + if (! S_ISREG (st.st_mode)) + { + free (canon_filename); + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + return NULL; } else { @@ -242,7 +287,12 @@ prelink_load_entry (const char *filename) } if (*devino_slot != NULL) - return (struct prelink_entry *) *devino_slot; + { + free (canon_filename); + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + return (struct prelink_entry *) *devino_slot; + } ent = (struct prelink_entry *) calloc (sizeof (struct prelink_entry), 1); if (ent == NULL) @@ -252,13 +302,7 @@ prelink_load_entry (const char *filename) if (ent->filename == NULL) goto error_out; - ent->canon_filename = strdup (filename); - if (ent->canon_filename == NULL) - { - free ((char *) ent->filename); - goto error_out; - } - + ent->canon_filename = canon_filename; ent->dev = e.dev; ent->ino = e.ino; ent->ctime = ctime; @@ -271,6 +315,18 @@ prelink_load_entry (const char *filename) error_out: free (ent); error (0, ENOMEM, "Could not insert %s into hash table", filename); +error_out2: + if (filename_slot != NULL) + { + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + } + if (devino_slot != NULL && devino_slot != &dummy) + { + *devino_slot = &dummy; + htab_clear_slot (prelink_devino_htab, devino_slot); + } + free (canon_filename); return NULL; } @@ -365,9 +421,9 @@ prelink_load_cache (void) ents[i]->end = cache->entry[i].end; ents[i]->type = (ents[i]->base == 0 && ents[i]->end == 0) ? ET_CACHE_EXEC : ET_CACHE_DYN; - ents[i]->flags = cache->entry[i].flags | PCF_VERIFY_CANONFNAME; + ents[i]->flags = cache->entry[i].flags; - if (ents[i]->flags == (PCF_UNPRELINKABLE | PCF_VERIFY_CANONFNAME)) + if (ents[i]->flags == PCF_UNPRELINKABLE) ents[i]->type = (quick || print_cache) ? ET_UNPRELINKABLE : ET_NONE; /* If mtime is equal to ctime, assume the filesystem does not store @@ -575,8 +631,7 @@ prelink_save_cache (int do_warn) data[i].filename = (strings - (char *) data) + sizeof (cache); strings = stpcpy (strings, l.ents[i]->canon_filename) + 1; data[i].checksum = l.ents[i]->checksum; - data[i].flags = l.ents[i]->flags - & ~(PCF_PRELINKED | PCF_VERIFY_CANONFNAME); + data[i].flags = l.ents[i]->flags & ~PCF_PRELINKED; data[i].ctime = l.ents[i]->ctime; data[i].mtime = l.ents[i]->mtime; if (l.ents[i]->type == ET_EXEC || l.ents[i]->type == ET_CACHE_EXEC) |