Automatic date update in version.in
[binutils-gdb.git] / bfd / bfdio.c
1 /* Low-level I/O routines for BFDs.
2
3 Copyright (C) 1990-2022 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 const unsigned int cp = ___lc_codepage_func();
126 #else
127 const unsigned int cp = CP_UTF8;
128 #endif
129
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));
135 size_t ix;
136
137 MultiByteToWideChar (cp, 0, filename, -1, partPath, partPathWSize);
138
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]))
142 partPath[ix] = '\\';
143
144 /* Getting the full path from the provided partial path.
145 1) Get the length.
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));
149
150 wcscpy (fullPath, prefix);
151
152 int prefixLen = sizeof(prefix) / sizeof(wchar_t);
153 wchar_t * fullPathOffset = fullPath + prefixLen - 1;
154
155 GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart);
156 free (partPath);
157
158 /* It is non-standard for modes to exceed 16 characters. */
159 wchar_t modesW[16];
160
161 MultiByteToWideChar (cp, 0, modes, -1, modesW, sizeof(modesW));
162
163 FILE * file = _wfopen (fullPath, modesW);
164 free (fullPath);
165
166 return close_on_exec (file);
167
168 #elif defined (HAVE_FOPEN64)
169 return close_on_exec (fopen64 (filename, modes));
170
171 #else
172 return close_on_exec (fopen (filename, modes));
173 #endif
174 }
175
176 /*
177 INTERNAL_DEFINITION
178 struct bfd_iovec
179
180 DESCRIPTION
181
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).
186
187 .struct bfd_iovec
188 .{
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,
197 . file_ptr nbytes);
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);
216 .};
217
218 .extern const struct bfd_iovec _bfd_memory_iovec;
219
220 */
221
222
223 /* Return value is amount read. */
224
225 bfd_size_type
226 bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
227 {
228 file_ptr nread;
229 bfd *element_bfd = abfd;
230 ufile_ptr offset = 0;
231
232 while (abfd->my_archive != NULL
233 && !bfd_is_thin_archive (abfd->my_archive))
234 {
235 offset += abfd->origin;
236 abfd = abfd->my_archive;
237 }
238 offset += abfd->origin;
239
240 /* If this is a non-thin archive element, don't read past the end of
241 this element. */
242 if (element_bfd->arelt_data != NULL
243 && element_bfd->my_archive != NULL
244 && !bfd_is_thin_archive (element_bfd->my_archive))
245 {
246 bfd_size_type maxbytes = arelt_size (element_bfd);
247
248 if (abfd->where < offset || abfd->where - offset >= maxbytes)
249 {
250 bfd_set_error (bfd_error_invalid_operation);
251 return -1;
252 }
253 if (abfd->where - offset + size > maxbytes)
254 size = maxbytes - (abfd->where - offset);
255 }
256
257 if (abfd->iovec == NULL)
258 {
259 bfd_set_error (bfd_error_invalid_operation);
260 return -1;
261 }
262
263 nread = abfd->iovec->bread (abfd, ptr, size);
264 if (nread != -1)
265 abfd->where += nread;
266
267 return nread;
268 }
269
270 bfd_size_type
271 bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
272 {
273 file_ptr nwrote;
274
275 while (abfd->my_archive != NULL
276 && !bfd_is_thin_archive (abfd->my_archive))
277 abfd = abfd->my_archive;
278
279 if (abfd->iovec == NULL)
280 {
281 bfd_set_error (bfd_error_invalid_operation);
282 return -1;
283 }
284
285 nwrote = abfd->iovec->bwrite (abfd, ptr, size);
286 if (nwrote != -1)
287 abfd->where += nwrote;
288 if ((bfd_size_type) nwrote != size)
289 {
290 #ifdef ENOSPC
291 errno = ENOSPC;
292 #endif
293 bfd_set_error (bfd_error_system_call);
294 }
295 return nwrote;
296 }
297
298 file_ptr
299 bfd_tell (bfd *abfd)
300 {
301 ufile_ptr offset = 0;
302 file_ptr ptr;
303
304 while (abfd->my_archive != NULL
305 && !bfd_is_thin_archive (abfd->my_archive))
306 {
307 offset += abfd->origin;
308 abfd = abfd->my_archive;
309 }
310 offset += abfd->origin;
311
312 if (abfd->iovec == NULL)
313 return 0;
314
315 ptr = abfd->iovec->btell (abfd);
316 abfd->where = ptr;
317 return ptr - offset;
318 }
319
320 int
321 bfd_flush (bfd *abfd)
322 {
323 while (abfd->my_archive != NULL
324 && !bfd_is_thin_archive (abfd->my_archive))
325 abfd = abfd->my_archive;
326
327 if (abfd->iovec == NULL)
328 return 0;
329
330 return abfd->iovec->bflush (abfd);
331 }
332
333 /* Returns 0 for success, negative value for failure (in which case
334 bfd_get_error can retrieve the error code). */
335 int
336 bfd_stat (bfd *abfd, struct stat *statbuf)
337 {
338 int result;
339
340 while (abfd->my_archive != NULL
341 && !bfd_is_thin_archive (abfd->my_archive))
342 abfd = abfd->my_archive;
343
344 if (abfd->iovec == NULL)
345 {
346 bfd_set_error (bfd_error_invalid_operation);
347 return -1;
348 }
349
350 result = abfd->iovec->bstat (abfd, statbuf);
351 if (result < 0)
352 bfd_set_error (bfd_error_system_call);
353 return result;
354 }
355
356 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
357 can retrieve the error code). */
358
359 int
360 bfd_seek (bfd *abfd, file_ptr position, int direction)
361 {
362 int result;
363 ufile_ptr offset = 0;
364
365 while (abfd->my_archive != NULL
366 && !bfd_is_thin_archive (abfd->my_archive))
367 {
368 offset += abfd->origin;
369 abfd = abfd->my_archive;
370 }
371 offset += abfd->origin;
372
373 if (abfd->iovec == NULL)
374 {
375 bfd_set_error (bfd_error_invalid_operation);
376 return -1;
377 }
378
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);
383
384 if (direction != SEEK_CUR)
385 position += offset;
386
387 if ((direction == SEEK_CUR && position == 0)
388 || (direction == SEEK_SET && (ufile_ptr) position == abfd->where))
389 return 0;
390
391 result = abfd->iovec->bseek (abfd, position, direction);
392 if (result != 0)
393 {
394 /* An EINVAL error probably means that the file offset was
395 absurd. */
396 if (errno == EINVAL)
397 bfd_set_error (bfd_error_file_truncated);
398 else
399 bfd_set_error (bfd_error_system_call);
400 }
401 else
402 {
403 /* Adjust `where' field. */
404 if (direction == SEEK_CUR)
405 abfd->where += position;
406 else
407 abfd->where = position;
408 }
409
410 return result;
411 }
412
413 /*
414 FUNCTION
415 bfd_get_mtime
416
417 SYNOPSIS
418 long bfd_get_mtime (bfd *abfd);
419
420 DESCRIPTION
421 Return the file modification time (as read from the file system, or
422 from the archive header for archive members).
423
424 */
425
426 long
427 bfd_get_mtime (bfd *abfd)
428 {
429 struct stat buf;
430
431 if (abfd->mtime_set)
432 return abfd->mtime;
433
434 if (bfd_stat (abfd, &buf) != 0)
435 return 0;
436
437 abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
438 return buf.st_mtime;
439 }
440
441 /*
442 FUNCTION
443 bfd_get_size
444
445 SYNOPSIS
446 ufile_ptr bfd_get_size (bfd *abfd);
447
448 DESCRIPTION
449 Return the file size (as read from file system) for the file
450 associated with BFD @var{abfd}.
451
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.
457
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
471 size reasonable?".
472
473 A return value of zero indicates the file size is unknown.
474 */
475
476 ufile_ptr
477 bfd_get_size (bfd *abfd)
478 {
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))
482 {
483 struct stat buf;
484
485 if (abfd->size == 1 && !bfd_write_p (abfd))
486 return 0;
487
488 if (bfd_stat (abfd, &buf) != 0
489 || buf.st_size == 0
490 || buf.st_size - (ufile_ptr) buf.st_size != 0)
491 {
492 abfd->size = 1;
493 return 0;
494 }
495 abfd->size = buf.st_size;
496 }
497 return abfd->size;
498 }
499
500 /*
501 FUNCTION
502 bfd_get_file_size
503
504 SYNOPSIS
505 ufile_ptr bfd_get_file_size (bfd *abfd);
506
507 DESCRIPTION
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.
511
512 */
513
514 ufile_ptr
515 bfd_get_file_size (bfd *abfd)
516 {
517 ufile_ptr file_size, archive_size = (ufile_ptr) -1;
518
519 if (abfd->my_archive != NULL
520 && !bfd_is_thin_archive (abfd->my_archive))
521 {
522 struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
523 if (adata != NULL)
524 {
525 archive_size = adata->parsed_size;
526 /* If the archive is compressed we can't compare against
527 file size. */
528 if (adata->arch_header != NULL
529 && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
530 "Z\012", 2) == 0)
531 return archive_size;
532 abfd = abfd->my_archive;
533 }
534 }
535
536 file_size = bfd_get_size (abfd);
537 if (archive_size < file_size)
538 return archive_size;
539 return file_size;
540 }
541
542 /*
543 FUNCTION
544 bfd_mmap
545
546 SYNOPSIS
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);
550
551 DESCRIPTION
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.
555
556 */
557
558 void *
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)
562 {
563 while (abfd->my_archive != NULL
564 && !bfd_is_thin_archive (abfd->my_archive))
565 {
566 offset += abfd->origin;
567 abfd = abfd->my_archive;
568 }
569 offset += abfd->origin;
570
571 if (abfd->iovec == NULL)
572 {
573 bfd_set_error (bfd_error_invalid_operation);
574 return (void *) -1;
575 }
576
577 return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
578 map_addr, map_len);
579 }
580
581 /* Memory file I/O operations. */
582
583 static file_ptr
584 memory_bread (bfd *abfd, void *ptr, file_ptr size)
585 {
586 struct bfd_in_memory *bim;
587 bfd_size_type get;
588
589 bim = (struct bfd_in_memory *) abfd->iostream;
590 get = size;
591 if (abfd->where + get > bim->size)
592 {
593 if (bim->size < (bfd_size_type) abfd->where)
594 get = 0;
595 else
596 get = bim->size - abfd->where;
597 bfd_set_error (bfd_error_file_truncated);
598 }
599 memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
600 return get;
601 }
602
603 static file_ptr
604 memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
605 {
606 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
607
608 if (abfd->where + size > bim->size)
609 {
610 bfd_size_type newsize, oldsize;
611
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)
617 {
618 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
619 if (bim->buffer == NULL)
620 {
621 bim->size = 0;
622 return 0;
623 }
624 if (newsize > bim->size)
625 memset (bim->buffer + bim->size, 0, newsize - bim->size);
626 }
627 }
628 memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
629 return size;
630 }
631
632 static file_ptr
633 memory_btell (bfd *abfd)
634 {
635 return abfd->where;
636 }
637
638 static int
639 memory_bseek (bfd *abfd, file_ptr position, int direction)
640 {
641 file_ptr nwhere;
642 struct bfd_in_memory *bim;
643
644 bim = (struct bfd_in_memory *) abfd->iostream;
645
646 if (direction == SEEK_SET)
647 nwhere = position;
648 else
649 nwhere = abfd->where + position;
650
651 if (nwhere < 0)
652 {
653 abfd->where = 0;
654 errno = EINVAL;
655 return -1;
656 }
657
658 if ((bfd_size_type)nwhere > bim->size)
659 {
660 if (abfd->direction == write_direction
661 || abfd->direction == both_direction)
662 {
663 bfd_size_type newsize, oldsize;
664
665 oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
666 bim->size = nwhere;
667 /* Round up to cut down on memory fragmentation */
668 newsize = (bim->size + 127) & ~(bfd_size_type) 127;
669 if (newsize > oldsize)
670 {
671 bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
672 if (bim->buffer == NULL)
673 {
674 errno = EINVAL;
675 bim->size = 0;
676 return -1;
677 }
678 memset (bim->buffer + oldsize, 0, newsize - oldsize);
679 }
680 }
681 else
682 {
683 abfd->where = bim->size;
684 errno = EINVAL;
685 bfd_set_error (bfd_error_file_truncated);
686 return -1;
687 }
688 }
689 return 0;
690 }
691
692 static int
693 memory_bclose (struct bfd *abfd)
694 {
695 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
696
697 free (bim->buffer);
698 free (bim);
699 abfd->iostream = NULL;
700
701 return 0;
702 }
703
704 static int
705 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
706 {
707 return 0;
708 }
709
710 static int
711 memory_bstat (bfd *abfd, struct stat *statbuf)
712 {
713 struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
714
715 memset (statbuf, 0, sizeof (*statbuf));
716 statbuf->st_size = bim->size;
717
718 return 0;
719 }
720
721 static void *
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)
727 {
728 return (void *)-1;
729 }
730
731 const struct bfd_iovec _bfd_memory_iovec =
732 {
733 &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
734 &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
735 };