bfdio.c revision 251225
1171854Sdes/* Low-level I/O routines for BFDs. 2178950Srpaulo 3171854Sdes Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 4171854Sdes 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 5171854Sdes Free Software Foundation, Inc. 6171854Sdes 7171854Sdes Written by Cygnus Support. 8171854Sdes 9171854SdesThis file is part of BFD, the Binary File Descriptor library. 10171854Sdes 11171854SdesThis program is free software; you can redistribute it and/or modify 12171854Sdesit under the terms of the GNU General Public License as published by 13171854Sdesthe Free Software Foundation; either version 2 of the License, or 14171854Sdes(at your option) any later version. 15171854Sdes 16171854SdesThis program is distributed in the hope that it will be useful, 17171854Sdesbut WITHOUT ANY WARRANTY; without even the implied warranty of 18171854SdesMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19171854SdesGNU General Public License for more details. 20171854Sdes 21171854SdesYou should have received a copy of the GNU General Public License 22171854Sdesalong with this program; if not, write to the Free Software 23171854SdesFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 24171854Sdes 25171854Sdes#include "sysdep.h" 26171854Sdes#include <limits.h> 27171854Sdes#include "bfd.h" 28171854Sdes#include "libbfd.h" 29171854Sdes 30171854Sdes#ifndef S_IXUSR 31171854Sdes#define S_IXUSR 0100 /* Execute by owner. */ 32171854Sdes#endif 33171854Sdes#ifndef S_IXGRP 34171854Sdes#define S_IXGRP 0010 /* Execute by group. */ 35171854Sdes#endif 36171854Sdes#ifndef S_IXOTH 37171854Sdes#define S_IXOTH 0001 /* Execute by others. */ 38171854Sdes#endif 39171854Sdes 40171854Sdesfile_ptr 41171854Sdesreal_ftell (FILE *file) 42172674Snetchild{ 43171854Sdes#if defined (HAVE_FTELLO64) 44171854Sdes return ftello64 (file); 45171854Sdes#elif defined (HAVE_FTELLO) 46171854Sdes return ftello (file); 47171854Sdes#else 48185341Sjkim return ftell (file); 49171854Sdes#endif 50171854Sdes} 51300421Sloos 52196889Snorkint 53225339Sdelphijreal_fseek (FILE *file, file_ptr offset, int whence) 54225339Sdelphij{ 55225339Sdelphij#if defined (HAVE_FSEEKO64) 56225339Sdelphij return fseeko64 (file, offset, whence); 57225339Sdelphij#elif defined (HAVE_FSEEKO) 58225339Sdelphij return fseeko (file, offset, whence); 59225339Sdelphij#else 60225339Sdelphij return fseek (file, offset, whence); 61225339Sdelphij#endif 62171854Sdes} 63172674Snetchild 64172674SnetchildFILE * 65225339Sdelphijreal_fopen (const char *filename, const char *modes) 66171854Sdes{ 67171854Sdes#if defined (HAVE_FOPEN64) 68171854Sdes return fopen64 (filename, modes); 69171854Sdes#else 70171854Sdes return fopen (filename, modes); 71171854Sdes#endif 72171854Sdes} 73171854Sdes 74171854Sdes/* 75171854SdesINTERNAL_DEFINITION 76225339Sdelphij struct bfd_iovec 77225339Sdelphij 78225339SdelphijDESCRIPTION 79225339Sdelphij 80171854Sdes The <<struct bfd_iovec>> contains the internal file I/O class. 81171854Sdes Each <<BFD>> has an instance of this class and all file I/O is 82171854Sdes routed through it (it is assumed that the instance implements 83171854Sdes all methods listed below). 84171854Sdes 85171854Sdes.struct bfd_iovec 86171854Sdes.{ 87171854Sdes. {* To avoid problems with macros, a "b" rather than "f" 88246128Ssbz. prefix is prepended to each method name. *} 89171854Sdes. {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching 90171854Sdes. bytes starting at PTR. Return the number of bytes actually 91171854Sdes. transfered (a read past end-of-file returns less than NBYTES), 92171854Sdes. or -1 (setting <<bfd_error>>) if an error occurs. *} 93171854Sdes. file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes); 94171854Sdes. file_ptr (*bwrite) (struct bfd *abfd, const void *ptr, 95171854Sdes. file_ptr nbytes); 96171854Sdes. {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>> 97225339Sdelphij. if an error occurs. *} 98225339Sdelphij. file_ptr (*btell) (struct bfd *abfd); 99225339Sdelphij. {* For the following, on successful completion a value of 0 is returned. 100225339Sdelphij. Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *} 101225339Sdelphij. int (*bseek) (struct bfd *abfd, file_ptr offset, int whence); 102225339Sdelphij. int (*bclose) (struct bfd *abfd); 103225339Sdelphij. int (*bflush) (struct bfd *abfd); 104171854Sdes. int (*bstat) (struct bfd *abfd, struct stat *sb); 105225339Sdelphij.}; 106225339Sdelphij 107171854Sdes*/ 108171854Sdes 109171854Sdes 110171854Sdes/* Return value is amount read. */ 111171854Sdes 112171854Sdesbfd_size_type 113171854Sdesbfd_bread (void *ptr, bfd_size_type size, bfd *abfd) 114171854Sdes{ 115171854Sdes size_t nread; 116171854Sdes 117171933Sdes /* If this is an archive element, don't read past the end of 118178950Srpaulo this element. */ 119185341Sjkim if (abfd->arelt_data != NULL) 120171854Sdes { 121171854Sdes size_t maxbytes = ((struct areltdata *) abfd->arelt_data)->parsed_size; 122171854Sdes if (size > maxbytes) 123171854Sdes size = maxbytes; 124171854Sdes } 125171854Sdes 126171854Sdes if ((abfd->flags & BFD_IN_MEMORY) != 0) 127171854Sdes { 128171854Sdes struct bfd_in_memory *bim; 129171854Sdes bfd_size_type get; 130171854Sdes 131171854Sdes bim = abfd->iostream; 132171854Sdes get = size; 133171854Sdes if (abfd->where + get > bim->size) 134171854Sdes { 135171854Sdes if (bim->size < (bfd_size_type) abfd->where) 136171854Sdes get = 0; 137171854Sdes else 138171854Sdes get = bim->size - abfd->where; 139171854Sdes bfd_set_error (bfd_error_file_truncated); 140171854Sdes } 141241885Seadler memcpy (ptr, bim->buffer + abfd->where, (size_t) get); 142241885Seadler abfd->where += get; 143171854Sdes return get; 144171854Sdes } 145171854Sdes 146171854Sdes if (abfd->iovec) 147171854Sdes nread = abfd->iovec->bread (abfd, ptr, size); 148171854Sdes else 149171854Sdes nread = 0; 150171854Sdes if (nread != (size_t) -1) 151171854Sdes abfd->where += nread; 152171854Sdes 153171854Sdes return nread; 154171854Sdes} 155210624Sdelphij 156210624Sdelphijbfd_size_type 157225339Sdelphijbfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd) 158225339Sdelphij{ 159171854Sdes size_t nwrote; 160171933Sdes 161171854Sdes if ((abfd->flags & BFD_IN_MEMORY) != 0) 162210624Sdelphij { 163210624Sdelphij struct bfd_in_memory *bim = abfd->iostream; 164171854Sdes 165176279Srpaulo size = (size_t) size; 166176279Srpaulo if (abfd->where + size > bim->size) 167176279Srpaulo { 168176279Srpaulo bfd_size_type newsize, oldsize; 169176279Srpaulo 170176279Srpaulo oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 171176279Srpaulo bim->size = abfd->where + size; 172176279Srpaulo /* Round up to cut down on memory fragmentation */ 173225339Sdelphij newsize = (bim->size + 127) & ~(bfd_size_type) 127; 174175214Srpaulo if (newsize > oldsize) 175175214Srpaulo { 176175214Srpaulo bim->buffer = bfd_realloc (bim->buffer, newsize); 177175214Srpaulo if (bim->buffer == 0) 178175214Srpaulo { 179171854Sdes bim->size = 0; 180171854Sdes return 0; 181171854Sdes } 182171854Sdes } 183171854Sdes } 184171854Sdes memcpy (bim->buffer + abfd->where, ptr, (size_t) size); 185171933Sdes abfd->where += size; 186210624Sdelphij return size; 187171854Sdes } 188171854Sdes 189171854Sdes if (abfd->iovec) 190171933Sdes nwrote = abfd->iovec->bwrite (abfd, ptr, size); 191171933Sdes else 192171854Sdes nwrote = 0; 193171854Sdes 194171854Sdes if (nwrote != (size_t) -1) 195175214Srpaulo abfd->where += nwrote; 196210624Sdelphij if (nwrote != size) 197171854Sdes { 198210624Sdelphij#ifdef ENOSPC 199210624Sdelphij errno = ENOSPC; 200210624Sdelphij#endif 201210624Sdelphij bfd_set_error (bfd_error_system_call); 202210624Sdelphij } 203210624Sdelphij return nwrote; 204210624Sdelphij} 205210624Sdelphij 206210624Sdelphijfile_ptr 207210624Sdelphijbfd_tell (bfd *abfd) 208210624Sdelphij{ 209210624Sdelphij file_ptr ptr; 210171854Sdes 211171933Sdes if ((abfd->flags & BFD_IN_MEMORY) != 0) 212171854Sdes return abfd->where; 213210833Sdelphij 214210833Sdelphij if (abfd->iovec) 215210833Sdelphij { 216221335Sdelphij ptr = abfd->iovec->btell (abfd); 217210833Sdelphij 218210833Sdelphij if (abfd->my_archive) 219210833Sdelphij ptr -= abfd->origin; 220210833Sdelphij } 221221509Sdelphij else 222221509Sdelphij ptr = 0; 223221509Sdelphij 224221509Sdelphij abfd->where = ptr; 225221509Sdelphij return ptr; 226221509Sdelphij} 227221509Sdelphij 228221509Sdelphijint 229221509Sdelphijbfd_flush (bfd *abfd) 230210833Sdelphij{ 231210833Sdelphij if ((abfd->flags & BFD_IN_MEMORY) != 0) 232210833Sdelphij return 0; 233210833Sdelphij 234210833Sdelphij if (abfd->iovec) 235210833Sdelphij return abfd->iovec->bflush (abfd); 236210833Sdelphij return 0; 237210833Sdelphij} 238210833Sdelphij 239210833Sdelphij/* Returns 0 for success, negative value for failure (in which case 240225339Sdelphij bfd_get_error can retrieve the error code). */ 241210833Sdelphijint 242210833Sdelphijbfd_stat (bfd *abfd, struct stat *statbuf) 243210833Sdelphij{ 244210833Sdelphij int result; 245210833Sdelphij 246210833Sdelphij if ((abfd->flags & BFD_IN_MEMORY) != 0) 247210833Sdelphij abort (); 248210833Sdelphij 249225009Sattilio if (abfd->iovec) 250210833Sdelphij result = abfd->iovec->bstat (abfd, statbuf); 251210833Sdelphij else 252210833Sdelphij result = -1; 253210833Sdelphij 254225009Sattilio if (result < 0) 255210833Sdelphij bfd_set_error (bfd_error_system_call); 256210833Sdelphij return result; 257210833Sdelphij} 258210833Sdelphij 259210833Sdelphij/* Returns 0 for success, nonzero for failure (in which case bfd_get_error 260210833Sdelphij can retrieve the error code). */ 261210833Sdelphij 262171933Sdesint 263171933Sdesbfd_seek (bfd *abfd, file_ptr position, int direction) 264210624Sdelphij{ 265210624Sdelphij int result; 266210624Sdelphij file_ptr file_position; 267225339Sdelphij /* For the time being, a BFD may not seek to it's end. The problem 268225339Sdelphij is that we don't easily have a way to recognize the end of an 269225339Sdelphij element in an archive. */ 270225339Sdelphij 271225339Sdelphij BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); 272225339Sdelphij 273171854Sdes if (direction == SEEK_CUR && position == 0) 274225339Sdelphij return 0; 275171854Sdes 276225339Sdelphij if ((abfd->flags & BFD_IN_MEMORY) != 0) 277246951Smarkj { 278246951Smarkj struct bfd_in_memory *bim; 279196889Snork 280225339Sdelphij bim = abfd->iostream; 281246951Smarkj 282225339Sdelphij if (direction == SEEK_SET) 283225339Sdelphij abfd->where = position; 284225339Sdelphij else 285246951Smarkj abfd->where += position; 286225339Sdelphij 287225339Sdelphij if (abfd->where > bim->size) 288225339Sdelphij { 289246951Smarkj if ((abfd->direction == write_direction) || 290225339Sdelphij (abfd->direction == both_direction)) 291225339Sdelphij { 292225339Sdelphij bfd_size_type newsize, oldsize; 293246951Smarkj 294225339Sdelphij oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 295225339Sdelphij bim->size = abfd->where; 296171854Sdes /* Round up to cut down on memory fragmentation */ 297171854Sdes newsize = (bim->size + 127) & ~(bfd_size_type) 127; 298171854Sdes if (newsize > oldsize) 299171854Sdes { 300171854Sdes bim->buffer = bfd_realloc (bim->buffer, newsize); 301171854Sdes if (bim->buffer == 0) 302171854Sdes { 303171854Sdes bim->size = 0; 304171854Sdes return -1; 305171854Sdes } 306225339Sdelphij } 307225339Sdelphij } 308171854Sdes else 309171933Sdes { 310171854Sdes abfd->where = bim->size; 311172674Snetchild bfd_set_error (bfd_error_file_truncated); 312172674Snetchild return -1; 313172674Snetchild } 314172674Snetchild } 315171854Sdes return 0; 316172674Snetchild } 317172674Snetchild 318172674Snetchild if (abfd->format != bfd_archive && abfd->my_archive == 0) 319172674Snetchild { 320172674Snetchild if (direction == SEEK_SET && (bfd_vma) position == abfd->where) 321172674Snetchild return 0; 322172674Snetchild } 323172674Snetchild else 324171854Sdes { 325172674Snetchild /* We need something smarter to optimize access to archives. 326171854Sdes Currently, anything inside an archive is read via the file 327172674Snetchild handle for the archive. Which means that a bfd_seek on one 328172674Snetchild component affects the `current position' in the archive, as 329172674Snetchild well as in any other component. 330172674Snetchild 331225339Sdelphij It might be sufficient to put a spike through the cache 332225339Sdelphij abstraction, and look to the archive for the file position, 333171854Sdes but I think we should try for something cleaner. 334225339Sdelphij 335225339Sdelphij In the meantime, no optimization for archives. */ 336225339Sdelphij } 337225339Sdelphij 338225339Sdelphij file_position = position; 339225339Sdelphij if (direction == SEEK_SET && abfd->my_archive != NULL) 340225339Sdelphij file_position += abfd->origin; 341225339Sdelphij 342225339Sdelphij if (abfd->iovec) 343225339Sdelphij result = abfd->iovec->bseek (abfd, file_position, direction); 344225339Sdelphij else 345225339Sdelphij result = -1; 346225339Sdelphij 347225339Sdelphij if (result != 0) 348225339Sdelphij { 349225339Sdelphij int hold_errno = errno; 350225339Sdelphij 351225339Sdelphij /* Force redetermination of `where' field. */ 352225339Sdelphij bfd_tell (abfd); 353225339Sdelphij 354225339Sdelphij /* An EINVAL error probably means that the file offset was 355225339Sdelphij absurd. */ 356225339Sdelphij if (hold_errno == EINVAL) 357225339Sdelphij bfd_set_error (bfd_error_file_truncated); 358225339Sdelphij else 359225339Sdelphij { 360225339Sdelphij bfd_set_error (bfd_error_system_call); 361225339Sdelphij errno = hold_errno; 362225339Sdelphij } 363225339Sdelphij } 364225339Sdelphij else 365225339Sdelphij { 366225339Sdelphij /* Adjust `where' field. */ 367225339Sdelphij if (direction == SEEK_SET) 368225339Sdelphij abfd->where = position; 369225339Sdelphij else 370225339Sdelphij abfd->where += position; 371225339Sdelphij } 372225339Sdelphij return result; 373225339Sdelphij} 374225339Sdelphij 375225339Sdelphij/* 376225339SdelphijFUNCTION 377225339Sdelphij bfd_get_mtime 378225339Sdelphij 379225339SdelphijSYNOPSIS 380225339Sdelphij time_t bfd_get_mtime (bfd *abfd); 381225339Sdelphij 382225339SdelphijDESCRIPTION 383225339Sdelphij Return the file modification time (as read from the file system, or 384225339Sdelphij from the archive header for archive members). 385225339Sdelphij 386225339Sdelphij*/ 387225662Sattilio 388225339Sdelphijtime_t 389225339Sdelphijbfd_get_mtime (bfd *abfd) 390171933Sdes{ 391225339Sdelphij struct stat buf; 392225339Sdelphij 393225339Sdelphij if (abfd->mtime_set) 394225339Sdelphij return abfd->mtime; 395225339Sdelphij 396225339Sdelphij if (abfd->iovec == NULL) 397225339Sdelphij return 0; 398225339Sdelphij 399225339Sdelphij if (abfd->iovec->bstat (abfd, &buf) != 0) 400171933Sdes return 0; 401225339Sdelphij 402225339Sdelphij abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ 403225339Sdelphij return buf.st_mtime; 404225339Sdelphij} 405225339Sdelphij 406225339Sdelphij/* 407225339SdelphijFUNCTION 408225339Sdelphij bfd_get_size 409225339Sdelphij 410225339SdelphijSYNOPSIS 411171854Sdes file_ptr bfd_get_size (bfd *abfd); 412171854Sdes 413225339SdelphijDESCRIPTION 414171854Sdes Return the file size (as read from file system) for the file 415171854Sdes associated with BFD @var{abfd}. 416172674Snetchild 417225339Sdelphij The initial motivation for, and use of, this routine is not 418171854Sdes so we can get the exact size of the object the BFD applies to, since 419225339Sdelphij that might not be generally possible (archive members for example). 420225339Sdelphij It would be ideal if someone could eventually modify 421225339Sdelphij it so that such results were guaranteed. 422225339Sdelphij 423171854Sdes Instead, we want to ask questions like "is this NNN byte sized 424225339Sdelphij object I'm about to try read from file offset YYY reasonable?" 425225339Sdelphij As as example of where we might do this, some object formats 426225339Sdelphij use string tables for which the first <<sizeof (long)>> bytes of the 427171854Sdes table contain the size of the table itself, including the size bytes. 428225662Sattilio If an application tries to read what it thinks is one of these 429225662Sattilio string tables, without some way to validate the size, and for 430225339Sdelphij some reason the size is wrong (byte swapping error, wrong location 431225662Sattilio for the string table, etc.), the only clue is likely to be a read 432225339Sdelphij error when it tries to read the table, or a "virtual memory 433225339Sdelphij exhausted" error when it tries to allocate 15 bazillon bytes 434225339Sdelphij of space for the 15 bazillon byte table it is about to read. 435225339Sdelphij This function at least allows us to answer the question, "is the 436225339Sdelphij size reasonable?". 437225339Sdelphij*/ 438225339Sdelphij 439225339Sdelphijfile_ptr 440225339Sdelphijbfd_get_size (bfd *abfd) 441225339Sdelphij{ 442225339Sdelphij struct stat buf; 443225339Sdelphij 444225339Sdelphij if ((abfd->flags & BFD_IN_MEMORY) != 0) 445225339Sdelphij return ((struct bfd_in_memory *) abfd->iostream)->size; 446171854Sdes 447 if (abfd->iovec == NULL) 448 return 0; 449 450 if (abfd->iovec->bstat (abfd, &buf) != 0) 451 return 0; 452 453 return buf.st_size; 454} 455