Fix SH2A machine variants in order to correctly select instruction inheritance
[deliverable/binutils-gdb.git] / bfd / bfdio.c
index f99fddd482981208350226df59056caf818c17ca..a7505270199c7e972bf0bca0440c18e64eeb04d3 100644 (file)
@@ -1,6 +1,8 @@
 /* Low-level I/O routines for BFDs.
 /* Low-level I/O routines for BFDs.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -36,38 +38,66 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define S_IXOTH 0001    /* Execute by others.  */
 #endif
 
 #define S_IXOTH 0001    /* Execute by others.  */
 #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.
-
-   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 size_t
-real_read (void *where, size_t a, size_t b, FILE *file)
+file_ptr
+real_ftell (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;
-
+#if defined (HAVE_FTELLO64)
+  return ftello64 (file);
+#elif defined (HAVE_FTELLO)
+  return ftello (file);
+#else
+  return ftell (file);
+#endif
+}
 
 
-#if defined (__VAX) && defined (VMS)
-  /* Apparently fread on Vax VMS does not keep the record length
-     information.  */
-  return read (fileno (file), where, a * b);
+int
+real_fseek (FILE *file, file_ptr offset, int whence)
+{
+#if defined (HAVE_FSEEKO64)
+  return fseeko64 (file, offset, whence);
+#elif defined (HAVE_FSEEKO)
+  return fseeko (file, offset, whence);
 #else
 #else
-  return fread (where, a, b, file);
+  return fseek (file, offset, whence);
 #endif
 }
 
 #endif
 }
 
+/*
+INTERNAL_DEFINITION
+       struct bfd_iovec
+
+DESCRIPTION
+
+       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);
+.};
+
+*/
+
+
 /* Return value is amount read.  */
 
 bfd_size_type
 /* Return value is amount read.  */
 
 bfd_size_type
@@ -95,25 +125,13 @@ bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
       return get;
     }
 
       return get;
     }
 
-  nread = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
+  if (abfd->iovec)
+    nread = abfd->iovec->bread (abfd, ptr, size);
+  else
+    nread = 0;
   if (nread != (size_t) -1)
     abfd->where += nread;
 
   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;
 }
 
   return nread;
 }
 
@@ -125,6 +143,7 @@ bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     {
       struct bfd_in_memory *bim = abfd->iostream;
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     {
       struct bfd_in_memory *bim = abfd->iostream;
+
       size = (size_t) size;
       if (abfd->where + size > bim->size)
        {
       size = (size_t) size;
       if (abfd->where + size > bim->size)
        {
@@ -149,7 +168,11 @@ bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
       return size;
     }
 
       return size;
     }
 
-  nwrote = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
+  if (abfd->iovec)
+    nwrote = abfd->iovec->bwrite (abfd, ptr, size);
+  else
+    nwrote = 0;
+
   if (nwrote != (size_t) -1)
     abfd->where += nwrote;
   if (nwrote != size)
   if (nwrote != (size_t) -1)
     abfd->where += nwrote;
   if (nwrote != size)
@@ -162,7 +185,7 @@ bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
   return nwrote;
 }
 
   return nwrote;
 }
 
-bfd_vma
+file_ptr
 bfd_tell (bfd *abfd)
 {
   file_ptr ptr;
 bfd_tell (bfd *abfd)
 {
   file_ptr ptr;
@@ -170,10 +193,16 @@ bfd_tell (bfd *abfd)
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     return abfd->where;
 
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     return abfd->where;
 
-  ptr = ftell (bfd_cache_lookup (abfd));
+  if (abfd->iovec)
+    {
+      ptr = abfd->iovec->btell (abfd);
+
+      if (abfd->my_archive)
+       ptr -= abfd->origin;
+    }
+  else
+    ptr = 0;
 
 
-  if (abfd->my_archive)
-    ptr -= abfd->origin;
   abfd->where = ptr;
   return ptr;
 }
   abfd->where = ptr;
   return ptr;
 }
@@ -183,7 +212,10 @@ bfd_flush (bfd *abfd)
 {
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     return 0;
 {
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     return 0;
-  return fflush (bfd_cache_lookup(abfd));
+
+  if (abfd->iovec)
+    return abfd->iovec->bflush (abfd);
+  return 0;
 }
 
 /* Returns 0 for success, negative value for failure (in which case
 }
 
 /* Returns 0 for success, negative value for failure (in which case
@@ -191,19 +223,16 @@ bfd_flush (bfd *abfd)
 int
 bfd_stat (bfd *abfd, struct stat *statbuf)
 {
 int
 bfd_stat (bfd *abfd, struct stat *statbuf)
 {
-  FILE *f;
   int result;
 
   if ((abfd->flags & BFD_IN_MEMORY) != 0)
     abort ();
 
   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);
+  if (abfd->iovec)
+    result = abfd->iovec->bstat (abfd, statbuf);
+  else
+    result = -1;
+
   if (result < 0)
     bfd_set_error (bfd_error_system_call);
   return result;
   if (result < 0)
     bfd_set_error (bfd_error_system_call);
   return result;
@@ -216,8 +245,7 @@ int
 bfd_seek (bfd *abfd, file_ptr position, int direction)
 {
   int result;
 bfd_seek (bfd *abfd, file_ptr position, int direction)
 {
   int result;
-  FILE *f;
-  long file_position;
+  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
      element in an archive.  */
   /* 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
      element in an archive.  */
@@ -244,6 +272,7 @@ bfd_seek (bfd *abfd, file_ptr position, int direction)
              (abfd->direction == both_direction))
            {
              bfd_size_type newsize, oldsize;
              (abfd->direction == both_direction))
            {
              bfd_size_type newsize, oldsize;
+
              oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
              bim->size = abfd->where;
              /* Round up to cut down on memory fragmentation */
              oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
              bim->size = abfd->where;
              /* Round up to cut down on memory fragmentation */
@@ -278,7 +307,7 @@ bfd_seek (bfd *abfd, file_ptr position, int direction)
         tripping the abort, we can probably safely disable this code,
         so that the real optimizations happen.  */
       file_ptr where_am_i_now;
         tripping the abort, we can probably safely disable this code,
         so that the real optimizations happen.  */
       file_ptr where_am_i_now;
-      where_am_i_now = ftell (bfd_cache_lookup (abfd));
+      where_am_i_now = real_ftell (bfd_cache_lookup (abfd));
       if (abfd->my_archive)
        where_am_i_now -= abfd->origin;
       if (where_am_i_now != abfd->where)
       if (abfd->my_archive)
        where_am_i_now -= abfd->origin;
       if (where_am_i_now != abfd->where)
@@ -302,12 +331,15 @@ bfd_seek (bfd *abfd, file_ptr position, int direction)
         In the meantime, no optimization for archives.  */
     }
 
         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;
 
   file_position = position;
   if (direction == SEEK_SET && abfd->my_archive != NULL)
     file_position += abfd->origin;
 
-  result = fseek (f, file_position, direction);
+  if (abfd->iovec)
+    result = abfd->iovec->bseek (abfd, file_position, direction);
+  else
+    result = -1;
+
   if (result != 0)
     {
       int hold_errno = errno;
   if (result != 0)
     {
       int hold_errno = errno;
@@ -352,14 +384,15 @@ DESCRIPTION
 long
 bfd_get_mtime (bfd *abfd)
 {
 long
 bfd_get_mtime (bfd *abfd)
 {
-  FILE *fp;
   struct stat buf;
 
   if (abfd->mtime_set)
     return abfd->mtime;
 
   struct stat buf;
 
   if (abfd->mtime_set)
     return abfd->mtime;
 
-  fp = bfd_cache_lookup (abfd);
-  if (0 != fstat (fileno (fp), &buf))
+  if (abfd->iovec == NULL)
+    return 0;
+
+  if (abfd->iovec->bstat (abfd, &buf) != 0)
     return 0;
 
   abfd->mtime = buf.st_mtime;          /* Save value in case anyone wants it */
     return 0;
 
   abfd->mtime = buf.st_mtime;          /* Save value in case anyone wants it */
@@ -395,21 +428,22 @@ DESCRIPTION
        error when it tries to read the table, or a "virtual memory
        exhausted" error when it tries to allocate 15 bazillon bytes
        of space for the 15 bazillon byte table it is about to read.
        error when it tries to read the table, or a "virtual memory
        exhausted" error when it tries to allocate 15 bazillon bytes
        of space for the 15 bazillon byte table it is about to read.
-       This function at least allows us to answer the quesion, "is the
+       This function at least allows us to answer the question, "is the
        size reasonable?".
 */
 
 long
 bfd_get_size (bfd *abfd)
 {
        size reasonable?".
 */
 
 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;
 
   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 == NULL)
+    return 0;
+
+  if (abfd->iovec->bstat (abfd, &buf) != 0)
     return 0;
 
   return buf.st_size;
     return 0;
 
   return buf.st_size;
This page took 0.027351 seconds and 4 git commands to generate.