]> Git Repo - binutils.git/blob - bfd/bfdio.c
Further correct the handling of long pathnames on Windows hosts.
[binutils.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 #endif
32
33 #ifndef S_IXUSR
34 #define S_IXUSR 0100    /* Execute by owner.  */
35 #endif
36 #ifndef S_IXGRP
37 #define S_IXGRP 0010    /* Execute by group.  */
38 #endif
39 #ifndef S_IXOTH
40 #define S_IXOTH 0001    /* Execute by others.  */
41 #endif
42
43 #ifndef FD_CLOEXEC
44 #define FD_CLOEXEC 1
45 #endif
46
47 file_ptr
48 _bfd_real_ftell (FILE *file)
49 {
50 #if defined (HAVE_FTELLO64)
51   return ftello64 (file);
52 #elif defined (HAVE_FTELLO)
53   return ftello (file);
54 #else
55   return ftell (file);
56 #endif
57 }
58
59 int
60 _bfd_real_fseek (FILE *file, file_ptr offset, int whence)
61 {
62 #if defined (HAVE_FSEEKO64)
63   return fseeko64 (file, offset, whence);
64 #elif defined (HAVE_FSEEKO)
65   return fseeko (file, offset, whence);
66 #else
67   return fseek (file, offset, whence);
68 #endif
69 }
70
71 /* Mark FILE as close-on-exec.  Return FILE.  FILE may be NULL, in
72    which case nothing is done.  */
73 static FILE *
74 close_on_exec (FILE *file)
75 {
76 #if defined (HAVE_FILENO) && defined (F_GETFD)
77   if (file)
78     {
79       int fd = fileno (file);
80       int old = fcntl (fd, F_GETFD, 0);
81       if (old >= 0)
82         fcntl (fd, F_SETFD, old | FD_CLOEXEC);
83     }
84 #endif
85   return file;
86 }
87
88 FILE *
89 _bfd_real_fopen (const char *filename, const char *modes)
90 {
91 #ifdef VMS
92   char *vms_attr;
93
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.
97      Split here.  */
98   vms_attr = strchr (modes, ',');
99   if (vms_attr != NULL)
100     {
101       /* Attributes found.  Split.  */
102       size_t modes_len = strlen (modes) + 1;
103       char attrs[modes_len + 1];
104       char *at[3];
105       int i;
106
107       memcpy (attrs, modes, modes_len);
108       at[0] = attrs;
109       for (i = 0; i < 2; i++)
110         {
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.  */
114         }
115       return close_on_exec (fopen (filename, at[0], at[1], at[2]));
116     }
117
118 #elif defined (_WIN32)
119   /* PR 25713: Handle extra long path names possibly containing '..' and '.'. */
120
121    wchar_t **lpFilePart = {NULL};
122    const wchar_t prefix[] = L"\\\\?\\";
123    const wchar_t ccs[] = L", ccs=UNICODE";
124    const size_t partPathLen = strlen(filename) + 1;
125
126    /* Converting the partial path from ascii to unicode.
127       1) get the length: Calling with lpWideCharStr set to null returns the length.
128       2) convert the string: Calling with cbMultiByte set to -1 includes the terminating null.  */
129    size_t partPathWSize = MultiByteToWideChar (CP_UTF8, 0, partPathOrig, -1, NULL, 0);
130    wchar_t *partPath = calloc (partPathWSize, sizeof(wchar_t));
131
132    MultiByteToWideChar (CP_UTF8, 0, partPathOrig, -1, partPath, partPathWSize);
133
134    /* Convert any UNIX style path separators into the DOS i.e. backslash separator.  */
135    size_t ix;
136    for (ix = 0; ix < partPathLen; ix++)
137      if (IS_UNIX_DIR_SEPARATOR(filename[ix]))
138        partPath[ix] = '\\';
139
140    /* Getting the full path from the provided partial path.
141       1) get the length:
142       2) resolve the path.  */
143    long fullPathWSize = GetFullPathNameW (partPath, 0, NULL, lpFilePart);
144    wchar_t *fullPath = calloc (fullPathWSize + sizeof(prefix) + 1, sizeof(wchar_t));
145
146    wcscpy (fullPath, prefix);
147    int prefixLen = sizeof(prefix) / sizeof(wchar_t);
148    wchar_t* fullPathOffset = fullPath + prefixLen - 1;
149    GetFullPathNameW (partPath, fullPathWSize, fullPathOffset, lpFilePart);
150    free (partPath);
151
152    /* It is non-standard for modes to exceed 16 characters.  */
153    wchar_t modesW[16 + sizeof(ccs)];
154    MultiByteToWideChar (CP_UTF8, 0, modes, -1, modesW, sizeof(modesW));
155    wcscat (modesW, ccs);
156
157    FILE* file = _wfopen (fullPath, mdesW);
158    free (fullPath);
159
160    return close_on_exec (file);
161
162 #elif defined (HAVE_FOPEN64)
163   return close_on_exec (fopen64 (filename, modes));
164
165 #else
166   return close_on_exec (fopen (filename, modes));
167 #endif
168 }
169
170 /*
171 INTERNAL_DEFINITION
172         struct bfd_iovec
173
174 DESCRIPTION
175
176         The <<struct bfd_iovec>> contains the internal file I/O class.
177         Each <<BFD>> has an instance of this class and all file I/O is
178         routed through it (it is assumed that the instance implements
179         all methods listed below).
180
181 .struct bfd_iovec
182 .{
183 .  {* To avoid problems with macros, a "b" rather than "f"
184 .     prefix is prepended to each method name.  *}
185 .  {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
186 .     bytes starting at PTR.  Return the number of bytes actually
187 .     transfered (a read past end-of-file returns less than NBYTES),
188 .     or -1 (setting <<bfd_error>>) if an error occurs.  *}
189 .  file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
190 .  file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
191 .                      file_ptr nbytes);
192 .  {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
193 .     if an error occurs.  *}
194 .  file_ptr (*btell) (struct bfd *abfd);
195 .  {* For the following, on successful completion a value of 0 is returned.
196 .     Otherwise, a value of -1 is returned (and <<bfd_error>> is set).  *}
197 .  int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
198 .  int (*bclose) (struct bfd *abfd);
199 .  int (*bflush) (struct bfd *abfd);
200 .  int (*bstat) (struct bfd *abfd, struct stat *sb);
201 .  {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual
202 .     mmap parameter, except that LEN and OFFSET do not need to be page
203 .     aligned.  Returns (void *)-1 on failure, mmapped address on success.
204 .     Also write in MAP_ADDR the address of the page aligned buffer and in
205 .     MAP_LEN the size mapped (a page multiple).  Use unmap with MAP_ADDR and
206 .     MAP_LEN to unmap.  *}
207 .  void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
208 .                  int prot, int flags, file_ptr offset,
209 .                  void **map_addr, bfd_size_type *map_len);
210 .};
211
212 .extern const struct bfd_iovec _bfd_memory_iovec;
213
214 */
215
216
217 /* Return value is amount read.  */
218
219 bfd_size_type
220 bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
221 {
222   file_ptr nread;
223   bfd *element_bfd = abfd;
224   ufile_ptr offset = 0;
225
226   while (abfd->my_archive != NULL
227          && !bfd_is_thin_archive (abfd->my_archive))
228     {
229       offset += abfd->origin;
230       abfd = abfd->my_archive;
231     }
232   offset += abfd->origin;
233
234   /* If this is a non-thin archive element, don't read past the end of
235      this element.  */
236   if (element_bfd->arelt_data != NULL
237       && element_bfd->my_archive != NULL
238       && !bfd_is_thin_archive (element_bfd->my_archive))
239     {
240       bfd_size_type maxbytes = arelt_size (element_bfd);
241
242       if (abfd->where < offset || abfd->where - offset >= maxbytes)
243         {
244           bfd_set_error (bfd_error_invalid_operation);
245           return -1;
246         }
247       if (abfd->where - offset + size > maxbytes)
248         size = maxbytes - (abfd->where - offset);
249     }
250
251   if (abfd->iovec == NULL)
252     {
253       bfd_set_error (bfd_error_invalid_operation);
254       return -1;
255     }
256
257   nread = abfd->iovec->bread (abfd, ptr, size);
258   if (nread != -1)
259     abfd->where += nread;
260
261   return nread;
262 }
263
264 bfd_size_type
265 bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
266 {
267   file_ptr nwrote;
268
269   while (abfd->my_archive != NULL
270          && !bfd_is_thin_archive (abfd->my_archive))
271     abfd = abfd->my_archive;
272
273   if (abfd->iovec == NULL)
274     {
275       bfd_set_error (bfd_error_invalid_operation);
276       return -1;
277     }
278
279   nwrote = abfd->iovec->bwrite (abfd, ptr, size);
280   if (nwrote != -1)
281     abfd->where += nwrote;
282   if ((bfd_size_type) nwrote != size)
283     {
284 #ifdef ENOSPC
285       errno = ENOSPC;
286 #endif
287       bfd_set_error (bfd_error_system_call);
288     }
289   return nwrote;
290 }
291
292 file_ptr
293 bfd_tell (bfd *abfd)
294 {
295   ufile_ptr offset = 0;
296   file_ptr ptr;
297
298   while (abfd->my_archive != NULL
299          && !bfd_is_thin_archive (abfd->my_archive))
300     {
301       offset += abfd->origin;
302       abfd = abfd->my_archive;
303     }
304   offset += abfd->origin;
305
306   if (abfd->iovec == NULL)
307     return 0;
308
309   ptr = abfd->iovec->btell (abfd);
310   abfd->where = ptr;
311   return ptr - offset;
312 }
313
314 int
315 bfd_flush (bfd *abfd)
316 {
317   while (abfd->my_archive != NULL
318          && !bfd_is_thin_archive (abfd->my_archive))
319     abfd = abfd->my_archive;
320
321   if (abfd->iovec == NULL)
322     return 0;
323
324   return abfd->iovec->bflush (abfd);
325 }
326
327 /* Returns 0 for success, negative value for failure (in which case
328    bfd_get_error can retrieve the error code).  */
329 int
330 bfd_stat (bfd *abfd, struct stat *statbuf)
331 {
332   int result;
333
334   while (abfd->my_archive != NULL
335          && !bfd_is_thin_archive (abfd->my_archive))
336     abfd = abfd->my_archive;
337
338   if (abfd->iovec == NULL)
339     {
340       bfd_set_error (bfd_error_invalid_operation);
341       return -1;
342     }
343
344   result = abfd->iovec->bstat (abfd, statbuf);
345   if (result < 0)
346     bfd_set_error (bfd_error_system_call);
347   return result;
348 }
349
350 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
351    can retrieve the error code).  */
352
353 int
354 bfd_seek (bfd *abfd, file_ptr position, int direction)
355 {
356   int result;
357   ufile_ptr offset = 0;
358
359   while (abfd->my_archive != NULL
360          && !bfd_is_thin_archive (abfd->my_archive))
361     {
362       offset += abfd->origin;
363       abfd = abfd->my_archive;
364     }
365   offset += abfd->origin;
366
367   if (abfd->iovec == NULL)
368     {
369       bfd_set_error (bfd_error_invalid_operation);
370       return -1;
371     }
372
373   /* For the time being, a BFD may not seek to it's end.  The problem
374      is that we don't easily have a way to recognize the end of an
375      element in an archive.  */
376   BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
377
378   if (direction != SEEK_CUR)
379     position += offset;
380
381   if ((direction == SEEK_CUR && position == 0)
382       || (direction == SEEK_SET && (ufile_ptr) position == abfd->where))
383     return 0;
384
385   result = abfd->iovec->bseek (abfd, position, direction);
386   if (result != 0)
387     {
388       /* An EINVAL error probably means that the file offset was
389          absurd.  */
390       if (errno == EINVAL)
391         bfd_set_error (bfd_error_file_truncated);
392       else
393         bfd_set_error (bfd_error_system_call);
394     }
395   else
396     {
397       /* Adjust `where' field.  */
398       if (direction == SEEK_CUR)
399         abfd->where += position;
400       else
401         abfd->where = position;
402     }
403
404   return result;
405 }
406
407 /*
408 FUNCTION
409         bfd_get_mtime
410
411 SYNOPSIS
412         long bfd_get_mtime (bfd *abfd);
413
414 DESCRIPTION
415         Return the file modification time (as read from the file system, or
416         from the archive header for archive members).
417
418 */
419
420 long
421 bfd_get_mtime (bfd *abfd)
422 {
423   struct stat buf;
424
425   if (abfd->mtime_set)
426     return abfd->mtime;
427
428   if (bfd_stat (abfd, &buf) != 0)
429     return 0;
430
431   abfd->mtime = buf.st_mtime;           /* Save value in case anyone wants it */
432   return buf.st_mtime;
433 }
434
435 /*
436 FUNCTION
437         bfd_get_size
438
439 SYNOPSIS
440         ufile_ptr bfd_get_size (bfd *abfd);
441
442 DESCRIPTION
443         Return the file size (as read from file system) for the file
444         associated with BFD @var{abfd}.
445
446         The initial motivation for, and use of, this routine is not
447         so we can get the exact size of the object the BFD applies to, since
448         that might not be generally possible (archive members for example).
449         It would be ideal if someone could eventually modify
450         it so that such results were guaranteed.
451
452         Instead, we want to ask questions like "is this NNN byte sized
453         object I'm about to try read from file offset YYY reasonable?"
454         As as example of where we might do this, some object formats
455         use string tables for which the first <<sizeof (long)>> bytes of the
456         table contain the size of the table itself, including the size bytes.
457         If an application tries to read what it thinks is one of these
458         string tables, without some way to validate the size, and for
459         some reason the size is wrong (byte swapping error, wrong location
460         for the string table, etc.), the only clue is likely to be a read
461         error when it tries to read the table, or a "virtual memory
462         exhausted" error when it tries to allocate 15 bazillon bytes
463         of space for the 15 bazillon byte table it is about to read.
464         This function at least allows us to answer the question, "is the
465         size reasonable?".
466
467         A return value of zero indicates the file size is unknown.
468 */
469
470 ufile_ptr
471 bfd_get_size (bfd *abfd)
472 {
473   /* A size of 0 means we haven't yet called bfd_stat.  A size of 1
474      means we have a cached value of 0, ie. unknown.  */
475   if (abfd->size <= 1 || bfd_write_p (abfd))
476     {
477       struct stat buf;
478
479       if (abfd->size == 1 && !bfd_write_p (abfd))
480         return 0;
481
482       if (bfd_stat (abfd, &buf) != 0
483           || buf.st_size == 0
484           || buf.st_size - (ufile_ptr) buf.st_size != 0)
485         {
486           abfd->size = 1;
487           return 0;
488         }
489       abfd->size = buf.st_size;
490     }
491   return abfd->size;
492 }
493
494 /*
495 FUNCTION
496         bfd_get_file_size
497
498 SYNOPSIS
499         ufile_ptr bfd_get_file_size (bfd *abfd);
500
501 DESCRIPTION
502         Return the file size (as read from file system) for the file
503         associated with BFD @var{abfd}.  It supports both normal files
504         and archive elements.
505
506 */
507
508 ufile_ptr
509 bfd_get_file_size (bfd *abfd)
510 {
511   ufile_ptr file_size, archive_size = (ufile_ptr) -1;
512
513   if (abfd->my_archive != NULL
514       && !bfd_is_thin_archive (abfd->my_archive))
515     {
516       struct areltdata *adata = (struct areltdata *) abfd->arelt_data;
517       if (adata != NULL)
518         {
519           archive_size = adata->parsed_size;
520           /* If the archive is compressed we can't compare against
521              file size.  */
522           if (adata->arch_header != NULL
523               && memcmp (((struct ar_hdr *) adata->arch_header)->ar_fmag,
524                          "Z\012", 2) == 0)
525             return archive_size;
526           abfd = abfd->my_archive;
527         }
528     }
529
530   file_size = bfd_get_size (abfd);
531   if (archive_size < file_size)
532     return archive_size;
533   return file_size;
534 }
535
536 /*
537 FUNCTION
538         bfd_mmap
539
540 SYNOPSIS
541         void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
542                         int prot, int flags, file_ptr offset,
543                         void **map_addr, bfd_size_type *map_len);
544
545 DESCRIPTION
546         Return mmap()ed region of the file, if possible and implemented.
547         LEN and OFFSET do not need to be page aligned.  The page aligned
548         address and length are written to MAP_ADDR and MAP_LEN.
549
550 */
551
552 void *
553 bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
554           int prot, int flags, file_ptr offset,
555           void **map_addr, bfd_size_type *map_len)
556 {
557   while (abfd->my_archive != NULL
558          && !bfd_is_thin_archive (abfd->my_archive))
559     {
560       offset += abfd->origin;
561       abfd = abfd->my_archive;
562     }
563   offset += abfd->origin;
564
565   if (abfd->iovec == NULL)
566     {
567       bfd_set_error (bfd_error_invalid_operation);
568       return (void *) -1;
569     }
570
571   return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset,
572                              map_addr, map_len);
573 }
574
575 /* Memory file I/O operations.  */
576
577 static file_ptr
578 memory_bread (bfd *abfd, void *ptr, file_ptr size)
579 {
580   struct bfd_in_memory *bim;
581   bfd_size_type get;
582
583   bim = (struct bfd_in_memory *) abfd->iostream;
584   get = size;
585   if (abfd->where + get > bim->size)
586     {
587       if (bim->size < (bfd_size_type) abfd->where)
588         get = 0;
589       else
590         get = bim->size - abfd->where;
591       bfd_set_error (bfd_error_file_truncated);
592     }
593   memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
594   return get;
595 }
596
597 static file_ptr
598 memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
599 {
600   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
601
602   if (abfd->where + size > bim->size)
603     {
604       bfd_size_type newsize, oldsize;
605
606       oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
607       bim->size = abfd->where + size;
608       /* Round up to cut down on memory fragmentation */
609       newsize = (bim->size + 127) & ~(bfd_size_type) 127;
610       if (newsize > oldsize)
611         {
612           bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
613           if (bim->buffer == NULL)
614             {
615               bim->size = 0;
616               return 0;
617             }
618           if (newsize > bim->size)
619             memset (bim->buffer + bim->size, 0, newsize - bim->size);
620         }
621     }
622   memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
623   return size;
624 }
625
626 static file_ptr
627 memory_btell (bfd *abfd)
628 {
629   return abfd->where;
630 }
631
632 static int
633 memory_bseek (bfd *abfd, file_ptr position, int direction)
634 {
635   file_ptr nwhere;
636   struct bfd_in_memory *bim;
637
638   bim = (struct bfd_in_memory *) abfd->iostream;
639
640   if (direction == SEEK_SET)
641     nwhere = position;
642   else
643     nwhere = abfd->where + position;
644
645   if (nwhere < 0)
646     {
647       abfd->where = 0;
648       errno = EINVAL;
649       return -1;
650     }
651
652   if ((bfd_size_type)nwhere > bim->size)
653     {
654       if (abfd->direction == write_direction
655           || abfd->direction == both_direction)
656         {
657           bfd_size_type newsize, oldsize;
658
659           oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
660           bim->size = nwhere;
661           /* Round up to cut down on memory fragmentation */
662           newsize = (bim->size + 127) & ~(bfd_size_type) 127;
663           if (newsize > oldsize)
664             {
665               bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
666               if (bim->buffer == NULL)
667                 {
668                   errno = EINVAL;
669                   bim->size = 0;
670                   return -1;
671                 }
672               memset (bim->buffer + oldsize, 0, newsize - oldsize);
673             }
674         }
675       else
676         {
677           abfd->where = bim->size;
678           errno = EINVAL;
679           bfd_set_error (bfd_error_file_truncated);
680           return -1;
681         }
682     }
683   return 0;
684 }
685
686 static int
687 memory_bclose (struct bfd *abfd)
688 {
689   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
690
691   free (bim->buffer);
692   free (bim);
693   abfd->iostream = NULL;
694
695   return 0;
696 }
697
698 static int
699 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
700 {
701   return 0;
702 }
703
704 static int
705 memory_bstat (bfd *abfd, struct stat *statbuf)
706 {
707   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
708
709   memset (statbuf, 0, sizeof (*statbuf));
710   statbuf->st_size = bim->size;
711
712   return 0;
713 }
714
715 static void *
716 memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
717               bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
718               int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED,
719               void **map_addr ATTRIBUTE_UNUSED,
720               bfd_size_type *map_len ATTRIBUTE_UNUSED)
721 {
722   return (void *)-1;
723 }
724
725 const struct bfd_iovec _bfd_memory_iovec =
726 {
727   &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
728   &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
729 };
This page took 0.068498 seconds and 4 git commands to generate.