diff options
author | Andrew Cagney <cagney@redhat.com> | 2004-04-21 17:05:12 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2004-04-21 17:05:12 +0000 |
commit | 40838a725a2186ffdc9621694e72f340928a0b13 (patch) | |
tree | 188ce229fccc9465d5149968ddf2af50a1a6ebdc /bfd/opncls.c | |
parent | 7f919c8471b407c6a8c698ee3b29cdf0e9c4eb3d (diff) | |
download | ppe42-binutils-40838a725a2186ffdc9621694e72f340928a0b13.tar.gz ppe42-binutils-40838a725a2186ffdc9621694e72f340928a0b13.zip |
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/opncls.c')
-rw-r--r-- | bfd/opncls.c | 185 |
1 files changed, 184 insertions, 1 deletions
diff --git a/bfd/opncls.c b/bfd/opncls.c index 6abd40509c..3291cbabae 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -103,6 +103,7 @@ _bfd_new_bfd_contained_in (bfd *obfd) if (nbfd == NULL) return NULL; nbfd->xvec = obfd->xvec; + nbfd->iovec = obfd->iovec; nbfd->my_archive = obfd; nbfd->direction = read_direction; nbfd->target_defaulted = obfd->target_defaulted; @@ -322,6 +323,183 @@ bfd_openstreamr (const char *filename, const char *target, void *streamarg) return nbfd; } + +/* +FUNCTION + bfd_openr_iovec + +SYNOPSIS + bfd *bfd_openr_iovec (const char *filename, const char *target, + void *(*open) (struct bfd *nbfd, + void *open_closure), + void *open_closure, + file_ptr (*pread) (struct bfd *nbfd, + void *stream, + void *buf, + file_ptr nbytes, + file_ptr offset), + int (*close) (struct bfd *nbfd, + void *stream)); + +DESCRIPTION + + Create and return a BFD backed by a read-only @var{stream}. + The @var{stream} is created using @var{open}, accessed using + @var{pread} and destroyed using @var{close}. + + Calls <<bfd_find_target>>, so @var{target} is interpreted as by + that function. + + Calls @var{open} (which can call <<bfd_zalloc>> and + <<bfd_get_filename>>) to obtain the read-only stream backing + the BFD. @var{open} either succeeds returning the + non-<<NULL>> @var{stream}, or fails returning <<NULL>> + (setting <<bfd_error>>). + + Calls @var{pread} to request @var{nbytes} of data from + @var{stream} starting at @var{offset} (e.g., via a call to + <<bfd_read>>). @var{pread} either succeeds returning the + number of bytes read (which can be less than @var{nbytes} when + end-of-file), or fails returning -1 (setting <<bfd_error>>). + + Calls @var{close} when the BFD is later closed using + <<bfd_close>>. @var{close} either succeeds returning 0, or + fails returning -1 (setting <<bfd_error>>). + + If <<bfd_openr_iovec>> returns <<NULL>> then an error has + occurred. Possible errors are <<bfd_error_no_memory>>, + <<bfd_error_invalid_target>> and <<bfd_error_system_call>>. + +*/ + +struct opncls +{ + void *stream; + file_ptr (*pread) (struct bfd *abfd, void *stream, void *buf, + file_ptr nbytes, file_ptr offset); + int (*close) (struct bfd *abfd, void *stream); + file_ptr where; +}; + +static file_ptr +opncls_btell (struct bfd *abfd) +{ + struct opncls *vec = abfd->iostream; + return vec->where; +} + +static int +opncls_bseek (struct bfd *abfd, file_ptr offset, int whence) +{ + struct opncls *vec = abfd->iostream; + switch (whence) + { + case SEEK_SET: vec->where = offset; break; + case SEEK_CUR: vec->where += offset; break; + case SEEK_END: return -1; + } + return 0; +} + +static file_ptr +opncls_bread (struct bfd *abfd, void *buf, file_ptr nbytes) +{ + struct opncls *vec = abfd->iostream; + file_ptr nread = vec->pread (abfd, vec->stream, buf, nbytes, vec->where); + if (nread < 0) + return nread; + vec->where += nread; + return nread; +} + +static file_ptr +opncls_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED, + const void *where ATTRIBUTE_UNUSED, + file_ptr nbytes ATTRIBUTE_UNUSED) +{ + return -1; +} + +static int +opncls_bclose (struct bfd *abfd) +{ + struct opncls *vec = abfd->iostream; + /* Since the VEC's memory is bound to the bfd deleting the bfd will + free it. */ + int status = 0; + if (vec->close != NULL) + status = vec->close (abfd, vec->stream); + abfd->iostream = NULL; + return status; +} + +static int +opncls_bflush (struct bfd *abfd ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +opncls_bstat (struct bfd *abfd ATTRIBUTE_UNUSED, struct stat *sb) +{ + memset (sb, 0, sizeof (*sb)); + return 0; +} + +static const struct bfd_iovec opncls_iovec = { + &opncls_bread, &opncls_bwrite, &opncls_btell, &opncls_bseek, + &opncls_bclose, &opncls_bflush, &opncls_bstat +}; + +bfd * +bfd_openr_iovec (const char *filename, const char *target, + void *(*open) (struct bfd *nbfd, + void *open_closure), + void *open_closure, + file_ptr (*pread) (struct bfd *abfd, + void *stream, + void *buf, + file_ptr nbytes, + file_ptr offset), + int (*close) (struct bfd *nbfd, + void *stream)) +{ + bfd *nbfd; + const bfd_target *target_vec; + struct opncls *vec; + void *stream; + + nbfd = _bfd_new_bfd (); + if (nbfd == NULL) + return NULL; + + target_vec = bfd_find_target (target, nbfd); + if (target_vec == NULL) + { + _bfd_delete_bfd (nbfd); + return NULL; + } + + nbfd->filename = filename; + nbfd->direction = read_direction; + + stream = open (nbfd, open_closure); + if (stream == NULL) + { + _bfd_delete_bfd (nbfd); + return NULL; + } + + vec = bfd_zalloc (nbfd, sizeof (struct opncls)); + vec->stream = stream; + vec->pread = pread; + vec->close = close; + + nbfd->iovec = &opncls_iovec; + nbfd->iostream = vec; + + return nbfd; +} /* bfd_openw -- open for writing. Returns a pointer to a freshly-allocated BFD on success, or NULL. @@ -415,7 +593,12 @@ bfd_close (bfd *abfd) if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) return FALSE; - ret = bfd_cache_close (abfd); + /* FIXME: cagney/2004-02-15: Need to implement a BFD_IN_MEMORY io + vector. */ + if (!(abfd->flags & BFD_IN_MEMORY)) + ret = abfd->iovec->bclose (abfd); + else + ret = 0; /* If the file was open for writing and is now executable, make it so. */ |