Automatic date update in version.in
[binutils-gdb.git] / bfd / bfdio.c
blob2a7f77fa8d457ff86ff63cd0cffbdca2f8e64be3
1 /* Low-level I/O routines for BFDs.
3 Copyright (C) 1990-2024 Free Software Foundation, Inc.
5 Written by Cygnus Support.
7 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
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
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
44 #ifndef FD_CLOEXEC
45 #define FD_CLOEXEC 1
46 #endif
48 file_ptr
49 _bfd_real_ftell (FILE *file)
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
60 int
61 _bfd_real_fseek (FILE *file, file_ptr offset, int whence)
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
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)
77 #if defined (HAVE_FILENO) && defined (F_GETFD)
78 if (file)
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);
85 #endif
86 return file;
89 FILE *
90 _bfd_real_fopen (const char *filename, const char *modes)
92 #ifdef VMS
93 char *vms_attr;
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)
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;
108 memcpy (attrs, modes, modes_len);
109 at[0] = attrs;
110 for (i = 0; i < 2; i++)
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. */
116 return close_on_exec (fopen (filename, at[0], at[1], at[2]));
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;
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.
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.
142 For more information see:
143 https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry
146 if (startswith (filename, "\\\\?\\"))
148 prefix = prefixNone;
149 sizeof_prefix = sizeof (prefixNone);
151 else if (startswith (filename, "\\\\") || startswith (filename, "//"))
153 prefix = prefixUNC;
154 sizeof_prefix = sizeof (prefixUNC);
155 strip_network_prefix = true;
157 else if (strlen (filename) > 2 && filename[1] == ':')
159 prefix = prefixDOS;
160 sizeof_prefix = sizeof (prefixDOS);
162 else
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)
173 prefix = prefixNone;
174 sizeof_prefix = sizeof (prefixNone);
176 else if (wcsncmp (pwdPath, L"\\\\", 2) == 0
177 || wcsncmp (pwdPath, L"//", 2) == 0)
179 prefix = prefixUNC;
180 sizeof_prefix = sizeof (prefixUNC);
181 strip_network_prefix = true;
183 else
185 prefix = prefixDOS;
186 sizeof_prefix = sizeof (prefixDOS);
188 free (pwdPath);
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
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;
208 MultiByteToWideChar (cp, 0, filename, -1, partPath, partPathWSize);
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] = '\\';
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));
221 wcscpy (fullPath, prefix);
223 int prefixLen = sizeof_prefix / sizeof(wchar_t);
225 /* Do not add a prefix to the null device. */
226 if (stricmp (filename, "nul") == 0)
227 prefixLen = 1;
229 wchar_t * fullPathOffset = fullPath + prefixLen - 1;
231 GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart);
233 if (strip_network_prefix)
235 /* Remove begining of the beginning two backslash characters (\\). */
236 wchar_t *_fullPath = calloc (fullPathWSize + sizeof_prefix + 1, sizeof(wchar_t));
238 GetFullPathNameW (fullPath, fullPathWSize + sizeof_prefix + 1, _fullPath, lpFilePart);
239 free (fullPath);
240 fullPath = _fullPath;
243 free (partPath);
245 /* It is non-standard for modes to exceed 16 characters. */
246 wchar_t modesW[16];
248 MultiByteToWideChar (cp, 0, modes, -1, modesW, sizeof(modesW));
250 FILE * file = _wfopen (fullPath, modesW);
251 free (fullPath);
253 return close_on_exec (file);
255 #elif defined (HAVE_FOPEN64)
256 return close_on_exec (fopen64 (filename, modes));
258 #else
259 return close_on_exec (fopen (filename, modes));
260 #endif
264 INTERNAL_DEFINITION
265 struct bfd_iovec
267 DESCRIPTION
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).
274 .struct bfd_iovec
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);
305 .extern const struct bfd_iovec _bfd_memory_iovec;
311 FUNCTION
312 bfd_read
314 SYNOPSIS
315 bfd_size_type bfd_read (void *, bfd_size_type, bfd *)
316 ATTRIBUTE_WARN_UNUSED_RESULT;
318 DESCRIPTION
319 Attempt to read SIZE bytes from ABFD's iostream to PTR.
320 Return the amount read.
323 bfd_size_type
324 bfd_read (void *ptr, bfd_size_type size, bfd *abfd)
326 file_ptr nread;
327 bfd *element_bfd = abfd;
328 ufile_ptr offset = 0;
330 while (abfd->my_archive != NULL
331 && !bfd_is_thin_archive (abfd->my_archive))
333 offset += abfd->origin;
334 abfd = abfd->my_archive;
336 offset += abfd->origin;
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))
344 bfd_size_type maxbytes = arelt_size (element_bfd);
346 if (abfd->where < offset || abfd->where - offset >= maxbytes)
348 bfd_set_error (bfd_error_invalid_operation);
349 return -1;
351 if (abfd->where - offset + size > maxbytes)
352 size = maxbytes - (abfd->where - offset);
355 if (abfd->iovec == NULL)
357 bfd_set_error (bfd_error_invalid_operation);
358 return -1;
361 if (abfd->last_io == bfd_io_write)
363 abfd->last_io = bfd_io_force;
364 if (bfd_seek (abfd, 0, SEEK_CUR) != 0)
365 return -1;
367 abfd->last_io = bfd_io_read;
369 nread = abfd->iovec->bread (abfd, ptr, size);
370 if (nread != -1)
371 abfd->where += nread;
373 return nread;
377 FUNCTION
378 bfd_write
380 SYNOPSIS
381 bfd_size_type bfd_write (const void *, bfd_size_type, bfd *)
382 ATTRIBUTE_WARN_UNUSED_RESULT;
384 DESCRIPTION
385 Attempt to write SIZE bytes to ABFD's iostream from PTR.
386 Return the amount written.
389 bfd_size_type
390 bfd_write (const void *ptr, bfd_size_type size, bfd *abfd)
392 file_ptr nwrote;
394 while (abfd->my_archive != NULL
395 && !bfd_is_thin_archive (abfd->my_archive))
396 abfd = abfd->my_archive;
398 if (abfd->iovec == NULL)
400 bfd_set_error (bfd_error_invalid_operation);
401 return -1;
404 if (abfd->last_io == bfd_io_read)
406 abfd->last_io = bfd_io_force;
407 if (bfd_seek (abfd, 0, SEEK_CUR) != 0)
408 return -1;
410 abfd->last_io = bfd_io_write;
412 nwrote = abfd->iovec->bwrite (abfd, ptr, size);
413 if (nwrote != -1)
414 abfd->where += nwrote;
415 if ((bfd_size_type) nwrote != size)
417 #ifdef ENOSPC
418 errno = ENOSPC;
419 #endif
420 bfd_set_error (bfd_error_system_call);
422 return nwrote;
426 FUNCTION
427 bfd_tell
429 SYNOPSIS
430 file_ptr bfd_tell (bfd *) ATTRIBUTE_WARN_UNUSED_RESULT;
432 DESCRIPTION
433 Return ABFD's iostream file position.
436 file_ptr
437 bfd_tell (bfd *abfd)
439 ufile_ptr offset = 0;
440 file_ptr ptr;
442 while (abfd->my_archive != NULL
443 && !bfd_is_thin_archive (abfd->my_archive))
445 offset += abfd->origin;
446 abfd = abfd->my_archive;
448 offset += abfd->origin;
450 if (abfd->iovec == NULL)
451 return 0;
453 ptr = abfd->iovec->btell (abfd);
454 abfd->where = ptr;
455 return ptr - offset;
459 FUNCTION
460 bfd_flush
462 SYNOPSIS
463 int bfd_flush (bfd *);
465 DESCRIPTION
466 Flush ABFD's iostream pending IO.
470 bfd_flush (bfd *abfd)
472 while (abfd->my_archive != NULL
473 && !bfd_is_thin_archive (abfd->my_archive))
474 abfd = abfd->my_archive;
476 if (abfd->iovec == NULL)
477 return 0;
479 return abfd->iovec->bflush (abfd);
483 FUNCTION
484 bfd_stat
486 SYNOPSIS
487 int bfd_stat (bfd *, struct stat *) ATTRIBUTE_WARN_UNUSED_RESULT;
489 DESCRIPTION
490 Call fstat on ABFD's iostream. Return 0 on success, and a
491 negative value on failure.
495 bfd_stat (bfd *abfd, struct stat *statbuf)
497 int result;
499 while (abfd->my_archive != NULL
500 && !bfd_is_thin_archive (abfd->my_archive))
501 abfd = abfd->my_archive;
503 if (abfd->iovec == NULL)
505 bfd_set_error (bfd_error_invalid_operation);
506 return -1;
509 result = abfd->iovec->bstat (abfd, statbuf);
510 if (result < 0)
511 bfd_set_error (bfd_error_system_call);
512 return result;
516 FUNCTION
517 bfd_seek
519 SYNOPSIS
520 int bfd_seek (bfd *, file_ptr, int) ATTRIBUTE_WARN_UNUSED_RESULT;
522 DESCRIPTION
523 Call fseek on ABFD's iostream. Return 0 on success, and a
524 negative value on failure.
528 bfd_seek (bfd *abfd, file_ptr position, int direction)
530 int result;
531 ufile_ptr offset = 0;
533 while (abfd->my_archive != NULL
534 && !bfd_is_thin_archive (abfd->my_archive))
536 offset += abfd->origin;
537 abfd = abfd->my_archive;
539 offset += abfd->origin;
541 if (abfd->iovec == NULL)
543 bfd_set_error (bfd_error_invalid_operation);
544 return -1;
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);
552 if (direction != SEEK_CUR)
553 position += offset;
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;
560 abfd->last_io = bfd_io_seek;
562 result = abfd->iovec->bseek (abfd, position, direction);
563 if (result != 0)
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);
572 else
574 /* Adjust `where' field. */
575 if (direction == SEEK_CUR)
576 abfd->where += position;
577 else
578 abfd->where = position;
581 return result;
585 FUNCTION
586 bfd_get_mtime
588 SYNOPSIS
589 long bfd_get_mtime (bfd *abfd);
591 DESCRIPTION
592 Return the file modification time (as read from the file system, or
593 from the archive header for archive members).
597 long
598 bfd_get_mtime (bfd *abfd)
600 struct stat buf;
602 if (abfd->mtime_set)
603 return abfd->mtime;
605 if (bfd_stat (abfd, &buf) != 0)
606 return 0;
608 abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
609 return buf.st_mtime;
613 FUNCTION
614 bfd_get_size
616 SYNOPSIS
617 ufile_ptr bfd_get_size (bfd *abfd);
619 DESCRIPTION
620 Return the file size (as read from file system) for the file
621 associated with BFD @var{abfd}.
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.
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?".
644 A return value of zero indicates the file size is unknown.
647 ufile_ptr
648 bfd_get_size (bfd *abfd)
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))
654 struct stat buf;
656 if (abfd->size == 1 && !bfd_write_p (abfd))
657 return 0;
659 if (bfd_stat (abfd, &buf) != 0
660 || buf.st_size == 0
661 || buf.st_size - (ufile_ptr) buf.st_size != 0)
663 abfd->size = 1;
664 return 0;
666 abfd->size = buf.st_size;
668 return abfd->size;
672 FUNCTION
673 bfd_get_file_size
675 SYNOPSIS
676 ufile_ptr bfd_get_file_size (bfd *abfd);
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.
685 ufile_ptr
686 bfd_get_file_size (bfd *abfd)
688 ufile_ptr file_size, archive_size = (ufile_ptr) -1;
689 unsigned int compression_p2 = 0;
691 if (abfd->my_archive != NULL
692 && !bfd_is_thin_archive (abfd->my_archive))
694 struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
695 if (adata != NULL)
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;
708 file_size = bfd_get_size (abfd) << compression_p2;
709 if (archive_size < file_size)
710 return archive_size;
711 return file_size;
715 FUNCTION
716 bfd_mmap
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;
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.
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)
736 while (abfd->my_archive != NULL
737 && !bfd_is_thin_archive (abfd->my_archive))
739 offset += abfd->origin;
740 abfd = abfd->my_archive;
742 offset += abfd->origin;
744 if (abfd->iovec == NULL)
746 bfd_set_error (bfd_error_invalid_operation);
747 return MAP_FAILED;
750 return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
751 map_addr, map_len);
754 /* Memory file I/O operations. */
756 static file_ptr
757 memory_bread (bfd *abfd, void *ptr, file_ptr size)
759 struct bfd_in_memory *bim;
760 bfd_size_type get;
762 bim = (struct bfd_in_memory *) abfd->iostream;
763 get = size;
764 if (abfd->where + get > bim->size)
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);
772 memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
773 return get;
776 static file_ptr
777 memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
779 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
781 if (abfd->where + size > bim->size)
783 bfd_size_type newsize, oldsize;
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)
791 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
792 if (bim->buffer == NULL)
794 bim->size = 0;
795 return 0;
797 if (newsize > bim->size)
798 memset (bim->buffer + bim->size, 0, newsize - bim->size);
801 memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
802 return size;
805 static file_ptr
806 memory_btell (bfd *abfd)
808 return abfd->where;
811 static int
812 memory_bseek (bfd *abfd, file_ptr position, int direction)
814 file_ptr nwhere;
815 struct bfd_in_memory *bim;
817 bim = (struct bfd_in_memory *) abfd->iostream;
819 if (direction == SEEK_SET)
820 nwhere = position;
821 else
822 nwhere = abfd->where + position;
824 if (nwhere < 0)
826 abfd->where = 0;
827 errno = EINVAL;
828 return -1;
831 if ((bfd_size_type)nwhere > bim->size)
833 if (abfd->direction == write_direction
834 || abfd->direction == both_direction)
836 bfd_size_type newsize, oldsize;
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)
844 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
845 if (bim->buffer == NULL)
847 errno = EINVAL;
848 bim->size = 0;
849 return -1;
851 memset (bim->buffer + oldsize, 0, newsize - oldsize);
854 else
856 abfd->where = bim->size;
857 errno = EINVAL;
858 bfd_set_error (bfd_error_file_truncated);
859 return -1;
862 return 0;
865 static int
866 memory_bclose (struct bfd *abfd)
868 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
870 free (bim->buffer);
871 free (bim);
872 abfd->iostream = NULL;
874 return 0;
877 static int
878 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
880 return 0;
883 static int
884 memory_bstat (bfd *abfd, struct stat *statbuf)
886 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
888 memset (statbuf, 0, sizeof (*statbuf));
889 statbuf->st_size = bim->size;
891 return 0;
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)
901 return (void *)-1;
904 const struct bfd_iovec _bfd_memory_iovec =
906 &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
907 &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
911 FUNCTION
912 bfd_get_current_time
914 SYNOPSIS
915 time_t bfd_get_current_time (time_t now);
917 DESCRIPTION
918 Returns the current time.
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.
927 time_t
928 bfd_get_current_time (time_t now)
930 char *source_date_epoch;
931 unsigned long long epoch;
933 /* FIXME: We could probably cache this lookup,
934 and the parsing of its value below. */
935 source_date_epoch = getenv ("SOURCE_DATE_EPOCH");
937 if (source_date_epoch == NULL)
939 if (now)
940 return now;
941 return time (NULL);
944 epoch = strtoull (source_date_epoch, NULL, 0);
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. */
951 return (time_t) epoch;