X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fbfdio.c;h=71ac17ec51515e157214769d8efb5fc45971d3df;hb=fe64b263e025c5abc02738138d9283f53641ca42;hp=136fa8b1d3f0f43dddc6b76cb28efcdc19b9b25d;hpb=5c4ce239a3ab9263163a0fe8e7487b39a41c43d1;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/bfdio.c b/bfd/bfdio.c index 136fa8b1d3..71ac17ec51 100644 --- a/bfd/bfdio.c +++ b/bfd/bfdio.c @@ -1,6 +1,6 @@ /* Low-level I/O routines for BFDs. - Copyright (C) 1990-2018 Free Software Foundation, Inc. + Copyright (C) 1990-2020 Free Software Foundation, Inc. Written by Cygnus Support. @@ -25,6 +25,7 @@ #include #include "bfd.h" #include "libbfd.h" +#include "aout/ar.h" #ifndef S_IXUSR #define S_IXUSR 0100 /* Execute by owner. */ @@ -330,6 +331,10 @@ bfd_seek (bfd *abfd, file_ptr position, int direction) if (direction != SEEK_CUR) position += offset; + if ((direction == SEEK_CUR && position == 0) + || (direction == SEEK_SET && (ufile_ptr) position == abfd->where)) + return 0; + result = abfd->iovec->bseek (abfd, position, direction); if (result != 0) { @@ -411,17 +416,32 @@ DESCRIPTION of space for the 15 bazillon byte table it is about to read. This function at least allows us to answer the question, "is the size reasonable?". + + A return value of zero indicates the file size is unknown. */ ufile_ptr bfd_get_size (bfd *abfd) { - struct stat buf; + /* A size of 0 means we haven't yet called bfd_stat. A size of 1 + means we have a cached value of 0, ie. unknown. */ + if (abfd->size <= 1 || bfd_write_p (abfd)) + { + struct stat buf; - if (bfd_stat (abfd, &buf) != 0) - return 0; + if (abfd->size == 1 && !bfd_write_p (abfd)) + return 0; - return buf.st_size; + if (bfd_stat (abfd, &buf) != 0 + || buf.st_size == 0 + || buf.st_size - (ufile_ptr) buf.st_size != 0) + { + abfd->size = 1; + return 0; + } + abfd->size = buf.st_size; + } + return abfd->size; } /* @@ -441,11 +461,24 @@ DESCRIPTION ufile_ptr bfd_get_file_size (bfd *abfd) { + ufile_ptr file_size, archive_size = (ufile_ptr) -1; + if (abfd->my_archive != NULL && !bfd_is_thin_archive (abfd->my_archive)) - return arelt_size (abfd); + { + struct areltdata *adata = (struct areltdata *) abfd->arelt_data; + archive_size = adata->parsed_size; + /* If the archive is compressed we can't compare against file size. */ + if (memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag, + "Z\012", 2) == 0) + return archive_size; + abfd = abfd->my_archive; + } - return bfd_get_size (abfd); + file_size = bfd_get_size (abfd); + if (archive_size < file_size) + return archive_size; + return file_size; } /*