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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [ar.c] - Blame information for rev 95

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

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

powered by: WebSVN 2.1.0

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