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 prefixDOS[] = L"\\\\?\\"; 123 const wchar_t prefixUNC[] = L"\\\\?\\UNC\\"; 124 const wchar_t prefixNone[] = L""; 125 const size_t partPathLen = strlen (filename) + 1; 126 const wchar_t * prefix; 127 size_t sizeof_prefix; 128 bool strip_network_prefix = false; 129 130 /* PR 31527: In order to not hit limits in the maximum file path, all paths 131 need converting to Universal Naming Convention (UNC) syntax. The following 132 forms may be provided to this function and are converted accordingly. 133 134 1. UNC paths (start with \\?\), these are unconverted; 135 2. Network paths (start with \\ or // but not \\?\), these are given the 136 \\?UNC\ prefix, and have the incoming \\ or // removed; 137 3. DOS drive paths (a letter followed by a colon), these are given the 138 \\?\ prefix; 139 4. Paths relative to CWD, the current working directory is tested for the 140 above conditions, and otherwise are assumed to be DOS paths. 141 142 For more information see: 143 https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry 144 */ 145 146 if (startswith (filename, "\\\\?\\")) 147 { 148 prefix = prefixNone; 149 sizeof_prefix = sizeof (prefixNone); 150 } 151 else if (startswith (filename, "\\\\") || startswith (filename, "//")) 152 { 153 prefix = prefixUNC; 154 sizeof_prefix = sizeof (prefixUNC); 155 strip_network_prefix = true; 156 } 157 else if (strlen (filename) > 2 && filename[1] == ':') 158 { 159 prefix = prefixDOS; 160 sizeof_prefix = sizeof (prefixDOS); 161 } 162 else 163 { 164 /* The partial path is relative to the current working directory, use this 165 to determine the prefix. 166 1) Get the length: Calling with lpBuffer set to null returns the length. 167 2) Resolve the path. */ 168 size_t pwdWSize = GetCurrentDirectoryW (0, NULL); 169 wchar_t * pwdPath = calloc (pwdWSize, sizeof(wchar_t)); 170 GetCurrentDirectoryW (pwdWSize, pwdPath); 171 if (wcsncmp (pwdPath, L"\\\\?\\", 6) == 0) 172 { 173 prefix = prefixNone; 174 sizeof_prefix = sizeof (prefixNone); 175 } 176 else if (wcsncmp (pwdPath, L"\\\\", 2) == 0 177 || wcsncmp (pwdPath, L"//", 2) == 0) 178 { 179 prefix = prefixUNC; 180 sizeof_prefix = sizeof (prefixUNC); 181 strip_network_prefix = true; 182 } 183 else 184 { 185 prefix = prefixDOS; 186 sizeof_prefix = sizeof (prefixDOS); 187 } 188 free (pwdPath); 189 } 190 191 #ifdef __MINGW32__ 192 #if !HAVE_DECL____LC_CODEPAGE_FUNC 193 /* This prototype was added to locale.h in version 9.0 of MinGW-w64. */ 194 _CRTIMP unsigned int __cdecl ___lc_codepage_func (void); 195 #endif 196 const unsigned int cp = ___lc_codepage_func (); 197 #else 198 const unsigned int cp = CP_UTF8; 199 #endif 200 201 /* Converting the partial path from ascii to unicode. 202 1) Get the length: Calling with lpWideCharStr set to null returns the length. 203 2) Convert the string: Calling with cbMultiByte set to -1 includes the terminating null. */ 204 size_t partPathWSize = MultiByteToWideChar (cp, 0, filename, -1, NULL, 0); 205 wchar_t * partPath = calloc (partPathWSize, sizeof(wchar_t)); 206 size_t ix; 207 208 MultiByteToWideChar (cp, 0, filename, -1, partPath, partPathWSize); 209 210 /* Convert any UNIX style path separators into the DOS i.e. backslash separator. */ 211 for (ix = 0; ix < partPathLen; ix++) 212 if (IS_UNIX_DIR_SEPARATOR(filename[ix])) 213 partPath[ix] = '\\'; 214 215 /* Getting the full path from the provided partial path. 216 1) Get the length. 217 2) Resolve the path. */ 218 long fullPathWSize = GetFullPathNameW (partPath, 0, NULL, lpFilePart); 219 wchar_t * fullPath = calloc (fullPathWSize + sizeof_prefix + 1, sizeof(wchar_t)); 220 221 wcscpy (fullPath, prefix); 222 223 int prefixLen = sizeof_prefix / sizeof(wchar_t); 224 225 /* Do not add a prefix to the null device. */ 226 if (stricmp (filename, "nul") == 0) 227 prefixLen = 1; 228 229 wchar_t * fullPathOffset = fullPath + prefixLen - 1; 230 231 GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart); 232 233 if (strip_network_prefix) 234 { 235 /* Remove begining of the beginning two backslash characters (\\). */ 236 wchar_t *_fullPath = calloc (fullPathWSize + sizeof_prefix + 1, sizeof(wchar_t)); 237 238 GetFullPathNameW (fullPath, fullPathWSize + sizeof_prefix + 1, _fullPath, lpFilePart); 239 free (fullPath); 240 fullPath = _fullPath; 241 } 242 243 free (partPath); 244 245 /* It is non-standard for modes to exceed 16 characters. */ 246 wchar_t modesW[16]; 247 248 MultiByteToWideChar (cp, 0, modes, -1, modesW, sizeof(modesW)); 249 250 FILE * file = _wfopen (fullPath, modesW); 251 free (fullPath); 252 253 return close_on_exec (file); 254 255 #elif defined (HAVE_FOPEN64) 256 return close_on_exec (fopen64 (filename, modes)); 257 258 #else 259 return close_on_exec (fopen (filename, modes)); 260 #endif 261 } 262 263 /* 264 INTERNAL_DEFINITION 265 struct bfd_iovec 266 267 DESCRIPTION 268 269 The <<struct bfd_iovec>> contains the internal file I/O class. 270 Each <<BFD>> has an instance of this class and all file I/O is 271 routed through it (it is assumed that the instance implements 272 all methods listed below). 273 274 .struct bfd_iovec 275 .{ 276 . {* To avoid problems with macros, a "b" rather than "f" 277 . prefix is prepended to each method name. *} 278 . {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching 279 . bytes starting at PTR. Return the number of bytes actually 280 . transfered (a read past end-of-file returns less than NBYTES), 281 . or -1 (setting <<bfd_error>>) if an error occurs. *} 282 . file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes); 283 . file_ptr (*bwrite) (struct bfd *abfd, const void *ptr, 284 . file_ptr nbytes); 285 . {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>> 286 . if an error occurs. *} 287 . file_ptr (*btell) (struct bfd *abfd); 288 . {* For the following, on successful completion a value of 0 is returned. 289 . Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *} 290 . int (*bseek) (struct bfd *abfd, file_ptr offset, int whence); 291 . int (*bclose) (struct bfd *abfd); 292 . int (*bflush) (struct bfd *abfd); 293 . int (*bstat) (struct bfd *abfd, struct stat *sb); 294 . {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual 295 . mmap parameter, except that LEN and OFFSET do not need to be page 296 . aligned. Returns (void *)-1 on failure, mmapped address on success. 297 . Also write in MAP_ADDR the address of the page aligned buffer and in 298 . MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and 299 . MAP_LEN to unmap. *} 300 . void *(*bmmap) (struct bfd *abfd, void *addr, size_t len, 301 . int prot, int flags, file_ptr offset, 302 . void **map_addr, size_t *map_len); 303 .}; 304 305 .extern const struct bfd_iovec _bfd_memory_iovec; 306 . 307 */ 308 309 310 /* 311 FUNCTION 312 bfd_read 313 314 SYNOPSIS 315 bfd_size_type bfd_read (void *, bfd_size_type, bfd *) 316 ATTRIBUTE_WARN_UNUSED_RESULT; 317 318 DESCRIPTION 319 Attempt to read SIZE bytes from ABFD's iostream to PTR. 320 Return the amount read. 321 */ 322 323 bfd_size_type 324 bfd_read (void *ptr, bfd_size_type size, bfd *abfd) 325 { 326 file_ptr nread; 327 bfd *element_bfd = abfd; 328 ufile_ptr offset = 0; 329 330 while (abfd->my_archive != NULL 331 && !bfd_is_thin_archive (abfd->my_archive)) 332 { 333 offset += abfd->origin; 334 abfd = abfd->my_archive; 335 } 336 offset += abfd->origin; 337 338 /* If this is a non-thin archive element, don't read past the end of 339 this element. */ 340 if (element_bfd->arelt_data != NULL 341 && element_bfd->my_archive != NULL 342 && !bfd_is_thin_archive (element_bfd->my_archive)) 343 { 344 bfd_size_type maxbytes = arelt_size (element_bfd); 345 346 if (abfd->where < offset || abfd->where - offset >= maxbytes) 347 { 348 bfd_set_error (bfd_error_invalid_operation); 349 return -1; 350 } 351 if (abfd->where - offset + size > maxbytes) 352 size = maxbytes - (abfd->where - offset); 353 } 354 355 if (abfd->iovec == NULL) 356 { 357 bfd_set_error (bfd_error_invalid_operation); 358 return -1; 359 } 360 361 if (abfd->last_io == bfd_io_write) 362 { 363 abfd->last_io = bfd_io_force; 364 if (bfd_seek (abfd, 0, SEEK_CUR) != 0) 365 return -1; 366 } 367 abfd->last_io = bfd_io_read; 368 369 nread = abfd->iovec->bread (abfd, ptr, size); 370 if (nread != -1) 371 abfd->where += nread; 372 373 return nread; 374 } 375 376 /* 377 FUNCTION 378 bfd_write 379 380 SYNOPSIS 381 bfd_size_type bfd_write (const void *, bfd_size_type, bfd *) 382 ATTRIBUTE_WARN_UNUSED_RESULT; 383 384 DESCRIPTION 385 Attempt to write SIZE bytes to ABFD's iostream from PTR. 386 Return the amount written. 387 */ 388 389 bfd_size_type 390 bfd_write (const void *ptr, bfd_size_type size, bfd *abfd) 391 { 392 file_ptr nwrote; 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 { 400 bfd_set_error (bfd_error_invalid_operation); 401 return -1; 402 } 403 404 if (abfd->last_io == bfd_io_read) 405 { 406 abfd->last_io = bfd_io_force; 407 if (bfd_seek (abfd, 0, SEEK_CUR) != 0) 408 return -1; 409 } 410 abfd->last_io = bfd_io_write; 411 412 nwrote = abfd->iovec->bwrite (abfd, ptr, size); 413 if (nwrote != -1) 414 abfd->where += nwrote; 415 if ((bfd_size_type) nwrote != size) 416 { 417 #ifdef ENOSPC 418 errno = ENOSPC; 419 #endif 420 bfd_set_error (bfd_error_system_call); 421 } 422 return nwrote; 423 } 424 425 /* 426 FUNCTION 427 bfd_tell 428 429 SYNOPSIS 430 file_ptr bfd_tell (bfd *) ATTRIBUTE_WARN_UNUSED_RESULT; 431 432 DESCRIPTION 433 Return ABFD's iostream file position. 434 */ 435 436 file_ptr 437 bfd_tell (bfd *abfd) 438 { 439 ufile_ptr offset = 0; 440 file_ptr ptr; 441 442 while (abfd->my_archive != NULL 443 && !bfd_is_thin_archive (abfd->my_archive)) 444 { 445 offset += abfd->origin; 446 abfd = abfd->my_archive; 447 } 448 offset += abfd->origin; 449 450 if (abfd->iovec == NULL) 451 return 0; 452 453 ptr = abfd->iovec->btell (abfd); 454 abfd->where = ptr; 455 return ptr - offset; 456 } 457 458 /* 459 FUNCTION 460 bfd_flush 461 462 SYNOPSIS 463 int bfd_flush (bfd *); 464 465 DESCRIPTION 466 Flush ABFD's iostream pending IO. 467 */ 468 469 int 470 bfd_flush (bfd *abfd) 471 { 472 while (abfd->my_archive != NULL 473 && !bfd_is_thin_archive (abfd->my_archive)) 474 abfd = abfd->my_archive; 475 476 if (abfd->iovec == NULL) 477 return 0; 478 479 return abfd->iovec->bflush (abfd); 480 } 481 482 /* 483 FUNCTION 484 bfd_stat 485 486 SYNOPSIS 487 int bfd_stat (bfd *, struct stat *) ATTRIBUTE_WARN_UNUSED_RESULT; 488 489 DESCRIPTION 490 Call fstat on ABFD's iostream. Return 0 on success, and a 491 negative value on failure. 492 */ 493 494 int 495 bfd_stat (bfd *abfd, struct stat *statbuf) 496 { 497 int result; 498 499 while (abfd->my_archive != NULL 500 && !bfd_is_thin_archive (abfd->my_archive)) 501 abfd = abfd->my_archive; 502 503 if (abfd->iovec == NULL) 504 { 505 bfd_set_error (bfd_error_invalid_operation); 506 return -1; 507 } 508 509 result = abfd->iovec->bstat (abfd, statbuf); 510 if (result < 0) 511 bfd_set_error (bfd_error_system_call); 512 return result; 513 } 514 515 /* 516 FUNCTION 517 bfd_seek 518 519 SYNOPSIS 520 int bfd_seek (bfd *, file_ptr, int) ATTRIBUTE_WARN_UNUSED_RESULT; 521 522 DESCRIPTION 523 Call fseek on ABFD's iostream. Return 0 on success, and a 524 negative value on failure. 525 */ 526 527 int 528 bfd_seek (bfd *abfd, file_ptr position, int direction) 529 { 530 int result; 531 ufile_ptr offset = 0; 532 533 while (abfd->my_archive != NULL 534 && !bfd_is_thin_archive (abfd->my_archive)) 535 { 536 offset += abfd->origin; 537 abfd = abfd->my_archive; 538 } 539 offset += abfd->origin; 540 541 if (abfd->iovec == NULL) 542 { 543 bfd_set_error (bfd_error_invalid_operation); 544 return -1; 545 } 546 547 /* For the time being, a BFD may not seek to it's end. The problem 548 is that we don't easily have a way to recognize the end of an 549 element in an archive. */ 550 BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); 551 552 if (direction != SEEK_CUR) 553 position += offset; 554 555 if (((direction == SEEK_CUR && position == 0) 556 || (direction == SEEK_SET && (ufile_ptr) position == abfd->where)) 557 && abfd->last_io != bfd_io_force) 558 return 0; 559 560 abfd->last_io = bfd_io_seek; 561 562 result = abfd->iovec->bseek (abfd, position, direction); 563 if (result != 0) 564 { 565 /* An EINVAL error probably means that the file offset was 566 absurd. */ 567 if (errno == EINVAL) 568 bfd_set_error (bfd_error_file_truncated); 569 else 570 bfd_set_error (bfd_error_system_call); 571 } 572 else 573 { 574 /* Adjust `where' field. */ 575 if (direction == SEEK_CUR) 576 abfd->where += position; 577 else 578 abfd->where = position; 579 } 580 581 return result; 582 } 583 584 /* 585 FUNCTION 586 bfd_get_mtime 587 588 SYNOPSIS 589 long bfd_get_mtime (bfd *abfd); 590 591 DESCRIPTION 592 Return the file modification time (as read from the file system, or 593 from the archive header for archive members). 594 595 */ 596 597 long 598 bfd_get_mtime (bfd *abfd) 599 { 600 struct stat buf; 601 602 if (abfd->mtime_set) 603 return abfd->mtime; 604 605 if (bfd_stat (abfd, &buf) != 0) 606 return 0; 607 608 abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */ 609 return buf.st_mtime; 610 } 611 612 /* 613 FUNCTION 614 bfd_get_size 615 616 SYNOPSIS 617 ufile_ptr bfd_get_size (bfd *abfd); 618 619 DESCRIPTION 620 Return the file size (as read from file system) for the file 621 associated with BFD @var{abfd}. 622 623 The initial motivation for, and use of, this routine is not 624 so we can get the exact size of the object the BFD applies to, since 625 that might not be generally possible (archive members for example). 626 It would be ideal if someone could eventually modify 627 it so that such results were guaranteed. 628 629 Instead, we want to ask questions like "is this NNN byte sized 630 object I'm about to try read from file offset YYY reasonable?" 631 As as example of where we might do this, some object formats 632 use string tables for which the first <<sizeof (long)>> bytes of the 633 table contain the size of the table itself, including the size bytes. 634 If an application tries to read what it thinks is one of these 635 string tables, without some way to validate the size, and for 636 some reason the size is wrong (byte swapping error, wrong location 637 for the string table, etc.), the only clue is likely to be a read 638 error when it tries to read the table, or a "virtual memory 639 exhausted" error when it tries to allocate 15 bazillon bytes 640 of space for the 15 bazillon byte table it is about to read. 641 This function at least allows us to answer the question, "is the 642 size reasonable?". 643 644 A return value of zero indicates the file size is unknown. 645 */ 646 647 ufile_ptr 648 bfd_get_size (bfd *abfd) 649 { 650 /* A size of 0 means we haven't yet called bfd_stat. A size of 1 651 means we have a cached value of 0, ie. unknown. */ 652 if (abfd->size <= 1 || bfd_write_p (abfd)) 653 { 654 struct stat buf; 655 656 if (abfd->size == 1 && !bfd_write_p (abfd)) 657 return 0; 658 659 if (bfd_stat (abfd, &buf) != 0 660 || buf.st_size == 0 661 || buf.st_size - (ufile_ptr) buf.st_size != 0) 662 { 663 abfd->size = 1; 664 return 0; 665 } 666 abfd->size = buf.st_size; 667 } 668 return abfd->size; 669 } 670 671 /* 672 FUNCTION 673 bfd_get_file_size 674 675 SYNOPSIS 676 ufile_ptr bfd_get_file_size (bfd *abfd); 677 678 DESCRIPTION 679 Return the file size (as read from file system) for the file 680 associated with BFD @var{abfd}. It supports both normal files 681 and archive elements. 682 683 */ 684 685 ufile_ptr 686 bfd_get_file_size (bfd *abfd) 687 { 688 ufile_ptr file_size, archive_size = (ufile_ptr) -1; 689 unsigned int compression_p2 = 0; 690 691 if (abfd->my_archive != NULL 692 && !bfd_is_thin_archive (abfd->my_archive)) 693 { 694 struct areltdata *adata = (struct areltdata *) abfd->arelt_data; 695 if (adata != NULL) 696 { 697 archive_size = adata->parsed_size; 698 /* If the archive is compressed, assume an element won't 699 expand more than eight times file size. */ 700 if (adata->arch_header != NULL 701 && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag, 702 "Z\012", 2) == 0) 703 compression_p2 = 3; 704 abfd = abfd->my_archive; 705 } 706 } 707 708 file_size = bfd_get_size (abfd) << compression_p2; 709 if (archive_size < file_size) 710 return archive_size; 711 return file_size; 712 } 713 714 /* 715 FUNCTION 716 bfd_mmap 717 718 SYNOPSIS 719 void *bfd_mmap (bfd *abfd, void *addr, size_t len, 720 int prot, int flags, file_ptr offset, 721 void **map_addr, size_t *map_len) 722 ATTRIBUTE_WARN_UNUSED_RESULT; 723 724 DESCRIPTION 725 Return mmap()ed region of the file, if possible and implemented. 726 LEN and OFFSET do not need to be page aligned. The page aligned 727 address and length are written to MAP_ADDR and MAP_LEN. 728 729 */ 730 731 void * 732 bfd_mmap (bfd *abfd, void *addr, size_t len, 733 int prot, int flags, file_ptr offset, 734 void **map_addr, size_t *map_len) 735 { 736 while (abfd->my_archive != NULL 737 && !bfd_is_thin_archive (abfd->my_archive)) 738 { 739 offset += abfd->origin; 740 abfd = abfd->my_archive; 741 } 742 offset += abfd->origin; 743 744 if (abfd->iovec == NULL) 745 { 746 bfd_set_error (bfd_error_invalid_operation); 747 return MAP_FAILED; 748 } 749 750 return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset, 751 map_addr, map_len); 752 } 753 754 /* Memory file I/O operations. */ 755 756 static file_ptr 757 memory_bread (bfd *abfd, void *ptr, file_ptr size) 758 { 759 struct bfd_in_memory *bim; 760 bfd_size_type get; 761 762 bim = (struct bfd_in_memory *) abfd->iostream; 763 get = size; 764 if (abfd->where + get > bim->size) 765 { 766 if (bim->size < (bfd_size_type) abfd->where) 767 get = 0; 768 else 769 get = bim->size - abfd->where; 770 bfd_set_error (bfd_error_file_truncated); 771 } 772 memcpy (ptr, bim->buffer + abfd->where, (size_t) get); 773 return get; 774 } 775 776 static file_ptr 777 memory_bwrite (bfd *abfd, const void *ptr, file_ptr size) 778 { 779 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream; 780 781 if (abfd->where + size > bim->size) 782 { 783 bfd_size_type newsize, oldsize; 784 785 oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 786 bim->size = abfd->where + size; 787 /* Round up to cut down on memory fragmentation */ 788 newsize = (bim->size + 127) & ~(bfd_size_type) 127; 789 if (newsize > oldsize) 790 { 791 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize); 792 if (bim->buffer == NULL) 793 { 794 bim->size = 0; 795 return 0; 796 } 797 if (newsize > bim->size) 798 memset (bim->buffer + bim->size, 0, newsize - bim->size); 799 } 800 } 801 memcpy (bim->buffer + abfd->where, ptr, (size_t) size); 802 return size; 803 } 804 805 static file_ptr 806 memory_btell (bfd *abfd) 807 { 808 return abfd->where; 809 } 810 811 static int 812 memory_bseek (bfd *abfd, file_ptr position, int direction) 813 { 814 file_ptr nwhere; 815 struct bfd_in_memory *bim; 816 817 bim = (struct bfd_in_memory *) abfd->iostream; 818 819 if (direction == SEEK_SET) 820 nwhere = position; 821 else 822 nwhere = abfd->where + position; 823 824 if (nwhere < 0) 825 { 826 abfd->where = 0; 827 errno = EINVAL; 828 return -1; 829 } 830 831 if ((bfd_size_type)nwhere > bim->size) 832 { 833 if (abfd->direction == write_direction 834 || abfd->direction == both_direction) 835 { 836 bfd_size_type newsize, oldsize; 837 838 oldsize = (bim->size + 127) & ~(bfd_size_type) 127; 839 bim->size = nwhere; 840 /* Round up to cut down on memory fragmentation */ 841 newsize = (bim->size + 127) & ~(bfd_size_type) 127; 842 if (newsize > oldsize) 843 { 844 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize); 845 if (bim->buffer == NULL) 846 { 847 errno = EINVAL; 848 bim->size = 0; 849 return -1; 850 } 851 memset (bim->buffer + oldsize, 0, newsize - oldsize); 852 } 853 } 854 else 855 { 856 abfd->where = bim->size; 857 errno = EINVAL; 858 bfd_set_error (bfd_error_file_truncated); 859 return -1; 860 } 861 } 862 return 0; 863 } 864 865 static int 866 memory_bclose (struct bfd *abfd) 867 { 868 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream; 869 870 free (bim->buffer); 871 free (bim); 872 abfd->iostream = NULL; 873 874 return 0; 875 } 876 877 static int 878 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED) 879 { 880 return 0; 881 } 882 883 static int 884 memory_bstat (bfd *abfd, struct stat *statbuf) 885 { 886 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream; 887 888 memset (statbuf, 0, sizeof (*statbuf)); 889 statbuf->st_size = bim->size; 890 891 return 0; 892 } 893 894 static void * 895 memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED, 896 size_t len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, 897 int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED, 898 void **map_addr ATTRIBUTE_UNUSED, 899 size_t *map_len ATTRIBUTE_UNUSED) 900 { 901 return (void *)-1; 902 } 903 904 const struct bfd_iovec _bfd_memory_iovec = 905 { 906 &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek, 907 &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap 908 }; 909 910 /* 911 FUNCTION 912 bfd_get_current_time 913 914 SYNOPSIS 915 time_t bfd_get_current_time (time_t now); 916 917 DESCRIPTION 918 Returns the current time. 919 920 If the environment variable SOURCE_DATE_EPOCH is defined 921 then this is parsed and its value is returned. Otherwise 922 if the paramter NOW is non-zero, then that is returned. 923 Otherwise the result of the system call "time(NULL)" is 924 returned. 925 */ 926 927 time_t 928 bfd_get_current_time (time_t now) 929 { 930 char *source_date_epoch; 931 unsigned long long epoch; 932 933 /* FIXME: We could probably cache this lookup, 934 and the parsing of its value below. */ 935 source_date_epoch = getenv ("SOURCE_DATE_EPOCH"); 936 937 if (source_date_epoch == NULL) 938 { 939 if (now) 940 return now; 941 return time (NULL); 942 } 943 944 epoch = strtoull (source_date_epoch, NULL, 0); 945 946 /* If epoch == 0 then something is wrong with SOURCE_DATE_EPOCH, 947 but we do not have an easy way to report it. Since the presence 948 of the environment variable implies that the user wants 949 deterministic behaviour we just accept the 0 value. */ 950 951 return (time_t) epoch; 952 } 953