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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [binutils/] [ar.c] - Blame information for rev 825

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

Line No. Rev Author Line
1 38 julius
/* ar.c - Archive modify and extract.
2
   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3
   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GNU Binutils.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
/*
24
   Bugs: should use getopt the way tar does (complete w/optional -) and
25
   should have long options too. GNU ar used to check file against filesystem
26
   in quick_update and replace operations (would check mtime). Doesn't warn
27
   when name truncated. No way to specify pos_end. Error messages should be
28
   more consistent.  */
29
 
30
#include "sysdep.h"
31
#include "bfd.h"
32
#include "libiberty.h"
33
#include "progress.h"
34
#include "aout/ar.h"
35
#include "libbfd.h"
36
#include "bucomm.h"
37
#include "arsup.h"
38
#include "filenames.h"
39
#include "binemul.h"
40
#include <sys/stat.h>
41
 
42
#ifdef __GO32___
43
#define EXT_NAME_LEN 3          /* Bufflen of addition to name if it's MS-DOS.  */
44
#else
45
#define EXT_NAME_LEN 6          /* Ditto for *NIX.  */
46
#endif
47
 
48
/* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX  */
49
 
50
struct ar_hdr *
51
  bfd_special_undocumented_glue (bfd * abfd, const char *filename);
52
 
53
/* Static declarations.  */
54
 
55
static void mri_emul (void);
56
static const char *normalize (const char *, bfd *);
57
static void remove_output (void);
58
static void map_over_members (bfd *, void (*)(bfd *), char **, int);
59
static void print_contents (bfd * member);
60
static void delete_members (bfd *, char **files_to_delete);
61
 
62
static void move_members (bfd *, char **files_to_move);
63
static void replace_members
64
  (bfd *, char **files_to_replace, bfd_boolean quick);
65
static void print_descr (bfd * abfd);
66
static void write_archive (bfd *);
67
static int  ranlib_only (const char *archname);
68
static int  ranlib_touch (const char *archname);
69
static void usage (int);
70
 
71
/** Globals and flags.  */
72
 
73
static int mri_mode;
74
 
75
/* This flag distinguishes between ar and ranlib:
76
   1 means this is 'ranlib'; 0 means this is 'ar'.
77
   -1 means if we should use argv[0] to decide.  */
78
extern int is_ranlib;
79
 
80
/* Nonzero means don't warn about creating the archive file if necessary.  */
81
int silent_create = 0;
82
 
83
/* Nonzero means describe each action performed.  */
84
int verbose = 0;
85
 
86
/* Nonzero means preserve dates of members when extracting them.  */
87
int preserve_dates = 0;
88
 
89
/* Nonzero means don't replace existing members whose dates are more recent
90
   than the corresponding files.  */
91
int newer_only = 0;
92
 
93
/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
94
   member).  -1 means we've been explicitly asked to not write a symbol table;
95
   +1 means we've been explicitly asked to write it;
96
 
97
   Traditionally, the default in BSD has been to not write the table.
98
   However, for POSIX.2 compliance the default is now to write a symbol table
99
   if any of the members are object files.  */
100
int write_armap = 0;
101
 
102
/* Nonzero means it's the name of an existing member; position new or moved
103
   files with respect to this one.  */
104
char *posname = NULL;
105
 
106
/* Sez how to use `posname': pos_before means position before that member.
107
   pos_after means position after that member. pos_end means always at end.
108
   pos_default means default appropriately. For the latter two, `posname'
109
   should also be zero.  */
110
enum pos
111
  {
112
    pos_default, pos_before, pos_after, pos_end
113
  } postype = pos_default;
114
 
115
static bfd **
116
get_pos_bfd (bfd **, enum pos, const char *);
117
 
118
/* For extract/delete only.  If COUNTED_NAME_MODE is TRUE, we only
119
   extract the COUNTED_NAME_COUNTER instance of that name.  */
120
static bfd_boolean counted_name_mode = 0;
121
static int counted_name_counter = 0;
122
 
123
/* Whether to truncate names of files stored in the archive.  */
124
static bfd_boolean ar_truncate = FALSE;
125
 
126
/* Whether to use a full file name match when searching an archive.
127
   This is convenient for archives created by the Microsoft lib
128
   program.  */
129
static bfd_boolean full_pathname = FALSE;
130
 
131
/* Whether to create a "thin" archive (symbol index only -- no files).  */
132
static bfd_boolean make_thin_archive = FALSE;
133
 
134
int interactive = 0;
135
 
136
static void
137
mri_emul (void)
138
{
139
  interactive = isatty (fileno (stdin));
140
  yyparse ();
141
}
142
 
143
/* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
144
   COUNT is the length of the FILES chain; FUNCTION is called on each entry
145
   whose name matches one in FILES.  */
146
 
147
static void
148
map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
149
{
150
  bfd *head;
151
  int match_count;
152
 
153
  if (count == 0)
154
    {
155
      for (head = arch->archive_next; head; head = head->archive_next)
156
        {
157
          PROGRESS (1);
158
          function (head);
159
        }
160
      return;
161
    }
162
 
163
  /* This may appear to be a baroque way of accomplishing what we want.
164
     However we have to iterate over the filenames in order to notice where
165
     a filename is requested but does not exist in the archive.  Ditto
166
     mapping over each file each time -- we want to hack multiple
167
     references.  */
168
 
169
  for (; count > 0; files++, count--)
170
    {
171
      bfd_boolean found = FALSE;
172
 
173
      match_count = 0;
174
      for (head = arch->archive_next; head; head = head->archive_next)
175
        {
176
          const char * filename;
177
 
178
          PROGRESS (1);
179
          filename = head->filename;
180
          if (filename == NULL)
181
            {
182
              /* Some archive formats don't get the filenames filled in
183
                 until the elements are opened.  */
184
              struct stat buf;
185
              bfd_stat_arch_elt (head, &buf);
186
            }
187
          else if (bfd_is_thin_archive (arch))
188
            {
189
              /* Thin archives store full pathnames.  Need to normalize.  */
190
              filename = normalize (filename, arch);
191
            }
192
 
193
          if ((filename != NULL) &&
194
              (!FILENAME_CMP (normalize (*files, arch), filename)))
195
            {
196
              ++match_count;
197
              if (counted_name_mode
198
                  && match_count != counted_name_counter)
199
                {
200
                  /* Counting, and didn't match on count; go on to the
201
                     next one.  */
202
                  continue;
203
                }
204
 
205
              found = TRUE;
206
              function (head);
207
            }
208
        }
209
 
210
      if (!found)
211
        /* xgettext:c-format */
212
        fprintf (stderr, _("no entry %s in archive\n"), *files);
213
    }
214
}
215
 
216
bfd_boolean operation_alters_arch = FALSE;
217
 
218
static void
219
usage (int help)
220
{
221
  FILE *s;
222
 
223
  s = help ? stdout : stderr;
224
 
225
  if (! is_ranlib)
226
    {
227
      /* xgettext:c-format */
228
      fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
229
               program_name);
230
      /* xgettext:c-format */
231
      fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
232
      fprintf (s, _(" commands:\n"));
233
      fprintf (s, _("  d            - delete file(s) from the archive\n"));
234
      fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
235
      fprintf (s, _("  p            - print file(s) found in the archive\n"));
236
      fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
237
      fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
238
      fprintf (s, _("  t            - display contents of archive\n"));
239
      fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
240
      fprintf (s, _(" command specific modifiers:\n"));
241
      fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
242
      fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
243
      fprintf (s, _("  [N]          - use instance [count] of name\n"));
244
      fprintf (s, _("  [f]          - truncate inserted file names\n"));
245
      fprintf (s, _("  [P]          - use full path names when matching\n"));
246
      fprintf (s, _("  [o]          - preserve original dates\n"));
247
      fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
248
      fprintf (s, _(" generic modifiers:\n"));
249
      fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
250
      fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
251
      fprintf (s, _("  [S]          - do not build a symbol table\n"));
252
      fprintf (s, _("  [T]          - make a thin archive\n"));
253
      fprintf (s, _("  [v]          - be verbose\n"));
254
      fprintf (s, _("  [V]          - display the version number\n"));
255
      fprintf (s, _("  @<file>      - read options from <file>\n"));
256
 
257
      ar_emul_usage (s);
258
    }
259
  else
260
    {
261
      /* xgettext:c-format */
262
      fprintf (s, _("Usage: %s [options] archive\n"), program_name);
263
      fprintf (s, _(" Generate an index to speed access to archives\n"));
264
      fprintf (s, _(" The options are:\n\
265
  @<file>                      Read options from <file>\n\
266
  -t                           Update the archive's symbol map timestamp\n\
267
  -h --help                    Print this help message\n\
268
  -v --version                 Print version information\n"));
269
    }
270
 
271
  list_supported_targets (program_name, s);
272
 
273
  if (REPORT_BUGS_TO[0] && help)
274
    fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
275
 
276
  xexit (help ? 0 : 1);
277
}
278
 
279
/* Normalize a file name specified on the command line into a file
280
   name which we will use in an archive.  */
281
 
282
static const char *
283
normalize (const char *file, bfd *abfd)
284
{
285
  const char *filename;
286
 
287
  if (full_pathname)
288
    return file;
289
 
290
  filename = strrchr (file, '/');
291
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
292
  {
293
    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
294
    char *bslash = strrchr (file, '\\');
295
 
296
    if (filename == NULL || (bslash != NULL && bslash > filename))
297
      filename = bslash;
298
    if (filename == NULL && file[0] != '\0' && file[1] == ':')
299
      filename = file + 1;
300
  }
301
#endif
302
  if (filename != (char *) NULL)
303
    filename++;
304
  else
305
    filename = file;
306
 
307
  if (ar_truncate
308
      && abfd != NULL
309
      && strlen (filename) > abfd->xvec->ar_max_namelen)
310
    {
311
      char *s;
312
 
313
      /* Space leak.  */
314
      s = xmalloc (abfd->xvec->ar_max_namelen + 1);
315
      memcpy (s, filename, abfd->xvec->ar_max_namelen);
316
      s[abfd->xvec->ar_max_namelen] = '\0';
317
      filename = s;
318
    }
319
 
320
  return filename;
321
}
322
 
323
/* Remove any output file.  This is only called via xatexit.  */
324
 
325
static const char *output_filename = NULL;
326
static FILE *output_file = NULL;
327
static bfd *output_bfd = NULL;
328
 
329
static void
330
remove_output (void)
331
{
332
  if (output_filename != NULL)
333
    {
334
      if (output_bfd != NULL)
335
        bfd_cache_close (output_bfd);
336
      if (output_file != NULL)
337
        fclose (output_file);
338
      unlink_if_ordinary (output_filename);
339
    }
340
}
341
 
342
/* The option parsing should be in its own function.
343
   It will be when I have getopt working.  */
344
 
345
int main (int, char **);
346
 
347
int
348
main (int argc, char **argv)
349
{
350
  char *arg_ptr;
351
  char c;
352
  enum
353
    {
354
      none = 0, delete, replace, print_table,
355
      print_files, extract, move, quick_append
356
    } operation = none;
357
  int arg_index;
358
  char **files;
359
  int file_count;
360
  char *inarch_filename;
361
  int show_version;
362
  int i;
363
  int do_posix = 0;
364
 
365
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
366
  setlocale (LC_MESSAGES, "");
367
#endif
368
#if defined (HAVE_SETLOCALE)
369
  setlocale (LC_CTYPE, "");
370
#endif
371
  bindtextdomain (PACKAGE, LOCALEDIR);
372
  textdomain (PACKAGE);
373
 
374
  program_name = argv[0];
375
  xmalloc_set_program_name (program_name);
376
 
377
  expandargv (&argc, &argv);
378
 
379
  if (is_ranlib < 0)
380
    {
381
      char *temp;
382
 
383
      temp = strrchr (program_name, '/');
384
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
385
      {
386
        /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
387
        char *bslash = strrchr (program_name, '\\');
388
 
389
        if (temp == NULL || (bslash != NULL && bslash > temp))
390
          temp = bslash;
391
        if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
392
          temp = program_name + 1;
393
      }
394
#endif
395
      if (temp == NULL)
396
        temp = program_name;
397
      else
398
        ++temp;
399
      if (strlen (temp) >= 6
400
          && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
401
        is_ranlib = 1;
402
      else
403
        is_ranlib = 0;
404
    }
405
 
406
  if (argc > 1 && argv[1][0] == '-')
407
    {
408
      if (strcmp (argv[1], "--help") == 0)
409
        usage (1);
410
      else if (strcmp (argv[1], "--version") == 0)
411
        {
412
          if (is_ranlib)
413
            print_version ("ranlib");
414
          else
415
            print_version ("ar");
416
        }
417
    }
418
 
419
  START_PROGRESS (program_name, 0);
420
 
421
  bfd_init ();
422
  set_default_bfd_target ();
423
 
424
  show_version = 0;
425
 
426
  xatexit (remove_output);
427
 
428
  for (i = 1; i < argc; i++)
429
    if (! ar_emul_parse_arg (argv[i]))
430
      break;
431
  argv += (i - 1);
432
  argc -= (i - 1);
433
 
434
  if (is_ranlib)
435
    {
436
      int status = 0;
437
      bfd_boolean touch = FALSE;
438
 
439
      if (argc < 2
440
          || strcmp (argv[1], "--help") == 0
441
          || strcmp (argv[1], "-h") == 0
442
          || strcmp (argv[1], "-H") == 0)
443
        usage (0);
444
      if (strcmp (argv[1], "-V") == 0
445
          || strcmp (argv[1], "-v") == 0
446
          || CONST_STRNEQ (argv[1], "--v"))
447
        print_version ("ranlib");
448
      arg_index = 1;
449
      if (strcmp (argv[1], "-t") == 0)
450
        {
451
          ++arg_index;
452
          touch = TRUE;
453
        }
454
      while (arg_index < argc)
455
        {
456
          if (! touch)
457
            status |= ranlib_only (argv[arg_index]);
458
          else
459
            status |= ranlib_touch (argv[arg_index]);
460
          ++arg_index;
461
        }
462
      xexit (status);
463
    }
464
 
465
  if (argc == 2 && strcmp (argv[1], "-M") == 0)
466
    {
467
      mri_emul ();
468
      xexit (0);
469
    }
470
 
471
  if (argc < 2)
472
    usage (0);
473
 
474
  arg_index = 1;
475
  arg_ptr = argv[arg_index];
476
 
477
  if (*arg_ptr == '-')
478
    {
479
      /* When the first option starts with '-' we support POSIX-compatible
480
         option parsing.  */
481
      do_posix = 1;
482
      ++arg_ptr;                        /* compatibility */
483
    }
484
 
485
  do
486
    {
487
      while ((c = *arg_ptr++) != '\0')
488
        {
489
          switch (c)
490
            {
491
            case 'd':
492
            case 'm':
493
            case 'p':
494
            case 'q':
495
            case 'r':
496
            case 't':
497
            case 'x':
498
              if (operation != none)
499
                fatal (_("two different operation options specified"));
500
              switch (c)
501
                {
502
                case 'd':
503
                  operation = delete;
504
                  operation_alters_arch = TRUE;
505
                  break;
506
                case 'm':
507
                  operation = move;
508
                  operation_alters_arch = TRUE;
509
                  break;
510
                case 'p':
511
                  operation = print_files;
512
                  break;
513
                case 'q':
514
                  operation = quick_append;
515
                  operation_alters_arch = TRUE;
516
                  break;
517
                case 'r':
518
                  operation = replace;
519
                  operation_alters_arch = TRUE;
520
                  break;
521
                case 't':
522
                  operation = print_table;
523
                  break;
524
                case 'x':
525
                  operation = extract;
526
                  break;
527
                }
528
            case 'l':
529
              break;
530
            case 'c':
531
              silent_create = 1;
532
              break;
533
            case 'o':
534
              preserve_dates = 1;
535
              break;
536
            case 'V':
537
              show_version = TRUE;
538
              break;
539
            case 's':
540
              write_armap = 1;
541
              break;
542
            case 'S':
543
              write_armap = -1;
544
              break;
545
            case 'u':
546
              newer_only = 1;
547
              break;
548
            case 'v':
549
              verbose = 1;
550
              break;
551
            case 'a':
552
              postype = pos_after;
553
              break;
554
            case 'b':
555
              postype = pos_before;
556
              break;
557
            case 'i':
558
              postype = pos_before;
559
              break;
560
            case 'M':
561
              mri_mode = 1;
562
              break;
563
            case 'N':
564
              counted_name_mode = TRUE;
565
              break;
566
            case 'f':
567
              ar_truncate = TRUE;
568
              break;
569
            case 'P':
570
              full_pathname = TRUE;
571
              break;
572
            case 'T':
573
              make_thin_archive = TRUE;
574
              break;
575
            default:
576
              /* xgettext:c-format */
577
              non_fatal (_("illegal option -- %c"), c);
578
              usage (0);
579
            }
580
        }
581
 
582
      /* With POSIX-compatible option parsing continue with the next
583
         argument if it starts with '-'.  */
584
      if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
585
        arg_ptr = argv[++arg_index] + 1;
586
      else
587
        do_posix = 0;
588
    }
589
  while (do_posix);
590
 
591
  if (show_version)
592
    print_version ("ar");
593
 
594
  ++arg_index;
595
  if (arg_index >= argc)
596
    usage (0);
597
 
598
  if (mri_mode)
599
    {
600
      mri_emul ();
601
    }
602
  else
603
    {
604
      bfd *arch;
605
 
606
      /* We don't use do_quick_append any more.  Too many systems
607
         expect ar to always rebuild the symbol table even when q is
608
         used.  */
609
 
610
      /* We can't write an armap when using ar q, so just do ar r
611
         instead.  */
612
      if (operation == quick_append && write_armap)
613
        operation = replace;
614
 
615
      if ((operation == none || operation == print_table)
616
          && write_armap == 1)
617
        xexit (ranlib_only (argv[arg_index]));
618
 
619
      if (operation == none)
620
        fatal (_("no operation specified"));
621
 
622
      if (newer_only && operation != replace)
623
        fatal (_("`u' is only meaningful with the `r' option."));
624
 
625
      if (postype != pos_default)
626
        posname = argv[arg_index++];
627
 
628
      if (counted_name_mode)
629
        {
630
          if (operation != extract && operation != delete)
631
             fatal (_("`N' is only meaningful with the `x' and `d' options."));
632
          counted_name_counter = atoi (argv[arg_index++]);
633
          if (counted_name_counter <= 0)
634
            fatal (_("Value for `N' must be positive."));
635
        }
636
 
637
      inarch_filename = argv[arg_index++];
638
 
639
      files = arg_index < argc ? argv + arg_index : NULL;
640
      file_count = argc - arg_index;
641
 
642
      arch = open_inarch (inarch_filename,
643
                          files == NULL ? (char *) NULL : files[0]);
644
 
645
      if (operation == extract && bfd_is_thin_archive (arch))
646
        fatal (_("`x' cannot be used on thin archives."));
647
 
648
      switch (operation)
649
        {
650
        case print_table:
651
          map_over_members (arch, print_descr, files, file_count);
652
          break;
653
 
654
        case print_files:
655
          map_over_members (arch, print_contents, files, file_count);
656
          break;
657
 
658
        case extract:
659
          map_over_members (arch, extract_file, files, file_count);
660
          break;
661
 
662
        case delete:
663
          if (files != NULL)
664
            delete_members (arch, files);
665
          else
666
            output_filename = NULL;
667
          break;
668
 
669
        case move:
670
          if (files != NULL)
671
            move_members (arch, files);
672
          else
673
            output_filename = NULL;
674
          break;
675
 
676
        case replace:
677
        case quick_append:
678
          if (files != NULL || write_armap > 0)
679
            replace_members (arch, files, operation == quick_append);
680
          else
681
            output_filename = NULL;
682
          break;
683
 
684
          /* Shouldn't happen! */
685
        default:
686
          /* xgettext:c-format */
687
          fatal (_("internal error -- this option not implemented"));
688
        }
689
    }
690
 
691
  END_PROGRESS (program_name);
692
 
693
  xexit (0);
694
  return 0;
695
}
696
 
697
bfd *
698
open_inarch (const char *archive_filename, const char *file)
699
{
700
  const char *target;
701
  bfd **last_one;
702
  bfd *next_one;
703
  struct stat sbuf;
704
  bfd *arch;
705
  char **matching;
706
 
707
  bfd_set_error (bfd_error_no_error);
708
 
709
  target = NULL;
710
 
711
  if (stat (archive_filename, &sbuf) != 0)
712
    {
713
#if !defined(__GO32__) || defined(__DJGPP__)
714
 
715
      /* FIXME: I don't understand why this fragment was ifndef'ed
716
         away for __GO32__; perhaps it was in the days of DJGPP v1.x.
717
         stat() works just fine in v2.x, so I think this should be
718
         removed.  For now, I enable it for DJGPP v2. -- EZ.  */
719
 
720
/* KLUDGE ALERT! Temporary fix until I figger why
721
   stat() is wrong ... think it's buried in GO32's IDT - Jax */
722
      if (errno != ENOENT)
723
        bfd_fatal (archive_filename);
724
#endif
725
 
726
      if (!operation_alters_arch)
727
        {
728
          fprintf (stderr, "%s: ", program_name);
729
          perror (archive_filename);
730
          maybequit ();
731
          return NULL;
732
        }
733
 
734
      /* Try to figure out the target to use for the archive from the
735
         first object on the list.  */
736
      if (file != NULL)
737
        {
738
          bfd *obj;
739
 
740
          obj = bfd_openr (file, NULL);
741
          if (obj != NULL)
742
            {
743
              if (bfd_check_format (obj, bfd_object))
744
                target = bfd_get_target (obj);
745
              (void) bfd_close (obj);
746
            }
747
        }
748
 
749
      /* Create an empty archive.  */
750
      arch = bfd_openw (archive_filename, target);
751
      if (arch == NULL
752
          || ! bfd_set_format (arch, bfd_archive)
753
          || ! bfd_close (arch))
754
        bfd_fatal (archive_filename);
755
      else if (!silent_create)
756
        non_fatal (_("creating %s"), archive_filename);
757
 
758
      /* If we die creating a new archive, don't leave it around.  */
759
      output_filename = archive_filename;
760
    }
761
 
762
  arch = bfd_openr (archive_filename, target);
763
  if (arch == NULL)
764
    {
765
    bloser:
766
      bfd_fatal (archive_filename);
767
    }
768
 
769
  if (! bfd_check_format_matches (arch, bfd_archive, &matching))
770
    {
771
      bfd_nonfatal (archive_filename);
772
      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
773
        {
774
          list_matching_formats (matching);
775
          free (matching);
776
        }
777
      xexit (1);
778
    }
779
 
780
  last_one = &(arch->archive_next);
781
  /* Read all the contents right away, regardless.  */
782
  for (next_one = bfd_openr_next_archived_file (arch, NULL);
783
       next_one;
784
       next_one = bfd_openr_next_archived_file (arch, next_one))
785
    {
786
      PROGRESS (1);
787
      *last_one = next_one;
788
      last_one = &next_one->archive_next;
789
    }
790
  *last_one = (bfd *) NULL;
791
  if (bfd_get_error () != bfd_error_no_more_archived_files)
792
    goto bloser;
793
  return arch;
794
}
795
 
796
static void
797
print_contents (bfd *abfd)
798
{
799
  size_t ncopied = 0;
800
  char *cbuf = xmalloc (BUFSIZE);
801
  struct stat buf;
802
  size_t size;
803
  if (bfd_stat_arch_elt (abfd, &buf) != 0)
804
    /* xgettext:c-format */
805
    fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
806
 
807
  if (verbose)
808
    /* xgettext:c-format */
809
    printf (_("\n<%s>\n\n"), bfd_get_filename (abfd));
810
 
811
  bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
812
 
813
  size = buf.st_size;
814
  while (ncopied < size)
815
    {
816
 
817
      size_t nread;
818
      size_t tocopy = size - ncopied;
819
      if (tocopy > BUFSIZE)
820
        tocopy = BUFSIZE;
821
 
822
      nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
823
      if (nread != tocopy)
824
        /* xgettext:c-format */
825
        fatal (_("%s is not a valid archive"),
826
               bfd_get_filename (bfd_my_archive (abfd)));
827
 
828
      /* fwrite in mingw32 may return int instead of size_t. Cast the
829
         return value to size_t to avoid comparison between signed and
830
         unsigned values.  */
831
      if ((size_t) fwrite (cbuf, 1, nread, stdout) != nread)
832
        fatal ("stdout: %s", strerror (errno));
833
      ncopied += tocopy;
834
    }
835
  free (cbuf);
836
}
837
 
838
/* Extract a member of the archive into its own file.
839
 
840
   We defer opening the new file until after we have read a BUFSIZ chunk of the
841
   old one, since we know we have just read the archive header for the old
842
   one.  Since most members are shorter than BUFSIZ, this means we will read
843
   the old header, read the old data, write a new inode for the new file, and
844
   write the new data, and be done. This 'optimization' is what comes from
845
   sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
846
   Gilmore  */
847
 
848
void
849
extract_file (bfd *abfd)
850
{
851
  FILE *ostream;
852
  char *cbuf = xmalloc (BUFSIZE);
853
  size_t nread, tocopy;
854
  size_t ncopied = 0;
855
  size_t size;
856
  struct stat buf;
857
 
858
  if (bfd_stat_arch_elt (abfd, &buf) != 0)
859
    /* xgettext:c-format */
860
    fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
861
  size = buf.st_size;
862
 
863
  if (verbose)
864
    printf ("x - %s\n", bfd_get_filename (abfd));
865
 
866
  bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
867
 
868
  ostream = NULL;
869
  if (size == 0)
870
    {
871
      /* Seems like an abstraction violation, eh?  Well it's OK! */
872
      output_filename = bfd_get_filename (abfd);
873
 
874
      ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
875
      if (ostream == NULL)
876
        {
877
          perror (bfd_get_filename (abfd));
878
          xexit (1);
879
        }
880
 
881
      output_file = ostream;
882
    }
883
  else
884
    while (ncopied < size)
885
      {
886
        tocopy = size - ncopied;
887
        if (tocopy > BUFSIZE)
888
          tocopy = BUFSIZE;
889
 
890
        nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
891
        if (nread != tocopy)
892
          /* xgettext:c-format */
893
          fatal (_("%s is not a valid archive"),
894
                 bfd_get_filename (bfd_my_archive (abfd)));
895
 
896
        /* See comment above; this saves disk arm motion */
897
        if (ostream == NULL)
898
          {
899
            /* Seems like an abstraction violation, eh?  Well it's OK! */
900
            output_filename = bfd_get_filename (abfd);
901
 
902
            ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
903
            if (ostream == NULL)
904
              {
905
                perror (bfd_get_filename (abfd));
906
                xexit (1);
907
              }
908
 
909
            output_file = ostream;
910
          }
911
 
912
        /* fwrite in mingw32 may return int instead of size_t. Cast
913
           the return value to size_t to avoid comparison between
914
           signed and unsigned values.  */
915
        if ((size_t) fwrite (cbuf, 1, nread, ostream) != nread)
916
          fatal ("%s: %s", output_filename, strerror (errno));
917
        ncopied += tocopy;
918
      }
919
 
920
  if (ostream != NULL)
921
    fclose (ostream);
922
 
923
  output_file = NULL;
924
  output_filename = NULL;
925
 
926
  chmod (bfd_get_filename (abfd), buf.st_mode);
927
 
928
  if (preserve_dates)
929
    {
930
      /* Set access time to modification time.  Only st_mtime is
931
         initialized by bfd_stat_arch_elt.  */
932
      buf.st_atime = buf.st_mtime;
933
      set_times (bfd_get_filename (abfd), &buf);
934
    }
935
 
936
  free (cbuf);
937
}
938
 
939
static void
940
write_archive (bfd *iarch)
941
{
942
  bfd *obfd;
943
  char *old_name, *new_name;
944
  bfd *contents_head = iarch->archive_next;
945
 
946
  old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
947
  strcpy (old_name, bfd_get_filename (iarch));
948
  new_name = make_tempname (old_name);
949
 
950
  if (new_name == NULL)
951
    bfd_fatal ("could not create temporary file whilst writing archive");
952
 
953
  output_filename = new_name;
954
 
955
  obfd = bfd_openw (new_name, bfd_get_target (iarch));
956
 
957
  if (obfd == NULL)
958
    bfd_fatal (old_name);
959
 
960
  output_bfd = obfd;
961
 
962
  bfd_set_format (obfd, bfd_archive);
963
 
964
  /* Request writing the archive symbol table unless we've
965
     been explicitly requested not to.  */
966
  obfd->has_armap = write_armap >= 0;
967
 
968
  if (ar_truncate)
969
    {
970
      /* This should really use bfd_set_file_flags, but that rejects
971
         archives.  */
972
      obfd->flags |= BFD_TRADITIONAL_FORMAT;
973
    }
974
 
975
  if (make_thin_archive || bfd_is_thin_archive (iarch))
976
    bfd_is_thin_archive (obfd) = 1;
977
 
978
  if (!bfd_set_archive_head (obfd, contents_head))
979
    bfd_fatal (old_name);
980
 
981
  if (!bfd_close (obfd))
982
    bfd_fatal (old_name);
983
 
984
  output_bfd = NULL;
985
  output_filename = NULL;
986
 
987
  /* We don't care if this fails; we might be creating the archive.  */
988
  bfd_close (iarch);
989
 
990
  if (smart_rename (new_name, old_name, 0) != 0)
991
    xexit (1);
992
}
993
 
994
/* Return a pointer to the pointer to the entry which should be rplacd'd
995
   into when altering.  DEFAULT_POS should be how to interpret pos_default,
996
   and should be a pos value.  */
997
 
998
static bfd **
999
get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
1000
{
1001
  bfd **after_bfd = contents;
1002
  enum pos realpos;
1003
  const char *realposname;
1004
 
1005
  if (postype == pos_default)
1006
    {
1007
      realpos = default_pos;
1008
      realposname = default_posname;
1009
    }
1010
  else
1011
    {
1012
      realpos = postype;
1013
      realposname = posname;
1014
    }
1015
 
1016
  if (realpos == pos_end)
1017
    {
1018
      while (*after_bfd)
1019
        after_bfd = &((*after_bfd)->archive_next);
1020
    }
1021
  else
1022
    {
1023
      for (; *after_bfd; after_bfd = &(*after_bfd)->archive_next)
1024
        if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
1025
          {
1026
            if (realpos == pos_after)
1027
              after_bfd = &(*after_bfd)->archive_next;
1028
            break;
1029
          }
1030
    }
1031
  return after_bfd;
1032
}
1033
 
1034
static void
1035
delete_members (bfd *arch, char **files_to_delete)
1036
{
1037
  bfd **current_ptr_ptr;
1038
  bfd_boolean found;
1039
  bfd_boolean something_changed = FALSE;
1040
  int match_count;
1041
 
1042
  for (; *files_to_delete != NULL; ++files_to_delete)
1043
    {
1044
      /* In a.out systems, the armap is optional.  It's also called
1045
         __.SYMDEF.  So if the user asked to delete it, we should remember
1046
         that fact. This isn't quite right for COFF systems (where
1047
         __.SYMDEF might be regular member), but it's very unlikely
1048
         to be a problem.  FIXME */
1049
 
1050
      if (!strcmp (*files_to_delete, "__.SYMDEF"))
1051
        {
1052
          arch->has_armap = FALSE;
1053
          write_armap = -1;
1054
          continue;
1055
        }
1056
 
1057
      found = FALSE;
1058
      match_count = 0;
1059
      current_ptr_ptr = &(arch->archive_next);
1060
      while (*current_ptr_ptr)
1061
        {
1062
          if (FILENAME_CMP (normalize (*files_to_delete, arch),
1063
                            (*current_ptr_ptr)->filename) == 0)
1064
            {
1065
              ++match_count;
1066
              if (counted_name_mode
1067
                  && match_count != counted_name_counter)
1068
                {
1069
                  /* Counting, and didn't match on count; go on to the
1070
                     next one.  */
1071
                }
1072
              else
1073
                {
1074
                  found = TRUE;
1075
                  something_changed = TRUE;
1076
                  if (verbose)
1077
                    printf ("d - %s\n",
1078
                            *files_to_delete);
1079
                  *current_ptr_ptr = ((*current_ptr_ptr)->archive_next);
1080
                  goto next_file;
1081
                }
1082
            }
1083
 
1084
          current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
1085
        }
1086
 
1087
      if (verbose && !found)
1088
        {
1089
          /* xgettext:c-format */
1090
          printf (_("No member named `%s'\n"), *files_to_delete);
1091
        }
1092
    next_file:
1093
      ;
1094
    }
1095
 
1096
  if (something_changed)
1097
    write_archive (arch);
1098
  else
1099
    output_filename = NULL;
1100
}
1101
 
1102
 
1103
/* Reposition existing members within an archive */
1104
 
1105
static void
1106
move_members (bfd *arch, char **files_to_move)
1107
{
1108
  bfd **after_bfd;              /* New entries go after this one */
1109
  bfd **current_ptr_ptr;        /* cdr pointer into contents */
1110
 
1111
  for (; *files_to_move; ++files_to_move)
1112
    {
1113
      current_ptr_ptr = &(arch->archive_next);
1114
      while (*current_ptr_ptr)
1115
        {
1116
          bfd *current_ptr = *current_ptr_ptr;
1117
          if (FILENAME_CMP (normalize (*files_to_move, arch),
1118
                            current_ptr->filename) == 0)
1119
            {
1120
              /* Move this file to the end of the list - first cut from
1121
                 where it is.  */
1122
              bfd *link;
1123
              *current_ptr_ptr = current_ptr->archive_next;
1124
 
1125
              /* Now glue to end */
1126
              after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
1127
              link = *after_bfd;
1128
              *after_bfd = current_ptr;
1129
              current_ptr->archive_next = link;
1130
 
1131
              if (verbose)
1132
                printf ("m - %s\n", *files_to_move);
1133
 
1134
              goto next_file;
1135
            }
1136
 
1137
          current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
1138
        }
1139
      /* xgettext:c-format */
1140
      fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1141
 
1142
    next_file:;
1143
    }
1144
 
1145
  write_archive (arch);
1146
}
1147
 
1148
/* Ought to default to replacing in place, but this is existing practice!  */
1149
 
1150
static void
1151
replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
1152
{
1153
  bfd_boolean changed = FALSE;
1154
  bfd **after_bfd;              /* New entries go after this one.  */
1155
  bfd *current;
1156
  bfd **current_ptr;
1157
 
1158
  while (files_to_move && *files_to_move)
1159
    {
1160
      if (! quick)
1161
        {
1162
          current_ptr = &arch->archive_next;
1163
          while (*current_ptr)
1164
            {
1165
              current = *current_ptr;
1166
 
1167
              /* For compatibility with existing ar programs, we
1168
                 permit the same file to be added multiple times.  */
1169
              if (FILENAME_CMP (normalize (*files_to_move, arch),
1170
                                normalize (current->filename, arch)) == 0
1171
                  && current->arelt_data != NULL)
1172
                {
1173
                  if (newer_only)
1174
                    {
1175
                      struct stat fsbuf, asbuf;
1176
 
1177
                      if (stat (*files_to_move, &fsbuf) != 0)
1178
                        {
1179
                          if (errno != ENOENT)
1180
                            bfd_fatal (*files_to_move);
1181
                          goto next_file;
1182
                        }
1183
                      if (bfd_stat_arch_elt (current, &asbuf) != 0)
1184
                        /* xgettext:c-format */
1185
                        fatal (_("internal stat error on %s"),
1186
                               current->filename);
1187
 
1188
                      if (fsbuf.st_mtime <= asbuf.st_mtime)
1189
                        goto next_file;
1190
                    }
1191
 
1192
                  after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
1193
                                           current->filename);
1194
                  if (ar_emul_replace (after_bfd, *files_to_move,
1195
                                       verbose))
1196
                    {
1197
                      /* Snip out this entry from the chain.  */
1198
                      *current_ptr = (*current_ptr)->archive_next;
1199
                      changed = TRUE;
1200
                    }
1201
 
1202
                  goto next_file;
1203
                }
1204
              current_ptr = &(current->archive_next);
1205
            }
1206
        }
1207
 
1208
      /* Add to the end of the archive.  */
1209
      after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
1210
 
1211
      if (ar_emul_append (after_bfd, *files_to_move, verbose,
1212
                          make_thin_archive))
1213
        changed = TRUE;
1214
 
1215
    next_file:;
1216
 
1217
      files_to_move++;
1218
    }
1219
 
1220
  if (changed)
1221
    write_archive (arch);
1222
  else
1223
    output_filename = NULL;
1224
}
1225
 
1226
static int
1227
ranlib_only (const char *archname)
1228
{
1229
  bfd *arch;
1230
 
1231
  if (get_file_size (archname) < 1)
1232
    return 1;
1233
  write_armap = 1;
1234
  arch = open_inarch (archname, (char *) NULL);
1235
  if (arch == NULL)
1236
    xexit (1);
1237
  write_archive (arch);
1238
  return 0;
1239
}
1240
 
1241
/* Update the timestamp of the symbol map of an archive.  */
1242
 
1243
static int
1244
ranlib_touch (const char *archname)
1245
{
1246
#ifdef __GO32__
1247
  /* I don't think updating works on go32.  */
1248
  ranlib_only (archname);
1249
#else
1250
  int f;
1251
  bfd *arch;
1252
  char **matching;
1253
 
1254
  if (get_file_size (archname) < 1)
1255
    return 1;
1256
  f = open (archname, O_RDWR | O_BINARY, 0);
1257
  if (f < 0)
1258
    {
1259
      bfd_set_error (bfd_error_system_call);
1260
      bfd_fatal (archname);
1261
    }
1262
 
1263
  arch = bfd_fdopenr (archname, (const char *) NULL, f);
1264
  if (arch == NULL)
1265
    bfd_fatal (archname);
1266
  if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1267
    {
1268
      bfd_nonfatal (archname);
1269
      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1270
        {
1271
          list_matching_formats (matching);
1272
          free (matching);
1273
        }
1274
      xexit (1);
1275
    }
1276
 
1277
  if (! bfd_has_map (arch))
1278
    /* xgettext:c-format */
1279
    fatal (_("%s: no archive map to update"), archname);
1280
 
1281
  bfd_update_armap_timestamp (arch);
1282
 
1283
  if (! bfd_close (arch))
1284
    bfd_fatal (archname);
1285
#endif
1286
  return 0;
1287
}
1288
 
1289
/* Things which are interesting to map over all or some of the files: */
1290
 
1291
static void
1292
print_descr (bfd *abfd)
1293
{
1294
  print_arelt_descr (stdout, abfd, verbose);
1295
}

powered by: WebSVN 2.1.0

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