1 /* Low-level I/O routines for BFDs. 2 3 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 4 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 5 6 Written by Cygnus Support. 7 8 This file is part of BFD, the Binary File Descriptor library. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 23 24 #include "sysdep.h" 25 26 #include "bfd.h" 27 #include "libbfd.h" 28 29 #include <limits.h> 30 31 #ifndef S_IXUSR 32 #define S_IXUSR 0100 /* Execute by owner. */ 33 #endif 34 #ifndef S_IXGRP 35 #define S_IXGRP 0010 /* Execute by group. */ 36 #endif 37 #ifndef S_IXOTH 38 #define S_IXOTH 0001 /* Execute by others. */ 39 #endif 40 41 file_ptr 42 real_ftell (FILE *file) 43 { 44 #if defined (HAVE_FTELLO64) 45 return ftello64 (file); 46 #elif defined (HAVE_FTELLO) 47 return ftello (file); 48 #else 49 return ftell (file); 50 #endif 51 } 52 53 int 54 real_fseek (FILE *file, file_ptr offset, int whence) 55 { 56 #if defined (HAVE_FSEEKO64) 57 return fseeko64 (file, offset, whence); 58 #elif defined (HAVE_FSEEKO) 59 return fseeko (file, offset, whence); 60 #else 61 return fseek (file, offset, whence); 62 #endif 63 } 64 65 /* Note that archive entries don't have streams; they share their parent's. 66 This allows someone to play with the iostream behind BFD's back. 67 68 Also, note that the origin pointer points to the beginning of a file's 69 contents (0 for non-archive elements). For archive entries this is the 70 first octet in the file, NOT the beginning of the archive header. */ 71 72 static size_t 73 real_read (void *where, size_t a, size_t b, FILE *file) 74 { 75 /* FIXME - this looks like an optimization, but it's really to cover 76 up for a feature of some OSs (not solaris - sigh) that 77 ld/pe-dll.c takes advantage of (apparently) when it creates BFDs 78 internally and tries to link against them. BFD seems to be smart 79 enough to realize there are no symbol records in the "file" that 80 doesn't exist but attempts to read them anyway. On Solaris, 81 attempting to read zero bytes from a NULL file results in a core 82 dump, but on other platforms it just returns zero bytes read. 83 This makes it to something reasonable. - DJ */ 84 if (a == 0 || b == 0) 85 return 0; 86 87 88 #if defined (__VAX) && defined (VMS) 89 /* Apparently fread on Vax VMS does not keep the record length 90 information. */ 91 return read (fileno (file), where, a * b); 92 #else 93 return fread (where, a, b, file); 94 #endif 95 } 96 97 /* Return value is amount read. */ 98 99 bfd_size_type 100 bfd_bread (void *ptr, bfd_size_type size, bfd *abfd) 101 { 102 size_t nread; 103 104 if ((abfd->flags & BFD_IN_MEMORY) != 0) 105 { 106 struct bfd_in_memory *bim; 107 bfd_size_type get; 108 109 bim = abfd->iostream; 110 get = size; 111 if (abfd->where + get > bim->size) 112 { 113 if (bim->size < (bfd_size_type) abfd->where) 114 get = 0; 115 else 116 get = bim->size - abfd->where; 117 bfd_set_error (bfd_error_file_truncated); 118 } 119 memcpy (ptr, bim->buffer + abfd->where, (size_t) get); 120 abfd->where += get; 121 return get; 122 } 123 124 nread = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); 125 if (nread != (size_t) -1) 126 abfd->where += nread; 127 128 /* Set bfd_error if we did not read as much data as we expected. 129 130 If the read failed due to an error set the bfd_error_system_call, 131 else set bfd_error_file_truncated. 132 133 A BFD backend may wish to override bfd_error_file_truncated to 134 provide something more useful (eg. no_symbols or wrong_format). */ 135 if (nread != size) 136 { 137 if (ferror (bfd_cache_lookup (abfd))) 138 bfd_set_error (bfd_error_system_call); 139 else 140 bfd_set_error (bfd_error_file_truncated); 141 } 142 143 return nread; 144 } 145 146 bfd_size_type 147 bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd) 148 { 149 size_t nwrote; 150 151 if ((abfd->flags & BFD_IN_MEMORY) != 0) 152 { 153 struct bfd_in_memory *bim = abfd->iostream; 154 size = (size_t) size; 155 if (abfd->where + size > bim->size) 156 { 157 bfd_size_type newsize, oldsize; 158 159 oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 160 bim->size = abfd->where + size; 161 /* Round up to cut down on memory fragmentation */ 162 newsize = (bim->size + 127) & ~(bfd_size_type) 127; 163 if (newsize > oldsize) 164 { 165 bim->buffer = bfd_realloc (bim->buffer, newsize); 166 if (bim->buffer == 0) 167 { 168 bim->size = 0; 169 return 0; 170 } 171 } 172 } 173 memcpy (bim->buffer + abfd->where, ptr, (size_t) size); 174 abfd->where += size; 175 return size; 176 } 177 178 nwrote = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd)); 179 if (nwrote != (size_t) -1) 180 abfd->where += nwrote; 181 if (nwrote != size) 182 { 183 #ifdef ENOSPC 184 errno = ENOSPC; 185 #endif 186 bfd_set_error (bfd_error_system_call); 187 } 188 return nwrote; 189 } 190 191 file_ptr 192 bfd_tell (bfd *abfd) 193 { 194 file_ptr ptr; 195 196 if ((abfd->flags & BFD_IN_MEMORY) != 0) 197 return abfd->where; 198 199 ptr = real_ftell (bfd_cache_lookup (abfd)); 200 201 if (abfd->my_archive) 202 ptr -= abfd->origin; 203 abfd->where = ptr; 204 return ptr; 205 } 206 207 int 208 bfd_flush (bfd *abfd) 209 { 210 if ((abfd->flags & BFD_IN_MEMORY) != 0) 211 return 0; 212 return fflush (bfd_cache_lookup(abfd)); 213 } 214 215 /* Returns 0 for success, negative value for failure (in which case 216 bfd_get_error can retrieve the error code). */ 217 int 218 bfd_stat (bfd *abfd, struct stat *statbuf) 219 { 220 FILE *f; 221 int result; 222 223 if ((abfd->flags & BFD_IN_MEMORY) != 0) 224 abort (); 225 226 f = bfd_cache_lookup (abfd); 227 if (f == NULL) 228 { 229 bfd_set_error (bfd_error_system_call); 230 return -1; 231 } 232 result = fstat (fileno (f), statbuf); 233 if (result < 0) 234 bfd_set_error (bfd_error_system_call); 235 return result; 236 } 237 238 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error 239 can retrieve the error code). */ 240 241 int 242 bfd_seek (bfd *abfd, file_ptr position, int direction) 243 { 244 int result; 245 FILE *f; 246 file_ptr file_position; 247 /* For the time being, a BFD may not seek to it's end. The problem 248 is that we don't easily have a way to recognize the end of an 249 element in an archive. */ 250 251 BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); 252 253 if (direction == SEEK_CUR && position == 0) 254 return 0; 255 256 if ((abfd->flags & BFD_IN_MEMORY) != 0) 257 { 258 struct bfd_in_memory *bim; 259 260 bim = abfd->iostream; 261 262 if (direction == SEEK_SET) 263 abfd->where = position; 264 else 265 abfd->where += position; 266 267 if (abfd->where > bim->size) 268 { 269 if ((abfd->direction == write_direction) || 270 (abfd->direction == both_direction)) 271 { 272 bfd_size_type newsize, oldsize; 273 oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 274 bim->size = abfd->where; 275 /* Round up to cut down on memory fragmentation */ 276 newsize = (bim->size + 127) & ~(bfd_size_type) 127; 277 if (newsize > oldsize) 278 { 279 bim->buffer = bfd_realloc (bim->buffer, newsize); 280 if (bim->buffer == 0) 281 { 282 bim->size = 0; 283 return -1; 284 } 285 } 286 } 287 else 288 { 289 abfd->where = bim->size; 290 bfd_set_error (bfd_error_file_truncated); 291 return -1; 292 } 293 } 294 return 0; 295 } 296 297 if (abfd->format != bfd_archive && abfd->my_archive == 0) 298 { 299 #if 0 300 /* Explanation for this code: I'm only about 95+% sure that the above 301 conditions are sufficient and that all i/o calls are properly 302 adjusting the `where' field. So this is sort of an `assert' 303 that the `where' field is correct. If we can go a while without 304 tripping the abort, we can probably safely disable this code, 305 so that the real optimizations happen. */ 306 file_ptr where_am_i_now; 307 where_am_i_now = real_ftell (bfd_cache_lookup (abfd)); 308 if (abfd->my_archive) 309 where_am_i_now -= abfd->origin; 310 if (where_am_i_now != abfd->where) 311 abort (); 312 #endif 313 if (direction == SEEK_SET && (bfd_vma) position == abfd->where) 314 return 0; 315 } 316 else 317 { 318 /* We need something smarter to optimize access to archives. 319 Currently, anything inside an archive is read via the file 320 handle for the archive. Which means that a bfd_seek on one 321 component affects the `current position' in the archive, as 322 well as in any other component. 323 324 It might be sufficient to put a spike through the cache 325 abstraction, and look to the archive for the file position, 326 but I think we should try for something cleaner. 327 328 In the meantime, no optimization for archives. */ 329 } 330 331 f = bfd_cache_lookup (abfd); 332 file_position = position; 333 if (direction == SEEK_SET && abfd->my_archive != NULL) 334 file_position += abfd->origin; 335 336 result = real_fseek (f, file_position, direction); 337 if (result != 0) 338 { 339 int hold_errno = errno; 340 341 /* Force redetermination of `where' field. */ 342 bfd_tell (abfd); 343 344 /* An EINVAL error probably means that the file offset was 345 absurd. */ 346 if (hold_errno == EINVAL) 347 bfd_set_error (bfd_error_file_truncated); 348 else 349 { 350 bfd_set_error (bfd_error_system_call); 351 errno = hold_errno; 352 } 353 } 354 else 355 { 356 /* Adjust `where' field. */ 357 if (direction == SEEK_SET) 358 abfd->where = position; 359 else 360 abfd->where += position; 361 } 362 return result; 363 } 364 365 /* 366 FUNCTION 367 bfd_get_mtime 368 369 SYNOPSIS 370 long bfd_get_mtime (bfd *abfd); 371 372 DESCRIPTION 373 Return the file modification time (as read from the file system, or 374 from the archive header for archive members). 375 376 */ 377 378 long 379 bfd_get_mtime (bfd *abfd) 380 { 381 FILE *fp; 382 struct stat buf; 383 384 if (abfd->mtime_set) 385 return abfd->mtime; 386 387 fp = bfd_cache_lookup (abfd); 388 if (0 != fstat (fileno (fp), &buf)) 389 return 0; 390 391 abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ 392 return buf.st_mtime; 393 } 394 395 /* 396 FUNCTION 397 bfd_get_size 398 399 SYNOPSIS 400 long bfd_get_size (bfd *abfd); 401 402 DESCRIPTION 403 Return the file size (as read from file system) for the file 404 associated with BFD @var{abfd}. 405 406 The initial motivation for, and use of, this routine is not 407 so we can get the exact size of the object the BFD applies to, since 408 that might not be generally possible (archive members for example). 409 It would be ideal if someone could eventually modify 410 it so that such results were guaranteed. 411 412 Instead, we want to ask questions like "is this NNN byte sized 413 object I'm about to try read from file offset YYY reasonable?" 414 As as example of where we might do this, some object formats 415 use string tables for which the first <<sizeof (long)>> bytes of the 416 table contain the size of the table itself, including the size bytes. 417 If an application tries to read what it thinks is one of these 418 string tables, without some way to validate the size, and for 419 some reason the size is wrong (byte swapping error, wrong location 420 for the string table, etc.), the only clue is likely to be a read 421 error when it tries to read the table, or a "virtual memory 422 exhausted" error when it tries to allocate 15 bazillon bytes 423 of space for the 15 bazillon byte table it is about to read. 424 This function at least allows us to answer the question, "is the 425 size reasonable?". 426 */ 427 428 long 429 bfd_get_size (bfd *abfd) 430 { 431 FILE *fp; 432 struct stat buf; 433 434 if ((abfd->flags & BFD_IN_MEMORY) != 0) 435 return ((struct bfd_in_memory *) abfd->iostream)->size; 436 437 fp = bfd_cache_lookup (abfd); 438 if (0 != fstat (fileno (fp), & buf)) 439 return 0; 440 441 return buf.st_size; 442 } 443