xref: /openbsd/gnu/usr.bin/binutils/bfd/bfdio.c (revision 7b36286a)
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 }
443