Bug Summary

File:src/gnu/usr.bin/binutils-2.17/binutils/ar.c
Warning:line 1066, column 5
Value stored to 'found' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ar.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/binutils-2.17/obj/binutils -resource-dir /usr/local/lib/clang/13.0.0 -D HAVE_CONFIG_H -I . -I /usr/src/gnu/usr.bin/binutils-2.17/binutils -I . -D _GNU_SOURCE -I . -I /usr/src/gnu/usr.bin/binutils-2.17/binutils -I ../bfd -I /usr/src/gnu/usr.bin/binutils-2.17/binutils/../bfd -I /usr/src/gnu/usr.bin/binutils-2.17/binutils/../include -I /usr/src/gnu/usr.bin/binutils-2.17/binutils/../intl -I ../intl -D LOCALEDIR="/usr/share/locale" -D bin_dummy_emulation=bin_vanilla_emulation -D PIE_DEFAULT=1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.bin/binutils-2.17/obj/binutils -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.bin/binutils-2.17/binutils/ar.c
1/* ar.c - Archive modify and extract.
2 Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
21
22/*
23 Bugs: should use getopt the way tar does (complete w/optional -) and
24 should have long options too. GNU ar used to check file against filesystem
25 in quick_update and replace operations (would check mtime). Doesn't warn
26 when name truncated. No way to specify pos_end. Error messages should be
27 more consistent. */
28
29#include "bfd.h"
30#include "libiberty.h"
31#include "progress.h"
32#include "bucomm.h"
33#include "aout/ar.h"
34#include "libbfd.h"
35#include "arsup.h"
36#include "filenames.h"
37#include "binemul.h"
38#include <sys/stat.h>
39
40#ifdef __GO32___
41#define EXT_NAME_LEN6 3 /* bufflen of addition to name if it's MS-DOS */
42#else
43#define EXT_NAME_LEN6 6 /* ditto for *NIX */
44#endif
45
46/* We need to open files in binary modes on system where that makes a
47 difference. */
48#ifndef O_BINARY0
49#define O_BINARY0 0
50#endif
51
52/* Kludge declaration from BFD! This is ugly! FIXME! XXX */
53
54struct ar_hdr *
55 bfd_special_undocumented_glue (bfd * abfd, const char *filename);
56
57/* Static declarations */
58
59static void mri_emul (void);
60static const char *normalize (const char *, bfd *);
61static void remove_output (void);
62static void map_over_members (bfd *, void (*)(bfd *), char **, int);
63static void print_contents (bfd * member);
64static void delete_members (bfd *, char **files_to_delete);
65
66static void move_members (bfd *, char **files_to_move);
67static void replace_members
68 (bfd *, char **files_to_replace, bfd_boolean quick);
69static void print_descr (bfd * abfd);
70static void write_archive (bfd *);
71static void ranlib_only (const char *archname);
72static void ranlib_touch (const char *archname);
73static void usage (int);
74
75/** Globals and flags */
76
77static int mri_mode;
78
79/* This flag distinguishes between ar and ranlib:
80 1 means this is 'ranlib'; 0 means this is 'ar'.
81 -1 means if we should use argv[0] to decide. */
82extern int is_ranlib;
83
84/* Nonzero means don't warn about creating the archive file if necessary. */
85int silent_create = 0;
86
87/* Nonzero means describe each action performed. */
88int verbose = 0;
89
90/* Nonzero means preserve dates of members when extracting them. */
91int preserve_dates = 0;
92
93/* Nonzero means don't replace existing members whose dates are more recent
94 than the corresponding files. */
95int newer_only = 0;
96
97/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
98 member). -1 means we've been explicitly asked to not write a symbol table;
99 +1 means we've been explicitly asked to write it;
100 0 is the default.
101 Traditionally, the default in BSD has been to not write the table.
102 However, for POSIX.2 compliance the default is now to write a symbol table
103 if any of the members are object files. */
104int write_armap = 0;
105
106/* Nonzero means it's the name of an existing member; position new or moved
107 files with respect to this one. */
108char *posname = NULL((void*)0);
109
110/* Sez how to use `posname': pos_before means position before that member.
111 pos_after means position after that member. pos_end means always at end.
112 pos_default means default appropriately. For the latter two, `posname'
113 should also be zero. */
114enum pos
115 {
116 pos_default, pos_before, pos_after, pos_end
117 } postype = pos_default;
118
119static bfd **
120get_pos_bfd (bfd **, enum pos, const char *);
121
122/* For extract/delete only. If COUNTED_NAME_MODE is TRUE, we only
123 extract the COUNTED_NAME_COUNTER instance of that name. */
124static bfd_boolean counted_name_mode = 0;
125static int counted_name_counter = 0;
126
127/* Whether to truncate names of files stored in the archive. */
128static bfd_boolean ar_truncate = FALSE0;
129
130/* Whether to use a full file name match when searching an archive.
131 This is convenient for archives created by the Microsoft lib
132 program. */
133static bfd_boolean full_pathname = FALSE0;
134
135/* Whether archive contents should be deterministic with uid, gid,
136 and mtime set to zero and permissions set to 644. This breaks
137 later use of the 'u' option as well as make's lib(member) feature.
138 Note that the symbol index may have a non-zero timestamp to meet
139 archive format requirements. */
140static bfd_boolean deterministic = FALSE0;
141
142int interactive = 0;
143
144static void
145mri_emul (void)
146{
147 interactive = isatty (fileno (stdin)(!__isthreaded ? (((&__sF[0]))->_file) : (fileno)((&
__sF[0])))
);
148 yyparse ();
149}
150
151/* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero,
152 COUNT is the length of the FILES chain; FUNCTION is called on each entry
153 whose name matches one in FILES. */
154
155static void
156map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
157{
158 bfd *head;
159 int match_count;
160
161 if (count == 0)
162 {
163 for (head = arch->next; head; head = head->next)
164 {
165 PROGRESS (1);
166 function (head);
167 }
168 return;
169 }
170
171 /* This may appear to be a baroque way of accomplishing what we want.
172 However we have to iterate over the filenames in order to notice where
173 a filename is requested but does not exist in the archive. Ditto
174 mapping over each file each time -- we want to hack multiple
175 references. */
176
177 for (; count > 0; files++, count--)
178 {
179 bfd_boolean found = FALSE0;
180
181 match_count = 0;
182 for (head = arch->next; head; head = head->next)
183 {
184 PROGRESS (1);
185 if (head->filename == NULL((void*)0))
186 {
187 /* Some archive formats don't get the filenames filled in
188 until the elements are opened. */
189 struct stat buf;
190 bfd_stat_arch_elt (head, &buf)((*((head)->xvec->_bfd_stat_arch_elt)) (head, &buf)
)
;
191 }
192 if ((head->filename != NULL((void*)0)) &&
193 (!FILENAME_CMP (normalize (*files, arch), head->filename)strcmp(normalize (*files, arch), head->filename)))
194 {
195 ++match_count;
196 if (counted_name_mode
197 && match_count != counted_name_counter)
198 {
199 /* Counting, and didn't match on count; go on to the
200 next one. */
201 continue;
202 }
203
204 found = TRUE1;
205 function (head);
206 }
207 }
208 if (!found)
209 /* xgettext:c-format */
210 fprintf (stderr(&__sF[2]), _("no entry %s in archive\n")("no entry %s in archive\n"), *files);
211 }
212}
213
214bfd_boolean operation_alters_arch = FALSE0;
215
216static void
217usage (int help)
218{
219 FILE *s;
220
221 s = help ? stdout(&__sF[1]) : stderr(&__sF[2]);
222
223 if (! is_ranlib)
224 {
225 /* xgettext:c-format */
226 fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n")("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"
)
,
227 program_name);
228 /* xgettext:c-format */
229 fprintf (s, _(" %s -M [<mri-script]\n")(" %s -M [<mri-script]\n"), program_name);
230 fprintf (s, _(" commands:\n")(" commands:\n"));
231 fprintf (s, _(" d - delete file(s) from the archive\n")(" d - delete file(s) from the archive\n"));
232 fprintf (s, _(" m[ab] - move file(s) in the archive\n")(" m[ab] - move file(s) in the archive\n"));
233 fprintf (s, _(" p - print file(s) found in the archive\n")(" p - print file(s) found in the archive\n"));
234 fprintf (s, _(" q[f] - quick append file(s) to the archive\n")(" q[f] - quick append file(s) to the archive\n"));
235 fprintf (s, _(" r[ab][f][u] - replace existing or insert new file(s) into the archive\n")(" r[ab][f][u] - replace existing or insert new file(s) into the archive\n"
)
);
236 fprintf (s, _(" t - display contents of archive\n")(" t - display contents of archive\n"));
237 fprintf (s, _(" x[o] - extract file(s) from the archive\n")(" x[o] - extract file(s) from the archive\n"));
238 fprintf (s, _(" command specific modifiers:\n")(" command specific modifiers:\n"));
239 fprintf (s, _(" [a] - put file(s) after [member-name]\n")(" [a] - put file(s) after [member-name]\n"));
240 fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n")(" [b] - put file(s) before [member-name] (same as [i])\n"
)
);
241 fprintf (s, _(" [N] - use instance [count] of name\n")(" [N] - use instance [count] of name\n"));
242 fprintf (s, _(" [f] - truncate inserted file names\n")(" [f] - truncate inserted file names\n"));
243 fprintf (s, _(" [P] - use full path names when matching\n")(" [P] - use full path names when matching\n"));
244 fprintf (s, _(" [o] - preserve original dates\n")(" [o] - preserve original dates\n"));
245 fprintf (s, _(" [u] - only replace files that are newer than current archive contents\n")(" [u] - only replace files that are newer than current archive contents\n"
)
);
246 fprintf (s, _(" [D] - set deterministic attributes in archive\n")(" [D] - set deterministic attributes in archive\n"
)
);
247 fprintf (s, _(" [U] - set accurate attributes in archive\n")(" [U] - set accurate attributes in archive\n"));
248 fprintf (s, _(" generic modifiers:\n")(" generic modifiers:\n"));
249 fprintf (s, _(" [c] - do not warn if the library had to be created\n")(" [c] - do not warn if the library had to be created\n"
)
);
250 fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n")(" [s] - create an archive index (cf. ranlib)\n"));
251 fprintf (s, _(" [S] - do not build a symbol table\n")(" [S] - do not build a symbol table\n"));
252 fprintf (s, _(" [v] - be verbose\n")(" [v] - be verbose\n"));
253 fprintf (s, _(" [V] - display the version number\n")(" [V] - display the version number\n"));
254 fprintf (s, _(" @<file> - read options from <file>\n")(" @<file> - read options from <file>\n"));
255
256 ar_emul_usage (s);
257 }
258 else
259 {
260 /* xgettext:c-format */
261 fprintf (s, _("Usage: %s [options] archive\n")("Usage: %s [options] archive\n"), program_name);
262 fprintf (s, _(" Generate an index to speed access to archives\n")(" Generate an index to speed access to archives\n"));
263 fprintf (s, _(" The options are:\n\(" The options are:\n @<file> Read options from <file>\n -h --help Print this help message\n -V --version Print version information\n"
)
264 @<file> Read options from <file>\n\(" The options are:\n @<file> Read options from <file>\n -h --help Print this help message\n -V --version Print version information\n"
)
265 -h --help Print this help message\n\(" The options are:\n @<file> Read options from <file>\n -h --help Print this help message\n -V --version Print version information\n"
)
266 -V --version Print version information\n")(" The options are:\n @<file> Read options from <file>\n -h --help Print this help message\n -V --version Print version information\n"
)
);
267 }
268
269 list_supported_targets (program_name, stderr(&__sF[2]));
270
271 if (help)
272 fprintf (s, _("Report bugs to %s\n")("Report bugs to %s\n"), REPORT_BUGS_TO"<URL:http://www.sourceware.org/bugzilla/>");
273
274 xexit (help ? 0 : 1);
275}
276
277/* Normalize a file name specified on the command line into a file
278 name which we will use in an archive. */
279
280static const char *
281normalize (const char *file, bfd *abfd)
282{
283 const char *filename;
284
285 if (full_pathname)
286 return file;
287
288 filename = strrchr (file, '/');
289#ifdef HAVE_DOS_BASED_FILE_SYSTEM
290 {
291 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
292 char *bslash = strrchr (file, '\\');
293 if (filename == NULL((void*)0) || (bslash != NULL((void*)0) && bslash > filename))
294 filename = bslash;
295 if (filename == NULL((void*)0) && file[0] != '\0' && file[1] == ':')
296 filename = file + 1;
297 }
298#endif
299 if (filename != (char *) NULL((void*)0))
300 filename++;
301 else
302 filename = file;
303
304 if (ar_truncate
305 && abfd != NULL((void*)0)
306 && strlen (filename) > abfd->xvec->ar_max_namelen)
307 {
308 char *s;
309
310 /* Space leak. */
311 s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
312 memcpy (s, filename, abfd->xvec->ar_max_namelen);
313 s[abfd->xvec->ar_max_namelen] = '\0';
314 filename = s;
315 }
316
317 return filename;
318}
319
320/* Remove any output file. This is only called via xatexit. */
321
322static const char *output_filename = NULL((void*)0);
323static FILE *output_file = NULL((void*)0);
324static bfd *output_bfd = NULL((void*)0);
325
326static void
327remove_output (void)
328{
329 if (output_filename != NULL((void*)0))
330 {
331 if (output_bfd != NULL((void*)0))
332 bfd_cache_close (output_bfd);
333 if (output_file != NULL((void*)0))
334 fclose (output_file);
335 unlink_if_ordinary (output_filename);
336 }
337}
338
339/* The option parsing should be in its own function.
340 It will be when I have getopt working. */
341
342int main (int, char **);
343
344int
345main (int argc, char **argv)
346{
347 char *arg_ptr;
348 char c;
349 enum
350 {
351 none = 0, delete, replace, print_table,
352 print_files, extract, move, quick_append
353 } operation = none;
354 int arg_index;
355 char **files;
356 int file_count;
357 char *inarch_filename;
358 int show_version;
359 int i;
360 int do_posix = 0;
361
362#if defined (HAVE_SETLOCALE1) && defined (HAVE_LC_MESSAGES1)
363 setlocale (LC_MESSAGES6, "");
364#endif
365#if defined (HAVE_SETLOCALE1)
366 setlocale (LC_CTYPE2, "");
367#endif
368 bindtextdomain (PACKAGE, LOCALEDIR)while (0);
369 textdomain (PACKAGE)while (0);
370
371 program_name = argv[0];
372 xmalloc_set_program_name (program_name);
373
374 if (pledge ("stdio rpath wpath cpath fattr", NULL((void*)0)) == -1)
375 fatal (_("pledge: %s")("pledge: %s"), strerror (errno(*__errno())));
376
377 expandargv (&argc, &argv);
378
379 if (is_ranlib < 0)
380 {
381 char *temp;
382
383 temp = strrchr (program_name, '/');
384#ifdef HAVE_DOS_BASED_FILE_SYSTEM
385 {
386 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
387 char *bslash = strrchr (program_name, '\\');
388 if (temp == NULL((void*)0) || (bslash != NULL((void*)0) && bslash > temp))
389 temp = bslash;
390 if (temp == NULL((void*)0) && program_name[0] != '\0' && program_name[1] == ':')
391 temp = program_name + 1;
392 }
393#endif
394 if (temp == NULL((void*)0))
395 temp = program_name;
396 else
397 ++temp;
398 if (strlen (temp) >= 6
399 && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib")strcmp(temp + strlen (temp) - 6, "ranlib") == 0)
400 is_ranlib = 1;
401 else
402 is_ranlib = 0;
403 }
404
405 if (argc > 1 && argv[1][0] == '-')
406 {
407 if (strcmp (argv[1], "--help") == 0)
408 usage (1);
409 else if (strcmp (argv[1], "--version") == 0)
410 {
411 if (is_ranlib)
412 print_version ("ranlib");
413 else
414 print_version ("ar");
415 }
416 }
417
418 START_PROGRESS (program_name, 0);
419
420 bfd_init ();
421 set_default_bfd_target ();
422
423 show_version = 0;
424
425 xatexit (remove_output);
426
427 for (i = 1; i < argc; i++)
428 if (! ar_emul_parse_arg (argv[i]))
429 break;
430 argv += (i - 1);
431 argc -= (i - 1);
432
433 if (is_ranlib)
434 {
435 bfd_boolean touch = FALSE0;
436
437 if (argc < 2
438 || strcmp (argv[1], "--help") == 0
439 || strcmp (argv[1], "-h") == 0
440 || strcmp (argv[1], "-H") == 0)
441 usage (0);
442 if (strcmp (argv[1], "-V") == 0
443 || strcmp (argv[1], "-v") == 0
444 || strncmp (argv[1], "--v", 3) == 0)
445 print_version ("ranlib");
446 arg_index = 1;
447 if (strcmp (argv[1], "-t") == 0)
448 {
449 ++arg_index;
450 touch = TRUE1;
451 }
452 while (arg_index < argc)
453 {
454 if (! touch)
455 ranlib_only (argv[arg_index]);
456 else
457 ranlib_touch (argv[arg_index]);
458 ++arg_index;
459 }
460 xexit (0);
461 }
462
463 if (argc == 2 && strcmp (argv[1], "-M") == 0)
464 {
465 mri_emul ();
466 xexit (0);
467 }
468
469 if (argc < 2)
470 usage (0);
471
472 arg_index = 1;
473 arg_ptr = argv[arg_index];
474
475 if (*arg_ptr == '-')
476 {
477 /* When the first option starts with '-' we support POSIX-compatible
478 option parsing. */
479 do_posix = 1;
480 ++arg_ptr; /* compatibility */
481 }
482
483 do
484 {
485 while ((c = *arg_ptr++) != '\0')
486 {
487 switch (c)
488 {
489 case 'd':
490 case 'm':
491 case 'p':
492 case 'q':
493 case 'r':
494 case 't':
495 case 'x':
496 if (operation != none)
497 fatal (_("two different operation options specified")("two different operation options specified"));
498 switch (c)
499 {
500 case 'd':
501 operation = delete;
502 operation_alters_arch = TRUE1;
503 break;
504 case 'm':
505 operation = move;
506 operation_alters_arch = TRUE1;
507 break;
508 case 'p':
509 operation = print_files;
510 break;
511 case 'q':
512 operation = quick_append;
513 operation_alters_arch = TRUE1;
514 break;
515 case 'r':
516 operation = replace;
517 operation_alters_arch = TRUE1;
518 break;
519 case 't':
520 operation = print_table;
521 break;
522 case 'x':
523 operation = extract;
524 break;
525 }
526 case 'l':
527 break;
528 case 'c':
529 silent_create = 1;
530 break;
531 case 'o':
532 preserve_dates = 1;
533 break;
534 case 'V':
535 show_version = TRUE1;
536 break;
537 case 's':
538 write_armap = 1;
539 break;
540 case 'S':
541 write_armap = -1;
542 break;
543 case 'u':
544 newer_only = 1;
545 break;
546 case 'v':
547 verbose = 1;
548 break;
549 case 'a':
550 postype = pos_after;
551 break;
552 case 'b':
553 postype = pos_before;
554 break;
555 case 'i':
556 postype = pos_before;
557 break;
558 case 'M':
559 mri_mode = 1;
560 break;
561 case 'N':
562 counted_name_mode = TRUE1;
563 break;
564 case 'f':
565 ar_truncate = TRUE1;
566 break;
567 case 'P':
568 full_pathname = TRUE1;
569 break;
570 case 'D':
571 deterministic = TRUE1;
572 break;
573 case 'U':
574 deterministic = FALSE0;
575 break;
576 default:
577 /* xgettext:c-format */
578 non_fatal (_("illegal option -- %c")("illegal option -- %c"), c);
579 usage (0);
580 }
581 }
582
583 /* With POSIX-compatible option parsing continue with the next
584 argument if it starts with '-'. */
585 if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
586 arg_ptr = argv[++arg_index] + 1;
587 else
588 do_posix = 0;
589 }
590 while (do_posix);
591
592 if (show_version)
593 print_version ("ar");
594
595 ++arg_index;
596 if (arg_index >= argc)
597 usage (0);
598
599 if (mri_mode)
600 {
601 mri_emul ();
602 }
603 else
604 {
605 bfd *arch;
606
607 /* We don't use do_quick_append any more. Too many systems
608 expect ar to always rebuild the symbol table even when q is
609 used. */
610
611 /* We can't write an armap when using ar q, so just do ar r
612 instead. */
613 if (operation == quick_append && write_armap)
614 operation = replace;
615
616 if ((operation == none || operation == print_table)
617 && write_armap == 1)
618 {
619 ranlib_only (argv[arg_index]);
620 xexit (0);
621 }
622
623 if (operation == none)
624 fatal (_("no operation specified")("no operation specified"));
625
626 if (newer_only && operation != replace)
627 fatal (_("`u' is only meaningful with the `r' option.")("`u' is only meaningful with the `r' option."));
628
629 if (postype != pos_default)
630 posname = argv[arg_index++];
631
632 if (counted_name_mode)
633 {
634 if (operation != extract && operation != delete)
635 fatal (_("`N' is only meaningful with the `x' and `d' options.")("`N' is only meaningful with the `x' and `d' options."));
636 counted_name_counter = atoi (argv[arg_index++]);
637 if (counted_name_counter <= 0)
638 fatal (_("Value for `N' must be positive.")("Value for `N' must be positive."));
639 }
640
641 inarch_filename = argv[arg_index++];
642
643 files = arg_index < argc ? argv + arg_index : NULL((void*)0);
644 file_count = argc - arg_index;
645
646 arch = open_inarch (inarch_filename,
647 files == NULL((void*)0) ? (char *) NULL((void*)0) : files[0]);
648
649 switch (operation)
650 {
651 case print_table:
652 map_over_members (arch, print_descr, files, file_count);
653 break;
654
655 case print_files:
656 map_over_members (arch, print_contents, files, file_count);
657 break;
658
659 case extract:
660 map_over_members (arch, extract_file, files, file_count);
661 break;
662
663 case delete:
664 if (files != NULL((void*)0))
665 delete_members (arch, files);
666 else
667 output_filename = NULL((void*)0);
668 break;
669
670 case move:
671 if (files != NULL((void*)0))
672 move_members (arch, files);
673 else
674 output_filename = NULL((void*)0);
675 break;
676
677 case replace:
678 case quick_append:
679 if (files != NULL((void*)0) || write_armap > 0)
680 replace_members (arch, files, operation == quick_append);
681 else
682 output_filename = NULL((void*)0);
683 break;
684
685 /* Shouldn't happen! */
686 default:
687 /* xgettext:c-format */
688 fatal (_("internal error -- this option not implemented")("internal error -- this option not implemented"));
689 }
690 }
691
692 END_PROGRESS (program_name);
693
694 xexit (0);
695 return 0;
696}
697
698bfd *
699open_inarch (const char *archive_filename, const char *file)
700{
701 const char *target;
702 bfd **last_one;
703 bfd *next_one;
704 struct stat sbuf;
705 bfd *arch;
706 char **matching;
707
708 bfd_set_error (bfd_error_no_error);
709
710 target = NULL((void*)0);
711
712 if (stat (archive_filename, &sbuf) != 0)
713 {
714#if !defined(__GO32__) || defined(__DJGPP__)
715
716 /* FIXME: I don't understand why this fragment was ifndef'ed
717 away for __GO32__; perhaps it was in the days of DJGPP v1.x.
718 stat() works just fine in v2.x, so I think this should be
719 removed. For now, I enable it for DJGPP v2. -- EZ. */
720
721/* KLUDGE ALERT! Temporary fix until I figger why
722 stat() is wrong ... think it's buried in GO32's IDT - Jax */
723 if (errno(*__errno()) != ENOENT2)
724 bfd_fatal (archive_filename);
725#endif
726
727 if (!operation_alters_arch)
728 {
729 fprintf (stderr(&__sF[2]), "%s: ", program_name);
730 perror (archive_filename);
731 maybequit ();
732 return NULL((void*)0);
733 }
734
735 /* Try to figure out the target to use for the archive from the
736 first object on the list. */
737 if (file != NULL((void*)0))
738 {
739 bfd *obj;
740
741 obj = bfd_openr (file, NULL((void*)0));
742 if (obj != NULL((void*)0))
743 {
744 if (bfd_check_format (obj, bfd_object))
745 target = bfd_get_target (obj)((obj)->xvec->name);
746 (void) bfd_close (obj);
747 }
748 }
749
750 /* Create an empty archive. */
751 arch = bfd_openw (archive_filename, target);
752 if (arch == NULL((void*)0)
753 || ! bfd_set_format (arch, bfd_archive)
754 || ! bfd_close (arch))
755 bfd_fatal (archive_filename);
756 else if (!silent_create)
757 non_fatal (_("creating %s")("creating %s"), archive_filename);
758
759 /* If we die creating a new archive, don't leave it around. */
760 output_filename = archive_filename;
761 }
762
763 arch = bfd_openr (archive_filename, target);
764 if (arch == NULL((void*)0))
765 {
766 bloser:
767 bfd_fatal (archive_filename);
768 }
769
770 if (! bfd_check_format_matches (arch, bfd_archive, &matching))
771 {
772 bfd_nonfatal (archive_filename);
773 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
774 {
775 list_matching_formats (matching);
776 free (matching);
777 }
778 xexit (1);
779 }
780
781 last_one = &(arch->next);
782 /* Read all the contents right away, regardless. */
783 for (next_one = bfd_openr_next_archived_file (arch, NULL((void*)0));
784 next_one;
785 next_one = bfd_openr_next_archived_file (arch, next_one))
786 {
787 PROGRESS (1);
788 *last_one = next_one;
789 last_one = &next_one->next;
790 }
791 *last_one = (bfd *) NULL((void*)0);
792 if (bfd_get_error () != bfd_error_no_more_archived_files)
793 goto bloser;
794 return arch;
795}
796
797static void
798print_contents (bfd *abfd)
799{
800 int ncopied = 0;
801 char *cbuf = xmalloc (BUFSIZE8192);
802 struct stat buf;
803 long size;
804 if (bfd_stat_arch_elt (abfd, &buf)((*((abfd)->xvec->_bfd_stat_arch_elt)) (abfd, &buf)
)
!= 0)
805 /* xgettext:c-format */
806 fatal (_("internal stat error on %s")("internal stat error on %s"), bfd_get_filename (abfd)((char *) (abfd)->filename));
807
808 if (verbose)
809 /* xgettext:c-format */
810 printf (_("\n<%s>\n\n")("\n<%s>\n\n"), bfd_get_filename (abfd)((char *) (abfd)->filename));
811
812 bfd_seek (abfd, (file_ptr) 0, SEEK_SET0);
813
814 size = buf.st_size;
815 while (ncopied < size)
816 {
817
818 int nread;
819 int tocopy = size - ncopied;
820 if (tocopy > BUFSIZE8192)
821 tocopy = BUFSIZE8192;
822
823 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
824 if (nread != tocopy)
825 /* xgettext:c-format */
826 fatal (_("%s is not a valid archive")("%s is not a valid archive"),
827 bfd_get_filename (bfd_my_archive (abfd))((char *) (((abfd)->my_archive))->filename));
828 fwrite (cbuf, 1, nread, stdout(&__sF[1]));
829 ncopied += tocopy;
830 }
831 free (cbuf);
832}
833
834/* Extract a member of the archive into its own file.
835
836 We defer opening the new file until after we have read a BUFSIZ chunk of the
837 old one, since we know we have just read the archive header for the old
838 one. Since most members are shorter than BUFSIZ, this means we will read
839 the old header, read the old data, write a new inode for the new file, and
840 write the new data, and be done. This 'optimization' is what comes from
841 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
842 Gilmore */
843
844void
845extract_file (bfd *abfd)
846{
847 FILE *ostream;
848 char *cbuf = xmalloc (BUFSIZE8192);
849 int nread, tocopy;
850 long ncopied = 0;
851 long size;
852 struct stat buf;
853
854 if (bfd_stat_arch_elt (abfd, &buf)((*((abfd)->xvec->_bfd_stat_arch_elt)) (abfd, &buf)
)
!= 0)
855 /* xgettext:c-format */
856 fatal (_("internal stat error on %s")("internal stat error on %s"), bfd_get_filename (abfd)((char *) (abfd)->filename));
857 size = buf.st_size;
858
859 if (size < 0)
860 /* xgettext:c-format */
861 fatal (_("stat returns negative size for %s")("stat returns negative size for %s"), bfd_get_filename (abfd)((char *) (abfd)->filename));
862
863 if (verbose)
864 printf ("x - %s\n", bfd_get_filename (abfd)((char *) (abfd)->filename));
865
866 bfd_seek (abfd, (file_ptr) 0, SEEK_SET0);
867
868 ostream = NULL((void*)0);
869 if (size == 0)
870 {
871 /* Seems like an abstraction violation, eh? Well it's OK! */
872 output_filename = bfd_get_filename (abfd)((char *) (abfd)->filename);
873
874 ostream = fopen (bfd_get_filename (abfd)((char *) (abfd)->filename), FOPEN_WB"w");
875 if (ostream == NULL((void*)0))
876 {
877 perror (bfd_get_filename (abfd)((char *) (abfd)->filename));
878 xexit (1);
879 }
880
881 output_file = ostream;
882 }
883 else
884 while (ncopied < size)
885 {
886 tocopy = size - ncopied;
887 if (tocopy > BUFSIZE8192)
888 tocopy = BUFSIZE8192;
889
890 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
891 if (nread != tocopy)
892 /* xgettext:c-format */
893 fatal (_("%s is not a valid archive")("%s is not a valid archive"),
894 bfd_get_filename (bfd_my_archive (abfd))((char *) (((abfd)->my_archive))->filename));
895
896 /* See comment above; this saves disk arm motion */
897 if (ostream == NULL((void*)0))
898 {
899 /* Seems like an abstraction violation, eh? Well it's OK! */
900 output_filename = bfd_get_filename (abfd)((char *) (abfd)->filename);
901
902 ostream = fopen (bfd_get_filename (abfd)((char *) (abfd)->filename), FOPEN_WB"w");
903 if (ostream == NULL((void*)0))
904 {
905 perror (bfd_get_filename (abfd)((char *) (abfd)->filename));
906 xexit (1);
907 }
908
909 output_file = ostream;
910 }
911 fwrite (cbuf, 1, nread, ostream);
912 ncopied += tocopy;
913 }
914
915 if (ostream != NULL((void*)0))
916 fclose (ostream);
917
918 output_file = NULL((void*)0);
919 output_filename = NULL((void*)0);
920
921 chmod (bfd_get_filename (abfd)((char *) (abfd)->filename), buf.st_mode & 0777);
922
923 if (preserve_dates)
924 {
925 /* Set access time to modification time. Only st_mtime is
926 initialized by bfd_stat_arch_elt. */
927 buf.st_atimest_atim.tv_sec = buf.st_mtimest_mtim.tv_sec;
928 set_times (bfd_get_filename (abfd)((char *) (abfd)->filename), &buf);
929 }
930
931 free (cbuf);
932}
933
934static void
935write_archive (bfd *iarch)
936{
937 bfd *obfd;
938 char *old_name, *new_name;
939 bfd *contents_head = iarch->next;
940
941 old_name = xmalloc (strlen (bfd_get_filename (iarch)((char *) (iarch)->filename)) + 1);
942 strcpy (old_name, bfd_get_filename (iarch)((char *) (iarch)->filename));
943 new_name = make_tempname (old_name, 0);
944
945 output_filename = new_name;
946
947 obfd = bfd_openw (new_name, bfd_get_target (iarch)((iarch)->xvec->name));
948
949 if (obfd == NULL((void*)0))
950 bfd_fatal (old_name);
951
952 output_bfd = obfd;
953
954 bfd_set_format (obfd, bfd_archive);
955
956 /* Request writing the archive symbol table unless we've
957 been explicitly requested not to. */
958 obfd->has_armap = write_armap >= 0;
959
960 if (ar_truncate)
961 {
962 /* This should really use bfd_set_file_flags, but that rejects
963 archives. */
964 obfd->flags |= BFD_TRADITIONAL_FORMAT0x400;
965 }
966
967 if (deterministic)
968 obfd->flags |= BFD_DETERMINISTIC0x4000;
969
970 if (!bfd_set_archive_head (obfd, contents_head))
971 bfd_fatal (old_name);
972
973 if (!bfd_close (obfd))
974 bfd_fatal (old_name);
975
976 output_bfd = NULL((void*)0);
977 output_filename = NULL((void*)0);
978
979 /* We don't care if this fails; we might be creating the archive. */
980 bfd_close (iarch);
981
982 if (smart_rename (new_name, old_name, 0) != 0)
983 xexit (1);
984}
985
986/* Return a pointer to the pointer to the entry which should be rplacd'd
987 into when altering. DEFAULT_POS should be how to interpret pos_default,
988 and should be a pos value. */
989
990static bfd **
991get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
992{
993 bfd **after_bfd = contents;
994 enum pos realpos;
995 const char *realposname;
996
997 if (postype == pos_default)
998 {
999 realpos = default_pos;
1000 realposname = default_posname;
1001 }
1002 else
1003 {
1004 realpos = postype;
1005 realposname = posname;
1006 }
1007
1008 if (realpos == pos_end)
1009 {
1010 while (*after_bfd)
1011 after_bfd = &((*after_bfd)->next);
1012 }
1013 else
1014 {
1015 for (; *after_bfd; after_bfd = &(*after_bfd)->next)
1016 if (FILENAME_CMP ((*after_bfd)->filename, realposname)strcmp((*after_bfd)->filename, realposname) == 0)
1017 {
1018 if (realpos == pos_after)
1019 after_bfd = &(*after_bfd)->next;
1020 break;
1021 }
1022 }
1023 return after_bfd;
1024}
1025
1026static void
1027delete_members (bfd *arch, char **files_to_delete)
1028{
1029 bfd **current_ptr_ptr;
1030 bfd_boolean found;
1031 bfd_boolean something_changed = FALSE0;
1032 int match_count;
1033
1034 for (; *files_to_delete != NULL((void*)0); ++files_to_delete)
1035 {
1036 /* In a.out systems, the armap is optional. It's also called
1037 __.SYMDEF. So if the user asked to delete it, we should remember
1038 that fact. This isn't quite right for COFF systems (where
1039 __.SYMDEF might be regular member), but it's very unlikely
1040 to be a problem. FIXME */
1041
1042 if (!strcmp (*files_to_delete, "__.SYMDEF"))
1043 {
1044 arch->has_armap = FALSE0;
1045 write_armap = -1;
1046 continue;
1047 }
1048
1049 found = FALSE0;
1050 match_count = 0;
1051 current_ptr_ptr = &(arch->next);
1052 while (*current_ptr_ptr)
1053 {
1054 if (FILENAME_CMP (normalize (*files_to_delete, arch),strcmp(normalize (*files_to_delete, arch), (*current_ptr_ptr)
->filename)
1055 (*current_ptr_ptr)->filename)strcmp(normalize (*files_to_delete, arch), (*current_ptr_ptr)
->filename)
== 0)
1056 {
1057 ++match_count;
1058 if (counted_name_mode
1059 && match_count != counted_name_counter)
1060 {
1061 /* Counting, and didn't match on count; go on to the
1062 next one. */
1063 }
1064 else
1065 {
1066 found = TRUE1;
Value stored to 'found' is never read
1067 something_changed = TRUE1;
1068 if (verbose)
1069 printf ("d - %s\n",
1070 *files_to_delete);
1071 *current_ptr_ptr = ((*current_ptr_ptr)->next);
1072 goto next_file;
1073 }
1074 }
1075
1076 current_ptr_ptr = &((*current_ptr_ptr)->next);
1077 }
1078
1079 if (verbose && !found)
1080 {
1081 /* xgettext:c-format */
1082 printf (_("No member named `%s'\n")("No member named `%s'\n"), *files_to_delete);
1083 }
1084 next_file:
1085 ;
1086 }
1087
1088 if (something_changed)
1089 write_archive (arch);
1090 else
1091 output_filename = NULL((void*)0);
1092}
1093
1094
1095/* Reposition existing members within an archive */
1096
1097static void
1098move_members (bfd *arch, char **files_to_move)
1099{
1100 bfd **after_bfd; /* New entries go after this one */
1101 bfd **current_ptr_ptr; /* cdr pointer into contents */
1102
1103 for (; *files_to_move; ++files_to_move)
1104 {
1105 current_ptr_ptr = &(arch->next);
1106 while (*current_ptr_ptr)
1107 {
1108 bfd *current_ptr = *current_ptr_ptr;
1109 if (FILENAME_CMP (normalize (*files_to_move, arch),strcmp(normalize (*files_to_move, arch), current_ptr->filename
)
1110 current_ptr->filename)strcmp(normalize (*files_to_move, arch), current_ptr->filename
)
== 0)
1111 {
1112 /* Move this file to the end of the list - first cut from
1113 where it is. */
1114 bfd *link;
1115 *current_ptr_ptr = current_ptr->next;
1116
1117 /* Now glue to end */
1118 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL((void*)0));
1119 link = *after_bfd;
1120 *after_bfd = current_ptr;
1121 current_ptr->next = link;
1122
1123 if (verbose)
1124 printf ("m - %s\n", *files_to_move);
1125
1126 goto next_file;
1127 }
1128
1129 current_ptr_ptr = &((*current_ptr_ptr)->next);
1130 }
1131 /* xgettext:c-format */
1132 fatal (_("no entry %s in archive %s!")("no entry %s in archive %s!"), *files_to_move, arch->filename);
1133
1134 next_file:;
1135 }
1136
1137 write_archive (arch);
1138}
1139
1140/* Ought to default to replacing in place, but this is existing practice! */
1141
1142static void
1143replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
1144{
1145 bfd_boolean changed = FALSE0;
1146 bfd **after_bfd; /* New entries go after this one. */
1147 bfd *current;
1148 bfd **current_ptr;
1149
1150 while (files_to_move && *files_to_move)
1151 {
1152 if (! quick)
1153 {
1154 current_ptr = &arch->next;
1155 while (*current_ptr)
1156 {
1157 current = *current_ptr;
1158
1159 /* For compatibility with existing ar programs, we
1160 permit the same file to be added multiple times. */
1161 if (FILENAME_CMP (normalize (*files_to_move, arch),strcmp(normalize (*files_to_move, arch), normalize (current->
filename, arch))
1162 normalize (current->filename, arch))strcmp(normalize (*files_to_move, arch), normalize (current->
filename, arch))
== 0
1163 && current->arelt_data != NULL((void*)0))
1164 {
1165 if (newer_only)
1166 {
1167 struct stat fsbuf, asbuf;
1168
1169 if (stat (*files_to_move, &fsbuf) != 0)
1170 {
1171 if (errno(*__errno()) != ENOENT2)
1172 bfd_fatal (*files_to_move);
1173 goto next_file;
1174 }
1175 if (bfd_stat_arch_elt (current, &asbuf)((*((current)->xvec->_bfd_stat_arch_elt)) (current, &
asbuf))
!= 0)
1176 /* xgettext:c-format */
1177 fatal (_("internal stat error on %s")("internal stat error on %s"),
1178 current->filename);
1179
1180 if (fsbuf.st_mtimest_mtim.tv_sec <= asbuf.st_mtimest_mtim.tv_sec)
1181 goto next_file;
1182 }
1183
1184 after_bfd = get_pos_bfd (&arch->next, pos_after,
1185 current->filename);
1186 if (ar_emul_replace (after_bfd, *files_to_move,
1187 verbose))
1188 {
1189 /* Snip out this entry from the chain. */
1190 *current_ptr = (*current_ptr)->next;
1191 changed = TRUE1;
1192 }
1193
1194 goto next_file;
1195 }
1196 current_ptr = &(current->next);
1197 }
1198 }
1199
1200 /* Add to the end of the archive. */
1201 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL((void*)0));
1202
1203 if (ar_emul_append (after_bfd, *files_to_move, verbose))
1204 changed = TRUE1;
1205
1206 next_file:;
1207
1208 files_to_move++;
1209 }
1210
1211 if (changed)
1212 write_archive (arch);
1213 else
1214 output_filename = NULL((void*)0);
1215}
1216
1217static void
1218ranlib_only (const char *archname)
1219{
1220 bfd *arch;
1221
1222 if (get_file_size (archname) < 1)
1223 return;
1224 write_armap = 1;
1225 arch = open_inarch (archname, (char *) NULL((void*)0));
1226 if (arch == NULL((void*)0))
1227 xexit (1);
1228 write_archive (arch);
1229}
1230
1231/* Update the timestamp of the symbol map of an archive. */
1232
1233static void
1234ranlib_touch (const char *archname)
1235{
1236#ifdef __GO32__
1237 /* I don't think updating works on go32. */
1238 ranlib_only (archname);
1239#else
1240 int f;
1241 bfd *arch;
1242 char **matching;
1243
1244 if (get_file_size (archname) < 1)
1245 return;
1246 f = open (archname, O_RDWR0x0002 | O_BINARY0, 0);
1247 if (f < 0)
1248 {
1249 bfd_set_error (bfd_error_system_call);
1250 bfd_fatal (archname);
1251 }
1252
1253 arch = bfd_fdopenr (archname, (const char *) NULL((void*)0), f);
1254 if (arch == NULL((void*)0))
1255 bfd_fatal (archname);
1256 if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1257 {
1258 bfd_nonfatal (archname);
1259 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1260 {
1261 list_matching_formats (matching);
1262 free (matching);
1263 }
1264 xexit (1);
1265 }
1266
1267 if (! bfd_has_map (arch)((arch)->has_armap))
1268 /* xgettext:c-format */
1269 fatal (_("%s: no archive map to update")("%s: no archive map to update"), archname);
1270
1271 bfd_update_armap_timestamp (arch)((*((arch)->xvec->_bfd_update_armap_timestamp)) (arch));
1272
1273 if (! bfd_close (arch))
1274 bfd_fatal (archname);
1275#endif
1276}
1277
1278/* Things which are interesting to map over all or some of the files: */
1279
1280static void
1281print_descr (bfd *abfd)
1282{
1283 print_arelt_descr (stdout(&__sF[1]), abfd, verbose);
1284}