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. */
34 #define S_IXUSR 0100 /* Execute by owner. */
37 #define S_IXGRP 0010 /* Execute by group. */
40 #define S_IXOTH 0001 /* Execute by others. */
48 _bfd_real_ftell (FILE *file
)
50 #if defined (HAVE_FTELLO64)
51 return ftello64 (file
);
52 #elif defined (HAVE_FTELLO)
60 _bfd_real_fseek (FILE *file
, file_ptr offset
, int whence
)
62 #if defined (HAVE_FSEEKO64)
63 return fseeko64 (file
, offset
, whence
);
64 #elif defined (HAVE_FSEEKO)
65 return fseeko (file
, offset
, whence
);
67 return fseek (file
, offset
, whence
);
71 /* Mark FILE as close-on-exec. Return FILE. FILE may be NULL, in
72 which case nothing is done. */
74 close_on_exec (FILE *file
)
76 #if defined (HAVE_FILENO) && defined (F_GETFD)
79 int fd
= fileno (file
);
80 int old
= fcntl (fd
, F_GETFD
, 0);
82 fcntl (fd
, F_SETFD
, old
| FD_CLOEXEC
);
89 _bfd_real_fopen (const char *filename
, const char *modes
)
94 /* On VMS, fopen allows file attributes as optional arguments.
95 We need to use them but we'd better to use the common prototype.
96 In fopen-vms.h, they are separated from the mode with a comma.
98 vms_attr
= strchr (modes
, ',');
101 /* Attributes found. Split. */
102 size_t modes_len
= strlen (modes
) + 1;
103 char attrs
[modes_len
+ 1];
107 memcpy (attrs
, modes
, modes_len
);
109 for (i
= 0; i
< 2; i
++)
111 at
[i
+ 1] = strchr (at
[i
], ',');
112 BFD_ASSERT (at
[i
+ 1] != NULL
);
113 *(at
[i
+ 1]++) = 0; /* Replace ',' with a nul, and skip it. */
115 return close_on_exec (fopen (filename
, at
[0], at
[1], at
[2]));
118 #elif defined (_WIN32)
119 /* PR 25713: Handle extra long path names possibly containing '..' and '.'. */
120 wchar_t ** lpFilePart
= {NULL
};
121 const wchar_t prefix
[] = L
"\\\\?\\";
122 const wchar_t ccs
[] = L
", ccs=UNICODE";
123 const size_t partPathLen
= strlen (filename
) + 1;
125 /* Converting the partial path from ascii to unicode.
126 1) Get the length: Calling with lpWideCharStr set to null returns the length.
127 2) Convert the string: Calling with cbMultiByte set to -1 includes the terminating null. */
128 size_t partPathWSize
= MultiByteToWideChar (CP_UTF8
, 0, filename
, -1, NULL
, 0);
129 wchar_t * partPath
= calloc (partPathWSize
, sizeof(wchar_t));
132 MultiByteToWideChar (CP_UTF8
, 0, filename
, -1, partPath
, partPathWSize
);
134 /* Convert any UNIX style path separators into the DOS i.e. backslash separator. */
135 for (ix
= 0; ix
< partPathLen
; ix
++)
136 if (IS_UNIX_DIR_SEPARATOR(filename
[ix
]))
139 /* Getting the full path from the provided partial path.
141 2) Resolve the path. */
142 long fullPathWSize
= GetFullPathNameW (partPath
, 0, NULL
, lpFilePart
);
143 wchar_t * fullPath
= calloc (fullPathWSize
+ sizeof(prefix
) + 1, sizeof(wchar_t));
145 wcscpy (fullPath
, prefix
);
147 int prefixLen
= sizeof(prefix
) / sizeof(wchar_t);
148 wchar_t * fullPathOffset
= fullPath
+ prefixLen
- 1;
150 GetFullPathNameW (partPath
, fullPathWSize
, fullPathOffset
, lpFilePart
);
153 /* It is non-standard for modes to exceed 16 characters. */
154 wchar_t modesW
[16 + sizeof(ccs
)];
156 MultiByteToWideChar (CP_UTF8
, 0, modes
, -1, modesW
, sizeof(modesW
));
157 wcscat (modesW
, ccs
);
159 FILE * file
= _wfopen (fullPath
, modesW
);
162 return close_on_exec (file
);
164 #elif defined (HAVE_FOPEN64)
165 return close_on_exec (fopen64 (filename
, modes
));
168 return close_on_exec (fopen (filename
, modes
));
178 The <<struct bfd_iovec>> contains the internal file I/O class.
179 Each <<BFD>> has an instance of this class and all file I/O is
180 routed through it (it is assumed that the instance implements
181 all methods listed below).
185 . {* To avoid problems with macros, a "b" rather than "f"
186 . prefix is prepended to each method name. *}
187 . {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
188 . bytes starting at PTR. Return the number of bytes actually
189 . transfered (a read past end-of-file returns less than NBYTES),
190 . or -1 (setting <<bfd_error>>) if an error occurs. *}
191 . file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
192 . file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
194 . {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
195 . if an error occurs. *}
196 . file_ptr (*btell) (struct bfd *abfd);
197 . {* For the following, on successful completion a value of 0 is returned.
198 . Otherwise, a value of -1 is returned (and <<bfd_error>> is set). *}
199 . int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
200 . int (*bclose) (struct bfd *abfd);
201 . int (*bflush) (struct bfd *abfd);
202 . int (*bstat) (struct bfd *abfd, struct stat *sb);
203 . {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
204 . mmap parameter, except that LEN and OFFSET do not need to be page
205 . aligned. Returns (void *)-1 on failure, mmapped address on success.
206 . Also write in MAP_ADDR the address of the page aligned buffer and in
207 . MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and
208 . MAP_LEN to unmap. *}
209 . void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
210 . int prot, int flags, file_ptr offset,
211 . void **map_addr, bfd_size_type *map_len);
214 .extern const struct bfd_iovec _bfd_memory_iovec;
219 /* Return value is amount read. */
222 bfd_bread (void *ptr
, bfd_size_type size
, bfd
*abfd
)
225 bfd
*element_bfd
= abfd
;
226 ufile_ptr offset
= 0;
228 while (abfd
->my_archive
!= NULL
229 && !bfd_is_thin_archive (abfd
->my_archive
))
231 offset
+= abfd
->origin
;
232 abfd
= abfd
->my_archive
;
234 offset
+= abfd
->origin
;
236 /* If this is a non-thin archive element, don't read past the end of
238 if (element_bfd
->arelt_data
!= NULL
239 && element_bfd
->my_archive
!= NULL
240 && !bfd_is_thin_archive (element_bfd
->my_archive
))
242 bfd_size_type maxbytes
= arelt_size (element_bfd
);
244 if (abfd
->where
< offset
|| abfd
->where
- offset
>= maxbytes
)
246 bfd_set_error (bfd_error_invalid_operation
);
249 if (abfd
->where
- offset
+ size
> maxbytes
)
250 size
= maxbytes
- (abfd
->where
- offset
);
253 if (abfd
->iovec
== NULL
)
255 bfd_set_error (bfd_error_invalid_operation
);
259 nread
= abfd
->iovec
->bread (abfd
, ptr
, size
);
261 abfd
->where
+= nread
;
267 bfd_bwrite (const void *ptr
, bfd_size_type size
, bfd
*abfd
)
271 while (abfd
->my_archive
!= NULL
272 && !bfd_is_thin_archive (abfd
->my_archive
))
273 abfd
= abfd
->my_archive
;
275 if (abfd
->iovec
== NULL
)
277 bfd_set_error (bfd_error_invalid_operation
);
281 nwrote
= abfd
->iovec
->bwrite (abfd
, ptr
, size
);
283 abfd
->where
+= nwrote
;
284 if ((bfd_size_type
) nwrote
!= size
)
289 bfd_set_error (bfd_error_system_call
);
297 ufile_ptr offset
= 0;
300 while (abfd
->my_archive
!= NULL
301 && !bfd_is_thin_archive (abfd
->my_archive
))
303 offset
+= abfd
->origin
;
304 abfd
= abfd
->my_archive
;
306 offset
+= abfd
->origin
;
308 if (abfd
->iovec
== NULL
)
311 ptr
= abfd
->iovec
->btell (abfd
);
317 bfd_flush (bfd
*abfd
)
319 while (abfd
->my_archive
!= NULL
320 && !bfd_is_thin_archive (abfd
->my_archive
))
321 abfd
= abfd
->my_archive
;
323 if (abfd
->iovec
== NULL
)
326 return abfd
->iovec
->bflush (abfd
);
329 /* Returns 0 for success, negative value for failure (in which case
330 bfd_get_error can retrieve the error code). */
332 bfd_stat (bfd
*abfd
, struct stat
*statbuf
)
336 while (abfd
->my_archive
!= NULL
337 && !bfd_is_thin_archive (abfd
->my_archive
))
338 abfd
= abfd
->my_archive
;
340 if (abfd
->iovec
== NULL
)
342 bfd_set_error (bfd_error_invalid_operation
);
346 result
= abfd
->iovec
->bstat (abfd
, statbuf
);
348 bfd_set_error (bfd_error_system_call
);
352 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
353 can retrieve the error code). */
356 bfd_seek (bfd
*abfd
, file_ptr position
, int direction
)
359 ufile_ptr offset
= 0;
361 while (abfd
->my_archive
!= NULL
362 && !bfd_is_thin_archive (abfd
->my_archive
))
364 offset
+= abfd
->origin
;
365 abfd
= abfd
->my_archive
;
367 offset
+= abfd
->origin
;
369 if (abfd
->iovec
== NULL
)
371 bfd_set_error (bfd_error_invalid_operation
);
375 /* For the time being, a BFD may not seek to it's end. The problem
376 is that we don't easily have a way to recognize the end of an
377 element in an archive. */
378 BFD_ASSERT (direction
== SEEK_SET
|| direction
== SEEK_CUR
);
380 if (direction
!= SEEK_CUR
)
383 if ((direction
== SEEK_CUR
&& position
== 0)
384 || (direction
== SEEK_SET
&& (ufile_ptr
) position
== abfd
->where
))
387 result
= abfd
->iovec
->bseek (abfd
, position
, direction
);
390 /* An EINVAL error probably means that the file offset was
393 bfd_set_error (bfd_error_file_truncated
);
395 bfd_set_error (bfd_error_system_call
);
399 /* Adjust `where' field. */
400 if (direction
== SEEK_CUR
)
401 abfd
->where
+= position
;
403 abfd
->where
= position
;
414 long bfd_get_mtime (bfd *abfd);
417 Return the file modification time (as read from the file system, or
418 from the archive header for archive members).
423 bfd_get_mtime (bfd
*abfd
)
430 if (bfd_stat (abfd
, &buf
) != 0)
433 abfd
->mtime
= buf
.st_mtime
; /* Save value in case anyone wants it */
442 ufile_ptr bfd_get_size (bfd *abfd);
445 Return the file size (as read from file system) for the file
446 associated with BFD @var{abfd}.
448 The initial motivation for, and use of, this routine is not
449 so we can get the exact size of the object the BFD applies to, since
450 that might not be generally possible (archive members for example).
451 It would be ideal if someone could eventually modify
452 it so that such results were guaranteed.
454 Instead, we want to ask questions like "is this NNN byte sized
455 object I'm about to try read from file offset YYY reasonable?"
456 As as example of where we might do this, some object formats
457 use string tables for which the first <<sizeof (long)>> bytes of the
458 table contain the size of the table itself, including the size bytes.
459 If an application tries to read what it thinks is one of these
460 string tables, without some way to validate the size, and for
461 some reason the size is wrong (byte swapping error, wrong location
462 for the string table, etc.), the only clue is likely to be a read
463 error when it tries to read the table, or a "virtual memory
464 exhausted" error when it tries to allocate 15 bazillon bytes
465 of space for the 15 bazillon byte table it is about to read.
466 This function at least allows us to answer the question, "is the
469 A return value of zero indicates the file size is unknown.
473 bfd_get_size (bfd
*abfd
)
475 /* A size of 0 means we haven't yet called bfd_stat. A size of 1
476 means we have a cached value of 0, ie. unknown. */
477 if (abfd
->size
<= 1 || bfd_write_p (abfd
))
481 if (abfd
->size
== 1 && !bfd_write_p (abfd
))
484 if (bfd_stat (abfd
, &buf
) != 0
486 || buf
.st_size
- (ufile_ptr
) buf
.st_size
!= 0)
491 abfd
->size
= buf
.st_size
;
501 ufile_ptr bfd_get_file_size (bfd *abfd);
504 Return the file size (as read from file system) for the file
505 associated with BFD @var{abfd}. It supports both normal files
506 and archive elements.
511 bfd_get_file_size (bfd
*abfd
)
513 ufile_ptr file_size
, archive_size
= (ufile_ptr
) -1;
515 if (abfd
->my_archive
!= NULL
516 && !bfd_is_thin_archive (abfd
->my_archive
))
518 struct areltdata
*adata
= (struct areltdata
*) abfd
->arelt_data
;
521 archive_size
= adata
->parsed_size
;
522 /* If the archive is compressed we can't compare against
524 if (adata
->arch_header
!= NULL
525 && memcmp (((struct ar_hdr
*) adata
->arch_header
)->ar_fmag
,
528 abfd
= abfd
->my_archive
;
532 file_size
= bfd_get_size (abfd
);
533 if (archive_size
< file_size
)
543 void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
544 int prot, int flags, file_ptr offset,
545 void **map_addr, bfd_size_type *map_len);
548 Return mmap()ed region of the file, if possible and implemented.
549 LEN and OFFSET do not need to be page aligned. The page aligned
550 address and length are written to MAP_ADDR and MAP_LEN.
555 bfd_mmap (bfd
*abfd
, void *addr
, bfd_size_type len
,
556 int prot
, int flags
, file_ptr offset
,
557 void **map_addr
, bfd_size_type
*map_len
)
559 while (abfd
->my_archive
!= NULL
560 && !bfd_is_thin_archive (abfd
->my_archive
))
562 offset
+= abfd
->origin
;
563 abfd
= abfd
->my_archive
;
565 offset
+= abfd
->origin
;
567 if (abfd
->iovec
== NULL
)
569 bfd_set_error (bfd_error_invalid_operation
);
573 return abfd
->iovec
->bmmap (abfd
, addr
, len
, prot
, flags
, offset
,
577 /* Memory file I/O operations. */
580 memory_bread (bfd
*abfd
, void *ptr
, file_ptr size
)
582 struct bfd_in_memory
*bim
;
585 bim
= (struct bfd_in_memory
*) abfd
->iostream
;
587 if (abfd
->where
+ get
> bim
->size
)
589 if (bim
->size
< (bfd_size_type
) abfd
->where
)
592 get
= bim
->size
- abfd
->where
;
593 bfd_set_error (bfd_error_file_truncated
);
595 memcpy (ptr
, bim
->buffer
+ abfd
->where
, (size_t) get
);
600 memory_bwrite (bfd
*abfd
, const void *ptr
, file_ptr size
)
602 struct bfd_in_memory
*bim
= (struct bfd_in_memory
*) abfd
->iostream
;
604 if (abfd
->where
+ size
> bim
->size
)
606 bfd_size_type newsize
, oldsize
;
608 oldsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
609 bim
->size
= abfd
->where
+ size
;
610 /* Round up to cut down on memory fragmentation */
611 newsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
612 if (newsize
> oldsize
)
614 bim
->buffer
= (bfd_byte
*) bfd_realloc_or_free (bim
->buffer
, newsize
);
615 if (bim
->buffer
== NULL
)
620 if (newsize
> bim
->size
)
621 memset (bim
->buffer
+ bim
->size
, 0, newsize
- bim
->size
);
624 memcpy (bim
->buffer
+ abfd
->where
, ptr
, (size_t) size
);
629 memory_btell (bfd
*abfd
)
635 memory_bseek (bfd
*abfd
, file_ptr position
, int direction
)
638 struct bfd_in_memory
*bim
;
640 bim
= (struct bfd_in_memory
*) abfd
->iostream
;
642 if (direction
== SEEK_SET
)
645 nwhere
= abfd
->where
+ position
;
654 if ((bfd_size_type
)nwhere
> bim
->size
)
656 if (abfd
->direction
== write_direction
657 || abfd
->direction
== both_direction
)
659 bfd_size_type newsize
, oldsize
;
661 oldsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
663 /* Round up to cut down on memory fragmentation */
664 newsize
= (bim
->size
+ 127) & ~(bfd_size_type
) 127;
665 if (newsize
> oldsize
)
667 bim
->buffer
= (bfd_byte
*) bfd_realloc_or_free (bim
->buffer
, newsize
);
668 if (bim
->buffer
== NULL
)
674 memset (bim
->buffer
+ oldsize
, 0, newsize
- oldsize
);
679 abfd
->where
= bim
->size
;
681 bfd_set_error (bfd_error_file_truncated
);
689 memory_bclose (struct bfd
*abfd
)
691 struct bfd_in_memory
*bim
= (struct bfd_in_memory
*) abfd
->iostream
;
695 abfd
->iostream
= NULL
;
701 memory_bflush (bfd
*abfd ATTRIBUTE_UNUSED
)
707 memory_bstat (bfd
*abfd
, struct stat
*statbuf
)
709 struct bfd_in_memory
*bim
= (struct bfd_in_memory
*) abfd
->iostream
;
711 memset (statbuf
, 0, sizeof (*statbuf
));
712 statbuf
->st_size
= bim
->size
;
718 memory_bmmap (bfd
*abfd ATTRIBUTE_UNUSED
, void *addr ATTRIBUTE_UNUSED
,
719 bfd_size_type len ATTRIBUTE_UNUSED
, int prot ATTRIBUTE_UNUSED
,
720 int flags ATTRIBUTE_UNUSED
, file_ptr offset ATTRIBUTE_UNUSED
,
721 void **map_addr ATTRIBUTE_UNUSED
,
722 bfd_size_type
*map_len ATTRIBUTE_UNUSED
)
727 const struct bfd_iovec _bfd_memory_iovec
=
729 &memory_bread
, &memory_bwrite
, &memory_btell
, &memory_bseek
,
730 &memory_bclose
, &memory_bflush
, &memory_bstat
, &memory_bmmap