* config/m68k/monitor.mt (TDEPFILE): Add remote-es.o.
[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)
215 PTR memhunk;
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;
c0367ba5
ILT
393
394 /* To allow us to do "strip *" without dying on the first
395 non-object file, failures are nonfatal. */
396
46050fe4 397 ibfd = bfd_openr (input_filename, input_target);
c0367ba5
ILT
398 if (ibfd == NULL)
399 {
46050fe4 400 nonfatal (input_filename);
c0367ba5
ILT
401 }
402
46050fe4
ILT
403 if (bfd_check_format (ibfd, bfd_object))
404 {
405 bfd *obfd = bfd_openw (output_filename, output_target);
406 if (obfd == NULL)
407 {
408 nonfatal (output_filename);
409 }
c0367ba5 410
46050fe4 411 copy_object (ibfd, obfd);
c0367ba5 412
46050fe4
ILT
413 if (!bfd_close (obfd))
414 {
415 nonfatal (output_filename);
416 }
417
418 if (!bfd_close (ibfd))
419 {
420 nonfatal (input_filename);
421 }
422 }
423 else if (bfd_check_format (ibfd, bfd_archive))
424 {
425 bfd *obfd = bfd_openw (output_filename, output_target);
426 if (obfd == NULL)
427 {
428 nonfatal (output_filename);
429 }
430 copy_archive (ibfd, obfd, output_target);
431 }
432 else
433 {
434 /* Get the right error message. */
435 bfd_check_format (ibfd, bfd_object);
436 nonfatal (input_filename);
437 }
438}
439
440/* Create a section in OBFD with the same name and attributes
441 as ISECTION in IBFD. */
c0367ba5 442
c0367ba5 443static void
f7b839f7 444setup_section (ibfd, isection, obfd)
46050fe4
ILT
445 bfd *ibfd;
446 sec_ptr isection;
447 bfd *obfd;
c0367ba5 448{
46050fe4
ILT
449 sec_ptr osection;
450 char *err;
451
452 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
453 && (strip_symbols == strip_debug
454 || strip_symbols == strip_all
455 || discard_locals == locals_all))
456 return;
457
458 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
459 if (osection == NULL)
460 {
461 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
462 if (osection == NULL)
463 {
464 err = "making";
465 goto loser;
c0367ba5
ILT
466 }
467 }
468
46050fe4
ILT
469 if (!bfd_set_section_size (obfd,
470 osection,
471 bfd_section_size (ibfd, isection)))
472 {
473 err = "size";
474 goto loser;
c0367ba5
ILT
475 }
476
46050fe4
ILT
477 if (bfd_set_section_vma (obfd,
478 osection,
479 bfd_section_vma (ibfd, isection))
480 == false)
481 {
482 err = "vma";
483 goto loser;
484 }
c0367ba5 485
46050fe4
ILT
486 if (bfd_set_section_alignment (obfd,
487 osection,
488 bfd_section_alignment (ibfd, isection))
489 == false)
490 {
491 err = "alignment";
492 goto loser;
493 }
c0367ba5 494
46050fe4
ILT
495 if (!bfd_set_section_flags (obfd, osection,
496 bfd_get_section_flags (ibfd, isection)))
497 {
498 err = "flags";
499 goto loser;
c0367ba5
ILT
500 }
501
46050fe4
ILT
502 /* All went well */
503 return;
c0367ba5
ILT
504
505loser:
46050fe4
ILT
506 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
507 program_name,
508 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
509 err, bfd_errmsg (bfd_error));
510 status = 1;
511}
512
513/* Copy the data of input section ISECTION of IBFD
514 to an output section with the same name in OBFD.
515 If stripping then don't copy any relocation info. */
516
c0367ba5 517static void
f7b839f7 518copy_section (ibfd, isection, obfd)
46050fe4
ILT
519 bfd *ibfd;
520 sec_ptr isection;
521 bfd *obfd;
c0367ba5 522{
46050fe4
ILT
523 arelent **relpp;
524 int relcount;
525 sec_ptr osection;
526 bfd_size_type size;
527
528 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
529 && (strip_symbols == strip_debug
530 || strip_symbols == strip_all
531 || discard_locals == locals_all))
532 {
533 return;
534 }
c0367ba5 535
46050fe4
ILT
536 osection = bfd_get_section_by_name (obfd,
537 bfd_section_name (ibfd, isection));
c0367ba5 538
46050fe4 539 size = bfd_get_section_size_before_reloc (isection);
c0367ba5
ILT
540
541 if (size == 0)
542 return;
543
544 if (strip_symbols == strip_all
46050fe4 545 || bfd_get_reloc_upper_bound (ibfd, isection) == 0)
c0367ba5 546 {
46050fe4
ILT
547 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
548 }
549 else
c0367ba5 550 {
46050fe4
ILT
551 relpp = (arelent **) xmalloc (bfd_get_reloc_upper_bound (ibfd, isection));
552 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
553 bfd_set_reloc (obfd, osection, relpp, relcount);
c0367ba5
ILT
554 }
555
556 isection->_cooked_size = isection->_raw_size;
46050fe4 557 isection->reloc_done = true;
c0367ba5 558
46050fe4 559 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
c0367ba5 560 {
46050fe4 561 PTR memhunk = (PTR) xmalloc ((unsigned) size);
c0367ba5 562
46050fe4
ILT
563 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
564 size))
565 {
566 nonfatal (bfd_get_filename (ibfd));
567 }
c0367ba5 568
f7b839f7
DM
569 if (copy_byte >= 0)
570 filter_bytes (memhunk, &size);
571
46050fe4
ILT
572 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
573 size))
574 {
575 nonfatal (bfd_get_filename (obfd));
576 }
577 free (memhunk);
c0367ba5 578 }
46050fe4 579}
c0367ba5 580
46050fe4
ILT
581/* All the symbols have been read in and point to their owning input section.
582 They have been relocated so that they are all relative to the base of
583 their owning section. On the way out, all the symbols will be relocated to
584 their new location in the output file, through some complex sums. */
c0367ba5 585
46050fe4 586static void
f7b839f7 587mangle_section (ibfd, p, obfd)
46050fe4
ILT
588 bfd *ibfd;
589 asection *p;
590 bfd *obfd;
591{
592 p->output_section = bfd_get_section_by_name (obfd, p->name);
593 p->output_offset = 0;
c0367ba5 594}
46050fe4
ILT
595
596/* The number of bytes to copy at once. */
597#define COPY_BUF 8192
598
599/* Copy file FROM to file TO, performing no translations.
600 Return 0 if ok, -1 if error. */
601
602static int
603simple_copy (from, to)
604 char *from, *to;
c0367ba5 605{
46050fe4
ILT
606 int fromfd, tofd, nread;
607 char buf[COPY_BUF];
608
609 fromfd = open (from, O_RDONLY);
610 if (fromfd < 0)
611 return -1;
612 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
613 if (tofd < 0)
614 {
615 close (fromfd);
616 return -1;
617 }
618 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
619 {
620 if (write (tofd, buf, nread) != nread)
621 {
622 close (fromfd);
623 close (tofd);
624 return -1;
625 }
626 }
627 close (fromfd);
628 close (tofd);
629 if (nread < 0)
630 return -1;
631 return 0;
632}
c0367ba5 633
46050fe4
ILT
634#ifndef S_ISLNK
635#ifdef S_IFLNK
636#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
637#else
638#define S_ISLNK(m) 0
639#define lstat stat
640#endif
641#endif
642
643/* Rename FROM to TO, copying if TO is a link.
644 Assumes that TO already exists, because FROM is a temp file.
645 Return 0 if ok, -1 if error. */
646
647static int
648smart_rename (from, to)
649 char *from, *to;
650{
651 struct stat s;
652 int ret = 0;
c0367ba5 653
46050fe4
ILT
654 if (lstat (to, &s))
655 return -1;
c0367ba5 656
46050fe4
ILT
657 /* Use rename only if TO is not a symbolic link and has
658 only one hard link. */
659 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
660 {
661 ret = rename (from, to);
662 if (ret == 0)
663 {
664 /* Try to preserve the permission bits and ownership of TO. */
665 chmod (to, s.st_mode & 07777);
666 chown (to, s.st_uid, s.st_gid);
667 }
668 }
669 else
670 {
671 ret = simple_copy (from, to);
672 if (ret == 0)
673 unlink (from);
674 }
675 return ret;
676}
677
678static int
679strip_main (argc, argv)
680 int argc;
681 char *argv[];
682{
683 char *input_target = NULL, *output_target = NULL;
684 boolean show_version = false;
685 int c, i;
686
687 while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv",
688 strip_options, (int *) 0)) != EOF)
689 {
690 switch (c)
691 {
692 case 'I':
693 input_target = optarg;
694 case 'O':
695 output_target = optarg;
696 break;
697 case 'F':
698 input_target = output_target = optarg;
699 break;
700 case 's':
c0367ba5 701 strip_symbols = strip_all;
46050fe4
ILT
702 break;
703 case 'S':
704 case 'g':
705 strip_symbols = strip_debug;
706 break;
707 case 'x':
708 discard_locals = locals_all;
709 break;
710 case 'X':
711 discard_locals = locals_start_L;
712 break;
713 case 'v':
714 verbose = true;
715 break;
716 case 'V':
717 show_version = true;
718 break;
719 case 0:
720 break; /* we've been given a long option */
721 case 'h':
722 strip_usage (stdout, 0);
723 default:
724 strip_usage (stderr, 1);
725 }
726 }
727
728 if (show_version)
729 {
730 printf ("GNU %s version %s\n", program_name, program_version);
731 exit (0);
732 }
c0367ba5 733
46050fe4
ILT
734 /* Default is to strip all symbols. */
735 if (strip_symbols == strip_undef && discard_locals == locals_undef)
736 strip_symbols = strip_all;
737
738 if (output_target == (char *) NULL)
739 output_target = input_target;
740
741 i = optind;
742 if (i == argc)
743 strip_usage (stderr, 1);
744
745 for (; i < argc; i++)
746 {
747 int hold_status = status;
c0367ba5 748
46050fe4
ILT
749 char *tmpname = make_tempname (argv[i]);
750 status = 0;
751 copy_file (argv[i], tmpname, input_target, output_target);
752 if (status == 0)
753 {
754 smart_rename (tmpname, argv[i]);
755 status = hold_status;
c0367ba5 756 }
46050fe4
ILT
757 else
758 unlink (tmpname);
759 free (tmpname);
760 }
761
762 return 0;
763}
764
765static int
766copy_main (argc, argv)
767 int argc;
768 char *argv[];
769{
770 char *input_filename, *output_filename;
771 char *input_target = NULL, *output_target = NULL;
772 boolean show_version = false;
773 int c;
774
f7b839f7 775 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
46050fe4
ILT
776 copy_options, (int *) 0)) != EOF)
777 {
778 switch (c)
779 {
f7b839f7
DM
780 case 'b':
781 copy_byte = atoi(optarg);
782 if (copy_byte < 0)
783 {
784 fprintf (stderr, "%s: byte number must be non-negative\n",
785 program_name);
786 exit (1);
787 }
788 break;
789 case 'i':
790 interleave = atoi(optarg);
791 if (interleave < 1)
792 {
793 fprintf(stderr, "%s: interleave must be positive\n",
794 program_name);
795 exit (1);
796 }
797 break;
c0367ba5 798 case 'I':
46050fe4 799 case 's': /* "source" - 'I' is preferred */
c0367ba5
ILT
800 input_target = optarg;
801 case 'O':
46050fe4 802 case 'd': /* "destination" - 'O' is preferred */
c0367ba5
ILT
803 output_target = optarg;
804 break;
805 case 'F':
c0367ba5
ILT
806 input_target = output_target = optarg;
807 break;
c0367ba5
ILT
808 case 'S':
809 strip_symbols = strip_all;
810 break;
811 case 'g':
812 strip_symbols = strip_debug;
813 break;
814 case 'x':
815 discard_locals = locals_all;
816 break;
817 case 'X':
818 discard_locals = locals_start_L;
819 break;
820 case 'v':
821 verbose = true;
822 break;
823 case 'V':
824 show_version = true;
825 break;
46050fe4 826 case 0:
c0367ba5
ILT
827 break; /* we've been given a long option */
828 case 'h':
829 copy_usage (stdout, 0);
830 default:
831 copy_usage (stderr, 1);
46050fe4
ILT
832 }
833 }
834
835 if (show_version)
836 {
837 printf ("GNU %s version %s\n", program_name, program_version);
838 exit (0);
839 }
c0367ba5 840
f7b839f7
DM
841 if (copy_byte >= interleave)
842 {
843 fprintf (stderr, "%s: byte number must be less than interleave\n",
844 program_name);
845 exit (1);
846 }
847
46050fe4
ILT
848 if (optind == argc || optind + 2 < argc)
849 copy_usage (stderr, 1);
c0367ba5
ILT
850
851 input_filename = argv[optind];
852 if (optind + 1 < argc)
46050fe4 853 output_filename = argv[optind + 1];
c0367ba5
ILT
854
855 /* Default is to strip no symbols. */
856 if (strip_symbols == strip_undef && discard_locals == locals_undef)
46050fe4 857 strip_symbols = strip_none;
c0367ba5
ILT
858
859 if (output_target == (char *) NULL)
860 output_target = input_target;
861
46050fe4
ILT
862 /* If there is no destination file then create a temp and rename
863 the result into the input. */
864
865 if (output_filename == (char *) NULL)
866 {
867 char *tmpname = make_tempname (input_filename);
868 copy_file (input_filename, tmpname, input_target, output_target);
869 if (status == 0)
870 smart_rename (tmpname, input_filename);
871 else
872 unlink (tmpname);
873 }
874 else
875 {
876 copy_file (input_filename, output_filename, input_target, output_target);
877 }
878
c0367ba5
ILT
879 return 0;
880}
46050fe4
ILT
881
882int
883main (argc, argv)
884 int argc;
885 char *argv[];
886{
887 program_name = argv[0];
888 strip_symbols = strip_undef;
889 discard_locals = locals_undef;
890
891 bfd_init ();
892
893 if (is_strip < 0)
894 {
895 int i = strlen (program_name);
896 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
897 }
898
899 if (is_strip)
900 strip_main (argc, argv);
901 else
902 copy_main (argc, argv);
903
904 return status;
905}
This page took 0.07535 seconds and 4 git commands to generate.