1 /* Low-level I/O routines for BFDs.
3 Copyright (C) 1990-2022 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. */
35 #define S_IXUSR 0100 /* Execute by owner. */
38 #define S_IXGRP 0010 /* Execute by group. */
41 #define S_IXOTH 0001 /* Execute by others. */
49 _bfd_real_ftell (FILE *file
)
51 #if defined (HAVE_FTELLO64)
52 return ftello64 (file
);
53 #elif defined (HAVE_FTELLO)
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
);
68 return fseek (file
, offset
, whence
);
72 /* Mark FILE as close-on-exec. Return FILE. FILE may be NULL, in
73 which case nothing is done. */
75 close_on_exec (FILE *file
)
77 #if defined (HAVE_FILENO) && defined (F_GETFD)
80 int fd
= fileno (file
);
81 int old
= fcntl (fd
, F_GETFD
, 0);
83 fcntl (fd
, F_SETFD
, old
| FD_CLOEXEC
);
90 _bfd_real_fopen (const char *filename
, const char *modes
)
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.
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];
108 memcpy (attrs
, modes
, modes_len
);
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 prefix
[] = L
"\\\\?\\";
123 const size_t partPathLen
= strlen (filename
) + 1;
125 const unsigned int cp
= ___lc_codepage_func();
127 const unsigned int cp
= CP_UTF8
;
130 /* Converting the partial path from ascii to unicode.
131 1) Get the length: Calling with lpWideCharStr set to null returns the length.
132 2) Convert the string: Calling with cbMultiByte set to -1 includes the terminating null. */
133 size_t partPathWSize
= MultiByteToWideChar (cp
, 0, filename
, -1, NULL
, 0);
134 wchar_t * partPath
= calloc (partPathWSize
, sizeof(wchar_t));
137 MultiByteToWideChar (cp
, 0, filename
, -1, partPath
, partPathWSize
);
139 /* Convert any UNIX style path separators into the DOS i.e. backslash separator. */
140 for (ix
= 0; ix
< partPathLen
; ix
++)
141 if (IS_UNIX_DIR_SEPARATOR(filename
[ix
]))
144 /* Getting the full path from the provided partial path.
146 2) Resolve the path. */
147 long fullPathWSize
= GetFullPathNameW (partPath
, 0, NULL
, lpFilePart
);
148 wchar_t * fullPath
= calloc (fullPathWSize
+ sizeof(prefix
) + 1, sizeof(wchar_t));
150 wcscpy (fullPath
, prefix
);
152 int prefixLen
= sizeof(prefix
) / sizeof(wchar_t);
153 wchar_t * fullPathOffset
= fullPath
+ prefixLen
- 1;
155 GetFullPathNameW (partPath
, fullPathWSize
, fullPathOffset
, lpFilePart
);
158 /* It is non-standard for modes to exceed 16 characters. */
161 MultiByteToWideChar (cp
, 0, modes
, -1, modesW
, sizeof(modesW
));
163 FILE * file
= _wfopen (fullPath
, modesW
);
166 return close_on_exec (file
);
168 #elif defined (HAVE_FOPEN64)
169 return close_on_exec (fopen64 (filename
, modes
));
172 return close_on_exec (fopen (filename
, modes
));
182 The <<struct bfd_iovec>> contains the internal file I/O class.
183 Each <<BFD>> has an instance of this class and all file I/O is
184 routed through it (it is assumed that the instance implements
185 all methods listed below).
189 . {* To avoid problems with macros, a "b" rather than "f"
190 . prefix is prepended to each method name. *}
191 . {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
192 . bytes starting at PTR. Return the number of bytes actually
193 . transfered (a read past end-of-file returns less than NBYTES),
194 . or -1 (setting <<bfd_error>>) if an error occurs. *}
195 . file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
196 . file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
198 . {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
199 . if an error occurs. *}
200 . file_ptr (*btell) (struct bfd *abfd);
201 . {* For the following, on successful completion a value of 0 is returned.
202 . Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *}
203 . int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
204 . int (*bclose) (struct bfd *abfd);
205 . int (*bflush) (struct bfd *abfd);
206 . int (*bstat) (struct bfd *abfd, struct stat *sb);
207 . {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
208 . mmap parameter, except that LEN and OFFSET do not need to be page
209 . aligned. Returns (void *)-1 on failure, mmapped address on success.
210 . Also write in MAP_ADDR the address of the page aligned buffer and in
211 . MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and
212 . MAP_LEN to unmap. *}
213 . void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
214 . int prot, int flags, file_ptr offset,
215 . void **map_addr, bfd_size_type *map_len);
218 .extern const struct bfd_iovec _bfd_memory_iovec;
223 /* Return value is amount read. */
226 bfd_bread (void *ptr
, bfd_size_type size
, bfd
*abfd
)
229 bfd
*element_bfd
= abfd
;
230 ufile_ptr offset
= 0;
232 while (abfd
->my_archive
!= NULL
233 && !bfd_is_thin_archive (abfd
->my_archive
))
235 offset
+= abfd
->origin
;
236 abfd
= abfd
->my_archive
;
238 offset
+= abfd
->origin
;
240 /* If this is a non-thin archive element, don't read past the end of
242 if (element_bfd
->arelt_data
!= NULL
243 && element_bfd
->my_archive
!= NULL
244 && !bfd_is_thin_archive (element_bfd
->my_archive
))
246 bfd_size_type maxbytes
= arelt_size (element_bfd
);
248 if (abfd
->where
< offset
|| abfd
->where
- offset
>= maxbytes
)
250 bfd_set_error (bfd_error_invalid_operation
);
253 if (abfd
->where
- offset
+ size
> maxbytes
)
254 size
= maxbytes
- (abfd
->where
- offset
);
257 if (abfd
->iovec
== NULL
)
259 bfd_set_error (bfd_error_invalid_operation
);
263 nread
= abfd
->iovec
->bread (abfd
, ptr
, size
);
265 abfd
->where
+= nread
;
271 bfd_bwrite (const void *ptr
, bfd_size_type size
, bfd
*abfd
)
275 while (abfd
->my_archive
!= NULL
276 && !bfd_is_thin_archive (abfd
->my_archive
))
277 abfd
= abfd
->my_archive
;
279 if (abfd
->iovec
== NULL
)
281 bfd_set_error (bfd_error_invalid_operation
);
285 nwrote
= abfd
->iovec
->bwrite (abfd
, ptr
, size
);
287 abfd
->where
+= nwrote
;
288 if ((bfd_size_type
) nwrote
!= size
)
293 bfd_set_error (bfd_error_system_call
);
301 ufile_ptr offset
= 0;
304 while (abfd
->my_archive
!= NULL
305 && !bfd_is_thin_archive (abfd
->my_archive
))
307 offset
+= abfd
->origin
;
308 abfd
= abfd
->my_archive
;
310 offset
+= abfd
->origin
;
312 if (abfd
->iovec
== NULL
)
315 ptr
= abfd
->iovec
->btell (abfd
);
321 bfd_flush (bfd
*abfd
)
323 while (abfd
->my_archive
!= NULL
324 && !bfd_is_thin_archive (abfd
->my_archive
))
325 abfd
= abfd
->my_archive
;
327 if (abfd
->iovec
== NULL
)
330 return abfd
->iovec
->bflush (abfd
);
333 /* Returns 0 for success, negative value for failure (in which case
334 bfd_get_error can retrieve the error code). */
336 bfd_stat (bfd
*abfd
, struct stat
*statbuf
)
340 while (abfd
->my_archive
!= NULL
341 && !bfd_is_thin_archive (abfd
->my_archive
))
342 abfd
= abfd
->my_archive
;
344 if (abfd
->iovec
== NULL
)
346 bfd_set_error (bfd_error_invalid_operation
);
350 result
= abfd
->iovec
->bstat (abfd
, statbuf
);
352 bfd_set_error (bfd_error_system_call
);
356 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
357 can retrieve the error code). */
360 bfd_seek (bfd
*abfd
, file_ptr position
, int direction
)
363 ufile_ptr offset
= 0;
365 while (abfd
->my_archive
!= NULL
366 && !bfd_is_thin_archive (abfd
->my_archive
))
368 offset
+= abfd
->origin
;
369 abfd
= abfd
->my_archive
;
371 offset
+= abfd
->origin
;
373 if (abfd
->iovec
== NULL
)
375 bfd_set_error (bfd_error_invalid_operation
);
379 /* For the time being, a BFD may not seek to it's end. The problem
380 is that we don't easily have a way to recognize the end of an
381 element in an archive. */
382 BFD_ASSERT (direction
== SEEK_SET
|| direction
== SEEK_CUR
);
384 if (direction
!= SEEK_CUR
)
387 if ((direction
== SEEK_CUR
&& position
== 0)
388 || (direction
== SEEK_SET
&& (ufile_ptr
) position
== abfd
->where
))
391 result
= abfd
->iovec
->bseek (abfd
, position
, direction
);
394 /* An EINVAL error probably means that the file offset was
397 bfd_set_error (bfd_error_file_truncated
);
399 bfd_set_error (bfd_error_system_call
);
403 /* Adjust `where' field. */
404 if (direction
== SEEK_CUR
)
405 abfd
->where
+= position
;
407 abfd
->where
= position
;
418 long bfd_get_mtime (bfd *abfd);
421 Return the file modification time (as read from the file system, or
422 from the archive header for archive members).
427 bfd_get_mtime (bfd
*abfd
)
434 if (bfd_stat (abfd
, &buf
) != 0)
437 abfd
->mtime
= buf
.st_mtime
; /* Save value in case anyone wants it */
446 ufile_ptr bfd_get_size (bfd *abfd);
449 Return the file size (as read from file system) for the file
450 associated with BFD @var{abfd}.
452 The initial motivation for, and use of, this routine is not
453 so we can get the exact size of the object the BFD applies to, since
454 that might not be generally possible (archive members for example).
455 It would be ideal if someone could eventually modify
456 it so that such results were guaranteed.
458 Instead, we want to ask questions like "is this NNN byte sized
459 object I'm about to try read from file offset YYY reasonable?"
460 As as example of where we might do this, some object formats
461 use string tables for which the first <<sizeof (long)>> bytes of the
462 table contain the size of the table itself, including the size bytes.
463 If an application tries to read what it thinks is one of these
464 string tables, without some way to validate the size, and for
465 some reason the size is wrong (byte swapping error, wrong location
466 for the string table, etc.), the only clue is likely to be a read
467 error when it tries to read the table, or a "virtual memory
468 exhausted" error when it tries to allocate 15 bazillon bytes
469 of space for the 15 bazillon byte table it is about to read.
470 This function at least allows us to answer the question, "is the
473 A return value of zero indicates the file size is unknown.
477 bfd_get_size (bfd
*abfd
)
479 /* A size of 0 means we haven't yet called bfd_stat. A size of 1
480 means we have a cached value of 0, ie. unknown. */
481 if (abfd
->size
<= 1 || bfd_write_p (abfd
))
485 if (abfd
->size
== 1 && !bfd_write_p (abfd
))
488 if (bfd_stat (abfd
, &buf
) != 0
490 || buf
.st_size
- (ufile_ptr
) buf
.st_size
!= 0)
495 abfd
->size
= buf
.st_size
;
505 ufile_ptr bfd_get_file_size (bfd *abfd);
508 Return the file size (as read from file system) for the file
509 associated with BFD @var{abfd}. It supports both normal files
510 and archive elements.
515 bfd_get_file_size (bfd
*abfd
)
517 ufile_ptr file_size
, archive_size
= (ufile_ptr
) -1;
519 if (abfd
->my_archive
!= NULL
520 && !bfd_is_thin_archive (abfd
->my_archive
))
522 struct areltdata
*adata
= (struct areltdata
*) abfd
->arelt_data
;
525 archive_size
= adata
->parsed_size
;
526 /* If the archive is compressed we can't compare against
528 if (adata
->arch_header
!= NULL
529 && memcmp (((struct ar_hdr
*) adata
->arch_header
)->ar_fmag
,
532 abfd
= abfd
->my_archive
;
536 file_size
= bfd_get_size (abfd
);
537 if (archive_size
< file_size
)
547 void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
548 int prot, int flags, file_ptr offset,
549 void **map_addr, bfd_size_type *map_len);
552 Return mmap()ed region of the file, if possible and implemented.
553 LEN and OFFSET do not need to be page aligned. The page aligned
554 address and length are written to MAP_ADDR and MAP_LEN.
559 bfd_mmap (bfd
*abfd
, void *addr
, bfd_size_type len
,
560 int prot
, int flags
, file_ptr offset
,
561 void **map_addr
, bfd_size_type
*map_len
)
563 while (abfd
->my_archive
!= NULL
564 && !bfd_is_thin_archive (abfd
->my_archive
))
566 offset
+= abfd
->origin
;
567 abfd
= abfd
->my_archive
;
569 offset
+= abfd
->origin
;
571 if (abfd
->iovec
== NULL
)
573 bfd_set_error (bfd_error_invalid_operation
);
577 return abfd
->iovec
->bmmap (abfd
, addr
, len
, prot
, flags
, offset
,
581 /* Memory file I/O operations. */
584 memory_bread (bfd
*abfd
, void *ptr
, file_ptr size
)
586 struct bfd_in_memory
*bim
;
589 bim
= (struct bfd_in_memory
*) abfd
->iostream
;
591 if (abfd
->where
+ get
> bim
->size
)
593 if (bim
->size
< (bfd_size_type
) abfd
->where
)
596 get
= bim
->size
- abfd
->where
;
597 bfd_set_error (bfd_error_file_truncated
);
599 memcpy (ptr
, bim
->buffer
+ abfd
->where
, (size_t) get
);
604 memory_bwrite (bfd
*abfd
, const void *ptr
, file_ptr size
)
606 struct bfd_in_memory
*bim
= (struct bfd_in_memory
*) abfd
->iostream
;
608 if (abfd
->where
+ size
> bim
->size
)
610 bfd_size_type newsize
, oldsize
;
612 oldsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
613 bim
->size
= abfd
->where
+ size
;
614 /* Round up to cut down on memory fragmentation */
615 newsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
616 if (newsize
> oldsize
)
618 bim
->buffer
= (bfd_byte
*) bfd_realloc_or_free (bim
->buffer
, newsize
);
619 if (bim
->buffer
== NULL
)
624 if (newsize
> bim
->size
)
625 memset (bim
->buffer
+ bim
->size
, 0, newsize
- bim
->size
);
628 memcpy (bim
->buffer
+ abfd
->where
, ptr
, (size_t) size
);
633 memory_btell (bfd
*abfd
)
639 memory_bseek (bfd
*abfd
, file_ptr position
, int direction
)
642 struct bfd_in_memory
*bim
;
644 bim
= (struct bfd_in_memory
*) abfd
->iostream
;
646 if (direction
== SEEK_SET
)
649 nwhere
= abfd
->where
+ position
;
658 if ((bfd_size_type
)nwhere
> bim
->size
)
660 if (abfd
->direction
== write_direction
661 || abfd
->direction
== both_direction
)
663 bfd_size_type newsize
, oldsize
;
665 oldsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
667 /* Round up to cut down on memory fragmentation */
668 newsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
669 if (newsize
> oldsize
)
671 bim
->buffer
= (bfd_byte
*) bfd_realloc_or_free (bim
->buffer
, newsize
);
672 if (bim
->buffer
== NULL
)
678 memset (bim
->buffer
+ oldsize
, 0, newsize
- oldsize
);
683 abfd
->where
= bim
->size
;
685 bfd_set_error (bfd_error_file_truncated
);
693 memory_bclose (struct bfd
*abfd
)
695 struct bfd_in_memory
*bim
= (struct bfd_in_memory
*) abfd
->iostream
;
699 abfd
->iostream
= NULL
;
705 memory_bflush (bfd
*abfd ATTRIBUTE_UNUSED
)
711 memory_bstat (bfd
*abfd
, struct stat
*statbuf
)
713 struct bfd_in_memory
*bim
= (struct bfd_in_memory
*) abfd
->iostream
;
715 memset (statbuf
, 0, sizeof (*statbuf
));
716 statbuf
->st_size
= bim
->size
;
722 memory_bmmap (bfd
*abfd ATTRIBUTE_UNUSED
, void *addr ATTRIBUTE_UNUSED
,
723 bfd_size_type len ATTRIBUTE_UNUSED
, int prot ATTRIBUTE_UNUSED
,
724 int flags ATTRIBUTE_UNUSED
, file_ptr offset ATTRIBUTE_UNUSED
,
725 void **map_addr ATTRIBUTE_UNUSED
,
726 bfd_size_type
*map_len ATTRIBUTE_UNUSED
)
731 const struct bfd_iovec _bfd_memory_iovec
=
733 &memory_bread
, &memory_bwrite
, &memory_btell
, &memory_bseek
,
734 &memory_bclose
, &memory_bflush
, &memory_bstat
, &memory_bmmap