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