1 /* Low-level I/O routines for BFDs. 2 3 Copyright (C) 1990-2024 Free Software Foundation, Inc. 4 5 Written by Cygnus Support. 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 22 MA 02110-1301, USA. */ 23 24 #include "sysdep.h" 25 #include <limits.h> 26 #include "bfd.h" 27 #include "libbfd.h" 28 #include "aout/ar.h" 29 #if defined (_WIN32) 30 #include <windows.h> 31 #include <locale.h> 32 #endif 33 34 #ifndef S_IXUSR 35 #define S_IXUSR 0100 /* Execute by owner. */ 36 #endif 37 #ifndef S_IXGRP 38 #define S_IXGRP 0010 /* Execute by group. */ 39 #endif 40 #ifndef S_IXOTH 41 #define S_IXOTH 0001 /* Execute by others. */ 42 #endif 43 44 #ifndef FD_CLOEXEC 45 #define FD_CLOEXEC 1 46 #endif 47 48 file_ptr 49 _bfd_real_ftell (FILE *file) 50 { 51 #if defined (HAVE_FTELLO64) 52 return ftello64 (file); 53 #elif defined (HAVE_FTELLO) 54 return ftello (file); 55 #else 56 return ftell (file); 57 #endif 58 } 59 60 int 61 _bfd_real_fseek (FILE *file, file_ptr offset, int whence) 62 { 63 #if defined (HAVE_FSEEKO64) 64 return fseeko64 (file, offset, whence); 65 #elif defined (HAVE_FSEEKO) 66 return fseeko (file, offset, whence); 67 #else 68 return fseek (file, offset, whence); 69 #endif 70 } 71 72 /* Mark FILE as close-on-exec. Return FILE. FILE may be NULL, in 73 which case nothing is done. */ 74 static FILE * 75 close_on_exec (FILE *file) 76 { 77 #if defined (HAVE_FILENO) && defined (F_GETFD) 78 if (file) 79 { 80 int fd = fileno (file); 81 int old = fcntl (fd, F_GETFD, 0); 82 if (old >= 0) 83 fcntl (fd, F_SETFD, old | FD_CLOEXEC); 84 } 85 #endif 86 return file; 87 } 88 89 FILE * 90 _bfd_real_fopen (const char *filename, const char *modes) 91 { 92 #ifdef VMS 93 char *vms_attr; 94 95 /* On VMS, fopen allows file attributes as optional arguments. 96 We need to use them but we'd better to use the common prototype. 97 In fopen-vms.h, they are separated from the mode with a comma. 98 Split here. */ 99 vms_attr = strchr (modes, ','); 100 if (vms_attr != NULL) 101 { 102 /* Attributes found. Split. */ 103 size_t modes_len = strlen (modes) + 1; 104 char attrs[modes_len + 1]; 105 char *at[3]; 106 int i; 107 108 memcpy (attrs, modes, modes_len); 109 at[0] = attrs; 110 for (i = 0; i < 2; i++) 111 { 112 at[i + 1] = strchr (at[i], ','); 113 BFD_ASSERT (at[i + 1] != NULL); 114 *(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it. */ 115 } 116 return close_on_exec (fopen (filename, at[0], at[1], at[2])); 117 } 118 119 #elif defined (_WIN32) 120 /* PR 25713: Handle extra long path names possibly containing '..' and '.'. */ 121 wchar_t ** lpFilePart = {NULL}; 122 const wchar_t prefix[] = L"\\\\?\\"; 123 const size_t partPathLen = strlen (filename) + 1; 124 #ifdef __MINGW32__ 125 #if !HAVE_DECL____LC_CODEPAGE_FUNC 126 /* This prototype was added to locale.h in version 9.0 of MinGW-w64. */ 127 _CRTIMP unsigned int __cdecl ___lc_codepage_func (void); 128 #endif 129 const unsigned int cp = ___lc_codepage_func (); 130 #else 131 const unsigned int cp = CP_UTF8; 132 #endif 133 134 /* Converting the partial path from ascii to unicode. 135 1) Get the length: Calling with lpWideCharStr set to null returns the length. 136 2) Convert the string: Calling with cbMultiByte set to -1 includes the terminating null. */ 137 size_t partPathWSize = MultiByteToWideChar (cp, 0, filename, -1, NULL, 0); 138 wchar_t * partPath = calloc (partPathWSize, sizeof(wchar_t)); 139 size_t ix; 140 141 MultiByteToWideChar (cp, 0, filename, -1, partPath, partPathWSize); 142 143 /* Convert any UNIX style path separators into the DOS i.e. backslash separator. */ 144 for (ix = 0; ix < partPathLen; ix++) 145 if (IS_UNIX_DIR_SEPARATOR(filename[ix])) 146 partPath[ix] = '\\'; 147 148 /* Getting the full path from the provided partial path. 149 1) Get the length. 150 2) Resolve the path. */ 151 long fullPathWSize = GetFullPathNameW (partPath, 0, NULL, lpFilePart); 152 wchar_t * fullPath = calloc (fullPathWSize + sizeof(prefix) + 1, sizeof(wchar_t)); 153 154 wcscpy (fullPath, prefix); 155 156 int prefixLen = sizeof(prefix) / sizeof(wchar_t); 157 158 /* Do not add a prefix to the null device. */ 159 if (stricmp (filename, "nul") == 0) 160 prefixLen = 1; 161 162 wchar_t * fullPathOffset = fullPath + prefixLen - 1; 163 164 GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart); 165 free (partPath); 166 167 /* It is non-standard for modes to exceed 16 characters. */ 168 wchar_t modesW[16]; 169 170 MultiByteToWideChar (cp, 0, modes, -1, modesW, sizeof(modesW)); 171 172 FILE * file = _wfopen (fullPath, modesW); 173 free (fullPath); 174 175 return close_on_exec (file); 176 177 #elif defined (HAVE_FOPEN64) 178 return close_on_exec (fopen64 (filename, modes)); 179 180 #else 181 return close_on_exec (fopen (filename, modes)); 182 #endif 183 } 184 185 /* 186 INTERNAL_DEFINITION 187 struct bfd_iovec 188 189 DESCRIPTION 190 191 The <<struct bfd_iovec>> contains the internal file I/O class. 192 Each <<BFD>> has an instance of this class and all file I/O is 193 routed through it (it is assumed that the instance implements 194 all methods listed below). 195 196 .struct bfd_iovec 197 .{ 198 . {* To avoid problems with macros, a "b" rather than "f" 199 . prefix is prepended to each method name. *} 200 . {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching 201 . bytes starting at PTR. Return the number of bytes actually 202 . transfered (a read past end-of-file returns less than NBYTES), 203 . or -1 (setting <<bfd_error>>) if an error occurs. *} 204 . file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes); 205 . file_ptr (*bwrite) (struct bfd *abfd, const void *ptr, 206 . file_ptr nbytes); 207 . {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>> 208 . if an error occurs. *} 209 . file_ptr (*btell) (struct bfd *abfd); 210 . {* For the following, on successful completion a value of 0 is returned. 211 . Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *} 212 . int (*bseek) (struct bfd *abfd, file_ptr offset, int whence); 213 . int (*bclose) (struct bfd *abfd); 214 . int (*bflush) (struct bfd *abfd); 215 . int (*bstat) (struct bfd *abfd, struct stat *sb); 216 . {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual 217 . mmap parameter, except that LEN and OFFSET do not need to be page 218 . aligned. Returns (void *)-1 on failure, mmapped address on success. 219 . Also write in MAP_ADDR the address of the page aligned buffer and in 220 . MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and 221 . MAP_LEN to unmap. *} 222 . void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len, 223 . int prot, int flags, file_ptr offset, 224 . void **map_addr, bfd_size_type *map_len); 225 .}; 226 227 .extern const struct bfd_iovec _bfd_memory_iovec; 228 . 229 */ 230 231 232 /* 233 FUNCTION 234 bfd_read 235 236 SYNOPSIS 237 bfd_size_type bfd_read (void *, bfd_size_type, bfd *) 238 ATTRIBUTE_WARN_UNUSED_RESULT; 239 240 DESCRIPTION 241 Attempt to read SIZE bytes from ABFD's iostream to PTR. 242 Return the amount read. 243 */ 244 245 bfd_size_type 246 bfd_read (void *ptr, bfd_size_type size, bfd *abfd) 247 { 248 file_ptr nread; 249 bfd *element_bfd = abfd; 250 ufile_ptr offset = 0; 251 252 while (abfd->my_archive != NULL 253 && !bfd_is_thin_archive (abfd->my_archive)) 254 { 255 offset += abfd->origin; 256 abfd = abfd->my_archive; 257 } 258 offset += abfd->origin; 259 260 /* If this is a non-thin archive element, don't read past the end of 261 this element. */ 262 if (element_bfd->arelt_data != NULL 263 && element_bfd->my_archive != NULL 264 && !bfd_is_thin_archive (element_bfd->my_archive)) 265 { 266 bfd_size_type maxbytes = arelt_size (element_bfd); 267 268 if (abfd->where < offset || abfd->where - offset >= maxbytes) 269 { 270 bfd_set_error (bfd_error_invalid_operation); 271 return -1; 272 } 273 if (abfd->where - offset + size > maxbytes) 274 size = maxbytes - (abfd->where - offset); 275 } 276 277 if (abfd->iovec == NULL) 278 { 279 bfd_set_error (bfd_error_invalid_operation); 280 return -1; 281 } 282 283 if (abfd->last_io == bfd_io_write) 284 { 285 abfd->last_io = bfd_io_force; 286 if (bfd_seek (abfd, 0, SEEK_CUR) != 0) 287 return -1; 288 } 289 abfd->last_io = bfd_io_read; 290 291 nread = abfd->iovec->bread (abfd, ptr, size); 292 if (nread != -1) 293 abfd->where += nread; 294 295 return nread; 296 } 297 298 /* 299 FUNCTION 300 bfd_write 301 302 SYNOPSIS 303 bfd_size_type bfd_write (const void *, bfd_size_type, bfd *) 304 ATTRIBUTE_WARN_UNUSED_RESULT; 305 306 DESCRIPTION 307 Attempt to write SIZE bytes to ABFD's iostream from PTR. 308 Return the amount written. 309 */ 310 311 bfd_size_type 312 bfd_write (const void *ptr, bfd_size_type size, bfd *abfd) 313 { 314 file_ptr nwrote; 315 316 while (abfd->my_archive != NULL 317 && !bfd_is_thin_archive (abfd->my_archive)) 318 abfd = abfd->my_archive; 319 320 if (abfd->iovec == NULL) 321 { 322 bfd_set_error (bfd_error_invalid_operation); 323 return -1; 324 } 325 326 if (abfd->last_io == bfd_io_read) 327 { 328 abfd->last_io = bfd_io_force; 329 if (bfd_seek (abfd, 0, SEEK_CUR) != 0) 330 return -1; 331 } 332 abfd->last_io = bfd_io_write; 333 334 nwrote = abfd->iovec->bwrite (abfd, ptr, size); 335 if (nwrote != -1) 336 abfd->where += nwrote; 337 if ((bfd_size_type) nwrote != size) 338 { 339 #ifdef ENOSPC 340 errno = ENOSPC; 341 #endif 342 bfd_set_error (bfd_error_system_call); 343 } 344 return nwrote; 345 } 346 347 /* 348 FUNCTION 349 bfd_tell 350 351 SYNOPSIS 352 file_ptr bfd_tell (bfd *) ATTRIBUTE_WARN_UNUSED_RESULT; 353 354 DESCRIPTION 355 Return ABFD's iostream file position. 356 */ 357 358 file_ptr 359 bfd_tell (bfd *abfd) 360 { 361 ufile_ptr offset = 0; 362 file_ptr ptr; 363 364 while (abfd->my_archive != NULL 365 && !bfd_is_thin_archive (abfd->my_archive)) 366 { 367 offset += abfd->origin; 368 abfd = abfd->my_archive; 369 } 370 offset += abfd->origin; 371 372 if (abfd->iovec == NULL) 373 return 0; 374 375 ptr = abfd->iovec->btell (abfd); 376 abfd->where = ptr; 377 return ptr - offset; 378 } 379 380 /* 381 FUNCTION 382 bfd_flush 383 384 SYNOPSIS 385 int bfd_flush (bfd *); 386 387 DESCRIPTION 388 Flush ABFD's iostream pending IO. 389 */ 390 391 int 392 bfd_flush (bfd *abfd) 393 { 394 while (abfd->my_archive != NULL 395 && !bfd_is_thin_archive (abfd->my_archive)) 396 abfd = abfd->my_archive; 397 398 if (abfd->iovec == NULL) 399 return 0; 400 401 return abfd->iovec->bflush (abfd); 402 } 403 404 /* 405 FUNCTION 406 bfd_stat 407 408 SYNOPSIS 409 int bfd_stat (bfd *, struct stat *) ATTRIBUTE_WARN_UNUSED_RESULT; 410 411 DESCRIPTION 412 Call fstat on ABFD's iostream. Return 0 on success, and a 413 negative value on failure. 414 */ 415 416 int 417 bfd_stat (bfd *abfd, struct stat *statbuf) 418 { 419 int result; 420 421 while (abfd->my_archive != NULL 422 && !bfd_is_thin_archive (abfd->my_archive)) 423 abfd = abfd->my_archive; 424 425 if (abfd->iovec == NULL) 426 { 427 bfd_set_error (bfd_error_invalid_operation); 428 return -1; 429 } 430 431 result = abfd->iovec->bstat (abfd, statbuf); 432 if (result < 0) 433 bfd_set_error (bfd_error_system_call); 434 return result; 435 } 436 437 /* 438 FUNCTION 439 bfd_seek 440 441 SYNOPSIS 442 int bfd_seek (bfd *, file_ptr, int) ATTRIBUTE_WARN_UNUSED_RESULT; 443 444 DESCRIPTION 445 Call fseek on ABFD's iostream. Return 0 on success, and a 446 negative value on failure. 447 */ 448 449 int 450 bfd_seek (bfd *abfd, file_ptr position, int direction) 451 { 452 int result; 453 ufile_ptr offset = 0; 454 455 while (abfd->my_archive != NULL 456 && !bfd_is_thin_archive (abfd->my_archive)) 457 { 458 offset += abfd->origin; 459 abfd = abfd->my_archive; 460 } 461 offset += abfd->origin; 462 463 if (abfd->iovec == NULL) 464 { 465 bfd_set_error (bfd_error_invalid_operation); 466 return -1; 467 } 468 469 /* For the time being, a BFD may not seek to it's end. The problem 470 is that we don't easily have a way to recognize the end of an 471 element in an archive. */ 472 BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); 473 474 if (direction != SEEK_CUR) 475 position += offset; 476 477 if (((direction == SEEK_CUR && position == 0) 478 || (direction == SEEK_SET && (ufile_ptr) position == abfd->where)) 479 && abfd->last_io != bfd_io_force) 480 return 0; 481 482 abfd->last_io = bfd_io_seek; 483 484 result = abfd->iovec->bseek (abfd, position, direction); 485 if (result != 0) 486 { 487 /* An EINVAL error probably means that the file offset was 488 absurd. */ 489 if (errno == EINVAL) 490 bfd_set_error (bfd_error_file_truncated); 491 else 492 bfd_set_error (bfd_error_system_call); 493 } 494 else 495 { 496 /* Adjust `where' field. */ 497 if (direction == SEEK_CUR) 498 abfd->where += position; 499 else 500 abfd->where = position; 501 } 502 503 return result; 504 } 505 506 /* 507 FUNCTION 508 bfd_get_mtime 509 510 SYNOPSIS 511 long bfd_get_mtime (bfd *abfd); 512 513 DESCRIPTION 514 Return the file modification time (as read from the file system, or 515 from the archive header for archive members). 516 517 */ 518 519 long 520 bfd_get_mtime (bfd *abfd) 521 { 522 struct stat buf; 523 524 if (abfd->mtime_set) 525 return abfd->mtime; 526 527 if (bfd_stat (abfd, &buf) != 0) 528 return 0; 529 530 abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ 531 return buf.st_mtime; 532 } 533 534 /* 535 FUNCTION 536 bfd_get_size 537 538 SYNOPSIS 539 ufile_ptr bfd_get_size (bfd *abfd); 540 541 DESCRIPTION 542 Return the file size (as read from file system) for the file 543 associated with BFD @var{abfd}. 544 545 The initial motivation for, and use of, this routine is not 546 so we can get the exact size of the object the BFD applies to, since 547 that might not be generally possible (archive members for example). 548 It would be ideal if someone could eventually modify 549 it so that such results were guaranteed. 550 551 Instead, we want to ask questions like "is this NNN byte sized 552 object I'm about to try read from file offset YYY reasonable?" 553 As as example of where we might do this, some object formats 554 use string tables for which the first <<sizeof (long)>> bytes of the 555 table contain the size of the table itself, including the size bytes. 556 If an application tries to read what it thinks is one of these 557 string tables, without some way to validate the size, and for 558 some reason the size is wrong (byte swapping error, wrong location 559 for the string table, etc.), the only clue is likely to be a read 560 error when it tries to read the table, or a "virtual memory 561 exhausted" error when it tries to allocate 15 bazillon bytes 562 of space for the 15 bazillon byte table it is about to read. 563 This function at least allows us to answer the question, "is the 564 size reasonable?". 565 566 A return value of zero indicates the file size is unknown. 567 */ 568 569 ufile_ptr 570 bfd_get_size (bfd *abfd) 571 { 572 /* A size of 0 means we haven't yet called bfd_stat. A size of 1 573 means we have a cached value of 0, ie. unknown. */ 574 if (abfd->size <= 1 || bfd_write_p (abfd)) 575 { 576 struct stat buf; 577 578 if (abfd->size == 1 && !bfd_write_p (abfd)) 579 return 0; 580 581 if (bfd_stat (abfd, &buf) != 0 582 || buf.st_size == 0 583 || buf.st_size - (ufile_ptr) buf.st_size != 0) 584 { 585 abfd->size = 1; 586 return 0; 587 } 588 abfd->size = buf.st_size; 589 } 590 return abfd->size; 591 } 592 593 /* 594 FUNCTION 595 bfd_get_file_size 596 597 SYNOPSIS 598 ufile_ptr bfd_get_file_size (bfd *abfd); 599 600 DESCRIPTION 601 Return the file size (as read from file system) for the file 602 associated with BFD @var{abfd}. It supports both normal files 603 and archive elements. 604 605 */ 606 607 ufile_ptr 608 bfd_get_file_size (bfd *abfd) 609 { 610 ufile_ptr file_size, archive_size = (ufile_ptr) -1; 611 unsigned int compression_p2 = 0; 612 613 if (abfd->my_archive != NULL 614 && !bfd_is_thin_archive (abfd->my_archive)) 615 { 616 struct areltdata *adata = (struct areltdata *) abfd->arelt_data; 617 if (adata != NULL) 618 { 619 archive_size = adata->parsed_size; 620 /* If the archive is compressed, assume an element won't 621 expand more than eight times file size. */ 622 if (adata->arch_header != NULL 623 && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag, 624 "Z\012", 2) == 0) 625 compression_p2 = 3; 626 abfd = abfd->my_archive; 627 } 628 } 629 630 file_size = bfd_get_size (abfd) << compression_p2; 631 if (archive_size < file_size) 632 return archive_size; 633 return file_size; 634 } 635 636 /* 637 FUNCTION 638 bfd_mmap 639 640 SYNOPSIS 641 void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, 642 int prot, int flags, file_ptr offset, 643 void **map_addr, bfd_size_type *map_len) 644 ATTRIBUTE_WARN_UNUSED_RESULT; 645 646 DESCRIPTION 647 Return mmap()ed region of the file, if possible and implemented. 648 LEN and OFFSET do not need to be page aligned. The page aligned 649 address and length are written to MAP_ADDR and MAP_LEN. 650 651 */ 652 653 void * 654 bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, 655 int prot, int flags, file_ptr offset, 656 void **map_addr, bfd_size_type *map_len) 657 { 658 while (abfd->my_archive != NULL 659 && !bfd_is_thin_archive (abfd->my_archive)) 660 { 661 offset += abfd->origin; 662 abfd = abfd->my_archive; 663 } 664 offset += abfd->origin; 665 666 if (abfd->iovec == NULL) 667 { 668 bfd_set_error (bfd_error_invalid_operation); 669 return (void *) -1; 670 } 671 672 return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset, 673 map_addr, map_len); 674 } 675 676 /* Memory file I/O operations. */ 677 678 static file_ptr 679 memory_bread (bfd *abfd, void *ptr, file_ptr size) 680 { 681 struct bfd_in_memory *bim; 682 bfd_size_type get; 683 684 bim = (struct bfd_in_memory *) abfd->iostream; 685 get = size; 686 if (abfd->where + get > bim->size) 687 { 688 if (bim->size < (bfd_size_type) abfd->where) 689 get = 0; 690 else 691 get = bim->size - abfd->where; 692 bfd_set_error (bfd_error_file_truncated); 693 } 694 memcpy (ptr, bim->buffer + abfd->where, (size_t) get); 695 return get; 696 } 697 698 static file_ptr 699 memory_bwrite (bfd *abfd, const void *ptr, file_ptr size) 700 { 701 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream; 702 703 if (abfd->where + size > bim->size) 704 { 705 bfd_size_type newsize, oldsize; 706 707 oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 708 bim->size = abfd->where + size; 709 /* Round up to cut down on memory fragmentation */ 710 newsize = (bim->size + 127) & ~(bfd_size_type) 127; 711 if (newsize > oldsize) 712 { 713 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize); 714 if (bim->buffer == NULL) 715 { 716 bim->size = 0; 717 return 0; 718 } 719 if (newsize > bim->size) 720 memset (bim->buffer + bim->size, 0, newsize - bim->size); 721 } 722 } 723 memcpy (bim->buffer + abfd->where, ptr, (size_t) size); 724 return size; 725 } 726 727 static file_ptr 728 memory_btell (bfd *abfd) 729 { 730 return abfd->where; 731 } 732 733 static int 734 memory_bseek (bfd *abfd, file_ptr position, int direction) 735 { 736 file_ptr nwhere; 737 struct bfd_in_memory *bim; 738 739 bim = (struct bfd_in_memory *) abfd->iostream; 740 741 if (direction == SEEK_SET) 742 nwhere = position; 743 else 744 nwhere = abfd->where + position; 745 746 if (nwhere < 0) 747 { 748 abfd->where = 0; 749 errno = EINVAL; 750 return -1; 751 } 752 753 if ((bfd_size_type)nwhere > bim->size) 754 { 755 if (abfd->direction == write_direction 756 || abfd->direction == both_direction) 757 { 758 bfd_size_type newsize, oldsize; 759 760 oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 761 bim->size = nwhere; 762 /* Round up to cut down on memory fragmentation */ 763 newsize = (bim->size + 127) & ~(bfd_size_type) 127; 764 if (newsize > oldsize) 765 { 766 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize); 767 if (bim->buffer == NULL) 768 { 769 errno = EINVAL; 770 bim->size = 0; 771 return -1; 772 } 773 memset (bim->buffer + oldsize, 0, newsize - oldsize); 774 } 775 } 776 else 777 { 778 abfd->where = bim->size; 779 errno = EINVAL; 780 bfd_set_error (bfd_error_file_truncated); 781 return -1; 782 } 783 } 784 return 0; 785 } 786 787 static int 788 memory_bclose (struct bfd *abfd) 789 { 790 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream; 791 792 free (bim->buffer); 793 free (bim); 794 abfd->iostream = NULL; 795 796 return 0; 797 } 798 799 static int 800 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED) 801 { 802 return 0; 803 } 804 805 static int 806 memory_bstat (bfd *abfd, struct stat *statbuf) 807 { 808 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream; 809 810 memset (statbuf, 0, sizeof (*statbuf)); 811 statbuf->st_size = bim->size; 812 813 return 0; 814 } 815 816 static void * 817 memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED, 818 bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, 819 int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED, 820 void **map_addr ATTRIBUTE_UNUSED, 821 bfd_size_type *map_len ATTRIBUTE_UNUSED) 822 { 823 return (void *)-1; 824 } 825 826 const struct bfd_iovec _bfd_memory_iovec = 827 { 828 &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek, 829 &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap 830 }; 831 832 /* 833 FUNCTION 834 bfd_get_current_time 835 836 SYNOPSIS 837 time_t bfd_get_current_time (time_t now); 838 839 DESCRIPTION 840 Returns the current time. 841 842 If the environment variable SOURCE_DATE_EPOCH is defined 843 then this is parsed and its value is returned. Otherwise 844 if the paramter NOW is non-zero, then that is returned. 845 Otherwise the result of the system call "time(NULL)" is 846 returned. 847 */ 848 849 time_t 850 bfd_get_current_time (time_t now) 851 { 852 char *source_date_epoch; 853 unsigned long long epoch; 854 855 /* FIXME: We could probably cache this lookup, 856 and the parsing of its value below. */ 857 source_date_epoch = getenv ("SOURCE_DATE_EPOCH"); 858 859 if (source_date_epoch == NULL) 860 { 861 if (now) 862 return now; 863 return time (NULL); 864 } 865 866 epoch = strtoull (source_date_epoch, NULL, 0); 867 868 /* If epoch == 0 then something is wrong with SOURCE_DATE_EPOCH, 869 but we do not have an easy way to report it. Since the presence 870 of the environment variable implies that the user wants 871 deterministic behaviour we just accept the 0 value. */ 872 873 return (time_t) epoch; 874 } 875