1/* bucomm.c -- Bin Utils COMmon code.
2   Copyright (C) 1991-2017 Free Software Foundation, Inc.
3
4   This file is part of GNU Binutils.
5
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.
10
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.
15
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.  */
20
21/* We might put this in a library someday so it could be dynamically
22   loaded, but for now it's not necessary.  */
23
24#include "sysdep.h"
25#include "bfd.h"
26#include "libiberty.h"
27#include "filenames.h"
28
29#include <time.h>		/* ctime, maybe time_t */
30#include <assert.h>
31#include "bucomm.h"
32
33#ifndef HAVE_TIME_T_IN_TIME_H
34#ifndef HAVE_TIME_T_IN_TYPES_H
35typedef long time_t;
36#endif
37#endif
38
39/* Error reporting.  */
40
41char *program_name;
42
43void
44bfd_nonfatal (const char *string)
45{
46  const char *errmsg;
47
48  errmsg = bfd_errmsg (bfd_get_error ());
49  fflush (stdout);
50  if (string)
51    fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg);
52  else
53    fprintf (stderr, "%s: %s\n", program_name, errmsg);
54}
55
56/* Issue a non fatal error message.  FILENAME, or if NULL then BFD,
57   are used to indicate the problematic file.  SECTION, if non NULL,
58   is used to provide a section name.  If FORMAT is non-null, then it
59   is used to print additional information via vfprintf.  Finally the
60   bfd error message is printed.  In summary, error messages are of
61   one of the following forms:
62
63   PROGRAM:file: bfd-error-message
64   PROGRAM:file[section]: bfd-error-message
65   PROGRAM:file: printf-message: bfd-error-message
66   PROGRAM:file[section]: printf-message: bfd-error-message.  */
67
68void
69bfd_nonfatal_message (const char *filename,
70		      const bfd *abfd,
71		      const asection *section,
72		      const char *format, ...)
73{
74  const char *errmsg;
75  const char *section_name;
76  va_list args;
77
78  errmsg = bfd_errmsg (bfd_get_error ());
79  fflush (stdout);
80  section_name = NULL;
81  va_start (args, format);
82  fprintf (stderr, "%s", program_name);
83
84  if (abfd)
85    {
86      if (!filename)
87	filename = bfd_get_archive_filename (abfd);
88      if (section)
89	section_name = bfd_get_section_name (abfd, section);
90    }
91  if (section_name)
92    fprintf (stderr, ":%s[%s]", filename, section_name);
93  else
94    fprintf (stderr, ":%s", filename);
95
96  if (format)
97    {
98      fprintf (stderr, ": ");
99      vfprintf (stderr, format, args);
100    }
101  fprintf (stderr, ": %s\n", errmsg);
102  va_end (args);
103}
104
105void
106bfd_fatal (const char *string)
107{
108  bfd_nonfatal (string);
109  xexit (1);
110}
111
112void
113report (const char * format, va_list args)
114{
115  fflush (stdout);
116  fprintf (stderr, "%s: ", program_name);
117  vfprintf (stderr, format, args);
118  putc ('\n', stderr);
119}
120
121void
122fatal (const char *format, ...)
123{
124  va_list args;
125
126  va_start (args, format);
127
128  report (format, args);
129  va_end (args);
130  xexit (1);
131}
132
133void
134non_fatal (const char *format, ...)
135{
136  va_list args;
137
138  va_start (args, format);
139
140  report (format, args);
141  va_end (args);
142}
143
144/* Set the default BFD target based on the configured target.  Doing
145   this permits the binutils to be configured for a particular target,
146   and linked against a shared BFD library which was configured for a
147   different target.  */
148
149void
150set_default_bfd_target (void)
151{
152  /* The macro TARGET is defined by Makefile.  */
153  const char *target = TARGET;
154
155  if (! bfd_set_default_target (target))
156    fatal (_("can't set BFD default target to `%s': %s"),
157	   target, bfd_errmsg (bfd_get_error ()));
158}
159
160/* After a FALSE return from bfd_check_format_matches with
161   bfd_get_error () == bfd_error_file_ambiguously_recognized, print
162   the possible matching targets.  */
163
164void
165list_matching_formats (char **p)
166{
167  fflush (stdout);
168  fprintf (stderr, _("%s: Matching formats:"), program_name);
169  while (*p)
170    fprintf (stderr, " %s", *p++);
171  fputc ('\n', stderr);
172}
173
174/* List the supported targets.  */
175
176void
177list_supported_targets (const char *name, FILE *f)
178{
179  int t;
180  const char **targ_names;
181
182  if (name == NULL)
183    fprintf (f, _("Supported targets:"));
184  else
185    fprintf (f, _("%s: supported targets:"), name);
186
187  targ_names = bfd_target_list ();
188  for (t = 0; targ_names[t] != NULL; t++)
189    fprintf (f, " %s", targ_names[t]);
190  fprintf (f, "\n");
191  free (targ_names);
192}
193
194/* List the supported architectures.  */
195
196void
197list_supported_architectures (const char *name, FILE *f)
198{
199  const char ** arch;
200  const char ** arches;
201
202  if (name == NULL)
203    fprintf (f, _("Supported architectures:"));
204  else
205    fprintf (f, _("%s: supported architectures:"), name);
206
207  for (arch = arches = bfd_arch_list (); *arch; arch++)
208    fprintf (f, " %s", *arch);
209  fprintf (f, "\n");
210  free (arches);
211}
212
213static const char *
214endian_string (enum bfd_endian endian)
215{
216  switch (endian)
217    {
218    case BFD_ENDIAN_BIG: return _("big endian");
219    case BFD_ENDIAN_LITTLE: return _("little endian");
220    default: return _("endianness unknown");
221    }
222}
223
224/* Data passed to do_display_target and other target iterators.  */
225
226struct display_target {
227  /* Temp file.  */
228  char *filename;
229  /* Return status.  */
230  int error;
231  /* Number of targets.  */
232  int count;
233  /* Size of info in bytes.  */
234  size_t alloc;
235  /* Per-target info.  */
236  struct {
237    /* Target name.  */
238    const char *name;
239    /* Non-zero if target/arch combination supported.  */
240    unsigned char arch[bfd_arch_last - bfd_arch_obscure - 1];
241  } *info;
242};
243
244/* List the targets that BFD is configured to support, each followed
245   by its endianness and the architectures it supports.  Also build
246   info about target/archs.  */
247
248static int
249do_display_target (const bfd_target *targ, void *data)
250{
251  struct display_target *param = (struct display_target *) data;
252  bfd *abfd;
253  size_t amt;
254
255  param->count += 1;
256  amt = param->count * sizeof (*param->info);
257  if (param->alloc < amt)
258    {
259      size_t size = ((param->count < 64 ? 64 : param->count)
260		     * sizeof (*param->info) * 2);
261      param->info = xrealloc (param->info, size);
262      memset ((char *) param->info + param->alloc, 0, size - param->alloc);
263      param->alloc = size;
264    }
265  param->info[param->count - 1].name = targ->name;
266
267  printf (_("%s\n (header %s, data %s)\n"), targ->name,
268	  endian_string (targ->header_byteorder),
269	  endian_string (targ->byteorder));
270
271  abfd = bfd_openw (param->filename, targ->name);
272  if (abfd == NULL)
273    {
274      bfd_nonfatal (param->filename);
275      param->error = 1;
276    }
277  else if (!bfd_set_format (abfd, bfd_object))
278    {
279      if (bfd_get_error () != bfd_error_invalid_operation)
280	{
281	  bfd_nonfatal (targ->name);
282	  param->error = 1;
283	}
284    }
285  else
286    {
287      enum bfd_architecture a;
288
289      for (a = bfd_arch_obscure + 1; a < bfd_arch_last; a++)
290	if (bfd_set_arch_mach (abfd, a, 0))
291	  {
292	    printf ("  %s\n", bfd_printable_arch_mach (a, 0));
293	    param->info[param->count - 1].arch[a - bfd_arch_obscure - 1] = 1;
294	  }
295    }
296  if (abfd != NULL)
297    bfd_close_all_done (abfd);
298
299  return param->error;
300}
301
302static void
303display_target_list (struct display_target *arg)
304{
305  arg->filename = make_temp_file (NULL);
306  arg->error = 0;
307  arg->count = 0;
308  arg->alloc = 0;
309  arg->info = NULL;
310
311  bfd_iterate_over_targets (do_display_target, arg);
312
313  unlink (arg->filename);
314  free (arg->filename);
315}
316
317/* Calculate how many targets we can print across the page.  */
318
319static int
320do_info_size (int targ, int width, const struct display_target *arg)
321{
322  while (targ < arg->count)
323    {
324      width -= strlen (arg->info[targ].name) + 1;
325      if (width < 0)
326	return targ;
327      ++targ;
328    }
329  return targ;
330}
331
332/* Print header of target names.  */
333
334static void
335do_info_header (int targ, int stop_targ, const struct display_target *arg)
336{
337  while (targ != stop_targ)
338    printf ("%s ", arg->info[targ++].name);
339}
340
341/* Print a table row.  */
342
343static void
344do_info_row (int targ, int stop_targ, enum bfd_architecture a,
345	     const struct display_target *arg)
346{
347  while (targ != stop_targ)
348    {
349      if (arg->info[targ].arch[a - bfd_arch_obscure - 1])
350	fputs (arg->info[targ].name, stdout);
351      else
352	{
353	  int l = strlen (arg->info[targ].name);
354	  while (l--)
355	    putchar ('-');
356	}
357      ++targ;
358      if (targ != stop_targ)
359	putchar (' ');
360    }
361}
362
363/* Print tables of all the target-architecture combinations that
364   BFD has been configured to support.  */
365
366static void
367display_target_tables (const struct display_target *arg)
368{
369  const char *columns;
370  int width, start_targ, stop_targ;
371  enum bfd_architecture arch;
372  int longest_arch = 0;
373
374  for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
375    {
376      const char *s = bfd_printable_arch_mach (arch, 0);
377      int len = strlen (s);
378      if (len > longest_arch)
379	longest_arch = len;
380    }
381
382  width = 0;
383  columns = getenv ("COLUMNS");
384  if (columns != NULL)
385    width = atoi (columns);
386  if (width == 0)
387    width = 80;
388
389  for (start_targ = 0; start_targ < arg->count; start_targ = stop_targ)
390    {
391      stop_targ = do_info_size (start_targ, width - longest_arch - 1, arg);
392
393      printf ("\n%*s", longest_arch + 1, " ");
394      do_info_header (start_targ, stop_targ, arg);
395      putchar ('\n');
396
397      for (arch = bfd_arch_obscure + 1; arch < bfd_arch_last; arch++)
398	{
399	  if (strcmp (bfd_printable_arch_mach (arch, 0), "UNKNOWN!") != 0)
400	    {
401	      printf ("%*s ", longest_arch,
402		      bfd_printable_arch_mach (arch, 0));
403
404	      do_info_row (start_targ, stop_targ, arch, arg);
405	      putchar ('\n');
406	    }
407	}
408    }
409}
410
411int
412display_info (void)
413{
414  struct display_target arg;
415
416  printf (_("BFD header file version %s\n"), BFD_VERSION_STRING);
417
418  display_target_list (&arg);
419  if (!arg.error)
420    display_target_tables (&arg);
421
422  return arg.error;
423}
424
425/* Display the archive header for an element as if it were an ls -l listing:
426
427   Mode       User\tGroup\tSize\tDate               Name */
428
429void
430print_arelt_descr (FILE *file, bfd *abfd, bfd_boolean verbose)
431{
432  struct stat buf;
433
434  if (verbose)
435    {
436      if (bfd_stat_arch_elt (abfd, &buf) == 0)
437	{
438	  char modebuf[11];
439	  char timebuf[40];
440	  time_t when = buf.st_mtime;
441	  const char *ctime_result = (const char *) ctime (&when);
442	  bfd_size_type size;
443
444	  /* PR binutils/17605: Check for corrupt time values.  */
445	  if (ctime_result == NULL)
446	    sprintf (timebuf, _("<time data corrupt>"));
447	  else
448	    /* POSIX format:  skip weekday and seconds from ctime output.  */
449	    sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20);
450
451	  mode_string (buf.st_mode, modebuf);
452	  modebuf[10] = '\0';
453	  size = buf.st_size;
454	  /* POSIX 1003.2/D11 says to skip first character (entry type).  */
455	  fprintf (file, "%s %ld/%ld %6" BFD_VMA_FMT "u %s ", modebuf + 1,
456		   (long) buf.st_uid, (long) buf.st_gid,
457		   size, timebuf);
458	}
459    }
460
461  fprintf (file, "%s\n", bfd_get_filename (abfd));
462}
463
464/* Return a path for a new temporary file in the same directory
465   as file PATH.  */
466
467static char *
468template_in_dir (const char *path)
469{
470#define template "stXXXXXX"
471  const char *slash = strrchr (path, '/');
472  char *tmpname;
473  size_t len;
474
475#ifdef HAVE_DOS_BASED_FILE_SYSTEM
476  {
477    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
478    char *bslash = strrchr (path, '\\');
479
480    if (slash == NULL || (bslash != NULL && bslash > slash))
481      slash = bslash;
482    if (slash == NULL && path[0] != '\0' && path[1] == ':')
483      slash = path + 1;
484  }
485#endif
486
487  if (slash != (char *) NULL)
488    {
489      len = slash - path;
490      tmpname = (char *) xmalloc (len + sizeof (template) + 2);
491      memcpy (tmpname, path, len);
492
493#ifdef HAVE_DOS_BASED_FILE_SYSTEM
494      /* If tmpname is "X:", appending a slash will make it a root
495	 directory on drive X, which is NOT the same as the current
496	 directory on drive X.  */
497      if (len == 2 && tmpname[1] == ':')
498	tmpname[len++] = '.';
499#endif
500      tmpname[len++] = '/';
501    }
502  else
503    {
504      tmpname = (char *) xmalloc (sizeof (template));
505      len = 0;
506    }
507
508  memcpy (tmpname + len, template, sizeof (template));
509  return tmpname;
510#undef template
511}
512
513/* Return the name of a created temporary file in the same directory
514   as FILENAME.  */
515
516char *
517make_tempname (char *filename)
518{
519  char *tmpname = template_in_dir (filename);
520  int fd;
521
522#ifdef HAVE_MKSTEMP
523  fd = mkstemp (tmpname);
524#else
525  tmpname = mktemp (tmpname);
526  if (tmpname == NULL)
527    return NULL;
528  fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
529#endif
530  if (fd == -1)
531    {
532      free (tmpname);
533      return NULL;
534    }
535  close (fd);
536  return tmpname;
537}
538
539/* Return the name of a created temporary directory inside the
540   directory containing FILENAME.  */
541
542char *
543make_tempdir (char *filename)
544{
545  char *tmpname = template_in_dir (filename);
546
547#ifdef HAVE_MKDTEMP
548  return mkdtemp (tmpname);
549#else
550  tmpname = mktemp (tmpname);
551  if (tmpname == NULL)
552    return NULL;
553#if defined (_WIN32) && !defined (__CYGWIN32__)
554  if (mkdir (tmpname) != 0)
555    return NULL;
556#else
557  if (mkdir (tmpname, 0700) != 0)
558    return NULL;
559#endif
560  return tmpname;
561#endif
562}
563
564/* Parse a string into a VMA, with a fatal error if it can't be
565   parsed.  */
566
567bfd_vma
568parse_vma (const char *s, const char *arg)
569{
570  bfd_vma ret;
571  const char *end;
572
573  ret = bfd_scan_vma (s, &end, 0);
574
575  if (*end != '\0')
576    fatal (_("%s: bad number: %s"), arg, s);
577
578  return ret;
579}
580
581/* Returns the size of the named file.  If the file does not
582   exist, or if it is not a real file, then a suitable non-fatal
583   error message is printed and (off_t) -1 is returned.  */
584
585off_t
586get_file_size (const char * file_name)
587{
588  struct stat statbuf;
589
590  if (stat (file_name, &statbuf) < 0)
591    {
592      if (errno == ENOENT)
593	non_fatal (_("'%s': No such file"), file_name);
594      else
595	non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
596		   file_name, strerror (errno));
597    }
598  else if (! S_ISREG (statbuf.st_mode))
599    non_fatal (_("Warning: '%s' is not an ordinary file"), file_name);
600  else if (statbuf.st_size < 0)
601    non_fatal (_("Warning: '%s' has negative size, probably it is too large"),
602               file_name);
603  else
604    return statbuf.st_size;
605
606  return (off_t) -1;
607}
608
609/* Return the filename in a static buffer.  */
610
611const char *
612bfd_get_archive_filename (const bfd *abfd)
613{
614  static size_t curr = 0;
615  static char *buf;
616  size_t needed;
617
618  assert (abfd != NULL);
619
620  if (abfd->my_archive == NULL
621      || bfd_is_thin_archive (abfd->my_archive))
622    return bfd_get_filename (abfd);
623
624  needed = (strlen (bfd_get_filename (abfd->my_archive))
625	    + strlen (bfd_get_filename (abfd)) + 3);
626  if (needed > curr)
627    {
628      if (curr)
629	free (buf);
630      curr = needed + (needed >> 1);
631      buf = (char *) xmalloc (curr);
632    }
633  sprintf (buf, "%s(%s)", bfd_get_filename (abfd->my_archive),
634	   bfd_get_filename (abfd));
635  return buf;
636}
637
638/* Returns TRUE iff PATHNAME, a filename of an archive member,
639   is valid for writing.  For security reasons absolute paths
640   and paths containing /../ are not allowed.  See PR 17533.  */
641
642bfd_boolean
643is_valid_archive_path (char const * pathname)
644{
645  const char * n = pathname;
646
647  if (IS_ABSOLUTE_PATH (n))
648    return FALSE;
649
650  while (*n)
651    {
652      if (*n == '.' && *++n == '.' && ( ! *++n || IS_DIR_SEPARATOR (*n)))
653	return FALSE;
654
655      while (*n && ! IS_DIR_SEPARATOR (*n))
656	n++;
657      while (IS_DIR_SEPARATOR (*n))
658	n++;
659    }
660
661  return TRUE;
662}
663