Sat Jan 22 16:25:09 1994 Stan Shebs (shebs@andros.cygnus.com)
[deliverable/binutils-gdb.git] / binutils / ar.c
CommitLineData
5f0e8767 1/* ar.c - Archive modify and extract.
37853673 2 Copyright 1991, 1992, 1994 Free Software Foundation, Inc.
5f0e8767
SC
3
4This file is part of GNU Binutils.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
2fa0b342
DHW
20/*
21 Bugs: should use getopt the way tar does (complete w/optional -) and
22 should have long options too. GNU ar used to check file against filesystem
23 in quick_update and replace operations (would check mtime). Doesn't warn
24 when name truncated. No way to specify pos_end. Error messages should be
25 more consistant.
26*/
2fa0b342 27#include "bfd.h"
5f0e8767 28#include "sysdep.h"
4b5ea362
SC
29#include "bucomm.h"
30#include "aout/ar.h"
37853673 31#include "libbfd.h"
c0cc6912 32#include "arsup.h"
2fa0b342 33#include <stdio.h>
42b600fa
ILT
34#ifdef POSIX_UTIME
35#include <utime.h>
36#else /* ! POSIX_UTIME */
37#ifdef USE_UTIME
c0cc6912 38#include <time.h>
42b600fa 39#else /* ! USE_UTIME */
2fa0b342 40#include <sys/time.h>
42b600fa
ILT
41#endif /* ! USE_UTIME */
42#endif /* ! POSIX_UTIME */
2fa0b342 43#include <errno.h>
5b07d693
PB
44#ifndef errno
45extern int errno;
46#endif
2fa0b342 47#define BUFSIZE 8192
2fa0b342 48
6336b309
ILT
49#ifdef __GO32___
50#define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */
51#else
52#define EXT_NAME_LEN 6 /* ditto for *NIX */
53#endif
54
e87cc816
JG
55/* Kludge declaration from BFD! This is ugly! FIXME! XXX */
56
57struct ar_hdr *
58bfd_special_undocumented_glue PARAMS ((bfd *abfd, char *filename));
59
151a6341 60/* Forward declarations */
5b07d693 61
151a6341
JG
62static void
63print_contents PARAMS ((bfd * member));
c0cc6912 64
151a6341
JG
65static void
66delete_members PARAMS ((char **files_to_delete));
c0cc6912 67
151a6341
JG
68static void
69do_quick_append PARAMS ((char *archive_filename, char **files_to_append));
70
71static void
72move_members PARAMS ((char **files_to_move));
73
74static void
75replace_members PARAMS ((char **files_to_replace));
76
77static void
78print_descr PARAMS ((bfd * abfd));
79
80static void
81ranlib_only PARAMS ((char *archname));
2fa0b342
DHW
82
83/** Globals and flags */
84
2fa0b342
DHW
85bfd *inarch; /* The input arch we're manipulating */
86
c0cc6912 87int mri_mode;
5f0e8767 88/* This flag distinguishes between ar and ranlib:
4b5ea362
SC
89 1 means this is 'ranlib'; 0 means this is 'ar'.
90 -1 means if we should use argv[0] to decide. */
5f0e8767 91extern int is_ranlib;
2fa0b342
DHW
92/* Nonzero means don't warn about creating the archive file if necessary. */
93int silent_create = 0;
94/* Nonzero means describe each action performed. */
95int verbose = 0;
96/* Nonzero means preserve dates of members when extracting them. */
97int preserve_dates = 0;
98/*
99 Nonzero means don't replace existing members whose dates are more recent
100 than the corresponding files.
101*/
102int newer_only = 0;
d2442698
DM
103
104/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
105 member). -1 means we've been explicitly asked to not write a symbol table;
106 +1 means we've been explictly asked to write it;
107 0 is the default.
108 Traditionally, the default in BSD has been to not write the table.
109 However, for Posix.2 compliance the default is now to write a symbol table
110 if any of the members are object files. */
111int write_armap = 0;
112
2fa0b342
DHW
113/*
114 Nonzero means it's the name of an existing member; position new or moved
115 files with respect to this one.
116*/
117char *posname = NULL;
118/*
119 Sez how to use `posname': pos_before means position before that member.
120 pos_after means position after that member. pos_end means always at end.
121 pos_default means default appropriately. For the latter two, `posname'
122 should also be zero.
123*/
124enum pos {
125 pos_default, pos_before, pos_after, pos_end
126} postype = pos_default;
127
c0cc6912
SC
128int interactive = 0;
129void
130DEFUN_VOID(mri_emul)
131{
132 interactive = isatty(fileno(stdin)) ;
133 yyparse();
134}
135
136/*
137 If count is 0, then function is called once on each entry. if nonzero,
138 count is the length of the files chain; function is called on each entry
139 whose name matches one in files
140*/
141void
142DEFUN(map_over_members,(function, files, count),
143 void (*function) () AND
144 char **files AND
145 int count)
146{
147 bfd *head;
148
149 if (count == 0) {
150 for (head = inarch->next; head; head = head->next)
151 function(head);
152 return;
153 }
154 /*
155 This may appear to be a baroque way of accomplishing what we want.
156 however we have to iterate over the filenames in order to notice where
157 a filename is requested but does not exist in the archive. Ditto
158 mapping over each file each time -- we want to hack multiple
159 references.
160 */
161
162 for (; count > 0; files++, count--) {
163 boolean found = false;
164 for (head = inarch->next; head; head = head->next)
42b600fa
ILT
165 {
166 if (head->filename == NULL)
167 {
168 /* Some archive formats don't get the filenames filled in
169 'till the elements are opened */
170 struct stat buf;
171 bfd_stat_arch_elt(head, &buf);
172 }
173 if ((head->filename != NULL) &&
174 (!strcmp(*files, head->filename))) {
175 found = true;
176 function(head);
177 }
178 }
c0cc6912 179 if (!found)
6336b309 180 fprintf(stderr, "no entry %s in archive\n", *files);
c0cc6912
SC
181 }
182}
ab01cf22 183
8ab76aa7
DHW
184
185boolean operation_alters_arch = false;
186
d2442698
DM
187extern char *program_version;
188
42b600fa
ILT
189void
190do_show_version ()
191{
6336b309
ILT
192 printf ("GNU %s version %s\n", program_name, program_version);
193 exit (0);
42b600fa
ILT
194}
195
d2442698
DM
196void
197usage ()
198{
6336b309
ILT
199 if (is_ranlib == 0)
200 fprintf(stderr, "\
201Usage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\
d2442698 202 %s -M [<mri-script]\n",
6336b309
ILT
203 program_name, program_name);
204 else
205 fprintf(stderr, "\
206Usage: %s [-vV] archive\n", program_name);
d2442698
DM
207 exit(1);
208}
209
2fa0b342
DHW
210/*
211 The option parsing should be in its own function. It will be when I have
212 getopt working.
213*/
214int
215main(argc, argv)
216 int argc;
217 char **argv;
218{
c0cc6912
SC
219 char *arg_ptr;
220 char c;
221 enum {
222 none = 0, delete, replace, print_table,
223 print_files, extract, move, quick_append
224 } operation = none;
225 int arg_index;
226 char **files;
227 char *inarch_filename;
228 char *temp;
8fb94c7a 229 int show_version;
c0cc6912
SC
230
231 bfd_init();
8fb94c7a 232 show_version = 0;
ab01cf22 233
c0cc6912
SC
234 program_name = argv[0];
235
236 temp = strrchr(program_name, '/');
237 if (temp == (char *) NULL)
238 temp = program_name; /* shouldn't happen, but... */
239 else
240 ++temp;
241 if (is_ranlib > 0 || (is_ranlib < 0 && strcmp(temp, "ranlib") == 0)) {
6336b309
ILT
242 is_ranlib = 1;
243 if (argc < 2 || argc > 3)
d2442698 244 usage ();
42b600fa 245 arg_ptr = argv[1];
6336b309 246 if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "-v") == 0)
42b600fa 247 do_show_version();
42b600fa 248 ranlib_only(arg_ptr);
c0cc6912 249 }
6336b309
ILT
250 else
251 is_ranlib = 0;
c0cc6912
SC
252
253 if (argc == 2 && strcmp(argv[1],"-M") == 0) {
254 mri_emul();
255 exit(0);
256 }
42b600fa
ILT
257
258 if (argc < 2)
d2442698 259 usage ();
c0cc6912
SC
260
261 arg_ptr = argv[1];
262
263 if (*arg_ptr == '-')
264 ++arg_ptr; /* compatibility */
265
6336b309 266 while ((c = *arg_ptr++) != '\0') {
c0cc6912
SC
267 switch (c) {
268 case 'd':
269 case 'm':
270 case 'p':
271 case 'q':
272 case 'r':
273 case 't':
274 case 'x':
275 if (operation != none)
6336b309 276 fatal("two different operation options specified");
c0cc6912
SC
277 switch (c) {
278 case 'd':
279 operation = delete;
280 operation_alters_arch = true;
281 break;
282 case 'm':
283 operation = move;
284 operation_alters_arch = true;
285 break;
286 case 'p':
287 operation = print_files;
288 break;
289 case 'q':
290 operation = quick_append;
291 operation_alters_arch = true;
292 break;
293 case 'r':
294 operation = replace;
295 operation_alters_arch = true;
296 break;
297 case 't':
298 operation = print_table;
299 break;
300 case 'x':
301 operation = extract;
302 break;
303 }
304 case 'l':
305 break;
306 case 'c':
307 silent_create = 1;
308 break;
309 case 'o':
310 preserve_dates = 1;
311 break;
8fb94c7a
RS
312 case 'V':
313 show_version = true;
314 break;
c0cc6912 315 case 's':
d2442698 316 write_armap = 1;
c0cc6912
SC
317 break;
318 case 'u':
319 newer_only = 1;
320 break;
321 case 'v':
322 verbose = 1;
323 break;
324 case 'a':
325 postype = pos_after;
326 break;
327 case 'b':
328 postype = pos_before;
329 break;
330 case 'i':
331 postype = pos_before;
332 break;
333 case 'M':
c0cc6912
SC
334 mri_mode = 1;
335 break;
336 default:
37853673 337 fprintf(stderr, "%s: illegal option -- %c\n", program_name, c);
6336b309 338 usage ();
2fa0b342 339 }
c0cc6912 340 }
2fa0b342 341
8fb94c7a 342 if (show_version)
6336b309 343 do_show_version();
42b600fa
ILT
344
345 if (argc < 3)
6336b309 346 usage ();
8fb94c7a 347
c0cc6912
SC
348 if (mri_mode) {
349 mri_emul();
350 }
351 else {
bb5ae298 352 if ((operation == none || operation == print_table)
d2442698 353 && write_armap == 1)
6336b309 354 ranlib_only(argv[2]);
2fa0b342
DHW
355
356 if (operation == none)
6336b309 357 fatal("no operation specified");
2fa0b342
DHW
358
359 if (newer_only && operation != replace)
6336b309 360 fatal("`u' is only meaningful with the `r' option.");
2fa0b342
DHW
361
362 arg_index = 2;
363
364 if (postype != pos_default)
6336b309 365 posname = argv[arg_index++];
2fa0b342
DHW
366
367 inarch_filename = argv[arg_index++];
368
d2442698 369 files = arg_index < argc ? argv + arg_index : NULL;
2fa0b342 370
6336b309
ILT
371 if (operation == quick_append)
372 {
373 /* Note that quick appending to a non-existent archive creates it,
374 even if there are no files to append. */
375 do_quick_append(inarch_filename, files);
376 exit(0);
377 }
2fa0b342
DHW
378
379 open_inarch(inarch_filename);
a00721fc 380
2fa0b342
DHW
381 switch (operation) {
382
c0cc6912
SC
383 case print_table:
384 map_over_members(print_descr, files, argc - 3);
385 break;
2fa0b342 386
c0cc6912
SC
387 case print_files:
388 map_over_members(print_contents, files, argc - 3);
389 break;
2fa0b342 390
c0cc6912
SC
391 case extract:
392 map_over_members(extract_file, files, argc - 3);
393 break;
2fa0b342 394
c0cc6912
SC
395 case delete:
396 if (files != NULL)
397 delete_members(files);
398 break;
2fa0b342 399
c0cc6912
SC
400 case move:
401 if (files != NULL)
402 move_members(files);
403 break;
2fa0b342 404
c0cc6912 405 case replace:
d2442698 406 if (files != NULL || write_armap > 0)
c0cc6912
SC
407 replace_members(files);
408 break;
2fa0b342 409
c0cc6912
SC
410 /* Shouldn't happen! */
411 default:
6336b309
ILT
412 fprintf(stderr, "%s: internal error -- this option not implemented\n",
413 program_name);
414 exit (1);
2fa0b342 415 }
c0cc6912
SC
416 }
417 return (0);
2fa0b342
DHW
418} /* main() */
419
420static
421char *normalize(file)
422char *file;
423{
424 char * filename = strrchr(file, '/');
425 if (filename != (char *)NULL) {
426 filename ++;
427 }
428 else {
429 filename = file;
430 }
431 return filename;
432}
433
5b07d693 434int
2fa0b342
DHW
435open_inarch(archive_filename)
436 char *archive_filename;
437{
438 bfd **last_one;
439 bfd *next_one;
440 struct stat sbuf;
441 bfd_error = no_error;
6336b309 442
2fa0b342 443 if (stat(archive_filename, &sbuf) != 0) {
6336b309
ILT
444
445#ifndef __GO32__
446
447/* KLUDGE ALERT! Temporary fix until I figger why
448 * stat() is wrong ... think it's buried in GO32's IDT
449 * - Jax
450 */
2fa0b342
DHW
451 if (errno != ENOENT)
452 bfd_fatal(archive_filename);
6336b309
ILT
453#endif
454
8ab76aa7 455 if (!operation_alters_arch) {
6336b309
ILT
456 fprintf (stderr, "%s: ", program_name);
457 perror (archive_filename);
c0cc6912 458 maybequit();
5b07d693 459 return 0;
8ab76aa7 460 }
2fa0b342 461
a00721fc 462 /* This routine is one way to forcibly create the archive. */
6336b309 463
a00721fc 464 do_quick_append(archive_filename, 0);
2fa0b342 465 }
a00721fc 466
a00721fc 467 inarch = bfd_openr(archive_filename, NULL);
a00721fc 468 if (inarch == NULL) {
6336b309 469
a00721fc 470 bloser:
6336b309 471
d2442698 472 fprintf (stderr, "%s: ", program_name);
a00721fc
PB
473 bfd_perror(archive_filename);
474 exit(1);
475 }
2fa0b342 476
a00721fc 477 if (bfd_check_format(inarch, bfd_archive) != true)
6336b309 478 fatal("%s is not an archive", archive_filename);
a00721fc
PB
479 last_one = &(inarch->next);
480 /* Read all the contents right away, regardless. */
481 for (next_one = bfd_openr_next_archived_file(inarch, NULL);
482 next_one;
483 next_one = bfd_openr_next_archived_file(inarch, next_one)) {
484 *last_one = next_one;
485 last_one = &next_one->next;
2fa0b342 486 }
a00721fc
PB
487 *last_one = (bfd *) NULL;
488 if (bfd_error != no_more_archived_files)
489 goto bloser;
490 return 1;
2fa0b342
DHW
491}
492
493
494
2fa0b342
DHW
495
496
151a6341 497static void
2fa0b342
DHW
498print_contents(abfd)
499 bfd *abfd;
500{
501 int ncopied = 0;
502 struct stat buf;
503 long size;
504 if (bfd_stat_arch_elt(abfd, &buf) != 0)
6336b309 505 fatal("internal stat error on %s", abfd->filename);
2fa0b342
DHW
506
507 if (verbose)
508 printf("\n<member %s>\n\n", abfd->filename);
509
510 bfd_seek(abfd, 0, SEEK_SET);
511
512 size = buf.st_size;
513 while (ncopied < size) {
514 char cbuf[BUFSIZE];
515 int nread;
516 int tocopy = size - ncopied;
517 if (tocopy > BUFSIZE)
518 tocopy = BUFSIZE;
519
520 nread = bfd_read(cbuf, 1, tocopy, abfd); /* oops -- broke
521 abstraction! */
522
523 if (nread != tocopy)
6336b309 524 fatal("%s is not a valid archive", abfd->my_archive->filename);
2fa0b342
DHW
525 fwrite(cbuf, 1, nread, stdout);
526 ncopied += tocopy;
527 }
528}
529
530
531/*
532 Extract a member of the archive into its own file.
533
534We defer opening the new file until after we have read a BUFSIZ chunk of the
535 old one, since we know we have just read the archive header for the old
536 one. Since most members are shorter than BUFSIZ, this means we will read
537 the old header, read the old data, write a new inode for the new file, and
538 write the new data, and be done. This 'optimization' is what comes from
539 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
540 Gilmore
541*/
542
543void
544extract_file(abfd)
545 bfd *abfd;
546{
547 FILE *ostream;
548 char cbuf[BUFSIZE];
549 int nread,
550 tocopy;
551 int ncopied = 0;
552 long size;
553 struct stat buf;
554 if (bfd_stat_arch_elt(abfd, &buf) != 0)
6336b309 555 fatal("internal stat error on %s", abfd->filename);
2fa0b342
DHW
556 size = buf.st_size;
557
558 if (verbose)
559 printf("x - %s\n", abfd->filename);
560
561 bfd_seek(abfd, 0, SEEK_SET);
562
563 ostream = 0;
8ab76aa7
DHW
564 if (size == 0) {
565 /* Seems like an abstraction violation, eh? Well it's OK! */
c0cc6912 566 ostream = fopen(abfd->filename, FOPEN_WB);
8ab76aa7
DHW
567 if (!ostream) {
568 perror(abfd->filename);
569 exit(1);
570 }
571 } else
2fa0b342
DHW
572 while (ncopied < size) {
573 tocopy = size - ncopied;
574 if (tocopy > BUFSIZE)
575 tocopy = BUFSIZE;
576
577 nread = bfd_read(cbuf, 1, tocopy, abfd);
578 if (nread != tocopy)
6336b309 579 fatal("%s is not a valid archive", abfd->my_archive->filename);
2fa0b342
DHW
580
581 /* See comment above; this saves disk arm motion */
582 if (!ostream) {
583 /* Seems like an abstraction violation, eh? Well it's OK! */
c0cc6912 584 ostream = fopen(abfd->filename, FOPEN_WB);
2fa0b342
DHW
585 if (!ostream) {
586 perror(abfd->filename);
587 exit(1);
588 }
589 }
2fa0b342
DHW
590 fwrite(cbuf, 1, nread, ostream);
591 ncopied += tocopy;
592 }
593
594 fclose(ostream);
595 chmod(abfd->filename, buf.st_mode);
596
597 if (preserve_dates) {
42b600fa
ILT
598#ifdef POSIX_UTIME
599 struct utimbuf tb;
600 tb.actime = buf.st_mtime;
601 tb.modtime = buf.st_mtime;
d2442698 602 utime(abfd->filename, &tb); /* FIXME check result */
42b600fa
ILT
603#else /* ! POSIX_UTIME */
604#ifdef USE_UTIME
2fa0b342
DHW
605 long tb[2];
606 tb[0] = buf.st_mtime;
607 tb[1] = buf.st_mtime;
608 utime(abfd->filename, tb); /* FIXME check result */
42b600fa 609#else /* ! USE_UTIME */
2fa0b342
DHW
610 struct timeval tv[2];
611 tv[0].tv_sec = buf.st_mtime;
612 tv[0].tv_usec = 0;
613 tv[1].tv_sec = buf.st_mtime;
614 tv[1].tv_usec = 0;
615 utimes(abfd->filename, tv); /* FIXME check result */
42b600fa
ILT
616#endif /* ! USE_UTIME */
617#endif /* ! POSIX_UTIME */
2fa0b342
DHW
618 }
619}
620
621
622/* Just do it quickly; don't worry about dups, armap, or anything like that */
623
151a6341 624static void
2fa0b342
DHW
625do_quick_append(archive_filename, files_to_append)
626 char *archive_filename;
627 char **files_to_append;
628
629{
630 FILE *ofile,
631 *ifile;
632 char buf[BUFSIZE];
633 long tocopy,
634 thistime;
635 bfd *temp;
636 struct stat sbuf;
637 boolean newfile = false;
638 bfd_error = no_error;
639
640 if (stat(archive_filename, &sbuf) != 0) {
6336b309
ILT
641
642#ifndef __GO32__
643
644/* KLUDGE ALERT! Temporary fix until I figger why
645 * stat() is wrong ... think it's buried in GO32's IDT
646 * - Jax
647 */
648
2fa0b342
DHW
649 if (errno != ENOENT)
650 bfd_fatal(archive_filename);
6336b309
ILT
651#endif
652
2fa0b342
DHW
653 newfile = true;
654 }
655
656
c0cc6912 657 ofile = fopen(archive_filename, FOPEN_AUB);
2fa0b342
DHW
658 if (ofile == NULL) {
659 perror(program_name);
660 exit(1);
661 }
662
2fa0b342
DHW
663 temp = bfd_openr(archive_filename, NULL);
664 if (temp == NULL) {
d2442698 665 fprintf (stderr, "%s: ", program_name);
2fa0b342
DHW
666 bfd_perror(archive_filename);
667 exit(1);
668 }
669 if (newfile == false) {
670 if (bfd_check_format(temp, bfd_archive) != true)
6336b309 671 fatal("%s is not an archive", archive_filename);
2fa0b342
DHW
672 }
673 else {
674 fwrite(ARMAG, 1, SARMAG, ofile);
675 if (!silent_create)
6336b309
ILT
676 fprintf(stderr, "%s: creating %s\n",
677 program_name, archive_filename);
2fa0b342
DHW
678 }
679
680 /* assume it's an achive, go straight to the end, sans $200 */
681 fseek(ofile, 0, 2);
682
683 for (; files_to_append && *files_to_append; ++files_to_append) {
9872a49c 684 struct ar_hdr *hdr = bfd_special_undocumented_glue(temp, *files_to_append);
2fa0b342 685 if (hdr == NULL) {
d2442698 686 fprintf (stderr, "%s: ", program_name);
2fa0b342
DHW
687 bfd_perror(*files_to_append);
688 exit(1);
689 }
690
691 BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
692
c0cc6912 693 ifile = fopen(*files_to_append, FOPEN_RB);
2fa0b342 694 if (ifile == NULL)
d2442698 695 {
2fa0b342 696 bfd_perror(program_name);
d2442698 697 }
2fa0b342
DHW
698
699 if (stat(*files_to_append, &sbuf) != 0)
d2442698
DM
700 {
701 fprintf (stderr, "%s: ", program_name);
2fa0b342 702 bfd_perror(*files_to_append);
d2442698 703 }
2fa0b342
DHW
704
705 tocopy = sbuf.st_size;
706
707 /* XXX should do error-checking! */
708 fwrite(hdr, 1, sizeof(struct ar_hdr), ofile);
709
710
711 while (tocopy > 0) {
712 thistime = tocopy;
713 if (thistime > BUFSIZE)
714 thistime = BUFSIZE;
715 fread(buf, 1, thistime, ifile);
716 fwrite(buf, 1, thistime, ofile);
717 tocopy -= thistime;
718 }
719 fclose(ifile);
720 if ((sbuf.st_size % 2) == 1)
721 putc('\n', ofile);
722 }
723 fclose(ofile);
724 bfd_close(temp);
725}
726
727
728void
729write_archive()
730{
731 bfd *obfd;
2fa0b342 732 int namelen = strlen(inarch->filename);
6336b309 733 char *new_name = xmalloc(namelen + EXT_NAME_LEN);
2fa0b342 734 bfd *contents_head = inarch->next;
a00721fc 735
2fa0b342 736 strcpy(new_name, inarch->filename);
6336b309
ILT
737
738#ifdef __GO32__ /* avoid long .extensions for MS-DOS */
739 strcpy(new_name + namelen, "-a");
740#else
4b5ea362 741 strcpy(new_name + namelen, "-art");
6336b309
ILT
742#endif
743
8ab76aa7 744 obfd = bfd_openw(new_name,
5f0e8767 745 /* FIXME: violates abstraction; need a better protocol */
8ab76aa7 746 (inarch->xvec ? bfd_get_target(inarch) : NULL));
2fa0b342
DHW
747
748 if (obfd == NULL)
749 bfd_fatal(inarch->filename);
750
751 bfd_set_format(obfd, bfd_archive);
d2442698
DM
752
753 /* Request writing the archive symbol table unless we've
754 been explicitly requested not to. */
755 obfd->has_armap = write_armap >= 0;
2fa0b342
DHW
756
757 if (bfd_set_archive_head(obfd, contents_head) != true)
758 bfd_fatal(inarch->filename);
759
760 if (!bfd_close(obfd))
761 bfd_fatal(inarch->filename);
0885eef1
SC
762
763 /* We don't care if this fails, we might be creating the
764 archive */
765 (void) unlink(inarch->filename);
766
2fa0b342
DHW
767 if (rename(new_name, inarch->filename) != 0)
768 bfd_fatal(inarch->filename);
2fa0b342
DHW
769}
770
771
772
773/*
774 returns a pointer to the pointer to the entry which should be rplacd'd
775 into when altering. default_pos should be how to interpret pos_default,
776 and should be a pos value.
777*/
778
779bfd **
780get_pos_bfd(contents, default_pos)
781 bfd **contents;
782 enum pos default_pos;
783{
bb5ae298 784 bfd **after_bfd = contents;
2fa0b342 785 enum pos realpos = (postype == pos_default ? default_pos : postype);
2fa0b342 786
bb5ae298
SC
787 if (realpos == pos_end) {
788 while (*after_bfd)
2fa0b342 789 after_bfd = &((*after_bfd)->next);
bb5ae298
SC
790 }
791 else {
792 for ( ; *after_bfd; after_bfd = &(*after_bfd)->next)
793 if (!strcmp((*after_bfd)->filename, posname)) {
794 if (realpos == pos_after)
795 after_bfd = &(*after_bfd)->next;
4b5ea362 796 break;
2fa0b342 797 }
2fa0b342 798 }
2fa0b342
DHW
799 return after_bfd;
800}
801
802
151a6341 803static void
2fa0b342
DHW
804delete_members(files_to_delete)
805 char **files_to_delete;
806{
807 bfd **current_ptr_ptr;
808 boolean found;
809 boolean something_changed = false;
810 for (; *files_to_delete != NULL; ++files_to_delete) {
811 /*
812 In a.out systems, the armap is optional. It's also called
813 __.SYMDEF. So if the user asked to delete it, we should remember
d2442698
DM
814 that fact. This isn't quite right for COFF systems (where
815 __.SYMDEF might be regular member), but it's very unlikely
816 to be a problem. FIXME */
817
2fa0b342
DHW
818 if (!strcmp(*files_to_delete, "__.SYMDEF")) {
819 inarch->has_armap = false;
d2442698 820 write_armap = -1;
2fa0b342
DHW
821 continue;
822 }
823
824 found = false;
825 current_ptr_ptr = &(inarch->next);
826 while (*current_ptr_ptr) {
827 if (strcmp(*files_to_delete, (*current_ptr_ptr)->filename) == 0) {
828 found = true;
829 something_changed = true;
830 if (verbose)
831 printf("d - %s\n",
832 *files_to_delete);
833 *current_ptr_ptr = ((*current_ptr_ptr)->next);
834 goto next_file;
835
836 }
837 else {
838 current_ptr_ptr = &((*current_ptr_ptr)->next);
839 }
840 }
841
842 if (verbose && found == false) {
843 printf("No member named `%s'\n", *files_to_delete);
844 }
845next_file:;
846
847 }
848
849 if (something_changed == true) {
850 write_archive();
851 }
852}
853
854
855/* Reposition existing members within an archive */
856
151a6341 857static void
2fa0b342
DHW
858move_members(files_to_move)
859 char **files_to_move;
860{
861 bfd **after_bfd; /* New entries go after this one */
862 bfd **current_ptr_ptr; /* cdr pointer into contents */
863
864
865
866
867 for (; *files_to_move; ++files_to_move) {
868 current_ptr_ptr = &(inarch->next);
869 while (*current_ptr_ptr) {
870 bfd *current_ptr = *current_ptr_ptr;
871 if (strcmp(normalize(*files_to_move), current_ptr->filename) == 0) {
872 /*
873 Move this file to the end of the list - first cut from
874 where it is.
875 */
876 *current_ptr_ptr = current_ptr->next;
877
878 /* Now glue to end */
879 after_bfd = get_pos_bfd(&inarch->next, pos_end);
880 *after_bfd = current_ptr;
881 current_ptr->next = (bfd *) NULL;
882
883 if (verbose)
884 printf("m - %s\n", *files_to_move);
885
886 goto next_file;
887 }
888 current_ptr_ptr = &((*current_ptr_ptr)->next);
889 }
6336b309
ILT
890 fprintf(stderr, "%s: no entry %s in archive %s!\n",
891 program_name, *files_to_move, inarch->filename);
2fa0b342
DHW
892 exit(1);
893next_file:;
894 }
895
896 write_archive();
897}
898
899
900/* Ought to default to replacing in place, but this is existing practice! */
901
151a6341 902static void
2fa0b342
DHW
903replace_members(files_to_move)
904 char **files_to_move;
905{
906 bfd **after_bfd; /* New entries go after this one */
907 bfd *current;
908 bfd **current_ptr;
909 bfd *temp;
2fa0b342
DHW
910
911 while (files_to_move && *files_to_move) {
912 current_ptr = &inarch->next;
913 while (*current_ptr) {
914 current = *current_ptr;
915
916 if (!strcmp(normalize(*files_to_move), current->filename)) {
2fa0b342
DHW
917 if (newer_only) {
918 struct stat fsbuf,
919 asbuf;
931004e4
DHW
920
921 if (current->arelt_data == NULL) {
922 /* This can only happen if you specify a file on the
923 command line more than once. */
6336b309 924 fprintf (stderr, "%s: duplicate file specified: %s -- skipping\n", program_name, *files_to_move);
931004e4
DHW
925 goto next_file;
926 }
927
2fa0b342
DHW
928 if (stat(*files_to_move, &fsbuf) != 0) {
929 if (errno != ENOENT)
930 bfd_fatal(*files_to_move);
931 goto next_file;
932 }
933 if (bfd_stat_arch_elt(current, &asbuf) != 0)
6336b309 934 fatal("internal stat error on %s", current->filename);
2fa0b342
DHW
935
936 if (fsbuf.st_mtime <= asbuf.st_mtime)
937 goto next_file;
938 }
939
2ef2fb7e
DHW
940 /* snip out this entry from the chain */
941 *current_ptr = current->next;
2fa0b342
DHW
942
943 after_bfd = get_pos_bfd(&inarch->next, pos_end);
944 temp = *after_bfd;
945 *after_bfd = bfd_openr(*files_to_move, NULL);
946 if (*after_bfd == (bfd *) NULL) {
6336b309
ILT
947 fprintf(stderr, "%s: ", program_name);
948 bfd_perror (*files_to_move);
2fa0b342
DHW
949 exit(1);
950 }
951 (*after_bfd)->next = temp;
952
953 if (verbose) {
954 printf("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
955 *files_to_move);
956 }
957 goto next_file;
958 }
959 current_ptr = &(current->next);
960 }
961
962 /* It isn't in there, so add to end */
963
964 after_bfd = get_pos_bfd(&inarch->next, pos_end);
965 temp = *after_bfd;
966 *after_bfd = bfd_openr(*files_to_move, NULL);
967 if (*after_bfd == (bfd *) NULL) {
6336b309
ILT
968 fprintf(stderr, "%s: ", program_name);
969 bfd_perror (*files_to_move);
970 exit(1);
2fa0b342
DHW
971 }
972 if (verbose) {
973 printf("c - %s\n", *files_to_move);
974 }
975
976 (*after_bfd)->next = temp;
977
978next_file:;
979
980 files_to_move++;
981 }
982
983
984 write_archive();
985}
986
151a6341 987static void
2fa0b342
DHW
988ranlib_only(archname)
989 char *archname;
990{
d2442698 991 write_armap = 1;
2fa0b342
DHW
992 open_inarch(archname);
993 write_archive();
994 exit(0);
995}
ab01cf22
DHW
996
997
4b5ea362
SC
998
999/* Things which are interesting to map over all or some of the files: */
1000
151a6341 1001static void
4b5ea362
SC
1002print_descr(abfd)
1003 bfd *abfd;
1004{
c0cc6912 1005 print_arelt_descr(stdout,abfd, verbose);
4b5ea362 1006}
This page took 0.13616 seconds and 4 git commands to generate.