bfdio.c revision 251225
1171854Sdes/* Low-level I/O routines for BFDs.
2178950Srpaulo
3171854Sdes   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4171854Sdes   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
5171854Sdes   Free Software Foundation, Inc.
6171854Sdes
7171854Sdes   Written by Cygnus Support.
8171854Sdes
9171854SdesThis file is part of BFD, the Binary File Descriptor library.
10171854Sdes
11171854SdesThis program is free software; you can redistribute it and/or modify
12171854Sdesit under the terms of the GNU General Public License as published by
13171854Sdesthe Free Software Foundation; either version 2 of the License, or
14171854Sdes(at your option) any later version.
15171854Sdes
16171854SdesThis program is distributed in the hope that it will be useful,
17171854Sdesbut WITHOUT ANY WARRANTY; without even the implied warranty of
18171854SdesMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19171854SdesGNU General Public License for more details.
20171854Sdes
21171854SdesYou should have received a copy of the GNU General Public License
22171854Sdesalong with this program; if not, write to the Free Software
23171854SdesFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
24171854Sdes
25171854Sdes#include "sysdep.h"
26171854Sdes#include <limits.h>
27171854Sdes#include "bfd.h"
28171854Sdes#include "libbfd.h"
29171854Sdes
30171854Sdes#ifndef S_IXUSR
31171854Sdes#define S_IXUSR 0100    /* Execute by owner.  */
32171854Sdes#endif
33171854Sdes#ifndef S_IXGRP
34171854Sdes#define S_IXGRP 0010    /* Execute by group.  */
35171854Sdes#endif
36171854Sdes#ifndef S_IXOTH
37171854Sdes#define S_IXOTH 0001    /* Execute by others.  */
38171854Sdes#endif
39171854Sdes
40171854Sdesfile_ptr
41171854Sdesreal_ftell (FILE *file)
42172674Snetchild{
43171854Sdes#if defined (HAVE_FTELLO64)
44171854Sdes  return ftello64 (file);
45171854Sdes#elif defined (HAVE_FTELLO)
46171854Sdes  return ftello (file);
47171854Sdes#else
48185341Sjkim  return ftell (file);
49171854Sdes#endif
50171854Sdes}
51300421Sloos
52196889Snorkint
53225339Sdelphijreal_fseek (FILE *file, file_ptr offset, int whence)
54225339Sdelphij{
55225339Sdelphij#if defined (HAVE_FSEEKO64)
56225339Sdelphij  return fseeko64 (file, offset, whence);
57225339Sdelphij#elif defined (HAVE_FSEEKO)
58225339Sdelphij  return fseeko (file, offset, whence);
59225339Sdelphij#else
60225339Sdelphij  return fseek (file, offset, whence);
61225339Sdelphij#endif
62171854Sdes}
63172674Snetchild
64172674SnetchildFILE *
65225339Sdelphijreal_fopen (const char *filename, const char *modes)
66171854Sdes{
67171854Sdes#if defined (HAVE_FOPEN64)
68171854Sdes  return fopen64 (filename, modes);
69171854Sdes#else
70171854Sdes  return fopen (filename, modes);
71171854Sdes#endif
72171854Sdes}
73171854Sdes
74171854Sdes/*
75171854SdesINTERNAL_DEFINITION
76225339Sdelphij	struct bfd_iovec
77225339Sdelphij
78225339SdelphijDESCRIPTION
79225339Sdelphij
80171854Sdes	The <<struct bfd_iovec>> contains the internal file I/O class.
81171854Sdes	Each <<BFD>> has an instance of this class and all file I/O is
82171854Sdes	routed through it (it is assumed that the instance implements
83171854Sdes	all methods listed below).
84171854Sdes
85171854Sdes.struct bfd_iovec
86171854Sdes.{
87171854Sdes.  {* To avoid problems with macros, a "b" rather than "f"
88246128Ssbz.     prefix is prepended to each method name.  *}
89171854Sdes.  {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
90171854Sdes.     bytes starting at PTR.  Return the number of bytes actually
91171854Sdes.     transfered (a read past end-of-file returns less than NBYTES),
92171854Sdes.     or -1 (setting <<bfd_error>>) if an error occurs.  *}
93171854Sdes.  file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
94171854Sdes.  file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
95171854Sdes.                      file_ptr nbytes);
96171854Sdes.  {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
97225339Sdelphij.     if an error occurs.  *}
98225339Sdelphij.  file_ptr (*btell) (struct bfd *abfd);
99225339Sdelphij.  {* For the following, on successful completion a value of 0 is returned.
100225339Sdelphij.     Otherwise, a value of -1 is returned (and  <<bfd_error>> is set).  *}
101225339Sdelphij.  int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
102225339Sdelphij.  int (*bclose) (struct bfd *abfd);
103225339Sdelphij.  int (*bflush) (struct bfd *abfd);
104171854Sdes.  int (*bstat) (struct bfd *abfd, struct stat *sb);
105225339Sdelphij.};
106225339Sdelphij
107171854Sdes*/
108171854Sdes
109171854Sdes
110171854Sdes/* Return value is amount read.  */
111171854Sdes
112171854Sdesbfd_size_type
113171854Sdesbfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
114171854Sdes{
115171854Sdes  size_t nread;
116171854Sdes
117171933Sdes  /* If this is an archive element, don't read past the end of
118178950Srpaulo     this element.  */
119185341Sjkim  if (abfd->arelt_data != NULL)
120171854Sdes    {
121171854Sdes      size_t maxbytes = ((struct areltdata *) abfd->arelt_data)->parsed_size;
122171854Sdes      if (size > maxbytes)
123171854Sdes	size = maxbytes;
124171854Sdes    }
125171854Sdes
126171854Sdes  if ((abfd->flags & BFD_IN_MEMORY) != 0)
127171854Sdes    {
128171854Sdes      struct bfd_in_memory *bim;
129171854Sdes      bfd_size_type get;
130171854Sdes
131171854Sdes      bim = abfd->iostream;
132171854Sdes      get = size;
133171854Sdes      if (abfd->where + get > bim->size)
134171854Sdes	{
135171854Sdes	  if (bim->size < (bfd_size_type) abfd->where)
136171854Sdes	    get = 0;
137171854Sdes	  else
138171854Sdes	    get = bim->size - abfd->where;
139171854Sdes	  bfd_set_error (bfd_error_file_truncated);
140171854Sdes	}
141241885Seadler      memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
142241885Seadler      abfd->where += get;
143171854Sdes      return get;
144171854Sdes    }
145171854Sdes
146171854Sdes  if (abfd->iovec)
147171854Sdes    nread = abfd->iovec->bread (abfd, ptr, size);
148171854Sdes  else
149171854Sdes    nread = 0;
150171854Sdes  if (nread != (size_t) -1)
151171854Sdes    abfd->where += nread;
152171854Sdes
153171854Sdes  return nread;
154171854Sdes}
155210624Sdelphij
156210624Sdelphijbfd_size_type
157225339Sdelphijbfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
158225339Sdelphij{
159171854Sdes  size_t nwrote;
160171933Sdes
161171854Sdes  if ((abfd->flags & BFD_IN_MEMORY) != 0)
162210624Sdelphij    {
163210624Sdelphij      struct bfd_in_memory *bim = abfd->iostream;
164171854Sdes
165176279Srpaulo      size = (size_t) size;
166176279Srpaulo      if (abfd->where + size > bim->size)
167176279Srpaulo	{
168176279Srpaulo	  bfd_size_type newsize, oldsize;
169176279Srpaulo
170176279Srpaulo	  oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
171176279Srpaulo	  bim->size = abfd->where + size;
172176279Srpaulo	  /* Round up to cut down on memory fragmentation */
173225339Sdelphij	  newsize = (bim->size + 127) & ~(bfd_size_type) 127;
174175214Srpaulo	  if (newsize > oldsize)
175175214Srpaulo	    {
176175214Srpaulo	      bim->buffer = bfd_realloc (bim->buffer, newsize);
177175214Srpaulo	      if (bim->buffer == 0)
178175214Srpaulo		{
179171854Sdes		  bim->size = 0;
180171854Sdes		  return 0;
181171854Sdes		}
182171854Sdes	    }
183171854Sdes	}
184171854Sdes      memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
185171933Sdes      abfd->where += size;
186210624Sdelphij      return size;
187171854Sdes    }
188171854Sdes
189171854Sdes  if (abfd->iovec)
190171933Sdes    nwrote = abfd->iovec->bwrite (abfd, ptr, size);
191171933Sdes  else
192171854Sdes    nwrote = 0;
193171854Sdes
194171854Sdes  if (nwrote != (size_t) -1)
195175214Srpaulo    abfd->where += nwrote;
196210624Sdelphij  if (nwrote != size)
197171854Sdes    {
198210624Sdelphij#ifdef ENOSPC
199210624Sdelphij      errno = ENOSPC;
200210624Sdelphij#endif
201210624Sdelphij      bfd_set_error (bfd_error_system_call);
202210624Sdelphij    }
203210624Sdelphij  return nwrote;
204210624Sdelphij}
205210624Sdelphij
206210624Sdelphijfile_ptr
207210624Sdelphijbfd_tell (bfd *abfd)
208210624Sdelphij{
209210624Sdelphij  file_ptr ptr;
210171854Sdes
211171933Sdes  if ((abfd->flags & BFD_IN_MEMORY) != 0)
212171854Sdes    return abfd->where;
213210833Sdelphij
214210833Sdelphij  if (abfd->iovec)
215210833Sdelphij    {
216221335Sdelphij      ptr = abfd->iovec->btell (abfd);
217210833Sdelphij
218210833Sdelphij      if (abfd->my_archive)
219210833Sdelphij	ptr -= abfd->origin;
220210833Sdelphij    }
221221509Sdelphij  else
222221509Sdelphij    ptr = 0;
223221509Sdelphij
224221509Sdelphij  abfd->where = ptr;
225221509Sdelphij  return ptr;
226221509Sdelphij}
227221509Sdelphij
228221509Sdelphijint
229221509Sdelphijbfd_flush (bfd *abfd)
230210833Sdelphij{
231210833Sdelphij  if ((abfd->flags & BFD_IN_MEMORY) != 0)
232210833Sdelphij    return 0;
233210833Sdelphij
234210833Sdelphij  if (abfd->iovec)
235210833Sdelphij    return abfd->iovec->bflush (abfd);
236210833Sdelphij  return 0;
237210833Sdelphij}
238210833Sdelphij
239210833Sdelphij/* Returns 0 for success, negative value for failure (in which case
240225339Sdelphij   bfd_get_error can retrieve the error code).  */
241210833Sdelphijint
242210833Sdelphijbfd_stat (bfd *abfd, struct stat *statbuf)
243210833Sdelphij{
244210833Sdelphij  int result;
245210833Sdelphij
246210833Sdelphij  if ((abfd->flags & BFD_IN_MEMORY) != 0)
247210833Sdelphij    abort ();
248210833Sdelphij
249225009Sattilio  if (abfd->iovec)
250210833Sdelphij    result = abfd->iovec->bstat (abfd, statbuf);
251210833Sdelphij  else
252210833Sdelphij    result = -1;
253210833Sdelphij
254225009Sattilio  if (result < 0)
255210833Sdelphij    bfd_set_error (bfd_error_system_call);
256210833Sdelphij  return result;
257210833Sdelphij}
258210833Sdelphij
259210833Sdelphij/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
260210833Sdelphij   can retrieve the error code).  */
261210833Sdelphij
262171933Sdesint
263171933Sdesbfd_seek (bfd *abfd, file_ptr position, int direction)
264210624Sdelphij{
265210624Sdelphij  int result;
266210624Sdelphij  file_ptr file_position;
267225339Sdelphij  /* For the time being, a BFD may not seek to it's end.  The problem
268225339Sdelphij     is that we don't easily have a way to recognize the end of an
269225339Sdelphij     element in an archive.  */
270225339Sdelphij
271225339Sdelphij  BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
272225339Sdelphij
273171854Sdes  if (direction == SEEK_CUR && position == 0)
274225339Sdelphij    return 0;
275171854Sdes
276225339Sdelphij  if ((abfd->flags & BFD_IN_MEMORY) != 0)
277246951Smarkj    {
278246951Smarkj      struct bfd_in_memory *bim;
279196889Snork
280225339Sdelphij      bim = abfd->iostream;
281246951Smarkj
282225339Sdelphij      if (direction == SEEK_SET)
283225339Sdelphij	abfd->where = position;
284225339Sdelphij      else
285246951Smarkj	abfd->where += position;
286225339Sdelphij
287225339Sdelphij      if (abfd->where > bim->size)
288225339Sdelphij	{
289246951Smarkj	  if ((abfd->direction == write_direction) ||
290225339Sdelphij	      (abfd->direction == both_direction))
291225339Sdelphij	    {
292225339Sdelphij	      bfd_size_type newsize, oldsize;
293246951Smarkj
294225339Sdelphij	      oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
295225339Sdelphij	      bim->size = abfd->where;
296171854Sdes	      /* Round up to cut down on memory fragmentation */
297171854Sdes	      newsize = (bim->size + 127) & ~(bfd_size_type) 127;
298171854Sdes	      if (newsize > oldsize)
299171854Sdes	        {
300171854Sdes		  bim->buffer = bfd_realloc (bim->buffer, newsize);
301171854Sdes		  if (bim->buffer == 0)
302171854Sdes		    {
303171854Sdes		      bim->size = 0;
304171854Sdes		      return -1;
305171854Sdes		    }
306225339Sdelphij	        }
307225339Sdelphij	    }
308171854Sdes	  else
309171933Sdes	    {
310171854Sdes	      abfd->where = bim->size;
311172674Snetchild	      bfd_set_error (bfd_error_file_truncated);
312172674Snetchild	      return -1;
313172674Snetchild	    }
314172674Snetchild	}
315171854Sdes      return 0;
316172674Snetchild    }
317172674Snetchild
318172674Snetchild  if (abfd->format != bfd_archive && abfd->my_archive == 0)
319172674Snetchild    {
320172674Snetchild      if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
321172674Snetchild	return 0;
322172674Snetchild    }
323172674Snetchild  else
324171854Sdes    {
325172674Snetchild      /* We need something smarter to optimize access to archives.
326171854Sdes	 Currently, anything inside an archive is read via the file
327172674Snetchild	 handle for the archive.  Which means that a bfd_seek on one
328172674Snetchild	 component affects the `current position' in the archive, as
329172674Snetchild	 well as in any other component.
330172674Snetchild
331225339Sdelphij	 It might be sufficient to put a spike through the cache
332225339Sdelphij	 abstraction, and look to the archive for the file position,
333171854Sdes	 but I think we should try for something cleaner.
334225339Sdelphij
335225339Sdelphij	 In the meantime, no optimization for archives.  */
336225339Sdelphij    }
337225339Sdelphij
338225339Sdelphij  file_position = position;
339225339Sdelphij  if (direction == SEEK_SET && abfd->my_archive != NULL)
340225339Sdelphij    file_position += abfd->origin;
341225339Sdelphij
342225339Sdelphij  if (abfd->iovec)
343225339Sdelphij    result = abfd->iovec->bseek (abfd, file_position, direction);
344225339Sdelphij  else
345225339Sdelphij    result = -1;
346225339Sdelphij
347225339Sdelphij  if (result != 0)
348225339Sdelphij    {
349225339Sdelphij      int hold_errno = errno;
350225339Sdelphij
351225339Sdelphij      /* Force redetermination of `where' field.  */
352225339Sdelphij      bfd_tell (abfd);
353225339Sdelphij
354225339Sdelphij      /* An EINVAL error probably means that the file offset was
355225339Sdelphij         absurd.  */
356225339Sdelphij      if (hold_errno == EINVAL)
357225339Sdelphij	bfd_set_error (bfd_error_file_truncated);
358225339Sdelphij      else
359225339Sdelphij	{
360225339Sdelphij	  bfd_set_error (bfd_error_system_call);
361225339Sdelphij	  errno = hold_errno;
362225339Sdelphij	}
363225339Sdelphij    }
364225339Sdelphij  else
365225339Sdelphij    {
366225339Sdelphij      /* Adjust `where' field.  */
367225339Sdelphij      if (direction == SEEK_SET)
368225339Sdelphij	abfd->where = position;
369225339Sdelphij      else
370225339Sdelphij	abfd->where += position;
371225339Sdelphij    }
372225339Sdelphij  return result;
373225339Sdelphij}
374225339Sdelphij
375225339Sdelphij/*
376225339SdelphijFUNCTION
377225339Sdelphij	bfd_get_mtime
378225339Sdelphij
379225339SdelphijSYNOPSIS
380225339Sdelphij	time_t bfd_get_mtime (bfd *abfd);
381225339Sdelphij
382225339SdelphijDESCRIPTION
383225339Sdelphij	Return the file modification time (as read from the file system, or
384225339Sdelphij	from the archive header for archive members).
385225339Sdelphij
386225339Sdelphij*/
387225662Sattilio
388225339Sdelphijtime_t
389225339Sdelphijbfd_get_mtime (bfd *abfd)
390171933Sdes{
391225339Sdelphij  struct stat buf;
392225339Sdelphij
393225339Sdelphij  if (abfd->mtime_set)
394225339Sdelphij    return abfd->mtime;
395225339Sdelphij
396225339Sdelphij  if (abfd->iovec == NULL)
397225339Sdelphij    return 0;
398225339Sdelphij
399225339Sdelphij  if (abfd->iovec->bstat (abfd, &buf) != 0)
400171933Sdes    return 0;
401225339Sdelphij
402225339Sdelphij  abfd->mtime = buf.st_mtime;		/* Save value in case anyone wants it */
403225339Sdelphij  return buf.st_mtime;
404225339Sdelphij}
405225339Sdelphij
406225339Sdelphij/*
407225339SdelphijFUNCTION
408225339Sdelphij	bfd_get_size
409225339Sdelphij
410225339SdelphijSYNOPSIS
411171854Sdes	file_ptr bfd_get_size (bfd *abfd);
412171854Sdes
413225339SdelphijDESCRIPTION
414171854Sdes	Return the file size (as read from file system) for the file
415171854Sdes	associated with BFD @var{abfd}.
416172674Snetchild
417225339Sdelphij	The initial motivation for, and use of, this routine is not
418171854Sdes	so we can get the exact size of the object the BFD applies to, since
419225339Sdelphij	that might not be generally possible (archive members for example).
420225339Sdelphij	It would be ideal if someone could eventually modify
421225339Sdelphij	it so that such results were guaranteed.
422225339Sdelphij
423171854Sdes	Instead, we want to ask questions like "is this NNN byte sized
424225339Sdelphij	object I'm about to try read from file offset YYY reasonable?"
425225339Sdelphij	As as example of where we might do this, some object formats
426225339Sdelphij	use string tables for which the first <<sizeof (long)>> bytes of the
427171854Sdes	table contain the size of the table itself, including the size bytes.
428225662Sattilio	If an application tries to read what it thinks is one of these
429225662Sattilio	string tables, without some way to validate the size, and for
430225339Sdelphij	some reason the size is wrong (byte swapping error, wrong location
431225662Sattilio	for the string table, etc.), the only clue is likely to be a read
432225339Sdelphij	error when it tries to read the table, or a "virtual memory
433225339Sdelphij	exhausted" error when it tries to allocate 15 bazillon bytes
434225339Sdelphij	of space for the 15 bazillon byte table it is about to read.
435225339Sdelphij	This function at least allows us to answer the question, "is the
436225339Sdelphij	size reasonable?".
437225339Sdelphij*/
438225339Sdelphij
439225339Sdelphijfile_ptr
440225339Sdelphijbfd_get_size (bfd *abfd)
441225339Sdelphij{
442225339Sdelphij  struct stat buf;
443225339Sdelphij
444225339Sdelphij  if ((abfd->flags & BFD_IN_MEMORY) != 0)
445225339Sdelphij    return ((struct bfd_in_memory *) abfd->iostream)->size;
446171854Sdes
447  if (abfd->iovec == NULL)
448    return 0;
449
450  if (abfd->iovec->bstat (abfd, &buf) != 0)
451    return 0;
452
453  return buf.st_size;
454}
455