|
|
|
@ -62,37 +62,41 @@ real_fseek (FILE *file, file_ptr offset, int whence) |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
/* 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. |
|
|
|
/*
|
|
|
|
INTERNAL_DEFINITION |
|
|
|
struct bfd_iovec |
|
|
|
|
|
|
|
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. */ |
|
|
|
DESCRIPTION |
|
|
|
|
|
|
|
static size_t |
|
|
|
real_read (void *where, size_t a, size_t b, FILE *file) |
|
|
|
{ |
|
|
|
/* 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 (a == 0 || b == 0) |
|
|
|
return 0; |
|
|
|
The <<struct bfd_iovec>> contains the internal file I/O class. |
|
|
|
Each <<BFD>> has an instance of this class and all file I/O is |
|
|
|
routed through it (it is assumed that the instance implements |
|
|
|
all methods listed below). |
|
|
|
|
|
|
|
.struct bfd_iovec |
|
|
|
.{ |
|
|
|
. {* To avoid problems with macros, a "b" rather than "f" |
|
|
|
. prefix is prepended to each method name. *} |
|
|
|
. {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching |
|
|
|
. bytes starting at PTR. Return the number of bytes actually |
|
|
|
. transfered (a read past end-of-file returns less than NBYTES), |
|
|
|
. or -1 (setting <<bfd_error>>) if an error occurs. *} |
|
|
|
. file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes); |
|
|
|
. file_ptr (*bwrite) (struct bfd *abfd, const void *ptr, |
|
|
|
. file_ptr nbytes); |
|
|
|
. {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>> |
|
|
|
. if an error occurs. *} |
|
|
|
. file_ptr (*btell) (struct bfd *abfd); |
|
|
|
. {* For the following, on successful completion a value of 0 is returned. |
|
|
|
. Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *} |
|
|
|
. int (*bseek) (struct bfd *abfd, file_ptr offset, int whence); |
|
|
|
. int (*bclose) (struct bfd *abfd); |
|
|
|
. int (*bflush) (struct bfd *abfd); |
|
|
|
. int (*bstat) (struct bfd *abfd, struct stat *sb); |
|
|
|
.}; |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
#if defined (__VAX) && defined (VMS) |
|
|
|
/* Apparently fread on Vax VMS does not keep the record length
|
|
|
|
information. */ |
|
|
|
return read (fileno (file), where, a * b); |
|
|
|
#else |
|
|
|
return fread (where, a, b, file); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
/* Return value is amount read. */ |
|
|
|
|
|
|
|
@ -121,25 +125,10 @@ bfd_bread (void *ptr, bfd_size_type size, bfd *abfd) |
|
|
|
return get; |
|
|
|
} |
|
|
|
|
|
|
|
nread = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); |
|
|
|
nread = abfd->iovec->bread (abfd, ptr, size); |
|
|
|
if (nread != (size_t) -1) |
|
|
|
abfd->where += nread; |
|
|
|
|
|
|
|
/* 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. |
|
|
|
|
|
|
|
A BFD backend may wish to override bfd_error_file_truncated to |
|
|
|
provide something more useful (eg. no_symbols or wrong_format). */ |
|
|
|
if (nread != size) |
|
|
|
{ |
|
|
|
if (ferror (bfd_cache_lookup (abfd))) |
|
|
|
bfd_set_error (bfd_error_system_call); |
|
|
|
else |
|
|
|
bfd_set_error (bfd_error_file_truncated); |
|
|
|
} |
|
|
|
|
|
|
|
return nread; |
|
|
|
} |
|
|
|
|
|
|
|
@ -175,7 +164,7 @@ bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd) |
|
|
|
return size; |
|
|
|
} |
|
|
|
|
|
|
|
nwrote = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); |
|
|
|
nwrote = abfd->iovec->bwrite (abfd, ptr, size); |
|
|
|
if (nwrote != (size_t) -1) |
|
|
|
abfd->where += nwrote; |
|
|
|
if (nwrote != size) |
|
|
|
@ -196,7 +185,7 @@ bfd_tell (bfd *abfd) |
|
|
|
if ((abfd->flags & BFD_IN_MEMORY) != 0) |
|
|
|
return abfd->where; |
|
|
|
|
|
|
|
ptr = real_ftell (bfd_cache_lookup (abfd)); |
|
|
|
ptr = abfd->iovec->btell (abfd); |
|
|
|
|
|
|
|
if (abfd->my_archive) |
|
|
|
ptr -= abfd->origin; |
|
|
|
@ -209,7 +198,7 @@ bfd_flush (bfd *abfd) |
|
|
|
{ |
|
|
|
if ((abfd->flags & BFD_IN_MEMORY) != 0) |
|
|
|
return 0; |
|
|
|
return fflush (bfd_cache_lookup(abfd)); |
|
|
|
return abfd->iovec->bflush (abfd); |
|
|
|
} |
|
|
|
|
|
|
|
/* Returns 0 for success, negative value for failure (in which case
|
|
|
|
@ -217,19 +206,12 @@ bfd_flush (bfd *abfd) |
|
|
|
int |
|
|
|
bfd_stat (bfd *abfd, struct stat *statbuf) |
|
|
|
{ |
|
|
|
FILE *f; |
|
|
|
int result; |
|
|
|
|
|
|
|
if ((abfd->flags & BFD_IN_MEMORY) != 0) |
|
|
|
abort (); |
|
|
|
|
|
|
|
f = bfd_cache_lookup (abfd); |
|
|
|
if (f == NULL) |
|
|
|
{ |
|
|
|
bfd_set_error (bfd_error_system_call); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
result = fstat (fileno (f), statbuf); |
|
|
|
result = abfd->iovec->bstat (abfd, statbuf); |
|
|
|
if (result < 0) |
|
|
|
bfd_set_error (bfd_error_system_call); |
|
|
|
return result; |
|
|
|
@ -242,7 +224,6 @@ int |
|
|
|
bfd_seek (bfd *abfd, file_ptr position, int direction) |
|
|
|
{ |
|
|
|
int result; |
|
|
|
FILE *f; |
|
|
|
file_ptr file_position; |
|
|
|
/* For the time being, a BFD may not seek to it's end. The problem
|
|
|
|
is that we don't easily have a way to recognize the end of an |
|
|
|
@ -328,12 +309,11 @@ bfd_seek (bfd *abfd, file_ptr position, int direction) |
|
|
|
In the meantime, no optimization for archives. */ |
|
|
|
} |
|
|
|
|
|
|
|
f = bfd_cache_lookup (abfd); |
|
|
|
file_position = position; |
|
|
|
if (direction == SEEK_SET && abfd->my_archive != NULL) |
|
|
|
file_position += abfd->origin; |
|
|
|
|
|
|
|
result = real_fseek (f, file_position, direction); |
|
|
|
result = abfd->iovec->bseek (abfd, file_position, direction); |
|
|
|
if (result != 0) |
|
|
|
{ |
|
|
|
int hold_errno = errno; |
|
|
|
@ -378,14 +358,12 @@ DESCRIPTION |
|
|
|
long |
|
|
|
bfd_get_mtime (bfd *abfd) |
|
|
|
{ |
|
|
|
FILE *fp; |
|
|
|
struct stat buf; |
|
|
|
|
|
|
|
if (abfd->mtime_set) |
|
|
|
return abfd->mtime; |
|
|
|
|
|
|
|
fp = bfd_cache_lookup (abfd); |
|
|
|
if (0 != fstat (fileno (fp), &buf)) |
|
|
|
if (abfd->iovec->bstat (abfd, &buf) != 0) |
|
|
|
return 0; |
|
|
|
|
|
|
|
abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ |
|
|
|
@ -428,14 +406,12 @@ DESCRIPTION |
|
|
|
long |
|
|
|
bfd_get_size (bfd *abfd) |
|
|
|
{ |
|
|
|
FILE *fp; |
|
|
|
struct stat buf; |
|
|
|
|
|
|
|
if ((abfd->flags & BFD_IN_MEMORY) != 0) |
|
|
|
return ((struct bfd_in_memory *) abfd->iostream)->size; |
|
|
|
|
|
|
|
fp = bfd_cache_lookup (abfd); |
|
|
|
if (0 != fstat (fileno (fp), & buf)) |
|
|
|
if (abfd->iovec->bstat (abfd, &buf) != 0) |
|
|
|
return 0; |
|
|
|
|
|
|
|
return buf.st_size; |
|
|
|
|