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