usr.sbin/makefs: Add -o c|C option to specify comp|check type
[dragonfly.git] / contrib / binutils-2.34 / binutils / bucomm.c
blob9e6a02843e6c7ba11545f69a6a31e927d177a9b0
1 /* bucomm.c -- Bin Utils COMmon code.
2 Copyright (C) 1991-2020 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, MA
19 02110-1301, USA. */
21 /* We might put this in a library someday so it could be dynamically
22 loaded, but for now it's not necessary. */
24 #include "sysdep.h"
25 #include "bfd.h"
26 #include "libiberty.h"
27 #include "filenames.h"
29 #include <time.h> /* ctime, maybe time_t */
30 #include <assert.h>
31 #include "bucomm.h"
33 #ifndef HAVE_TIME_T_IN_TIME_H
34 #ifndef HAVE_TIME_T_IN_TYPES_H
35 typedef long time_t;
36 #endif
37 #endif
39 /* Error reporting. */
41 char *program_name;
43 void
44 bfd_nonfatal (const char *string)
46 const char *errmsg;
47 enum bfd_error err = bfd_get_error ();
49 if (err == bfd_error_no_error)
50 errmsg = _("cause of error unknown");
51 else
52 errmsg = bfd_errmsg (err);
53 fflush (stdout);
54 if (string)
55 fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
56 else
57 fprintf (stderr, "%s: %s\n", program_name, errmsg);
60 /* Issue a non fatal error message. FILENAME, or if NULL then BFD,
61 are used to indicate the problematic file. SECTION, if non NULL,
62 is used to provide a section name. If FORMAT is non-null, then it
63 is used to print additional information via vfprintf. Finally the
64 bfd error message is printed. In summary, error messages are of
65 one of the following forms:
67 PROGRAM: file: bfd-error-message
68 PROGRAM: file[section]: bfd-error-message
69 PROGRAM: file: printf-message: bfd-error-message
70 PROGRAM: file[section]: printf-message: bfd-error-message. */
72 void
73 bfd_nonfatal_message (const char *filename,
74 const bfd *abfd,
75 const asection *section,
76 const char *format, ...)
78 const char *errmsg;
79 const char *section_name;
80 va_list args;
81 enum bfd_error err = bfd_get_error ();
83 if (err == bfd_error_no_error)
84 errmsg = _("cause of error unknown");
85 else
86 errmsg = bfd_errmsg (err);
87 fflush (stdout);
88 section_name = NULL;
89 va_start (args, format);
90 fprintf (stderr, "%s", program_name);
92 if (abfd)
94 if (!filename)
95 filename = bfd_get_archive_filename (abfd);
96 if (section)
97 section_name = bfd_section_name (section);
99 if (section_name)
100 fprintf (stderr, ": %s[%s]", filename, section_name);
101 else
102 fprintf (stderr, ": %s", filename);
104 if (format)
106 fprintf (stderr, ": ");
107 vfprintf (stderr, format, args);
109 fprintf (stderr, ": %s\n", errmsg);
110 va_end (args);
113 void
114 bfd_fatal (const char *string)
116 bfd_nonfatal (string);
117 xexit (1);
120 void
121 report (const char * format, va_list args)
123 fflush (stdout);
124 fprintf (stderr, "%s: ", program_name);
125 vfprintf (stderr, format, args);
126 putc ('\n', stderr);
129 void
130 fatal (const char *format, ...)
132 va_list args;
134 va_start (args, format);
136 report (format, args);
137 va_end (args);
138 xexit (1);
141 void
142 non_fatal (const char *format, ...)
144 va_list args;
146 va_start (args, format);
148 report (format, args);
149 va_end (args);
152 /* Set the default BFD target based on the configured target. Doing
153 this permits the binutils to be configured for a particular target,
154 and linked against a shared BFD library which was configured for a
155 different target. */
157 void
158 set_default_bfd_target (void)
160 /* The macro TARGET is defined by Makefile. */
161 const char *target = TARGET;
163 if (! bfd_set_default_target (target))
164 fatal (_("can't set BFD default target to `%s': %s"),
165 target, bfd_errmsg (bfd_get_error ()));
168 /* After a FALSE return from bfd_check_format_matches with
169 bfd_get_error () == bfd_error_file_ambiguously_recognized, print
170 the possible matching targets. */
172 void
173 list_matching_formats (char **p)
175 fflush (stdout);
176 fprintf (stderr, _("%s: Matching formats:"), program_name);
177 while (*p)
178 fprintf (stderr, " %s", *p++);
179 fputc ('\n', stderr);
182 /* List the supported targets. */
184 void
185 list_supported_targets (const char *name, FILE *f)
187 int t;
188 const char **targ_names;
190 if (name == NULL)
191 fprintf (f, _("Supported targets:"));
192 else
193 fprintf (f, _("%s: supported targets:"), name);
195 targ_names = bfd_target_list ();
196 for (t = 0; targ_names[t] != NULL; t++)
197 fprintf (f, " %s", targ_names[t]);
198 fprintf (f, "\n");
199 free (targ_names);
202 /* List the supported architectures. */
204 void
205 list_supported_architectures (const char *name, FILE *f)
207 const char ** arch;
208 const char ** arches;
210 if (name == NULL)
211 fprintf (f, _("Supported architectures:"));
212 else
213 fprintf (f, _("%s: supported architectures:"), name);
215 for (arch = arches = bfd_arch_list (); *arch; arch++)
216 fprintf (f, " %s", *arch);
217 fprintf (f, "\n");
218 free (arches);
221 static const char *
222 endian_string (enum bfd_endian endian)
224 switch (endian)
226 case BFD_ENDIAN_BIG: return _("big endian");
227 case BFD_ENDIAN_LITTLE: return _("little endian");
228 default: return _("endianness unknown");
232 /* Data passed to do_display_target and other target iterators. */
234 struct display_target {
235 /* Temp file. */
236 char *filename;
237 /* Return status. */
238 int error;
239 /* Number of targets. */
240 int count;
241 /* Size of info in bytes. */
242 size_t alloc;
243 /* Per-target info. */
244 struct {
245 /* Target name. */
246 const char *name;
247 /* Non-zero if target/arch combination supported. */
248 unsigned char arch[bfd_arch_last - bfd_arch_obscure - 1];
249 } *info;
252 /* List the targets that BFD is configured to support, each followed
253 by its endianness and the architectures it supports. Also build
254 info about target/archs. */
256 static int
257 do_display_target (const bfd_target *targ, void *data)
259 struct display_target *param = (struct display_target *) data;
260 bfd *abfd;
261 size_t amt;
263 param->count += 1;
264 amt = param->count * sizeof (*param->info);
265 if (param->alloc < amt)
267 size_t size = ((param->count < 64 ? 64 : param->count)
268 * sizeof (*param->info) * 2);
269 param->info = xrealloc (param->info, size);
270 memset ((char *) param->info + param->alloc, 0, size - param->alloc);
271 param->alloc = size;
273 param->info[param->count - 1].name = targ->name;
275 printf (_("%s\n (header %s, data %s)\n"), targ->name,
276 endian_string (targ->header_byteorder),
277 endian_string (targ->byteorder));
279 abfd = bfd_openw (param->filename, targ->name);
280 if (abfd == NULL)
282 bfd_nonfatal (param->filename);
283 param->error = 1;
285 else if (!bfd_set_format (abfd, bfd_object))
287 if (bfd_get_error () != bfd_error_invalid_operation)
289 bfd_nonfatal (targ->name);
290 param->error = 1;
293 else
295 enum bfd_architecture a;
297 for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
298 if (bfd_set_arch_mach (abfd, a, 0))
300 printf (" %s\n", bfd_printable_arch_mach (a, 0));
301 param->info[param->count - 1].arch[a - bfd_arch_obscure - 1] = 1;
304 if (abfd != NULL)
305 bfd_close_all_done (abfd);
307 return param->error;
310 static void
311 display_target_list (struct display_target *arg)
313 arg->filename = make_temp_file (NULL);
314 arg->error = 0;
315 arg->count = 0;
316 arg->alloc = 0;
317 arg->info = NULL;
319 bfd_iterate_over_targets (do_display_target, arg);
321 unlink (arg->filename);
322 free (arg->filename);
325 /* Calculate how many targets we can print across the page. */
327 static int
328 do_info_size (int targ, int width, const struct display_target *arg)
330 while (targ < arg->count)
332 width -= strlen (arg->info[targ].name) + 1;
333 if (width < 0)
334 return targ;
335 ++targ;
337 return targ;
340 /* Print header of target names. */
342 static void
343 do_info_header (int targ, int stop_targ, const struct display_target *arg)
345 while (targ != stop_targ)
346 printf ("%s ", arg->info[targ++].name);
349 /* Print a table row. */
351 static void
352 do_info_row (int targ, int stop_targ, enum bfd_architecture a,
353 const struct display_target *arg)
355 while (targ != stop_targ)
357 if (arg->info[targ].arch[a - bfd_arch_obscure - 1])
358 fputs (arg->info[targ].name, stdout);
359 else
361 int l = strlen (arg->info[targ].name);
362 while (l--)
363 putchar ('-');
365 ++targ;
366 if (targ != stop_targ)
367 putchar (' ');
371 /* Print tables of all the target-architecture combinations that
372 BFD has been configured to support. */
374 static void
375 display_target_tables (const struct display_target *arg)
377 const char *columns;
378 int width, start_targ, stop_targ;
379 enum bfd_architecture arch;
380 int longest_arch = 0;
382 for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
384 const char *s = bfd_printable_arch_mach (arch, 0);
385 int len = strlen (s);
386 if (len > longest_arch)
387 longest_arch = len;
390 width = 0;
391 columns = getenv ("COLUMNS");
392 if (columns != NULL)
393 width = atoi (columns);
394 if (width == 0)
395 width = 80;
397 for (start_targ = 0; start_targ < arg->count; start_targ = stop_targ)
399 stop_targ = do_info_size (start_targ, width - longest_arch - 1, arg);
401 printf ("\n%*s", longest_arch + 1, " ");
402 do_info_header (start_targ, stop_targ, arg);
403 putchar ('\n');
405 for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
407 if (strcmp (bfd_printable_arch_mach (arch, 0), "UNKNOWN!") != 0)
409 printf ("%*s ", longest_arch,
410 bfd_printable_arch_mach (arch, 0));
412 do_info_row (start_targ, stop_targ, arch, arg);
413 putchar ('\n');
420 display_info (void)
422 struct display_target arg;
424 printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
426 display_target_list (&arg);
427 if (!arg.error)
428 display_target_tables (&arg);
430 return arg.error;
433 /* Display the archive header for an element as if it were an ls -l listing:
435 Mode User\tGroup\tSize\tDate Name */
437 void
438 print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose, bfd_boolean offsets)
440 struct stat buf;
442 if (verbose)
444 if (bfd_stat_arch_elt (abfd, &buf) == 0)
446 char modebuf[11];
447 char timebuf[40];
448 time_t when = buf.st_mtime;
449 const char *ctime_result = (const char *) ctime (&when);
450 bfd_size_type size;
452 /* PR binutils/17605: Check for corrupt time values. */
453 if (ctime_result == NULL)
454 sprintf (timebuf, _("<time data corrupt>"));
455 else
456 /* POSIX format: skip weekday and seconds from ctime output. */
457 sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
459 mode_string (buf.st_mode, modebuf);
460 modebuf[10] = '\0';
461 size = buf.st_size;
462 /* POSIX 1003.2/D11 says to skip first character (entry type). */
463 fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1,
464 (long) buf.st_uid, (long) buf.st_gid,
465 size, timebuf);
469 fprintf (file, "%s", bfd_get_filename (abfd));
471 if (offsets)
473 if (bfd_is_thin_archive (abfd) && abfd->proxy_origin)
474 fprintf (file, " 0x%lx", (unsigned long) abfd->proxy_origin);
475 else if (!bfd_is_thin_archive (abfd) && abfd->origin)
476 fprintf (file, " 0x%lx", (unsigned long) abfd->origin);
479 fprintf (file, "\n");
482 /* Return a path for a new temporary file in the same directory
483 as file PATH. */
485 static char *
486 template_in_dir (const char *path)
488 #define template "stXXXXXX"
489 const char *slash = strrchr (path, '/');
490 char *tmpname;
491 size_t len;
493 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
495 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
496 char *bslash = strrchr (path, '\\');
498 if (slash == NULL || (bslash != NULL && bslash > slash))
499 slash = bslash;
500 if (slash == NULL && path[0] != '\0' && path[1] == ':')
501 slash = path + 1;
503 #endif
505 if (slash != (char *) NULL)
507 len = slash - path;
508 tmpname = (char *) xmalloc (len + sizeof (template) + 2);
509 memcpy (tmpname, path, len);
511 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
512 /* If tmpname is "X:", appending a slash will make it a root
513 directory on drive X, which is NOT the same as the current
514 directory on drive X. */
515 if (len == 2 && tmpname[1] == ':')
516 tmpname[len++] = '.';
517 #endif
518 tmpname[len++] = '/';
520 else
522 tmpname = (char *) xmalloc (sizeof (template));
523 len = 0;
526 memcpy (tmpname + len, template, sizeof (template));
527 return tmpname;
528 #undef template
531 /* Return the name of a created temporary file in the same directory
532 as FILENAME. */
534 char *
535 make_tempname (const char *filename)
537 char *tmpname = template_in_dir (filename);
538 int fd;
540 #ifdef HAVE_MKSTEMP
541 fd = mkstemp (tmpname);
542 #else
543 tmpname = mktemp (tmpname);
544 if (tmpname == NULL)
545 return NULL;
546 fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
547 #endif
548 if (fd == -1)
550 free (tmpname);
551 return NULL;
553 close (fd);
554 return tmpname;
557 /* Return the name of a created temporary directory inside the
558 directory containing FILENAME. */
560 char *
561 make_tempdir (const char *filename)
563 char *tmpname = template_in_dir (filename);
565 #ifdef HAVE_MKDTEMP
566 return mkdtemp (tmpname);
567 #else
568 tmpname = mktemp (tmpname);
569 if (tmpname == NULL)
570 return NULL;
571 #if defined (_WIN32) && !defined (__CYGWIN32__)
572 if (mkdir (tmpname) != 0)
573 return NULL;
574 #else
575 if (mkdir (tmpname, 0700) != 0)
576 return NULL;
577 #endif
578 return tmpname;
579 #endif
582 /* Parse a string into a VMA, with a fatal error if it can't be
583 parsed. */
585 bfd_vma
586 parse_vma (const char *s, const char *arg)
588 bfd_vma ret;
589 const char *end;
591 ret = bfd_scan_vma (s, &end, 0);
593 if (*end != '\0')
594 fatal (_("%s: bad number: %s"), arg, s);
596 return ret;
599 /* Returns the size of the named file. If the file does not
600 exist, or if it is not a real file, then a suitable non-fatal
601 error message is printed and (off_t) -1 is returned. */
603 off_t
604 get_file_size (const char * file_name)
606 struct stat statbuf;
608 if (file_name == NULL)
609 return (off_t) -1;
611 if (stat (file_name, &statbuf) < 0)
613 if (errno == ENOENT)
614 non_fatal (_("'%s': No such file"), file_name);
615 else
616 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
617 file_name, strerror (errno));
619 else if (S_ISDIR (statbuf.st_mode))
620 non_fatal (_("Warning: '%s' is a directory"), file_name);
621 else if (! S_ISREG (statbuf.st_mode))
622 non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
623 else if (statbuf.st_size < 0)
624 non_fatal (_("Warning: '%s' has negative size, probably it is too large"),
625 file_name);
626 else
627 return statbuf.st_size;
629 return (off_t) -1;
632 /* Return the filename in a static buffer. */
634 const char *
635 bfd_get_archive_filename (const bfd *abfd)
637 static size_t curr = 0;
638 static char *buf;
639 size_t needed;
641 assert (abfd != NULL);
643 if (abfd->my_archive == NULL
644 || bfd_is_thin_archive (abfd->my_archive))
645 return bfd_get_filename (abfd);
647 needed = (strlen (bfd_get_filename (abfd->my_archive))
648 + strlen (bfd_get_filename (abfd)) + 3);
649 if (needed > curr)
651 if (curr)
652 free (buf);
653 curr = needed + (needed >> 1);
654 buf = (char *) xmalloc (curr);
656 sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
657 bfd_get_filename (abfd));
658 return buf;
661 /* Returns TRUE iff PATHNAME, a filename of an archive member,
662 is valid for writing. For security reasons absolute paths
663 and paths containing /../ are not allowed. See PR 17533. */
665 bfd_boolean
666 is_valid_archive_path (char const * pathname)
668 const char * n = pathname;
670 if (IS_ABSOLUTE_PATH (n))
671 return FALSE;
673 while (*n)
675 if (*n == '.' && *++n == '.' && ( ! *++n || IS_DIR_SEPARATOR (*n)))
676 return FALSE;
678 while (*n && ! IS_DIR_SEPARATOR (*n))
679 n++;
680 while (IS_DIR_SEPARATOR (*n))
681 n++;
684 return TRUE;