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 |
||
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 | }>>>>>>> |