1 /* arsup.c - Archive support for MRI compatibility
2 Copyright (C) 1992-2023 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
22 /* Contributed by Steve Chamberlain
25 This file looks after requests from arparse.y, to provide the MRI
26 style librarian command syntax + 1 word LIST. */
30 #include "libiberty.h"
31 #include "filenames.h"
35 static void map_over_list
36 (bfd
*, void (*function
) (bfd
*, bfd
*), struct list
*);
37 static void ar_directory_doer (bfd
*, bfd
*);
38 static void ar_addlib_doer (bfd
*, bfd
*);
41 extern int deterministic
;
44 static char *real_name
;
45 static char *temp_name
;
50 map_over_list (bfd
*arch
, void (*function
) (bfd
*, bfd
*), struct list
*list
)
58 head
= arch
->archive_next
;
61 next
= head
->archive_next
;
62 function (head
, (bfd
*) NULL
);
70 /* This may appear to be a baroque way of accomplishing what we
71 want. however we have to iterate over the filenames in order
72 to notice where a filename is requested but does not exist in
73 the archive. Ditto mapping over each file each time -- we
74 want to hack multiple references. */
75 for (ptr
= list
; ptr
; ptr
= ptr
->next
)
80 for (head
= arch
->archive_next
; head
; head
= head
->archive_next
)
82 if (bfd_get_filename (head
) != NULL
83 && FILENAME_CMP (ptr
->name
, bfd_get_filename (head
)) == 0)
86 function (head
, prev
);
91 fprintf (stderr
, _("No entry %s in archive.\n"), ptr
->name
);
99 ar_directory_doer (bfd
*abfd
, bfd
*ignore ATTRIBUTE_UNUSED
)
101 print_arelt_descr(outfile
, abfd
, verbose
, false);
105 ar_directory (char *ar_name
, struct list
*list
, char *output
)
109 arch
= open_inarch (ar_name
, (char *) NULL
);
112 outfile
= fopen(output
,"w");
116 fprintf (stderr
,_("Can't open file %s\n"), output
);
123 map_over_list (arch
, ar_directory_doer
, list
);
134 extern int interactive
;
152 ar_open (char *name
, int t
)
154 real_name
= xstrdup (name
);
155 temp_name
= make_tempname (real_name
, &temp_fd
);
157 if (temp_name
== NULL
)
159 fprintf (stderr
, _("%s: Can't open temporary file (%s)\n"),
160 program_name
, strerror(errno
));
165 obfd
= bfd_fdopenw (temp_name
, NULL
, temp_fd
);
170 _("%s: Can't open output archive %s\n"),
171 program_name
, temp_name
);
183 #if BFD_SUPPORTS_PLUGINS
184 ibfd
= bfd_openr (name
, "plugin");
186 ibfd
= bfd_openr (name
, NULL
);
191 fprintf (stderr
,_("%s: Can't open input archive %s\n"),
197 if (!bfd_check_format(ibfd
, bfd_archive
))
200 _("%s: file %s is not an archive\n"),
206 ptr
= &(obfd
->archive_head
);
207 element
= bfd_openr_next_archived_file (ibfd
, NULL
);
212 ptr
= &element
->archive_next
;
213 element
= bfd_openr_next_archived_file (ibfd
, element
);
217 bfd_set_format (obfd
, bfd_archive
);
220 obfd
->is_thin_archive
= 0;
225 ar_addlib_doer (bfd
*abfd
, bfd
*prev
)
227 /* Add this module to the output bfd. */
229 prev
->archive_next
= abfd
->archive_next
;
231 abfd
->archive_next
= obfd
->archive_head
;
232 obfd
->archive_head
= abfd
;
236 ar_addlib (char *name
, struct list
*list
)
240 fprintf (stderr
, _("%s: no output archive specified yet\n"), program_name
);
247 arch
= open_inarch (name
, (char *) NULL
);
249 map_over_list (arch
, ar_addlib_doer
, list
);
251 /* Don't close the bfd, since it will make the elements disappear. */
256 ar_addmod (struct list
*list
)
260 fprintf (stderr
, _("%s: no open output archive\n"), program_name
);
269 #if BFD_SUPPORTS_PLUGINS
270 abfd
= bfd_openr (list
->name
, "plugin");
272 abfd
= bfd_openr (list
->name
, NULL
);
276 fprintf (stderr
, _("%s: can't open file %s\n"),
277 program_name
, list
->name
);
282 abfd
->archive_next
= obfd
->archive_head
;
283 obfd
->archive_head
= abfd
;
295 obfd
->archive_head
= 0;
299 ar_delete (struct list
*list
)
303 fprintf (stderr
, _("%s: no open output archive\n"), program_name
);
310 /* Find this name in the archive. */
311 bfd
*member
= obfd
->archive_head
;
312 bfd
**prev
= &(obfd
->archive_head
);
317 if (FILENAME_CMP (bfd_get_filename (member
), list
->name
) == 0)
319 *prev
= member
->archive_next
;
323 prev
= &(member
->archive_next
);
325 member
= member
->archive_next
;
330 fprintf (stderr
, _("%s: can't find module file %s\n"),
331 program_name
, list
->name
);
345 fprintf (stderr
, _("%s: no open output archive\n"), program_name
);
350 struct stat target_stat
;
352 if (deterministic
> 0)
353 obfd
->flags
|= BFD_DETERMINISTIC_OUTPUT
;
355 temp_fd
= dup (temp_fd
);
358 if (stat (real_name
, &target_stat
) != 0)
360 /* The temp file created in ar_open has mode 0600 as per mkstemp.
361 Create the real empty output file here so smart_rename will
362 update the mode according to the process umask. */
363 obfd
= bfd_openw (real_name
, NULL
);
366 bfd_set_format (obfd
, bfd_archive
);
371 smart_rename (temp_name
, real_name
, temp_fd
, NULL
, false);
379 ar_replace (struct list
*list
)
383 fprintf (stderr
, _("%s: no open output archive\n"), program_name
);
390 /* Find this name in the archive. */
391 bfd
*member
= obfd
->archive_head
;
392 bfd
**prev
= &(obfd
->archive_head
);
397 if (FILENAME_CMP (bfd_get_filename (member
), list
->name
) == 0)
399 /* Found the one to replace. */
400 bfd
*abfd
= bfd_openr (list
->name
, NULL
);
404 fprintf (stderr
, _("%s: can't open file %s\n"),
405 program_name
, list
->name
);
411 abfd
->archive_next
= member
->archive_next
;
417 prev
= &(member
->archive_next
);
419 member
= member
->archive_next
;
424 bfd
*abfd
= bfd_openr (list
->name
, NULL
);
426 fprintf (stderr
,_("%s: can't find module file %s\n"),
427 program_name
, list
->name
);
430 fprintf (stderr
, _("%s: can't open file %s\n"),
431 program_name
, list
->name
);
443 /* And I added this one. */
449 fprintf (stderr
, _("%s: no open output archive\n"), program_name
);
458 printf (_("Current open archive is %s\n"), bfd_get_filename (obfd
));
460 for (abfd
= obfd
->archive_head
;
462 abfd
= abfd
->archive_next
)
463 ar_directory_doer (abfd
, (bfd
*) NULL
);
472 const char *filename
= bfd_get_filename (obfd
);
473 bfd_close_all_done (obfd
);
479 ar_extract (struct list
*list
)
483 fprintf (stderr
, _("%s: no open archive\n"), program_name
);
490 /* Find this name in the archive. */
491 bfd
*member
= obfd
->archive_head
;
494 while (member
&& !found
)
496 if (FILENAME_CMP (bfd_get_filename (member
), list
->name
) == 0)
498 extract_file (member
);
502 member
= member
->archive_next
;
507 bfd_openr (list
->name
, NULL
);
508 fprintf (stderr
, _("%s: can't find module file %s\n"),
509 program_name
, list
->name
);