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