OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [bfdio.c] - Blame information for rev 853

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* 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
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
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
FILE *
66
real_fopen (const char *filename, const char *modes)
67
{
68
#if defined (HAVE_FOPEN64)
69
  return fopen64 (filename, modes);
70
#else
71
  return fopen (filename, modes);
72
#endif
73
}
74
 
75
/*
76
INTERNAL_DEFINITION
77
        struct bfd_iovec
78
 
79
DESCRIPTION
80
 
81
        The <<struct bfd_iovec>> contains the internal file I/O class.
82
        Each <<BFD>> has an instance of this class and all file I/O is
83
        routed through it (it is assumed that the instance implements
84
        all methods listed below).
85
 
86
.struct bfd_iovec
87
.{
88
.  {* To avoid problems with macros, a "b" rather than "f"
89
.     prefix is prepended to each method name.  *}
90
.  {* Attempt to read/write NBYTES on ABFD's IOSTREAM storing/fetching
91
.     bytes starting at PTR.  Return the number of bytes actually
92
.     transfered (a read past end-of-file returns less than NBYTES),
93
.     or -1 (setting <<bfd_error>>) if an error occurs.  *}
94
.  file_ptr (*bread) (struct bfd *abfd, void *ptr, file_ptr nbytes);
95
.  file_ptr (*bwrite) (struct bfd *abfd, const void *ptr,
96
.                      file_ptr nbytes);
97
.  {* Return the current IOSTREAM file offset, or -1 (setting <<bfd_error>>
98
.     if an error occurs.  *}
99
.  file_ptr (*btell) (struct bfd *abfd);
100
.  {* For the following, on successful completion a value of 0 is returned.
101
.     Otherwise, a value of -1 is returned (and  <<bfd_error>> is set).  *}
102
.  int (*bseek) (struct bfd *abfd, file_ptr offset, int whence);
103
.  int (*bclose) (struct bfd *abfd);
104
.  int (*bflush) (struct bfd *abfd);
105
.  int (*bstat) (struct bfd *abfd, struct stat *sb);
106
.};
107
 
108
*/
109
 
110
 
111
/* Return value is amount read.  */
112
 
113
bfd_size_type
114
bfd_bread (void *ptr, bfd_size_type size, bfd *abfd)
115
{
116
  size_t nread;
117
 
118
  /* If this is an archive element, don't read past the end of
119
     this element.  */
120
  if (abfd->arelt_data != NULL)
121
    {
122
      size_t maxbytes = ((struct areltdata *) abfd->arelt_data)->parsed_size;
123
      if (size > maxbytes)
124
        size = maxbytes;
125
    }
126
 
127
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
128
    {
129
      struct bfd_in_memory *bim;
130
      bfd_size_type get;
131
 
132
      bim = abfd->iostream;
133
      get = size;
134
      if (abfd->where + get > bim->size)
135
        {
136
          if (bim->size < (bfd_size_type) abfd->where)
137
            get = 0;
138
          else
139
            get = bim->size - abfd->where;
140
          bfd_set_error (bfd_error_file_truncated);
141
        }
142
      memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
143
      abfd->where += get;
144
      return get;
145
    }
146
 
147
  if (abfd->iovec)
148
    nread = abfd->iovec->bread (abfd, ptr, size);
149
  else
150
    nread = 0;
151
  if (nread != (size_t) -1)
152
    abfd->where += nread;
153
 
154
  return nread;
155
}
156
 
157
bfd_size_type
158
bfd_bwrite (const void *ptr, bfd_size_type size, bfd *abfd)
159
{
160
  size_t nwrote;
161
 
162
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
163
    {
164
      struct bfd_in_memory *bim = abfd->iostream;
165
 
166
      size = (size_t) size;
167
      if (abfd->where + size > bim->size)
168
        {
169
          bfd_size_type newsize, oldsize;
170
 
171
          oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
172
          bim->size = abfd->where + size;
173
          /* Round up to cut down on memory fragmentation */
174
          newsize = (bim->size + 127) & ~(bfd_size_type) 127;
175
          if (newsize > oldsize)
176
            {
177
              bim->buffer = bfd_realloc_or_free (bim->buffer, newsize);
178
              if (bim->buffer == NULL)
179
                {
180
                  bim->size = 0;
181
                  return 0;
182
                }
183
            }
184
        }
185
      memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
186
      abfd->where += size;
187
      return size;
188
    }
189
 
190
  if (abfd->iovec)
191
    nwrote = abfd->iovec->bwrite (abfd, ptr, size);
192
  else
193
    nwrote = 0;
194
 
195
  if (nwrote != (size_t) -1)
196
    abfd->where += nwrote;
197
  if (nwrote != size)
198
    {
199
#ifdef ENOSPC
200
      errno = ENOSPC;
201
#endif
202
      bfd_set_error (bfd_error_system_call);
203
    }
204
  return nwrote;
205
}
206
 
207
file_ptr
208
bfd_tell (bfd *abfd)
209
{
210
  file_ptr ptr;
211
 
212
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
213
    return abfd->where;
214
 
215
  if (abfd->iovec)
216
    {
217
      ptr = abfd->iovec->btell (abfd);
218
 
219
      if (abfd->my_archive)
220
        ptr -= abfd->origin;
221
    }
222
  else
223
    ptr = 0;
224
 
225
  abfd->where = ptr;
226
  return ptr;
227
}
228
 
229
int
230
bfd_flush (bfd *abfd)
231
{
232
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
233
    return 0;
234
 
235
  if (abfd->iovec)
236
    return abfd->iovec->bflush (abfd);
237
  return 0;
238
}
239
 
240
/* Returns 0 for success, negative value for failure (in which case
241
   bfd_get_error can retrieve the error code).  */
242
int
243
bfd_stat (bfd *abfd, struct stat *statbuf)
244
{
245
  int result;
246
 
247
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
248
    abort ();
249
 
250
  if (abfd->iovec)
251
    result = abfd->iovec->bstat (abfd, statbuf);
252
  else
253
    result = -1;
254
 
255
  if (result < 0)
256
    bfd_set_error (bfd_error_system_call);
257
  return result;
258
}
259
 
260
/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
261
   can retrieve the error code).  */
262
 
263
int
264
bfd_seek (bfd *abfd, file_ptr position, int direction)
265
{
266
  int result;
267
  file_ptr file_position;
268
  /* For the time being, a BFD may not seek to it's end.  The problem
269
     is that we don't easily have a way to recognize the end of an
270
     element in an archive.  */
271
 
272
  BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
273
 
274
  if (direction == SEEK_CUR && position == 0)
275
    return 0;
276
 
277
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
278
    {
279
      struct bfd_in_memory *bim;
280
 
281
      bim = abfd->iostream;
282
 
283
      if (direction == SEEK_SET)
284
        abfd->where = position;
285
      else
286
        abfd->where += position;
287
 
288
      if (abfd->where > bim->size)
289
        {
290
          if ((abfd->direction == write_direction) ||
291
              (abfd->direction == both_direction))
292
            {
293
              bfd_size_type newsize, oldsize;
294
 
295
              oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
296
              bim->size = abfd->where;
297
              /* Round up to cut down on memory fragmentation */
298
              newsize = (bim->size + 127) & ~(bfd_size_type) 127;
299
              if (newsize > oldsize)
300
                {
301
                  bim->buffer = bfd_realloc_or_free (bim->buffer, newsize);
302
                  if (bim->buffer == NULL)
303
                    {
304
                      bim->size = 0;
305
                      return -1;
306
                    }
307
                }
308
            }
309
          else
310
            {
311
              abfd->where = bim->size;
312
              bfd_set_error (bfd_error_file_truncated);
313
              return -1;
314
            }
315
        }
316
      return 0;
317
    }
318
 
319
  if (abfd->format != bfd_archive && abfd->my_archive == 0)
320
    {
321
      if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
322
        return 0;
323
    }
324
  else
325
    {
326
      /* We need something smarter to optimize access to archives.
327
         Currently, anything inside an archive is read via the file
328
         handle for the archive.  Which means that a bfd_seek on one
329
         component affects the `current position' in the archive, as
330
         well as in any other component.
331
 
332
         It might be sufficient to put a spike through the cache
333
         abstraction, and look to the archive for the file position,
334
         but I think we should try for something cleaner.
335
 
336
         In the meantime, no optimization for archives.  */
337
    }
338
 
339
  file_position = position;
340
  if (direction == SEEK_SET && abfd->my_archive != NULL)
341
    file_position += abfd->origin;
342
 
343
  if (abfd->iovec)
344
    result = abfd->iovec->bseek (abfd, file_position, direction);
345
  else
346
    result = -1;
347
 
348
  if (result != 0)
349
    {
350
      int hold_errno = errno;
351
 
352
      /* Force redetermination of `where' field.  */
353
      bfd_tell (abfd);
354
 
355
      /* An EINVAL error probably means that the file offset was
356
         absurd.  */
357
      if (hold_errno == EINVAL)
358
        bfd_set_error (bfd_error_file_truncated);
359
      else
360
        {
361
          bfd_set_error (bfd_error_system_call);
362
          errno = hold_errno;
363
        }
364
    }
365
  else
366
    {
367
      /* Adjust `where' field.  */
368
      if (direction == SEEK_SET)
369
        abfd->where = position;
370
      else
371
        abfd->where += position;
372
    }
373
  return result;
374
}
375
 
376
/*
377
FUNCTION
378
        bfd_get_mtime
379
 
380
SYNOPSIS
381
        long bfd_get_mtime (bfd *abfd);
382
 
383
DESCRIPTION
384
        Return the file modification time (as read from the file system, or
385
        from the archive header for archive members).
386
 
387
*/
388
 
389
long
390
bfd_get_mtime (bfd *abfd)
391
{
392
  struct stat buf;
393
 
394
  if (abfd->mtime_set)
395
    return abfd->mtime;
396
 
397
  if (abfd->iovec == NULL)
398
    return 0;
399
 
400
  if (abfd->iovec->bstat (abfd, &buf) != 0)
401
    return 0;
402
 
403
  abfd->mtime = buf.st_mtime;           /* Save value in case anyone wants it */
404
  return buf.st_mtime;
405
}
406
 
407
/*
408
FUNCTION
409
        bfd_get_size
410
 
411
SYNOPSIS
412
        file_ptr bfd_get_size (bfd *abfd);
413
 
414
DESCRIPTION
415
        Return the file size (as read from file system) for the file
416
        associated with BFD @var{abfd}.
417
 
418
        The initial motivation for, and use of, this routine is not
419
        so we can get the exact size of the object the BFD applies to, since
420
        that might not be generally possible (archive members for example).
421
        It would be ideal if someone could eventually modify
422
        it so that such results were guaranteed.
423
 
424
        Instead, we want to ask questions like "is this NNN byte sized
425
        object I'm about to try read from file offset YYY reasonable?"
426
        As as example of where we might do this, some object formats
427
        use string tables for which the first <<sizeof (long)>> bytes of the
428
        table contain the size of the table itself, including the size bytes.
429
        If an application tries to read what it thinks is one of these
430
        string tables, without some way to validate the size, and for
431
        some reason the size is wrong (byte swapping error, wrong location
432
        for the string table, etc.), the only clue is likely to be a read
433
        error when it tries to read the table, or a "virtual memory
434
        exhausted" error when it tries to allocate 15 bazillon bytes
435
        of space for the 15 bazillon byte table it is about to read.
436
        This function at least allows us to answer the question, "is the
437
        size reasonable?".
438
*/
439
 
440
file_ptr
441
bfd_get_size (bfd *abfd)
442
{
443
  struct stat buf;
444
 
445
  if ((abfd->flags & BFD_IN_MEMORY) != 0)
446
    return ((struct bfd_in_memory *) abfd->iostream)->size;
447
 
448
  if (abfd->iovec == NULL)
449
    return 0;
450
 
451
  if (abfd->iovec->bstat (abfd, &buf) != 0)
452
    return 0;
453
 
454
  return buf.st_size;
455
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.