* configure.host: Add Lynx/rs6000 support.
[deliverable/binutils-gdb.git] / binutils / objcopy.c
CommitLineData
c0367ba5 1/* objcopy.c -- copy object file from input to output, optionally massaging it.
f7b839f7 2 Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
c0367ba5 3
46050fe4
ILT
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
19\f
c0367ba5
ILT
20#include "bfd.h"
21#include "sysdep.h"
22#include "bucomm.h"
23#include <getopt.h>
24
f7b839f7
DM
25static void setup_section ();
26static void copy_section ();
27static void mangle_section ();
c0367ba5 28
46050fe4 29#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
c0367ba5 30
46050fe4
ILT
31static asymbol **isympp = NULL; /* Input symbols */
32static asymbol **osympp = NULL; /* Output symbols that survive stripping */
f7b839f7
DM
33
34/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
35static int copy_byte = -1;
36static int interleave = 4;
37
46050fe4 38static boolean verbose; /* Print file and target names. */
f7b839f7 39static int status = 0; /* Exit status. */
c0367ba5
ILT
40
41enum strip_action
46050fe4
ILT
42 {
43 strip_undef,
44 strip_none, /* don't strip */
45 strip_debug, /* strip all debugger symbols */
46 strip_all /* strip all symbols */
47 };
c0367ba5
ILT
48
49/* Which symbols to remove. */
46050fe4 50static enum strip_action strip_symbols;
c0367ba5
ILT
51
52enum locals_action
46050fe4
ILT
53 {
54 locals_undef,
55 locals_start_L, /* discard locals starting with L */
56 locals_all /* discard all locals */
57 };
58
59/* Which local symbols to remove. Overrides strip_all. */
60static enum locals_action discard_locals;
61
62/* Options to handle if running as "strip". */
63
64static struct option strip_options[] =
c0367ba5 65{
46050fe4
ILT
66 {"discard-all", no_argument, 0, 'x'},
67 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 68 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 69 {"help", no_argument, 0, 'h'},
46050fe4 70 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7 71 {"input-target", required_argument, 0, 'I'},
46050fe4 72 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7
DM
73 {"output-target", required_argument, 0, 'O'},
74 {"strip-all", no_argument, 0, 's'},
75 {"strip-debug", no_argument, 0, 'S'},
46050fe4 76 {"target", required_argument, 0, 'F'},
46050fe4 77 {"verbose", no_argument, 0, 'v'},
f7b839f7 78 {"version", no_argument, 0, 'V'},
46050fe4 79 {0, no_argument, 0, 0}
c0367ba5
ILT
80};
81
46050fe4 82/* Options to handle if running as "objcopy". */
c0367ba5 83
46050fe4
ILT
84static struct option copy_options[] =
85{
f7b839f7 86 {"byte", required_argument, 0, 'b'},
46050fe4
ILT
87 {"discard-all", no_argument, 0, 'x'},
88 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 89 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 90 {"help", no_argument, 0, 'h'},
46050fe4 91 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7
DM
92 {"input-target", required_argument, 0, 'I'},
93 {"interleave", required_argument, 0, 'i'},
46050fe4 94 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7
DM
95 {"output-target", required_argument, 0, 'O'},
96 {"strip-all", no_argument, 0, 'S'},
97 {"strip-debug", no_argument, 0, 'g'},
46050fe4 98 {"target", required_argument, 0, 'F'},
46050fe4 99 {"verbose", no_argument, 0, 'v'},
f7b839f7 100 {"version", no_argument, 0, 'V'},
46050fe4 101 {0, no_argument, 0, 0}
c0367ba5
ILT
102};
103
104/* IMPORTS */
46050fe4
ILT
105extern char *program_name;
106extern char *program_version;
107
108/* This flag distinguishes between strip and objcopy:
109 1 means this is 'strip'; 0 means this is 'objcopy'.
110 -1 means if we should use argv[0] to decide. */
111extern int is_strip;
c0367ba5
ILT
112
113
46050fe4
ILT
114static void
115copy_usage (stream, status)
c0367ba5
ILT
116 FILE *stream;
117 int status;
118{
46050fe4 119 fprintf (stream, "\
f7b839f7
DM
120Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
121 [-i interleave] [--interleave=interleave] [--byte=byte]\n\
46050fe4
ILT
122 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
123 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
f7b839f7
DM
124 [--verbose] [--version] [--help] in-file [out-file]\n",
125 program_name);
46050fe4 126 exit (status);
c0367ba5
ILT
127}
128
46050fe4
ILT
129static void
130strip_usage (stream, status)
c0367ba5
ILT
131 FILE *stream;
132 int status;
133{
46050fe4
ILT
134 fprintf (stream, "\
135Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\
136 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
137 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
138 [--verbose] [--version] [--help] file...\n",
139 program_name);
140 exit (status);
c0367ba5
ILT
141}
142
143
46050fe4 144/* Return the name of a temporary file in the same directory as FILENAME. */
c0367ba5 145
46050fe4
ILT
146static char *
147make_tempname (filename)
148 char *filename;
c0367ba5 149{
46050fe4
ILT
150 static char template[] = "stXXXXXX";
151 char *tmpname;
152 char *slash = strrchr (filename, '/');
153
154 if (slash != (char *) NULL)
155 {
156 *slash = 0;
157 tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
158 strcpy (tmpname, filename);
159 strcat (tmpname, "/");
160 strcat (tmpname, template);
161 mktemp (tmpname);
162 *slash = '/';
163 }
164 else
165 {
166 tmpname = xmalloc (sizeof (template));
167 strcpy (tmpname, template);
168 mktemp (tmpname);
c0367ba5 169 }
46050fe4 170 return tmpname;
c0367ba5
ILT
171}
172
46050fe4 173/* Choose which symbol entries to copy; put the result in OSYMS.
c0367ba5 174 We don't copy in place, because that confuses the relocs.
46050fe4
ILT
175 Return the number of symbols to print. */
176
c0367ba5
ILT
177static unsigned int
178filter_symbols (abfd, osyms, isyms, symcount)
179 bfd *abfd;
180 asymbol **osyms, **isyms;
181 unsigned long symcount;
182{
183 register asymbol **from = isyms, **to = osyms;
46050fe4
ILT
184 char locals_prefix = bfd_get_symbol_leading_char (abfd) == '_' ? 'L' : '.';
185 unsigned int src_count = 0, dst_count = 0;
c0367ba5 186
46050fe4
ILT
187 for (; src_count < symcount; src_count++)
188 {
189 asymbol *sym = from[src_count];
190 flagword flags = sym->flags;
191 int keep;
c0367ba5 192
46050fe4
ILT
193 if ((flags & BSF_GLOBAL) /* Keep if external. */
194 || bfd_get_section (sym) == &bfd_und_section
195 || bfd_is_com_section (bfd_get_section (sym)))
196 keep = 1;
197 else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */
198 keep = strip_symbols != strip_debug;
199 else /* Local symbol. */
200 keep = discard_locals != locals_all
201 && (discard_locals != locals_start_L ||
202 bfd_asymbol_name (sym)[0] != locals_prefix);
203 if (keep)
204 to[dst_count++] = sym;
c0367ba5 205 }
c0367ba5
ILT
206
207 return dst_count;
208}
209
f7b839f7
DM
210/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
211 Adjust *SIZE. */
212
213void
214filter_bytes (memhunk, size)
5d2f7e30 215 char *memhunk;
f7b839f7
DM
216 bfd_size_type *size;
217{
218 char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
219
220 for (; from < end; from += interleave)
221 *to++ = *from;
222 *size /= interleave;
223}
224
46050fe4
ILT
225/* Copy object file IBFD onto OBFD. */
226
c0367ba5 227static void
46050fe4
ILT
228copy_object (ibfd, obfd)
229 bfd *ibfd;
230 bfd *obfd;
c0367ba5 231{
46050fe4 232 unsigned int symcount;
c0367ba5 233
46050fe4
ILT
234 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
235 {
236 nonfatal (bfd_get_filename (obfd));
237 }
c0367ba5 238
46050fe4
ILT
239 if (verbose)
240 printf ("copy from %s(%s) to %s(%s)\n",
241 bfd_get_filename(ibfd), bfd_get_target(ibfd),
242 bfd_get_filename(obfd), bfd_get_target(obfd));
c0367ba5 243
46050fe4
ILT
244 if (!bfd_set_start_address (obfd, bfd_get_start_address (ibfd))
245 || !bfd_set_file_flags (obfd,
246 (bfd_get_file_flags (ibfd)
247 & bfd_applicable_file_flags (obfd))))
248 {
249 nonfatal (bfd_get_filename (ibfd));
250 }
c0367ba5 251
46050fe4
ILT
252 /* Copy architecture of input file to output file */
253 if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
254 bfd_get_mach (ibfd)))
255 {
256 fprintf (stderr, "Output file cannot represent architecture %s\n",
257 bfd_printable_arch_mach (bfd_get_arch (ibfd),
258 bfd_get_mach (ibfd)));
259 }
260 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
261 {
262 nonfatal (bfd_get_filename(ibfd));
263 }
c0367ba5 264
46050fe4
ILT
265 if (isympp)
266 free (isympp);
267 if (osympp != isympp)
268 free (osympp);
c0367ba5 269
46050fe4
ILT
270 if (strip_symbols == strip_all && discard_locals == locals_undef)
271 {
272 osympp = isympp = NULL;
273 symcount = 0;
c0367ba5 274 }
46050fe4
ILT
275 else
276 {
277 osympp = isympp = (asymbol **) xmalloc (get_symtab_upper_bound (ibfd));
278 symcount = bfd_canonicalize_symtab (ibfd, isympp);
279
280 if (strip_symbols == strip_debug || discard_locals != locals_undef)
c0367ba5 281 {
46050fe4
ILT
282 osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
283 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
c0367ba5 284 }
46050fe4
ILT
285 }
286
287 bfd_set_symtab (obfd, osympp, symcount);
c0367ba5 288
46050fe4
ILT
289 /* bfd mandates that all output sections be created and sizes set before
290 any output is done. Thus, we traverse all sections multiple times. */
f7b839f7
DM
291 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
292 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
293 bfd_map_over_sections (ibfd, mangle_section, (void *) obfd);
c0367ba5 294}
46050fe4
ILT
295
296static char *
297cat (a, b, c)
298 char *a;
299 char *b;
300 char *c;
c0367ba5 301{
46050fe4
ILT
302 size_t size = strlen (a) + strlen (b) + strlen (c);
303 char *r = xmalloc (size + 1);
304
305 strcpy (r, a);
306 strcat (r, b);
307 strcat (r, c);
308 return r;
c0367ba5
ILT
309}
310
46050fe4
ILT
311/* Read each archive element in turn from IBFD, copy the
312 contents to temp file, and keep the temp file handle. */
313
314static void
315copy_archive (ibfd, obfd, output_target)
316 bfd *ibfd;
317 bfd *obfd;
318 char *output_target;
c0367ba5 319{
46050fe4
ILT
320 bfd **ptr = &obfd->archive_head;
321 bfd *this_element;
322 char *dir = cat ("./#", make_tempname (""), "cd");
323
324 /* Make a temp directory to hold the contents. */
325 mkdir (dir, 0777);
326 obfd->has_armap = ibfd->has_armap;
327
328 this_element = bfd_openr_next_archived_file (ibfd, NULL);
329 ibfd->archive_head = this_element;
330 while (this_element != (bfd *) NULL)
331 {
332 /* Create an output file for this member. */
333 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
334 bfd *output_bfd = bfd_openw (output_name, output_target);
335
336 if (output_bfd == (bfd *) NULL)
337 {
338 nonfatal (output_name);
c0367ba5 339 }
46050fe4
ILT
340 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
341 {
342 nonfatal (bfd_get_filename (obfd));
c0367ba5
ILT
343 }
344
46050fe4
ILT
345 if (bfd_check_format (this_element, bfd_object) == true)
346 {
347 copy_object (this_element, output_bfd);
348 }
c0367ba5 349
46050fe4
ILT
350 bfd_close (output_bfd);
351 /* Open the newly output file and attatch to our list. */
352 output_bfd = bfd_openr (output_name, output_target);
c0367ba5 353
46050fe4
ILT
354 /* Mark it for deletion. */
355 *ptr = output_bfd;
356 ptr = &output_bfd->next;
357 this_element->next = bfd_openr_next_archived_file (ibfd, this_element);
358 this_element = this_element->next;
c0367ba5 359 }
46050fe4 360 *ptr = (bfd *) NULL;
c0367ba5 361
46050fe4
ILT
362 if (!bfd_close (obfd))
363 {
364 nonfatal (bfd_get_filename (obfd));
c0367ba5 365 }
c0367ba5 366
46050fe4
ILT
367 /* Delete all the files that we opened.
368 Construct their names again, unfortunately, but
369 we're about to exit anyway. */
370 for (this_element = ibfd->archive_head;
371 this_element != (bfd *) NULL;
372 this_element = this_element->next)
373 {
374 unlink (cat (dir, "/", bfd_get_filename (this_element)));
375 }
376 rmdir (dir);
377 if (!bfd_close (ibfd))
378 {
379 nonfatal (bfd_get_filename (ibfd));
380 }
c0367ba5
ILT
381}
382
46050fe4
ILT
383/* The top-level control. */
384
385static void
386copy_file (input_filename, output_filename, input_target, output_target)
387 char *input_filename;
388 char *output_filename;
389 char *input_target;
390 char *output_target;
c0367ba5 391{
46050fe4 392 bfd *ibfd;
cef35d48 393 char **matching;
c0367ba5
ILT
394
395 /* To allow us to do "strip *" without dying on the first
396 non-object file, failures are nonfatal. */
397
46050fe4 398 ibfd = bfd_openr (input_filename, input_target);
c0367ba5
ILT
399 if (ibfd == NULL)
400 {
46050fe4 401 nonfatal (input_filename);
c0367ba5
ILT
402 }
403
cef35d48
DM
404 if (bfd_check_format (ibfd, bfd_archive))
405 {
406 bfd *obfd = bfd_openw (output_filename, output_target);
407 if (obfd == NULL)
408 {
409 nonfatal (output_filename);
410 }
411 copy_archive (ibfd, obfd, output_target);
412 }
413 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
46050fe4
ILT
414 {
415 bfd *obfd = bfd_openw (output_filename, output_target);
416 if (obfd == NULL)
417 {
418 nonfatal (output_filename);
419 }
c0367ba5 420
46050fe4 421 copy_object (ibfd, obfd);
c0367ba5 422
46050fe4
ILT
423 if (!bfd_close (obfd))
424 {
425 nonfatal (output_filename);
426 }
427
428 if (!bfd_close (ibfd))
429 {
430 nonfatal (input_filename);
431 }
432 }
cef35d48 433 else
46050fe4 434 {
cef35d48
DM
435 bfd_nonfatal (input_filename);
436 if (bfd_error == file_ambiguously_recognized)
46050fe4 437 {
cef35d48
DM
438 list_matching_formats (matching);
439 free (matching);
46050fe4 440 }
cef35d48 441 status = 1;
46050fe4
ILT
442 }
443}
444
445/* Create a section in OBFD with the same name and attributes
446 as ISECTION in IBFD. */
c0367ba5 447
c0367ba5 448static void
f7b839f7 449setup_section (ibfd, isection, obfd)
46050fe4
ILT
450 bfd *ibfd;
451 sec_ptr isection;
452 bfd *obfd;
c0367ba5 453{
46050fe4
ILT
454 sec_ptr osection;
455 char *err;
456
457 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
458 && (strip_symbols == strip_debug
459 || strip_symbols == strip_all
460 || discard_locals == locals_all))
461 return;
462
463 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
464 if (osection == NULL)
465 {
466 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
467 if (osection == NULL)
468 {
469 err = "making";
470 goto loser;
c0367ba5
ILT
471 }
472 }
473
46050fe4
ILT
474 if (!bfd_set_section_size (obfd,
475 osection,
476 bfd_section_size (ibfd, isection)))
477 {
478 err = "size";
479 goto loser;
c0367ba5
ILT
480 }
481
46050fe4
ILT
482 if (bfd_set_section_vma (obfd,
483 osection,
484 bfd_section_vma (ibfd, isection))
485 == false)
486 {
487 err = "vma";
488 goto loser;
489 }
c0367ba5 490
46050fe4
ILT
491 if (bfd_set_section_alignment (obfd,
492 osection,
493 bfd_section_alignment (ibfd, isection))
494 == false)
495 {
496 err = "alignment";
497 goto loser;
498 }
c0367ba5 499
46050fe4
ILT
500 if (!bfd_set_section_flags (obfd, osection,
501 bfd_get_section_flags (ibfd, isection)))
502 {
503 err = "flags";
504 goto loser;
c0367ba5
ILT
505 }
506
46050fe4
ILT
507 /* All went well */
508 return;
c0367ba5
ILT
509
510loser:
46050fe4
ILT
511 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
512 program_name,
513 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
514 err, bfd_errmsg (bfd_error));
515 status = 1;
516}
517
518/* Copy the data of input section ISECTION of IBFD
519 to an output section with the same name in OBFD.
520 If stripping then don't copy any relocation info. */
521
c0367ba5 522static void
f7b839f7 523copy_section (ibfd, isection, obfd)
46050fe4
ILT
524 bfd *ibfd;
525 sec_ptr isection;
526 bfd *obfd;
c0367ba5 527{
46050fe4
ILT
528 arelent **relpp;
529 int relcount;
530 sec_ptr osection;
531 bfd_size_type size;
532
533 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
534 && (strip_symbols == strip_debug
535 || strip_symbols == strip_all
536 || discard_locals == locals_all))
537 {
538 return;
539 }
c0367ba5 540
46050fe4
ILT
541 osection = bfd_get_section_by_name (obfd,
542 bfd_section_name (ibfd, isection));
c0367ba5 543
46050fe4 544 size = bfd_get_section_size_before_reloc (isection);
c0367ba5
ILT
545
546 if (size == 0)
547 return;
548
549 if (strip_symbols == strip_all
46050fe4 550 || bfd_get_reloc_upper_bound (ibfd, isection) == 0)
c0367ba5 551 {
46050fe4
ILT
552 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
553 }
554 else
c0367ba5 555 {
46050fe4
ILT
556 relpp = (arelent **) xmalloc (bfd_get_reloc_upper_bound (ibfd, isection));
557 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
558 bfd_set_reloc (obfd, osection, relpp, relcount);
c0367ba5
ILT
559 }
560
561 isection->_cooked_size = isection->_raw_size;
46050fe4 562 isection->reloc_done = true;
c0367ba5 563
46050fe4 564 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
c0367ba5 565 {
46050fe4 566 PTR memhunk = (PTR) xmalloc ((unsigned) size);
c0367ba5 567
46050fe4
ILT
568 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
569 size))
570 {
571 nonfatal (bfd_get_filename (ibfd));
572 }
c0367ba5 573
f7b839f7
DM
574 if (copy_byte >= 0)
575 filter_bytes (memhunk, &size);
576
46050fe4
ILT
577 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
578 size))
579 {
580 nonfatal (bfd_get_filename (obfd));
581 }
582 free (memhunk);
c0367ba5 583 }
46050fe4 584}
c0367ba5 585
46050fe4
ILT
586/* All the symbols have been read in and point to their owning input section.
587 They have been relocated so that they are all relative to the base of
588 their owning section. On the way out, all the symbols will be relocated to
589 their new location in the output file, through some complex sums. */
c0367ba5 590
46050fe4 591static void
f7b839f7 592mangle_section (ibfd, p, obfd)
46050fe4
ILT
593 bfd *ibfd;
594 asection *p;
595 bfd *obfd;
596{
597 p->output_section = bfd_get_section_by_name (obfd, p->name);
598 p->output_offset = 0;
c0367ba5 599}
46050fe4
ILT
600
601/* The number of bytes to copy at once. */
602#define COPY_BUF 8192
603
604/* Copy file FROM to file TO, performing no translations.
605 Return 0 if ok, -1 if error. */
606
607static int
608simple_copy (from, to)
609 char *from, *to;
c0367ba5 610{
46050fe4
ILT
611 int fromfd, tofd, nread;
612 char buf[COPY_BUF];
613
614 fromfd = open (from, O_RDONLY);
615 if (fromfd < 0)
616 return -1;
617 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
618 if (tofd < 0)
619 {
620 close (fromfd);
621 return -1;
622 }
623 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
624 {
625 if (write (tofd, buf, nread) != nread)
626 {
627 close (fromfd);
628 close (tofd);
629 return -1;
630 }
631 }
632 close (fromfd);
633 close (tofd);
634 if (nread < 0)
635 return -1;
636 return 0;
637}
c0367ba5 638
46050fe4
ILT
639#ifndef S_ISLNK
640#ifdef S_IFLNK
641#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
642#else
643#define S_ISLNK(m) 0
644#define lstat stat
645#endif
646#endif
647
648/* Rename FROM to TO, copying if TO is a link.
649 Assumes that TO already exists, because FROM is a temp file.
650 Return 0 if ok, -1 if error. */
651
652static int
653smart_rename (from, to)
654 char *from, *to;
655{
656 struct stat s;
657 int ret = 0;
c0367ba5 658
46050fe4
ILT
659 if (lstat (to, &s))
660 return -1;
c0367ba5 661
46050fe4
ILT
662 /* Use rename only if TO is not a symbolic link and has
663 only one hard link. */
664 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
665 {
666 ret = rename (from, to);
667 if (ret == 0)
668 {
669 /* Try to preserve the permission bits and ownership of TO. */
670 chmod (to, s.st_mode & 07777);
671 chown (to, s.st_uid, s.st_gid);
672 }
673 }
674 else
675 {
676 ret = simple_copy (from, to);
677 if (ret == 0)
678 unlink (from);
679 }
680 return ret;
681}
682
683static int
684strip_main (argc, argv)
685 int argc;
686 char *argv[];
687{
688 char *input_target = NULL, *output_target = NULL;
689 boolean show_version = false;
690 int c, i;
691
692 while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv",
693 strip_options, (int *) 0)) != EOF)
694 {
695 switch (c)
696 {
697 case 'I':
698 input_target = optarg;
699 case 'O':
700 output_target = optarg;
701 break;
702 case 'F':
703 input_target = output_target = optarg;
704 break;
705 case 's':
c0367ba5 706 strip_symbols = strip_all;
46050fe4
ILT
707 break;
708 case 'S':
709 case 'g':
710 strip_symbols = strip_debug;
711 break;
712 case 'x':
713 discard_locals = locals_all;
714 break;
715 case 'X':
716 discard_locals = locals_start_L;
717 break;
718 case 'v':
719 verbose = true;
720 break;
721 case 'V':
722 show_version = true;
723 break;
724 case 0:
725 break; /* we've been given a long option */
726 case 'h':
727 strip_usage (stdout, 0);
728 default:
729 strip_usage (stderr, 1);
730 }
731 }
732
733 if (show_version)
734 {
735 printf ("GNU %s version %s\n", program_name, program_version);
736 exit (0);
737 }
c0367ba5 738
46050fe4
ILT
739 /* Default is to strip all symbols. */
740 if (strip_symbols == strip_undef && discard_locals == locals_undef)
741 strip_symbols = strip_all;
742
743 if (output_target == (char *) NULL)
744 output_target = input_target;
745
746 i = optind;
747 if (i == argc)
748 strip_usage (stderr, 1);
749
750 for (; i < argc; i++)
751 {
752 int hold_status = status;
c0367ba5 753
46050fe4
ILT
754 char *tmpname = make_tempname (argv[i]);
755 status = 0;
756 copy_file (argv[i], tmpname, input_target, output_target);
757 if (status == 0)
758 {
759 smart_rename (tmpname, argv[i]);
760 status = hold_status;
c0367ba5 761 }
46050fe4
ILT
762 else
763 unlink (tmpname);
764 free (tmpname);
765 }
766
767 return 0;
768}
769
770static int
771copy_main (argc, argv)
772 int argc;
773 char *argv[];
774{
775 char *input_filename, *output_filename;
776 char *input_target = NULL, *output_target = NULL;
777 boolean show_version = false;
778 int c;
779
f7b839f7 780 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
46050fe4
ILT
781 copy_options, (int *) 0)) != EOF)
782 {
783 switch (c)
784 {
f7b839f7
DM
785 case 'b':
786 copy_byte = atoi(optarg);
787 if (copy_byte < 0)
788 {
789 fprintf (stderr, "%s: byte number must be non-negative\n",
790 program_name);
791 exit (1);
792 }
793 break;
794 case 'i':
795 interleave = atoi(optarg);
796 if (interleave < 1)
797 {
798 fprintf(stderr, "%s: interleave must be positive\n",
799 program_name);
800 exit (1);
801 }
802 break;
c0367ba5 803 case 'I':
46050fe4 804 case 's': /* "source" - 'I' is preferred */
c0367ba5
ILT
805 input_target = optarg;
806 case 'O':
46050fe4 807 case 'd': /* "destination" - 'O' is preferred */
c0367ba5
ILT
808 output_target = optarg;
809 break;
810 case 'F':
c0367ba5
ILT
811 input_target = output_target = optarg;
812 break;
c0367ba5
ILT
813 case 'S':
814 strip_symbols = strip_all;
815 break;
816 case 'g':
817 strip_symbols = strip_debug;
818 break;
819 case 'x':
820 discard_locals = locals_all;
821 break;
822 case 'X':
823 discard_locals = locals_start_L;
824 break;
825 case 'v':
826 verbose = true;
827 break;
828 case 'V':
829 show_version = true;
830 break;
46050fe4 831 case 0:
c0367ba5
ILT
832 break; /* we've been given a long option */
833 case 'h':
834 copy_usage (stdout, 0);
835 default:
836 copy_usage (stderr, 1);
46050fe4
ILT
837 }
838 }
839
840 if (show_version)
841 {
842 printf ("GNU %s version %s\n", program_name, program_version);
843 exit (0);
844 }
c0367ba5 845
f7b839f7
DM
846 if (copy_byte >= interleave)
847 {
848 fprintf (stderr, "%s: byte number must be less than interleave\n",
849 program_name);
850 exit (1);
851 }
852
46050fe4
ILT
853 if (optind == argc || optind + 2 < argc)
854 copy_usage (stderr, 1);
c0367ba5
ILT
855
856 input_filename = argv[optind];
857 if (optind + 1 < argc)
46050fe4 858 output_filename = argv[optind + 1];
c0367ba5
ILT
859
860 /* Default is to strip no symbols. */
861 if (strip_symbols == strip_undef && discard_locals == locals_undef)
46050fe4 862 strip_symbols = strip_none;
c0367ba5
ILT
863
864 if (output_target == (char *) NULL)
865 output_target = input_target;
866
46050fe4
ILT
867 /* If there is no destination file then create a temp and rename
868 the result into the input. */
869
870 if (output_filename == (char *) NULL)
871 {
872 char *tmpname = make_tempname (input_filename);
873 copy_file (input_filename, tmpname, input_target, output_target);
874 if (status == 0)
875 smart_rename (tmpname, input_filename);
876 else
877 unlink (tmpname);
878 }
879 else
880 {
881 copy_file (input_filename, output_filename, input_target, output_target);
882 }
883
c0367ba5
ILT
884 return 0;
885}
46050fe4
ILT
886
887int
888main (argc, argv)
889 int argc;
890 char *argv[];
891{
892 program_name = argv[0];
893 strip_symbols = strip_undef;
894 discard_locals = locals_undef;
895
896 bfd_init ();
897
898 if (is_strip < 0)
899 {
900 int i = strlen (program_name);
901 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
902 }
903
904 if (is_strip)
905 strip_main (argc, argv);
906 else
907 copy_main (argc, argv);
908
909 return status;
910}
This page took 0.076492 seconds and 4 git commands to generate.