103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Copyright (C) 1999, 2000, 2002 Red Hat, Inc. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Written by Ulrich Drepper <drepper@redhat.com>, 1999. 403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of the GNU General Public License as published by 703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the Free Software Foundation; either version 3 of the License, or 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes (at your option) any later version. 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes WITHOUT ANY WARRANTY; without even the implied warranty of 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GNU General Public License for more details. 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received a copy of the GNU General Public License 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef HAVE_CONFIG_H 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes# include <config.h> 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif 2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <fcntl.h> 2303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <gelf.h> 2403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <stdio.h> 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <stdlib.h> 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <string.h> 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <unistd.h> 2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <sys/param.h> 2903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint 3203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesmain (int argc, char *argv[]) 3303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 3403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int fd; 3503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf *elf; 3603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf *subelf; 3703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf_Cmd cmd; 3803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes off_t offset; 3903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t todo; 4003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (argc < 4) 4203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 4303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Open the archive. */ 4503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes fd = open (argv[1], O_RDONLY); 4603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (fd == -1) 4703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 4803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("Cannot open input file: %m"); 4903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 5003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 5103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Set the ELF version. */ 5303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_version (EV_CURRENT); 5403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Create an ELF descriptor. */ 5603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes cmd = ELF_C_READ; 5703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf = elf_begin (fd, cmd, NULL); 5803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf == NULL) 5903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 6003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("Cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 6103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 6203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* If it is no archive punt. */ 6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf_kind (elf) != ELF_K_AR) 6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("`%s' is no archive\n", argv[1]); 6803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 6903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 7003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 7103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Get the elements of the archive one after the other. */ 7203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while ((subelf = elf_begin (fd, cmd, elf)) != NULL) 7303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* The the header for this element. */ 7503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf_Arhdr *arhdr = elf_getarhdr (subelf); 7603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 7703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (arhdr == NULL) 7803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 7903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); 8003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 8103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 8203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 8303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (strcmp (arhdr->ar_name, argv[2]) == 0) 8403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 8503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int outfd; 8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Get the offset of the file in the archive. */ 8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes offset = elf_getbase (subelf); 8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (offset == -1) 9003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 9103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("\ 9203333823c75a1c1887e923828113a1b0fd12020cElliott HughesFailed to get base address for the archive element: %s\n", 9303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_errmsg (-1)); 9403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 9503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 9603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 9703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Open the output file. */ 9803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes outfd = open (argv[3], O_CREAT | O_TRUNC | O_RDWR, 0666); 9903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (outfd == -1) 10003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 10103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("cannot open output file: %m"); 10203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 10303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 10403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 10503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Now write out the data. */ 10603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes todo = arhdr->ar_size; 10703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (todo > 0) 10803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 10903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes char buf[1024]; 11003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ssize_t n = pread (fd, buf, MIN (sizeof buf, todo), offset); 11103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (n == 0) 11203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 11303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 11403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (write (outfd, buf, n) != n) 11503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 11603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes puts ("Writing output failed"); 11703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 11803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 11903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 12003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes offset += n; 12103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes todo -= n; 12203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 12303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 12403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Check whether all the date was read and written out. */ 12503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (todo != 0) 12603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 12703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes puts ("Reading archive member failed."); 12803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 12903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 13003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 13103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Close the descriptors. */ 13203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf_end (subelf) != 0 || elf_end (elf) != 0) 13303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 13403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("Freeing ELF descriptors failed: %s", elf_errmsg (-1)); 13503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 13603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 13703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 13803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (outfd); 13903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 14003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 14103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* All went well. */ 14203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (0); 14303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 14403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 14503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Get next archive element. */ 14603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes cmd = elf_next (subelf); 14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf_end (subelf) != 0) 14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 14903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("error while freeing sub-ELF descriptor: %s\n", 15003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_errmsg (-1)); 15103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 15203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 15303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 15403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 15503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* When we reach this point we haven't found the given file in the 15603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes archive. */ 15703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("File `%s' not found in archive\n", argv[2]); 15803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exit (1); 15903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 160