Subversion Repositories Kolibri OS

Rev

Rev 5217 | Details | Compare with Previous | Last modification | View Log | RSS feed

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