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