s/pxeldr/pxeboot/
[dragonfly.git] / contrib / binutils-2.15 / 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 Free Software Foundation, Inc.
5
6    Written by Cygnus Support.
7
8 This file is part of BFD, the Binary File Descriptor library.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24 #include "sysdep.h"
25
26 #include "bfd.h"
27 #include "libbfd.h"
28
29 #include <limits.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 file_ptr
42 real_ftell (FILE *file)
43 {
44 #if defined (HAVE_FTELLO64)
45   return ftello64 (file);
46 #elif defined (HAVE_FTELLO)
47   return ftello (file);
48 #else
49   return ftell (file);
50 #endif
51 }
52
53 int
54 real_fseek (FILE *file, file_ptr offset, int whence)
55 {
56 #if defined (HAVE_FSEEKO64)
57   return fseeko64 (file, offset, whence);
58 #elif defined (HAVE_FSEEKO)
59   return fseeko (file, offset, whence);
60 #else
61   return fseek (file, offset, whence);
62 #endif
63 }
64
65 /* Note that archive entries don't have streams; they share their parent's.
66    This allows someone to play with the iostream behind BFD's back.
67
68    Also, note that the origin pointer points to the beginning of a file's
69    contents (0 for non-archive elements).  For archive entries this is the
70    first octet in the file, NOT the beginning of the archive header.  */
71
72 static size_t
73 real_read (void *where, size_t a, size_t b, FILE *file)
74 {
75   /* FIXME - this looks like an optimization, but it's really to cover
76      up for a feature of some OSs (not solaris - sigh) that
77      ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
78      internally and tries to link against them.  BFD seems to be smart
79      enough to realize there are no symbol records in the "file" that
80      doesn't exist but attempts to read them anyway.  On Solaris,
81      attempting to read zero bytes from a NULL file results in a core
82      dump, but on other platforms it just returns zero bytes read.
83      This makes it to something reasonable. - DJ */
84   if (a == 0 || b == 0)
85     return 0;
86
87
88 #if defined (__VAX) && defined (VMS)
89   /* Apparently fread on Vax VMS does not keep the record length
90      information.  */
91   return read (fileno (file), where, a * b);
92 #else
93   return fread (where, a, b, file);
94 #endif
95 }
96
97 /* Return value is amount read.  */
98
99 bfd_size_type
100 bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
101 {
102   size_t nread;
103
104   if ((abfd->flags & BFD_IN_MEMORY) != 0)
105     {
106       struct bfd_in_memory *bim;
107       bfd_size_type get;
108
109       bim = abfd->iostream;
110       get = size;
111       if (abfd->where + get > bim->size)
112         {
113           if (bim->size < (bfd_size_type) abfd->where)
114             get = 0;
115           else
116             get = bim->size - abfd->where;
117           bfd_set_error (bfd_error_file_truncated);
118         }
119       memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
120       abfd->where += get;
121       return get;
122     }
123
124   nread = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
125   if (nread != (size_t) -1)
126     abfd->where += nread;
127
128   /* Set bfd_error if we did not read as much data as we expected.
129
130      If the read failed due to an error set the bfd_error_system_call,
131      else set bfd_error_file_truncated.
132
133      A BFD backend may wish to override bfd_error_file_truncated to
134      provide something more useful (eg. no_symbols or wrong_format).  */
135   if (nread != size)
136     {
137       if (ferror (bfd_cache_lookup (abfd)))
138         bfd_set_error (bfd_error_system_call);
139       else
140         bfd_set_error (bfd_error_file_truncated);
141     }
142
143   return nread;
144 }
145
146 bfd_size_type
147 bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
148 {
149   size_t nwrote;
150
151   if ((abfd->flags & BFD_IN_MEMORY) != 0)
152     {
153       struct bfd_in_memory *bim = abfd->iostream;
154       size = (size_t) size;
155       if (abfd->where + size > bim->size)
156         {
157           bfd_size_type newsize, oldsize;
158
159           oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
160           bim->size = abfd->where + size;
161           /* Round up to cut down on memory fragmentation */
162           newsize = (bim->size + 127) & ~(bfd_size_type) 127;
163           if (newsize > oldsize)
164             {
165               bim->buffer = bfd_realloc (bim->buffer, newsize);
166               if (bim->buffer == 0)
167                 {
168                   bim->size = 0;
169                   return 0;
170                 }
171             }
172         }
173       memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
174       abfd->where += size;
175       return size;
176     }
177
178   nwrote = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
179   if (nwrote != (size_t) -1)
180     abfd->where += nwrote;
181   if (nwrote != size)
182     {
183 #ifdef ENOSPC
184       errno = ENOSPC;
185 #endif
186       bfd_set_error (bfd_error_system_call);
187     }
188   return nwrote;
189 }
190
191 file_ptr
192 bfd_tell (bfd *abfd)
193 {
194   file_ptr ptr;
195
196   if ((abfd->flags & BFD_IN_MEMORY) != 0)
197     return abfd->where;
198
199   ptr = real_ftell (bfd_cache_lookup (abfd));
200
201   if (abfd->my_archive)
202     ptr -= abfd->origin;
203   abfd->where = ptr;
204   return ptr;
205 }
206
207 int
208 bfd_flush (bfd *abfd)
209 {
210   if ((abfd->flags & BFD_IN_MEMORY) != 0)
211     return 0;
212   return fflush (bfd_cache_lookup(abfd));
213 }
214
215 /* Returns 0 for success, negative value for failure (in which case
216    bfd_get_error can retrieve the error code).  */
217 int
218 bfd_stat (bfd *abfd, struct stat *statbuf)
219 {
220   FILE *f;
221   int result;
222
223   if ((abfd->flags & BFD_IN_MEMORY) != 0)
224     abort ();
225
226   f = bfd_cache_lookup (abfd);
227   if (f == NULL)
228     {
229       bfd_set_error (bfd_error_system_call);
230       return -1;
231     }
232   result = fstat (fileno (f), statbuf);
233   if (result < 0)
234     bfd_set_error (bfd_error_system_call);
235   return result;
236 }
237
238 /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
239    can retrieve the error code).  */
240
241 int
242 bfd_seek (bfd *abfd, file_ptr position, int direction)
243 {
244   int result;
245   FILE *f;
246   file_ptr file_position;
247   /* For the time being, a BFD may not seek to it's end.  The problem
248      is that we don't easily have a way to recognize the end of an
249      element in an archive.  */
250
251   BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
252
253   if (direction == SEEK_CUR && position == 0)
254     return 0;
255
256   if ((abfd->flags & BFD_IN_MEMORY) != 0)
257     {
258       struct bfd_in_memory *bim;
259
260       bim = abfd->iostream;
261
262       if (direction == SEEK_SET)
263         abfd->where = position;
264       else
265         abfd->where += position;
266
267       if (abfd->where > bim->size)
268         {
269           if ((abfd->direction == write_direction) ||
270               (abfd->direction == both_direction))
271             {
272               bfd_size_type newsize, oldsize;
273               oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
274               bim->size = abfd->where;
275               /* Round up to cut down on memory fragmentation */
276               newsize = (bim->size + 127) & ~(bfd_size_type) 127;
277               if (newsize > oldsize)
278                 {
279                   bim->buffer = bfd_realloc (bim->buffer, newsize);
280                   if (bim->buffer == 0)
281                     {
282                       bim->size = 0;
283                       return -1;
284                     }
285                 }
286             }
287           else
288             {
289               abfd->where = bim->size;
290               bfd_set_error (bfd_error_file_truncated);
291               return -1;
292             }
293         }
294       return 0;
295     }
296
297   if (abfd->format != bfd_archive && abfd->my_archive == 0)
298     {
299 #if 0
300       /* Explanation for this code: I'm only about 95+% sure that the above
301          conditions are sufficient and that all i/o calls are properly
302          adjusting the `where' field.  So this is sort of an `assert'
303          that the `where' field is correct.  If we can go a while without
304          tripping the abort, we can probably safely disable this code,
305          so that the real optimizations happen.  */
306       file_ptr where_am_i_now;
307       where_am_i_now = real_ftell (bfd_cache_lookup (abfd));
308       if (abfd->my_archive)
309         where_am_i_now -= abfd->origin;
310       if (where_am_i_now != abfd->where)
311         abort ();
312 #endif
313       if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
314         return 0;
315     }
316   else
317     {
318       /* We need something smarter to optimize access to archives.
319          Currently, anything inside an archive is read via the file
320          handle for the archive.  Which means that a bfd_seek on one
321          component affects the `current position' in the archive, as
322          well as in any other component.
323
324          It might be sufficient to put a spike through the cache
325          abstraction, and look to the archive for the file position,
326          but I think we should try for something cleaner.
327
328          In the meantime, no optimization for archives.  */
329     }
330
331   f = bfd_cache_lookup (abfd);
332   file_position = position;
333   if (direction == SEEK_SET && abfd->my_archive != NULL)
334     file_position += abfd->origin;
335
336   result = real_fseek (f, file_position, direction);
337   if (result != 0)
338     {
339       int hold_errno = errno;
340
341       /* Force redetermination of `where' field.  */
342       bfd_tell (abfd);
343
344       /* An EINVAL error probably means that the file offset was
345          absurd.  */
346       if (hold_errno == EINVAL)
347         bfd_set_error (bfd_error_file_truncated);
348       else
349         {
350           bfd_set_error (bfd_error_system_call);
351           errno = hold_errno;
352         }
353     }
354   else
355     {
356       /* Adjust `where' field.  */
357       if (direction == SEEK_SET)
358         abfd->where = position;
359       else
360         abfd->where += position;
361     }
362   return result;
363 }
364
365 /*
366 FUNCTION
367         bfd_get_mtime
368
369 SYNOPSIS
370         long bfd_get_mtime (bfd *abfd);
371
372 DESCRIPTION
373         Return the file modification time (as read from the file system, or
374         from the archive header for archive members).
375
376 */
377
378 long
379 bfd_get_mtime (bfd *abfd)
380 {
381   FILE *fp;
382   struct stat buf;
383
384   if (abfd->mtime_set)
385     return abfd->mtime;
386
387   fp = bfd_cache_lookup (abfd);
388   if (0 != fstat (fileno (fp), &buf))
389     return 0;
390
391   abfd->mtime = buf.st_mtime;           /* Save value in case anyone wants it */
392   return buf.st_mtime;
393 }
394
395 /*
396 FUNCTION
397         bfd_get_size
398
399 SYNOPSIS
400         long bfd_get_size (bfd *abfd);
401
402 DESCRIPTION
403         Return the file size (as read from file system) for the file
404         associated with BFD @var{abfd}.
405
406         The initial motivation for, and use of, this routine is not
407         so we can get the exact size of the object the BFD applies to, since
408         that might not be generally possible (archive members for example).
409         It would be ideal if someone could eventually modify
410         it so that such results were guaranteed.
411
412         Instead, we want to ask questions like "is this NNN byte sized
413         object I'm about to try read from file offset YYY reasonable?"
414         As as example of where we might do this, some object formats
415         use string tables for which the first <<sizeof (long)>> bytes of the
416         table contain the size of the table itself, including the size bytes.
417         If an application tries to read what it thinks is one of these
418         string tables, without some way to validate the size, and for
419         some reason the size is wrong (byte swapping error, wrong location
420         for the string table, etc.), the only clue is likely to be a read
421         error when it tries to read the table, or a "virtual memory
422         exhausted" error when it tries to allocate 15 bazillon bytes
423         of space for the 15 bazillon byte table it is about to read.
424         This function at least allows us to answer the question, "is the
425         size reasonable?".
426 */
427
428 long
429 bfd_get_size (bfd *abfd)
430 {
431   FILE *fp;
432   struct stat buf;
433
434   if ((abfd->flags & BFD_IN_MEMORY) != 0)
435     return ((struct bfd_in_memory *) abfd->iostream)->size;
436
437   fp = bfd_cache_lookup (abfd);
438   if (0 != fstat (fileno (fp), & buf))
439     return 0;
440
441   return buf.st_size;
442 }