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 161

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 161 khays
          /* PR 12558: Creating and moving at the same time does
749
             not make sense.  Just create the archive instead.  */
750
          if (! silent_create)
751
            {
752
              if (files != NULL)
753
                move_members (arch, files);
754
              else
755
                output_filename = NULL;
756
              break;
757
            }
758
          /* Fall through.  */
759 15 khays
 
760
        case replace:
761
        case quick_append:
762
          if (files != NULL || write_armap > 0)
763
            replace_members (arch, files, operation == quick_append);
764
          else
765
            output_filename = NULL;
766
          break;
767
 
768
          /* Shouldn't happen! */
769
        default:
770
          /* xgettext:c-format */
771
          fatal (_("internal error -- this option not implemented"));
772
        }
773
    }
774
 
775
  END_PROGRESS (program_name);
776
 
777
  xexit (0);
778
  return 0;
779
}
780
 
781
bfd *
782
open_inarch (const char *archive_filename, const char *file)
783
{
784
  bfd **last_one;
785
  bfd *next_one;
786
  struct stat sbuf;
787
  bfd *arch;
788
  char **matching;
789
 
790
  bfd_set_error (bfd_error_no_error);
791
 
792
  if (target == NULL)
793
    target = plugin_target;
794
 
795
  if (stat (archive_filename, &sbuf) != 0)
796
    {
797
#if !defined(__GO32__) || defined(__DJGPP__)
798
 
799
      /* FIXME: I don't understand why this fragment was ifndef'ed
800
         away for __GO32__; perhaps it was in the days of DJGPP v1.x.
801
         stat() works just fine in v2.x, so I think this should be
802
         removed.  For now, I enable it for DJGPP v2. -- EZ.  */
803
 
804
      /* KLUDGE ALERT! Temporary fix until I figger why
805
         stat() is wrong ... think it's buried in GO32's IDT - Jax */
806
      if (errno != ENOENT)
807
        bfd_fatal (archive_filename);
808
#endif
809
 
810
      if (!operation_alters_arch)
811
        {
812
          fprintf (stderr, "%s: ", program_name);
813
          perror (archive_filename);
814
          maybequit ();
815
          return NULL;
816
        }
817
 
818
      /* Try to figure out the target to use for the archive from the
819
         first object on the list.  */
820
      if (file != NULL)
821
        {
822
          bfd *obj;
823
 
824
          obj = bfd_openr (file, target);
825
          if (obj != NULL)
826
            {
827
              if (bfd_check_format (obj, bfd_object))
828
                target = bfd_get_target (obj);
829
              (void) bfd_close (obj);
830
            }
831
        }
832
 
833
      /* Create an empty archive.  */
834
      arch = bfd_openw (archive_filename, target);
835
      if (arch == NULL
836
          || ! bfd_set_format (arch, bfd_archive)
837
          || ! bfd_close (arch))
838
        bfd_fatal (archive_filename);
839
      else if (!silent_create)
840
        non_fatal (_("creating %s"), archive_filename);
841
 
842
      /* If we die creating a new archive, don't leave it around.  */
843
      output_filename = archive_filename;
844
    }
845
 
846
  arch = bfd_openr (archive_filename, target);
847
  if (arch == NULL)
848
    {
849
    bloser:
850
      bfd_fatal (archive_filename);
851
    }
852
 
853
  if (! bfd_check_format_matches (arch, bfd_archive, &matching))
854
    {
855
      bfd_nonfatal (archive_filename);
856
      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
857
        {
858
          list_matching_formats (matching);
859
          free (matching);
860
        }
861
      xexit (1);
862
    }
863
 
864
  last_one = &(arch->archive_next);
865
  /* Read all the contents right away, regardless.  */
866
  for (next_one = bfd_openr_next_archived_file (arch, NULL);
867
       next_one;
868
       next_one = bfd_openr_next_archived_file (arch, next_one))
869
    {
870
      PROGRESS (1);
871
      *last_one = next_one;
872
      last_one = &next_one->archive_next;
873
    }
874
  *last_one = (bfd *) NULL;
875
  if (bfd_get_error () != bfd_error_no_more_archived_files)
876
    goto bloser;
877
  return arch;
878
}
879
 
880
static void
881
print_contents (bfd *abfd)
882
{
883
  size_t ncopied = 0;
884
  char *cbuf = (char *) xmalloc (BUFSIZE);
885
  struct stat buf;
886
  size_t size;
887
  if (bfd_stat_arch_elt (abfd, &buf) != 0)
888
    /* xgettext:c-format */
889
    fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
890
 
891
  if (verbose)
892
    printf ("\n<%s>\n\n", bfd_get_filename (abfd));
893
 
894
  bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
895
 
896
  size = buf.st_size;
897
  while (ncopied < size)
898
    {
899
 
900
      size_t nread;
901
      size_t tocopy = size - ncopied;
902
      if (tocopy > BUFSIZE)
903
        tocopy = BUFSIZE;
904
 
905
      nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
906
      if (nread != tocopy)
907
        /* xgettext:c-format */
908
        fatal (_("%s is not a valid archive"),
909
               bfd_get_filename (bfd_my_archive (abfd)));
910
 
911
      /* fwrite in mingw32 may return int instead of size_t. Cast the
912
         return value to size_t to avoid comparison between signed and
913
         unsigned values.  */
914
      if ((size_t) fwrite (cbuf, 1, nread, stdout) != nread)
915
        fatal ("stdout: %s", strerror (errno));
916
      ncopied += tocopy;
917
    }
918
  free (cbuf);
919
}
920
 
921
/* Extract a member of the archive into its own file.
922
 
923
   We defer opening the new file until after we have read a BUFSIZ chunk of the
924
   old one, since we know we have just read the archive header for the old
925
   one.  Since most members are shorter than BUFSIZ, this means we will read
926
   the old header, read the old data, write a new inode for the new file, and
927
   write the new data, and be done. This 'optimization' is what comes from
928
   sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
929
   Gilmore  */
930
 
931
void
932
extract_file (bfd *abfd)
933
{
934
  FILE *ostream;
935
  char *cbuf = (char *) xmalloc (BUFSIZE);
936
  size_t nread, tocopy;
937
  size_t ncopied = 0;
938
  size_t size;
939
  struct stat buf;
940
 
941
  if (bfd_stat_arch_elt (abfd, &buf) != 0)
942
    /* xgettext:c-format */
943
    fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
944
  size = buf.st_size;
945
 
946
  if (verbose)
947
    printf ("x - %s\n", bfd_get_filename (abfd));
948
 
949
  bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
950
 
951
  ostream = NULL;
952
  if (size == 0)
953
    {
954
      /* Seems like an abstraction violation, eh?  Well it's OK! */
955
      output_filename = bfd_get_filename (abfd);
956
 
957
      ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
958
      if (ostream == NULL)
959
        {
960
          perror (bfd_get_filename (abfd));
961
          xexit (1);
962
        }
963
 
964
      output_file = ostream;
965
    }
966
  else
967
    while (ncopied < size)
968
      {
969
        tocopy = size - ncopied;
970
        if (tocopy > BUFSIZE)
971
          tocopy = BUFSIZE;
972
 
973
        nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
974
        if (nread != tocopy)
975
          /* xgettext:c-format */
976
          fatal (_("%s is not a valid archive"),
977
                 bfd_get_filename (bfd_my_archive (abfd)));
978
 
979
        /* See comment above; this saves disk arm motion */
980
        if (ostream == NULL)
981
          {
982
            /* Seems like an abstraction violation, eh?  Well it's OK! */
983
            output_filename = bfd_get_filename (abfd);
984
 
985
            ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
986
            if (ostream == NULL)
987
              {
988
                perror (bfd_get_filename (abfd));
989
                xexit (1);
990
              }
991
 
992
            output_file = ostream;
993
          }
994
 
995
        /* fwrite in mingw32 may return int instead of size_t. Cast
996
           the return value to size_t to avoid comparison between
997
           signed and unsigned values.  */
998
        if ((size_t) fwrite (cbuf, 1, nread, ostream) != nread)
999
          fatal ("%s: %s", output_filename, strerror (errno));
1000
        ncopied += tocopy;
1001
      }
1002
 
1003
  if (ostream != NULL)
1004
    fclose (ostream);
1005
 
1006
  output_file = NULL;
1007
  output_filename = NULL;
1008
 
1009
  chmod (bfd_get_filename (abfd), buf.st_mode);
1010
 
1011
  if (preserve_dates)
1012
    {
1013
      /* Set access time to modification time.  Only st_mtime is
1014
         initialized by bfd_stat_arch_elt.  */
1015
      buf.st_atime = buf.st_mtime;
1016
      set_times (bfd_get_filename (abfd), &buf);
1017
    }
1018
 
1019
  free (cbuf);
1020
}
1021
 
1022
static void
1023
write_archive (bfd *iarch)
1024
{
1025
  bfd *obfd;
1026
  char *old_name, *new_name;
1027
  bfd *contents_head = iarch->archive_next;
1028
 
1029
  old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1);
1030
  strcpy (old_name, bfd_get_filename (iarch));
1031
  new_name = make_tempname (old_name);
1032
 
1033
  if (new_name == NULL)
1034
    bfd_fatal ("could not create temporary file whilst writing archive");
1035
 
1036
  output_filename = new_name;
1037
 
1038
  obfd = bfd_openw (new_name, bfd_get_target (iarch));
1039
 
1040
  if (obfd == NULL)
1041
    bfd_fatal (old_name);
1042
 
1043
  output_bfd = obfd;
1044
 
1045
  bfd_set_format (obfd, bfd_archive);
1046
 
1047
  /* Request writing the archive symbol table unless we've
1048
     been explicitly requested not to.  */
1049
  obfd->has_armap = write_armap >= 0;
1050
 
1051
  if (ar_truncate)
1052
    {
1053
      /* This should really use bfd_set_file_flags, but that rejects
1054
         archives.  */
1055
      obfd->flags |= BFD_TRADITIONAL_FORMAT;
1056
    }
1057
 
1058
  if (deterministic)
1059
    obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
1060
 
1061
  if (make_thin_archive || bfd_is_thin_archive (iarch))
1062
    bfd_is_thin_archive (obfd) = 1;
1063
 
1064
  if (!bfd_set_archive_head (obfd, contents_head))
1065
    bfd_fatal (old_name);
1066
 
1067
  if (!bfd_close (obfd))
1068
    bfd_fatal (old_name);
1069
 
1070
  output_bfd = NULL;
1071
  output_filename = NULL;
1072
 
1073
  /* We don't care if this fails; we might be creating the archive.  */
1074
  bfd_close (iarch);
1075
 
1076
  if (smart_rename (new_name, old_name, 0) != 0)
1077
    xexit (1);
1078
  free (old_name);
1079
}
1080
 
1081
/* Return a pointer to the pointer to the entry which should be rplacd'd
1082
   into when altering.  DEFAULT_POS should be how to interpret pos_default,
1083
   and should be a pos value.  */
1084
 
1085
static bfd **
1086
get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
1087
{
1088
  bfd **after_bfd = contents;
1089
  enum pos realpos;
1090
  const char *realposname;
1091
 
1092
  if (postype == pos_default)
1093
    {
1094
      realpos = default_pos;
1095
      realposname = default_posname;
1096
    }
1097
  else
1098
    {
1099
      realpos = postype;
1100
      realposname = posname;
1101
    }
1102
 
1103
  if (realpos == pos_end)
1104
    {
1105
      while (*after_bfd)
1106
        after_bfd = &((*after_bfd)->archive_next);
1107
    }
1108
  else
1109
    {
1110
      for (; *after_bfd; after_bfd = &(*after_bfd)->archive_next)
1111
        if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
1112
          {
1113
            if (realpos == pos_after)
1114
              after_bfd = &(*after_bfd)->archive_next;
1115
            break;
1116
          }
1117
    }
1118
  return after_bfd;
1119
}
1120
 
1121
static void
1122
delete_members (bfd *arch, char **files_to_delete)
1123
{
1124
  bfd **current_ptr_ptr;
1125
  bfd_boolean found;
1126
  bfd_boolean something_changed = FALSE;
1127
  int match_count;
1128
 
1129
  for (; *files_to_delete != NULL; ++files_to_delete)
1130
    {
1131
      /* In a.out systems, the armap is optional.  It's also called
1132
         __.SYMDEF.  So if the user asked to delete it, we should remember
1133
         that fact. This isn't quite right for COFF systems (where
1134
         __.SYMDEF might be regular member), but it's very unlikely
1135
         to be a problem.  FIXME */
1136
 
1137
      if (!strcmp (*files_to_delete, "__.SYMDEF"))
1138
        {
1139
          arch->has_armap = FALSE;
1140
          write_armap = -1;
1141
          continue;
1142
        }
1143
 
1144
      found = FALSE;
1145
      match_count = 0;
1146
      current_ptr_ptr = &(arch->archive_next);
1147
      while (*current_ptr_ptr)
1148
        {
1149
          if (FILENAME_CMP (normalize (*files_to_delete, arch),
1150
                            (*current_ptr_ptr)->filename) == 0)
1151
            {
1152
              ++match_count;
1153
              if (counted_name_mode
1154
                  && match_count != counted_name_counter)
1155
                {
1156
                  /* Counting, and didn't match on count; go on to the
1157
                     next one.  */
1158
                }
1159
              else
1160
                {
1161
                  found = TRUE;
1162
                  something_changed = TRUE;
1163
                  if (verbose)
1164
                    printf ("d - %s\n",
1165
                            *files_to_delete);
1166
                  *current_ptr_ptr = ((*current_ptr_ptr)->archive_next);
1167
                  goto next_file;
1168
                }
1169
            }
1170
 
1171
          current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
1172
        }
1173
 
1174
      if (verbose && !found)
1175
        {
1176
          /* xgettext:c-format */
1177
          printf (_("No member named `%s'\n"), *files_to_delete);
1178
        }
1179
    next_file:
1180
      ;
1181
    }
1182
 
1183
  if (something_changed)
1184
    write_archive (arch);
1185
  else
1186
    output_filename = NULL;
1187
}
1188
 
1189
 
1190
/* Reposition existing members within an archive */
1191
 
1192
static void
1193
move_members (bfd *arch, char **files_to_move)
1194
{
1195
  bfd **after_bfd;              /* New entries go after this one */
1196
  bfd **current_ptr_ptr;        /* cdr pointer into contents */
1197
 
1198
  for (; *files_to_move; ++files_to_move)
1199
    {
1200
      current_ptr_ptr = &(arch->archive_next);
1201
      while (*current_ptr_ptr)
1202
        {
1203
          bfd *current_ptr = *current_ptr_ptr;
1204
          if (FILENAME_CMP (normalize (*files_to_move, arch),
1205
                            current_ptr->filename) == 0)
1206
            {
1207
              /* Move this file to the end of the list - first cut from
1208
                 where it is.  */
1209
              bfd *link_bfd;
1210
              *current_ptr_ptr = current_ptr->archive_next;
1211
 
1212
              /* Now glue to end */
1213
              after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
1214
              link_bfd = *after_bfd;
1215
              *after_bfd = current_ptr;
1216
              current_ptr->archive_next = link_bfd;
1217
 
1218
              if (verbose)
1219
                printf ("m - %s\n", *files_to_move);
1220
 
1221
              goto next_file;
1222
            }
1223
 
1224
          current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
1225
        }
1226
      /* xgettext:c-format */
1227
      fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1228
 
1229
    next_file:;
1230
    }
1231
 
1232
  write_archive (arch);
1233
}
1234
 
1235
/* Ought to default to replacing in place, but this is existing practice!  */
1236
 
1237
static void
1238
replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
1239
{
1240
  bfd_boolean changed = FALSE;
1241
  bfd **after_bfd;              /* New entries go after this one.  */
1242
  bfd *current;
1243
  bfd **current_ptr;
1244
 
1245
  while (files_to_move && *files_to_move)
1246
    {
1247
      if (! quick)
1248
        {
1249
          current_ptr = &arch->archive_next;
1250
          while (*current_ptr)
1251
            {
1252
              current = *current_ptr;
1253
 
1254
              /* For compatibility with existing ar programs, we
1255
                 permit the same file to be added multiple times.  */
1256
              if (FILENAME_CMP (normalize (*files_to_move, arch),
1257
                                normalize (current->filename, arch)) == 0
1258
                  && current->arelt_data != NULL)
1259
                {
1260
                  if (newer_only)
1261
                    {
1262
                      struct stat fsbuf, asbuf;
1263
 
1264
                      if (stat (*files_to_move, &fsbuf) != 0)
1265
                        {
1266
                          if (errno != ENOENT)
1267
                            bfd_fatal (*files_to_move);
1268
                          goto next_file;
1269
                        }
1270
                      if (bfd_stat_arch_elt (current, &asbuf) != 0)
1271
                        /* xgettext:c-format */
1272
                        fatal (_("internal stat error on %s"),
1273
                               current->filename);
1274
 
1275
                      if (fsbuf.st_mtime <= asbuf.st_mtime)
1276
                        goto next_file;
1277
                    }
1278
 
1279
                  after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
1280
                                           current->filename);
1281
                  if (ar_emul_replace (after_bfd, *files_to_move,
1282
                                       target, verbose))
1283
                    {
1284
                      /* Snip out this entry from the chain.  */
1285
                      *current_ptr = (*current_ptr)->archive_next;
1286
                      changed = TRUE;
1287
                    }
1288
 
1289
                  goto next_file;
1290
                }
1291
              current_ptr = &(current->archive_next);
1292
            }
1293
        }
1294
 
1295
      /* Add to the end of the archive.  */
1296
      after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
1297
 
1298
      if (ar_emul_append (after_bfd, *files_to_move, target,
1299
                          verbose, make_thin_archive))
1300
        changed = TRUE;
1301
 
1302
    next_file:;
1303
 
1304
      files_to_move++;
1305
    }
1306
 
1307
  if (changed)
1308
    write_archive (arch);
1309
  else
1310
    output_filename = NULL;
1311
}
1312
 
1313
static int
1314
ranlib_only (const char *archname)
1315
{
1316
  bfd *arch;
1317
 
1318
  if (get_file_size (archname) < 1)
1319
    return 1;
1320
  write_armap = 1;
1321
  arch = open_inarch (archname, (char *) NULL);
1322
  if (arch == NULL)
1323
    xexit (1);
1324
  write_archive (arch);
1325
  return 0;
1326
}
1327
 
1328
/* Update the timestamp of the symbol map of an archive.  */
1329
 
1330
static int
1331
ranlib_touch (const char *archname)
1332
{
1333
#ifdef __GO32__
1334
  /* I don't think updating works on go32.  */
1335
  ranlib_only (archname);
1336
#else
1337
  int f;
1338
  bfd *arch;
1339
  char **matching;
1340
 
1341
  if (get_file_size (archname) < 1)
1342
    return 1;
1343
  f = open (archname, O_RDWR | O_BINARY, 0);
1344
  if (f < 0)
1345
    {
1346
      bfd_set_error (bfd_error_system_call);
1347
      bfd_fatal (archname);
1348
    }
1349
 
1350
  arch = bfd_fdopenr (archname, (const char *) NULL, f);
1351
  if (arch == NULL)
1352
    bfd_fatal (archname);
1353
  if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1354
    {
1355
      bfd_nonfatal (archname);
1356
      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1357
        {
1358
          list_matching_formats (matching);
1359
          free (matching);
1360
        }
1361
      xexit (1);
1362
    }
1363
 
1364
  if (! bfd_has_map (arch))
1365
    /* xgettext:c-format */
1366
    fatal (_("%s: no archive map to update"), archname);
1367
 
1368
  bfd_update_armap_timestamp (arch);
1369
 
1370
  if (! bfd_close (arch))
1371
    bfd_fatal (archname);
1372
#endif
1373
  return 0;
1374
}
1375
 
1376
/* Things which are interesting to map over all or some of the files: */
1377
 
1378
static void
1379
print_descr (bfd *abfd)
1380
{
1381
  print_arelt_descr (stdout, abfd, verbose);
1382
}

powered by: WebSVN 2.1.0

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