summaryrefslogtreecommitdiff
path: root/bfd/cache.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2004-04-21 17:05:12 +0000
committerAndrew Cagney <cagney@redhat.com>2004-04-21 17:05:12 +0000
commit4985f72cb52e77556d9c150176ccecbe74ca1f95 (patch)
tree0f55fadca1c47fdef8eb0dab220c6192005c8359 /bfd/cache.c
parent4970cd21d9feacbf6efde0c79af322f2ee692708 (diff)
downloadbinutils-redhat-4985f72cb52e77556d9c150176ccecbe74ca1f95.tar.gz
2004-04-21 Andrew Cagney <cagney@redhat.com>
* opncls.c (_bfd_new_bfd_contained_in): Copy "iovec". (struct opncls, opncls_btell, opncls_bseek, opncls_bread) (opncls_bwrite, opncls_bclose, opncls_bflush) (opncls_bstat, opncls_iovec, bfd_openr_iovec): Implement a bfd iovec that uses function callbacks. (bfd_close): Use the iovec's bclose. * cache.c (cache_btell, cache_bseek, cache_bread, cache_bwrite) (cache_bclose, cache_bflush, cache_bstat) (cache_iovec): New functions and global variable, implement a cache "iovec", where applicable set bfd_error. (bfd_cache_init, bfd_cache_close): Set/test the bfd's iovec. * bfdio.c (struct bfd_iovec): Define. (real_read): Delete function. (bfd_bread, bfd_bread, bfd_bwrite, bfd_tell, bfd_flush, bfd_stat) (bfd_seek, bfd_get_mtime, bfd_get_size): Use the bfd's "iovec", assume that bread and bwrite set bfd_error. * bfd.c (struct bfd): Add "iovec", update comments. * bfd-in2.h, libbfd.h: Re-generate.
Diffstat (limited to 'bfd/cache.c')
-rw-r--r--bfd/cache.c107
1 files changed, 105 insertions, 2 deletions
diff --git a/bfd/cache.c b/bfd/cache.c
index 7d056ea0cf..9146c05cac 100644
--- a/bfd/cache.c
+++ b/bfd/cache.c
@@ -44,6 +44,109 @@ SECTION
static bfd_boolean bfd_cache_delete (bfd *);
+
+static file_ptr
+cache_btell (struct bfd *abfd)
+{
+ return real_ftell (bfd_cache_lookup (abfd));
+}
+
+static int
+cache_bseek (struct bfd *abfd, file_ptr offset, int whence)
+{
+ return real_fseek (bfd_cache_lookup (abfd), offset, whence);
+}
+
+/* Note that archive entries don't have streams; they share their parent's.
+ This allows someone to play with the iostream behind BFD's back.
+
+ Also, note that the origin pointer points to the beginning of a file's
+ contents (0 for non-archive elements). For archive entries this is the
+ first octet in the file, NOT the beginning of the archive header. */
+
+static file_ptr
+cache_bread (struct bfd *abfd, void *buf, file_ptr nbytes)
+{
+ file_ptr nread;
+ /* FIXME - this looks like an optimization, but it's really to cover
+ up for a feature of some OSs (not solaris - sigh) that
+ ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
+ internally and tries to link against them. BFD seems to be smart
+ enough to realize there are no symbol records in the "file" that
+ doesn't exist but attempts to read them anyway. On Solaris,
+ attempting to read zero bytes from a NULL file results in a core
+ dump, but on other platforms it just returns zero bytes read.
+ This makes it to something reasonable. - DJ */
+ if (nbytes == 0)
+ return 0;
+
+#if defined (__VAX) && defined (VMS)
+ /* Apparently fread on Vax VMS does not keep the record length
+ information. */
+ nread = read (fileno (bfd_cache_lookup (abfd)), buf, nbytes);
+ /* Set bfd_error if we did not read as much data as we expected. If
+ the read failed due to an error set the bfd_error_system_call,
+ else set bfd_error_file_truncated. */
+ if (nread == (file_ptr)-1)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return -1;
+ }
+#else
+ nread = fread (buf, 1, nbytes, bfd_cache_lookup (abfd));
+ /* Set bfd_error if we did not read as much data as we expected. If
+ the read failed due to an error set the bfd_error_system_call,
+ else set bfd_error_file_truncated. */
+ if (nread < nbytes && ferror (bfd_cache_lookup (abfd)))
+ {
+ bfd_set_error (bfd_error_system_call);
+ return -1;
+ }
+#endif
+ return nread;
+}
+
+static file_ptr
+cache_bwrite (struct bfd *abfd, const void *where, file_ptr nbytes)
+{
+ file_ptr nwrite = fwrite (where, 1, nbytes, bfd_cache_lookup (abfd));
+ if (nwrite < nbytes && ferror (bfd_cache_lookup (abfd)))
+ {
+ bfd_set_error (bfd_error_system_call);
+ return -1;
+ }
+ return nwrite;
+}
+
+static int
+cache_bclose (struct bfd *abfd)
+{
+ return bfd_cache_close (abfd);
+}
+
+static int
+cache_bflush (struct bfd *abfd)
+{
+ int sts = fflush (bfd_cache_lookup (abfd));
+ if (sts < 0)
+ bfd_set_error (bfd_error_system_call);
+ return sts;
+}
+
+static int
+cache_bstat (struct bfd *abfd, struct stat *sb)
+{
+ int sts = fstat (fileno (bfd_cache_lookup (abfd)), sb);
+ if (sts < 0)
+ bfd_set_error (bfd_error_system_call);
+ return sts;
+}
+
+static const struct bfd_iovec cache_iovec = {
+ &cache_bread, &cache_bwrite, &cache_btell, &cache_bseek,
+ &cache_bclose, &cache_bflush, &cache_bstat
+};
+
/*
INTERNAL_FUNCTION
BFD_CACHE_MAX_OPEN macro
@@ -205,6 +308,7 @@ bfd_cache_init (bfd *abfd)
if (! close_one ())
return FALSE;
}
+ abfd->iovec = &cache_iovec;
insert (abfd);
++open_files;
return TRUE;
@@ -229,8 +333,7 @@ RETURNS
bfd_boolean
bfd_cache_close (bfd *abfd)
{
- if (abfd->iostream == NULL
- || (abfd->flags & BFD_IN_MEMORY) != 0)
+ if (abfd->iovec != &cache_iovec)
return TRUE;
return bfd_cache_delete (abfd);