* bfdio.c (memory_bstat): Pass correct size to memset.
[platform/upstream/binutils.git] / bfd / bfdio.c
1 /* Low-level I/O routines for BFDs.
2
3    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
5    Free Software Foundation, Inc.
6
7    Written by Cygnus Support.
8
9    This file is part of BFD, the Binary File Descriptor library.
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
24    MA 02110-1301, USA.  */
25
26 #include "sysdep.h"
27 #include <limits.h>
28 #include "bfd.h"
29 #include "libbfd.h"
30
31 #ifndef S_IXUSR
32 #define S_IXUSR 0100    /* Execute by owner.  */
33 #endif
34 #ifndef S_IXGRP
35 #define S_IXGRP 0010    /* Execute by group.  */
36 #endif
37 #ifndef S_IXOTH
38 #define S_IXOTH 0001    /* Execute by others.  */
39 #endif
40
41 #ifndef FD_CLOEXEC
42 #define FD_CLOEXEC 1
43 #endif
44
45 file_ptr
46 real_ftell (FILE *file)
47 {
48 #if defined (HAVE_FTELLO64)
49   return ftello64 (file);
50 #elif defined (HAVE_FTELLO)
51   return ftello (file);
52 #else
53   return ftell (file);
54 #endif
55 }
56
57 int
58 real_fseek (FILE *file, file_ptr offset, int whence)
59 {
60 #if defined (HAVE_FSEEKO64)
61   return fseeko64 (file, offset, whence);
62 #elif defined (HAVE_FSEEKO)
63   return fseeko (file, offset, whence);
64 #else
65   return fseek (file, offset, whence);
66 #endif
67 }
68
69 /* Mark FILE as close-on-exec.  Return FILE.  FILE may be NULL, in
70    which case nothing is done.  */
71 static FILE *
72 close_on_exec (FILE *file)
73 {
74 #if defined (HAVE_FILENO) && defined (F_GETFD)
75   if (file)
76     {
77       int fd = fileno (file);
78       int old = fcntl (fd, F_GETFD, 0);
79       if (old >= 0)
80         fcntl (fd, F_SETFD, old | FD_CLOEXEC);
81     }
82 #endif
83   return file;
84 }
85
86 FILE *
87 real_fopen (const char *filename, const char *modes)
88 {
89 #ifdef VMS
90   char vms_modes[4];
91   char *vms_attr;
92
93   /* On VMS, fopen allows file attributes as optionnal arguments.
94      We need to use them but we'd better to use the common prototype.
95      In fopen-vms.h, they are separated from the mode with a comma.
96      Split here.  */
97   vms_attr = strchr (modes, ',');
98   if (vms_attr == NULL)
99     {
100       /* No attributes.  */
101       return close_on_exec (fopen (filename, modes));
102     }
103   else
104     {
105       /* Attributes found.  Split.  */
106       size_t modes_len = strlen (modes) + 1;
107       char attrs[modes_len + 1];
108       char *at[3];
109       int i;
110
111       memcpy (attrs, modes, modes_len);
112       at[0] = attrs;
113       for (i = 0; i < 2; i++)
114         {
115           at[i + 1] = strchr (at[i], ',');
116           BFD_ASSERT (at[i + 1] != NULL);
117           *(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it.  */
118         }
119       return close_on_exec (fopen (filename, at[0], at[1], at[2]));
120     }
121 #else /* !VMS */
122 #if defined (HAVE_FOPEN64)
123   return close_on_exec (fopen64 (filename, modes));
124 #else
125   return close_on_exec (fopen (filename, modes));
126 #endif
127 #endif /* !VMS */
128 }
129
130 /*
131 INTERNAL_DEFINITION
132         struct bfd_iovec
133
134 DESCRIPTION
135
136         The <<struct bfd_iovec>> contains the internal file I/O class.
137         Each <<BFD>> has an instance of this class and all file I/O is
138         routed through it (it is assumed that the instance implements
139         all methods listed below).
140
141 .struct bfd_iovec
142 .{
143 .  {* To avoid problems with macros, a "b" rather than "f"
144 .     prefix is prepended to each method name.  *}
145 .  {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
146 .     bytes starting at PTR.  Return the number of bytes actually
147 .     transfered (a read past end-of-file returns less than NBYTES),
148 .     or -1 (setting <<bfd_error>>) if an error occurs.  *}
149 .  file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
150 .  file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
151 .                      file_ptr nbytes);
152 .  {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
153 .     if an error occurs.  *}
154 .  file_ptr (*btell) (struct bfd *abfd);
155 .  {* For the following, on successful completion a value of 0 is returned.
156 .     Otherwise, a value of -1 is returned (and  <<bfd_error>> is set).  *}
157 .  int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
158 .  int (*bclose) (struct bfd *abfd);
159 .  int (*bflush) (struct bfd *abfd);
160 .  int (*bstat) (struct bfd *abfd, struct stat *sb);
161 .  {* Just like mmap: (void*)-1 on failure, mmapped address on success.  *}
162 .  void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len,
163 .                  int prot, int flags, file_ptr offset);
164 .};
165
166 .extern const struct bfd_iovec _bfd_memory_iovec;
167
168 */
169
170
171 /* Return value is amount read.  */
172
173 bfd_size_type
174 bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
175 {
176   size_t nread;
177
178   /* If this is an archive element, don't read past the end of
179      this element.  */
180   if (abfd->arelt_data != NULL)
181     {
182       size_t maxbytes = ((struct areltdata *) abfd->arelt_data)->parsed_size;
183       if (abfd->where + size > maxbytes)
184         {
185           if (abfd->where >= maxbytes)
186             return 0;
187           size = maxbytes - abfd->where;
188         }
189     }
190
191   if (abfd->iovec)
192     nread = abfd->iovec->bread (abfd, ptr, size);
193   else
194     nread = 0;
195   if (nread != (size_t) -1)
196     abfd->where += nread;
197
198   return nread;
199 }
200
201 bfd_size_type
202 bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
203 {
204   size_t nwrote;
205
206   if (abfd->iovec)
207     nwrote = abfd->iovec->bwrite (abfd, ptr, size);
208   else
209     nwrote = 0;
210
211   if (nwrote != (size_t) -1)
212     abfd->where += nwrote;
213   if (nwrote != size)
214     {
215 #ifdef ENOSPC
216       errno = ENOSPC;
217 #endif
218       bfd_set_error (bfd_error_system_call);
219     }
220   return nwrote;
221 }
222
223 file_ptr
224 bfd_tell (bfd *abfd)
225 {
226   file_ptr ptr;
227
228   if (abfd->iovec)
229     {
230       ptr = abfd->iovec->btell (abfd);
231
232       if (abfd->my_archive)
233         ptr -= abfd->origin;
234     }
235   else
236     ptr = 0;
237
238   abfd->where = ptr;
239   return ptr;
240 }
241
242 int
243 bfd_flush (bfd *abfd)
244 {
245   if (abfd->iovec)
246     return abfd->iovec->bflush (abfd);
247   return 0;
248 }
249
250 /* Returns 0 for success, negative value for failure (in which case
251    bfd_get_error can retrieve the error code).  */
252 int
253 bfd_stat (bfd *abfd, struct stat *statbuf)
254 {
255   int result;
256
257   if (abfd->iovec)
258     result = abfd->iovec->bstat (abfd, statbuf);
259   else
260     result = -1;
261
262   if (result < 0)
263     bfd_set_error (bfd_error_system_call);
264   return result;
265 }
266
267 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
268    can retrieve the error code).  */
269
270 int
271 bfd_seek (bfd *abfd, file_ptr position, int direction)
272 {
273   int result;
274   file_ptr file_position;
275   /* For the time being, a BFD may not seek to it's end.  The problem
276      is that we don't easily have a way to recognize the end of an
277      element in an archive.  */
278
279   BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
280
281   if (direction == SEEK_CUR && position == 0)
282     return 0;
283
284   if (abfd->format != bfd_archive && abfd->my_archive == 0)
285     {
286       if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
287         return 0;
288     }
289   else
290     {
291       /* We need something smarter to optimize access to archives.
292          Currently, anything inside an archive is read via the file
293          handle for the archive.  Which means that a bfd_seek on one
294          component affects the `current position' in the archive, as
295          well as in any other component.
296
297          It might be sufficient to put a spike through the cache
298          abstraction, and look to the archive for the file position,
299          but I think we should try for something cleaner.
300
301          In the meantime, no optimization for archives.  */
302     }
303
304   file_position = position;
305   if (direction == SEEK_SET && abfd->my_archive != NULL)
306     file_position += abfd->origin;
307
308   if (abfd->iovec)
309     result = abfd->iovec->bseek (abfd, file_position, direction);
310   else
311     result = -1;
312
313   if (result != 0)
314     {
315       int hold_errno = errno;
316
317       /* Force redetermination of `where' field.  */
318       bfd_tell (abfd);
319
320       /* An EINVAL error probably means that the file offset was
321          absurd.  */
322       if (hold_errno == EINVAL)
323         bfd_set_error (bfd_error_file_truncated);
324       else
325         {
326           bfd_set_error (bfd_error_system_call);
327           errno = hold_errno;
328         }
329     }
330   else
331     {
332       /* Adjust `where' field.  */
333       if (direction == SEEK_SET)
334         abfd->where = position;
335       else
336         abfd->where += position;
337     }
338   return result;
339 }
340
341 /*
342 FUNCTION
343         bfd_get_mtime
344
345 SYNOPSIS
346         long bfd_get_mtime (bfd *abfd);
347
348 DESCRIPTION
349         Return the file modification time (as read from the file system, or
350         from the archive header for archive members).
351
352 */
353
354 long
355 bfd_get_mtime (bfd *abfd)
356 {
357   struct stat buf;
358
359   if (abfd->mtime_set)
360     return abfd->mtime;
361
362   if (abfd->iovec == NULL)
363     return 0;
364
365   if (abfd->iovec->bstat (abfd, &buf) != 0)
366     return 0;
367
368   abfd->mtime = buf.st_mtime;           /* Save value in case anyone wants it */
369   return buf.st_mtime;
370 }
371
372 /*
373 FUNCTION
374         bfd_get_size
375
376 SYNOPSIS
377         file_ptr bfd_get_size (bfd *abfd);
378
379 DESCRIPTION
380         Return the file size (as read from file system) for the file
381         associated with BFD @var{abfd}.
382
383         The initial motivation for, and use of, this routine is not
384         so we can get the exact size of the object the BFD applies to, since
385         that might not be generally possible (archive members for example).
386         It would be ideal if someone could eventually modify
387         it so that such results were guaranteed.
388
389         Instead, we want to ask questions like "is this NNN byte sized
390         object I'm about to try read from file offset YYY reasonable?"
391         As as example of where we might do this, some object formats
392         use string tables for which the first <<sizeof (long)>> bytes of the
393         table contain the size of the table itself, including the size bytes.
394         If an application tries to read what it thinks is one of these
395         string tables, without some way to validate the size, and for
396         some reason the size is wrong (byte swapping error, wrong location
397         for the string table, etc.), the only clue is likely to be a read
398         error when it tries to read the table, or a "virtual memory
399         exhausted" error when it tries to allocate 15 bazillon bytes
400         of space for the 15 bazillon byte table it is about to read.
401         This function at least allows us to answer the question, "is the
402         size reasonable?".
403 */
404
405 file_ptr
406 bfd_get_size (bfd *abfd)
407 {
408   struct stat buf;
409
410   if (abfd->iovec == NULL)
411     return 0;
412
413   if (abfd->iovec->bstat (abfd, &buf) != 0)
414     return 0;
415
416   return buf.st_size;
417 }
418
419
420 /*
421 FUNCTION
422         bfd_mmap
423
424 SYNOPSIS
425         void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
426                         int prot, int flags, file_ptr offset);
427
428 DESCRIPTION
429         Return mmap()ed region of the file, if possible and implemented.
430
431 */
432
433 void *
434 bfd_mmap (bfd *abfd, void *addr, bfd_size_type len,
435           int prot, int flags, file_ptr offset)
436 {
437   void *ret = (void *)-1;
438
439   if (abfd->iovec == NULL)
440     return ret;
441
442   return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset);
443 }
444
445 /* Memory file I/O operations.  */
446
447 static file_ptr
448 memory_bread (bfd *abfd, void *ptr, file_ptr size)
449 {
450   struct bfd_in_memory *bim;
451   bfd_size_type get;
452
453   bim = (struct bfd_in_memory *) abfd->iostream;
454   get = size;
455   if (abfd->where + get > bim->size)
456     {
457       if (bim->size < (bfd_size_type) abfd->where)
458         get = 0;
459       else
460         get = bim->size - abfd->where;
461       bfd_set_error (bfd_error_file_truncated);
462     }
463   memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
464   return get;
465 }
466
467 static file_ptr
468 memory_bwrite (bfd *abfd, const void *ptr, file_ptr size)
469 {
470   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
471
472   if (abfd->where + size > bim->size)
473     {
474       bfd_size_type newsize, oldsize;
475
476       oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
477       bim->size = abfd->where + size;
478       /* Round up to cut down on memory fragmentation */
479       newsize = (bim->size + 127) & ~(bfd_size_type) 127;
480       if (newsize > oldsize)
481         {
482           bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
483           if (bim->buffer == NULL)
484             {
485               bim->size = 0;
486               return 0;
487             }
488           if (newsize > bim->size)
489             memset (bim->buffer + bim->size, 0, newsize - bim->size);
490         }
491     }
492   memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
493   return size;
494 }
495
496 static file_ptr
497 memory_btell (bfd *abfd)
498 {
499   return abfd->where;
500 }
501
502 static int
503 memory_bseek (bfd *abfd, file_ptr position, int direction)
504 {
505   file_ptr nwhere;
506   struct bfd_in_memory *bim;
507
508   bim = (struct bfd_in_memory *) abfd->iostream;
509
510   if (direction == SEEK_SET)
511     nwhere = position;
512   else
513     nwhere = abfd->where + position;
514
515   if (nwhere < 0)
516     {
517       abfd->where = 0;
518       errno = EINVAL;
519       return -1;
520     }
521
522   if ((bfd_size_type)nwhere > bim->size)
523     {
524       if (abfd->direction == write_direction
525           || abfd->direction == both_direction)
526         {
527           bfd_size_type newsize, oldsize;
528
529           oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
530           bim->size = nwhere;
531           /* Round up to cut down on memory fragmentation */
532           newsize = (bim->size + 127) & ~(bfd_size_type) 127;
533           if (newsize > oldsize)
534             {
535               bim->buffer = (bfd_byte *) bfd_realloc_or_free (bim->buffer, newsize);
536               if (bim->buffer == NULL)
537                 {
538                   errno = EINVAL;
539                   bim->size = 0;
540                   return -1;
541                 }
542               memset (bim->buffer + oldsize, 0, newsize - oldsize);
543             }
544         }
545       else
546         {
547           abfd->where = bim->size;
548           errno = EINVAL;
549           bfd_set_error (bfd_error_file_truncated);
550           return -1;
551         }
552     }
553   return 0;
554 }
555
556 static int
557 memory_bclose (struct bfd *abfd)
558 {
559   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
560
561   if (bim->buffer != NULL)
562     free (bim->buffer);
563   free (bim);
564   abfd->iostream = NULL;
565
566   return TRUE;
567 }
568
569 static int
570 memory_bflush (bfd *abfd ATTRIBUTE_UNUSED)
571 {
572   return 0;
573 }
574
575 static int
576 memory_bstat (bfd *abfd, struct stat *statbuf)
577 {
578   struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream;
579
580   memset (statbuf, 0, sizeof (*statbuf));
581   statbuf->st_size = bim->size;
582
583   return 0;
584 }
585
586 static void *
587 memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED,
588               bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED,
589               int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED)
590 {
591   return (void *)-1;
592 }
593
594 const struct bfd_iovec _bfd_memory_iovec =
595 {
596   &memory_bread, &memory_bwrite, &memory_btell, &memory_bseek,
597   &memory_bclose, &memory_bflush, &memory_bstat, &memory_bmmap
598 };