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