Coverage Report

Created: 2024-05-21 06:29

/src/binutils-gdb/bfd/bfdio.c
Line
Count
Source (jump to first uncovered line)
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
5.55M
{
51
5.55M
#if defined (HAVE_FTELLO64)
52
5.55M
  return ftello64 (file);
53
#elif defined (HAVE_FTELLO)
54
  return ftello (file);
55
#else
56
  return ftell (file);
57
#endif
58
5.55M
}
59
60
int
61
_bfd_real_fseek (FILE *file, file_ptr offset, int whence)
62
502M
{
63
502M
#if defined (HAVE_FSEEKO64)
64
502M
  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
502M
}
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
110k
{
77
110k
#if defined (HAVE_FILENO) && defined (F_GETFD)
78
110k
  if (file)
79
109k
    {
80
109k
      int fd = fileno (file);
81
109k
      int old = fcntl (fd, F_GETFD, 0);
82
109k
      if (old >= 0)
83
109k
  fcntl (fd, F_SETFD, old | FD_CLOEXEC);
84
109k
    }
85
110k
#endif
86
110k
  return file;
87
110k
}
88
89
FILE *
90
_bfd_real_fopen (const char *filename, const char *modes)
91
110k
{
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
110k
}
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
614M
{
326
614M
  file_ptr nread;
327
614M
  bfd *element_bfd = abfd;
328
614M
  ufile_ptr offset = 0;
329
330
1.14G
  while (abfd->my_archive != NULL
331
1.14G
   && !bfd_is_thin_archive (abfd->my_archive))
332
534M
    {
333
534M
      offset += abfd->origin;
334
534M
      abfd = abfd->my_archive;
335
534M
    }
336
614M
  offset += abfd->origin;
337
338
  /* If this is a non-thin archive element, don't read past the end of
339
     this element.  */
340
614M
  if (element_bfd->arelt_data != NULL
341
614M
      && element_bfd->my_archive != NULL
342
614M
      && !bfd_is_thin_archive (element_bfd->my_archive))
343
533M
    {
344
533M
      bfd_size_type maxbytes = arelt_size (element_bfd);
345
346
533M
      if (abfd->where < offset || abfd->where - offset >= maxbytes)
347
1.29M
  {
348
1.29M
    bfd_set_error (bfd_error_invalid_operation);
349
1.29M
    return -1;
350
1.29M
  }
351
532M
      if (abfd->where - offset + size > maxbytes)
352
3.24M
  size = maxbytes - (abfd->where - offset);
353
532M
    }
354
355
613M
  if (abfd->iovec == NULL)
356
0
    {
357
0
      bfd_set_error (bfd_error_invalid_operation);
358
0
      return -1;
359
0
    }
360
361
613M
  if (abfd->last_io == bfd_io_write)
362
0
    {
363
0
      abfd->last_io = bfd_io_force;
364
0
      if (bfd_seek (abfd, 0, SEEK_CUR) != 0)
365
0
  return -1;
366
0
    }
367
613M
  abfd->last_io = bfd_io_read;
368
369
613M
  nread = abfd->iovec->bread (abfd, ptr, size);
370
613M
  if (nread != -1)
371
613M
    abfd->where += nread;
372
373
613M
  return nread;
374
613M
}
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
25.8k
{
392
25.8k
  file_ptr nwrote;
393
394
25.8k
  while (abfd->my_archive != NULL
395
25.8k
   && !bfd_is_thin_archive (abfd->my_archive))
396
0
    abfd = abfd->my_archive;
397
398
25.8k
  if (abfd->iovec == NULL)
399
0
    {
400
0
      bfd_set_error (bfd_error_invalid_operation);
401
0
      return -1;
402
0
    }
403
404
25.8k
  if (abfd->last_io == bfd_io_read)
405
1
    {
406
1
      abfd->last_io = bfd_io_force;
407
1
      if (bfd_seek (abfd, 0, SEEK_CUR) != 0)
408
0
  return -1;
409
1
    }
410
25.8k
  abfd->last_io = bfd_io_write;
411
412
25.8k
  nwrote = abfd->iovec->bwrite (abfd, ptr, size);
413
25.8k
  if (nwrote != -1)
414
25.8k
    abfd->where += nwrote;
415
25.8k
  if ((bfd_size_type) nwrote != size)
416
0
    {
417
0
#ifdef ENOSPC
418
0
      errno = ENOSPC;
419
0
#endif
420
0
      bfd_set_error (bfd_error_system_call);
421
0
    }
422
25.8k
  return nwrote;
423
25.8k
}
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
5.55M
{
439
5.55M
  ufile_ptr offset = 0;
440
5.55M
  file_ptr ptr;
441
442
7.36M
  while (abfd->my_archive != NULL
443
7.36M
   && !bfd_is_thin_archive (abfd->my_archive))
444
1.80M
    {
445
1.80M
      offset += abfd->origin;
446
1.80M
      abfd = abfd->my_archive;
447
1.80M
    }
448
5.55M
  offset += abfd->origin;
449
450
5.55M
  if (abfd->iovec == NULL)
451
0
    return 0;
452
453
5.55M
  ptr = abfd->iovec->btell (abfd);
454
5.55M
  abfd->where = ptr;
455
5.55M
  return ptr - offset;
456
5.55M
}
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
1.84k
{
472
1.84k
  while (abfd->my_archive != NULL
473
1.84k
   && !bfd_is_thin_archive (abfd->my_archive))
474
0
    abfd = abfd->my_archive;
475
476
1.84k
  if (abfd->iovec == NULL)
477
0
    return 0;
478
479
1.84k
  return abfd->iovec->bflush (abfd);
480
1.84k
}
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
30.8M
{
497
30.8M
  int result;
498
499
34.1M
  while (abfd->my_archive != NULL
500
34.1M
   && !bfd_is_thin_archive (abfd->my_archive))
501
3.22M
    abfd = abfd->my_archive;
502
503
30.8M
  if (abfd->iovec == NULL)
504
0
    {
505
0
      bfd_set_error (bfd_error_invalid_operation);
506
0
      return -1;
507
0
    }
508
509
30.8M
  result = abfd->iovec->bstat (abfd, statbuf);
510
30.8M
  if (result < 0)
511
0
    bfd_set_error (bfd_error_system_call);
512
30.8M
  return result;
513
30.8M
}
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
572M
{
530
572M
  int result;
531
572M
  ufile_ptr offset = 0;
532
533
1.08G
  while (abfd->my_archive != NULL
534
1.08G
   && !bfd_is_thin_archive (abfd->my_archive))
535
507M
    {
536
507M
      offset += abfd->origin;
537
507M
      abfd = abfd->my_archive;
538
507M
    }
539
572M
  offset += abfd->origin;
540
541
572M
  if (abfd->iovec == NULL)
542
0
    {
543
0
      bfd_set_error (bfd_error_invalid_operation);
544
0
      return -1;
545
0
    }
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
572M
  BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
551
552
572M
  if (direction != SEEK_CUR)
553
563M
    position += offset;
554
555
572M
  if (((direction == SEEK_CUR && position == 0)
556
572M
       || (direction == SEEK_SET && (ufile_ptr) position == abfd->where))
557
572M
      && abfd->last_io != bfd_io_force)
558
70.6M
    return 0;
559
560
502M
  abfd->last_io = bfd_io_seek;
561
562
502M
  result = abfd->iovec->bseek (abfd, position, direction);
563
502M
  if (result != 0)
564
87.6k
    {
565
      /* An EINVAL error probably means that the file offset was
566
   absurd.  */
567
87.6k
      if (errno == EINVAL)
568
87.6k
  bfd_set_error (bfd_error_file_truncated);
569
0
      else
570
0
  bfd_set_error (bfd_error_system_call);
571
87.6k
    }
572
502M
  else
573
502M
    {
574
      /* Adjust `where' field.  */
575
502M
      if (direction == SEEK_CUR)
576
8.95M
  abfd->where += position;
577
493M
      else
578
493M
  abfd->where = position;
579
502M
    }
580
581
502M
  return result;
582
572M
}
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
0
{
600
0
  struct stat buf;
601
602
0
  if (abfd->mtime_set)
603
0
    return abfd->mtime;
604
605
0
  if (bfd_stat (abfd, &buf) != 0)
606
0
    return 0;
607
608
0
  abfd->mtime = buf.st_mtime;   /* Save value in case anyone wants it */
609
0
  return buf.st_mtime;
610
0
}
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
79.3M
{
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
79.3M
  if (abfd->size <= 1 || bfd_write_p (abfd))
653
27.5M
    {
654
27.5M
      struct stat buf;
655
656
27.5M
      if (abfd->size == 1 && !bfd_write_p (abfd))
657
286
  return 0;
658
659
27.5M
      if (bfd_stat (abfd, &buf) != 0
660
27.5M
    || buf.st_size == 0
661
27.5M
    || buf.st_size - (ufile_ptr) buf.st_size != 0)
662
0
  {
663
0
    abfd->size = 1;
664
0
    return 0;
665
0
  }
666
27.5M
      abfd->size = buf.st_size;
667
27.5M
    }
668
79.3M
  return abfd->size;
669
79.3M
}
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
79.3M
{
688
79.3M
  ufile_ptr file_size, archive_size = (ufile_ptr) -1;
689
79.3M
  unsigned int compression_p2 = 0;
690
691
79.3M
  if (abfd->my_archive != NULL
692
79.3M
      && !bfd_is_thin_archive (abfd->my_archive))
693
68.0M
    {
694
68.0M
      struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
695
68.0M
      if (adata != NULL)
696
68.0M
  {
697
68.0M
    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
68.0M
    if (adata->arch_header != NULL
701
68.0M
        && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
702
68.0M
       "Z\012", 2) == 0)
703
2.79k
      compression_p2 = 3;
704
68.0M
    abfd = abfd->my_archive;
705
68.0M
  }
706
68.0M
    }
707
708
79.3M
  file_size = bfd_get_size (abfd) << compression_p2;
709
79.3M
  if (archive_size < file_size)
710
3.46M
    return archive_size;
711
75.8M
  return file_size;
712
79.3M
}
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
426
{
736
426
  while (abfd->my_archive != NULL
737
426
   && !bfd_is_thin_archive (abfd->my_archive))
738
0
    {
739
0
      offset += abfd->origin;
740
0
      abfd = abfd->my_archive;
741
0
    }
742
426
  offset += abfd->origin;
743
744
426
  if (abfd->iovec == NULL)
745
0
    {
746
0
      bfd_set_error (bfd_error_invalid_operation);
747
0
      return MAP_FAILED;
748
0
    }
749
750
426
  return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
751
426
           map_addr, map_len);
752
426
}
753
754
/* Memory file I/O operations.  */
755
756
static file_ptr
757
memory_bread (bfd *abfd, void *ptr, file_ptr size)
758
0
{
759
0
  struct bfd_in_memory *bim;
760
0
  bfd_size_type get;
761
762
0
  bim = (struct bfd_in_memory *) abfd->iostream;
763
0
  get = size;
764
0
  if (abfd->where + get > bim->size)
765
0
    {
766
0
      if (bim->size < (bfd_size_type) abfd->where)
767
0
  get = 0;
768
0
      else
769
0
  get = bim->size - abfd->where;
770
0
      bfd_set_error (bfd_error_file_truncated);
771
0
    }
772
0
  memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
773
0
  return get;
774
0
}
775
776
static file_ptr
777
memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
778
243
{
779
243
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
780
781
243
  if (abfd->where + size > bim->size)
782
243
    {
783
243
      bfd_size_type newsize, oldsize;
784
785
243
      oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
786
243
      bim->size = abfd->where + size;
787
      /* Round up to cut down on memory fragmentation */
788
243
      newsize = (bim->size + 127) & ~(bfd_size_type) 127;
789
243
      if (newsize > oldsize)
790
243
  {
791
243
    bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
792
243
    if (bim->buffer == NULL)
793
0
      {
794
0
        bim->size = 0;
795
0
        return 0;
796
0
      }
797
243
    if (newsize > bim->size)
798
82
      memset (bim->buffer + bim->size, 0, newsize - bim->size);
799
243
  }
800
243
    }
801
243
  memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
802
243
  return size;
803
243
}
804
805
static file_ptr
806
memory_btell (bfd *abfd)
807
0
{
808
0
  return abfd->where;
809
0
}
810
811
static int
812
memory_bseek (bfd *abfd, file_ptr position, int direction)
813
0
{
814
0
  file_ptr nwhere;
815
0
  struct bfd_in_memory *bim;
816
817
0
  bim = (struct bfd_in_memory *) abfd->iostream;
818
819
0
  if (direction == SEEK_SET)
820
0
    nwhere = position;
821
0
  else
822
0
    nwhere = abfd->where + position;
823
824
0
  if (nwhere < 0)
825
0
    {
826
0
      abfd->where = 0;
827
0
      errno = EINVAL;
828
0
      return -1;
829
0
    }
830
831
0
  if ((bfd_size_type)nwhere > bim->size)
832
0
    {
833
0
      if (abfd->direction == write_direction
834
0
    || abfd->direction == both_direction)
835
0
  {
836
0
    bfd_size_type newsize, oldsize;
837
838
0
    oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
839
0
    bim->size = nwhere;
840
    /* Round up to cut down on memory fragmentation */
841
0
    newsize = (bim->size + 127) & ~(bfd_size_type) 127;
842
0
    if (newsize > oldsize)
843
0
      {
844
0
        bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
845
0
        if (bim->buffer == NULL)
846
0
    {
847
0
      errno = EINVAL;
848
0
      bim->size = 0;
849
0
      return -1;
850
0
    }
851
0
        memset (bim->buffer + oldsize, 0, newsize - oldsize);
852
0
      }
853
0
  }
854
0
      else
855
0
  {
856
0
    abfd->where = bim->size;
857
0
    errno = EINVAL;
858
0
    bfd_set_error (bfd_error_file_truncated);
859
0
    return -1;
860
0
  }
861
0
    }
862
0
  return 0;
863
0
}
864
865
static int
866
memory_bclose (struct bfd *abfd)
867
20.7k
{
868
20.7k
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
869
870
20.7k
  free (bim->buffer);
871
20.7k
  free (bim);
872
20.7k
  abfd->iostream = NULL;
873
874
20.7k
  return 0;
875
20.7k
}
876
877
static int
878
memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
879
0
{
880
0
  return 0;
881
0
}
882
883
static int
884
memory_bstat (bfd *abfd, struct stat *statbuf)
885
11
{
886
11
  struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
887
888
11
  memset (statbuf, 0, sizeof (*statbuf));
889
11
  statbuf->st_size = bim->size;
890
891
11
  return 0;
892
11
}
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
0
{
901
0
  return (void *)-1;
902
0
}
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
1
{
930
1
  char *source_date_epoch;
931
1
  unsigned long long epoch;
932
933
  /* FIXME: We could probably cache this lookup,
934
     and the parsing of its value below.  */
935
1
  source_date_epoch = getenv ("SOURCE_DATE_EPOCH");
936
937
1
  if (source_date_epoch == NULL)
938
1
    {
939
1
      if (now)
940
0
  return now;
941
1
      return time (NULL);
942
1
    }
943
944
0
  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
0
  return (time_t) epoch;
952
1
}