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