1/* Copyright (C) 1999, 2000, 2002 Red Hat, Inc. 2 This file is part of elfutils. 3 Written by Ulrich Drepper <drepper@redhat.com>, 1999. 4 5 This file is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <fcntl.h> 23#include <gelf.h> 24#include <stdio.h> 25#include <stdlib.h> 26#include <string.h> 27#include <unistd.h> 28#include <sys/param.h> 29 30 31int 32main (int argc, char *argv[]) 33{ 34 int fd; 35 Elf *elf; 36 Elf *subelf; 37 Elf_Cmd cmd; 38 off_t offset; 39 size_t todo; 40 41 if (argc < 4) 42 exit (1); 43 44 /* Open the archive. */ 45 fd = open (argv[1], O_RDONLY); 46 if (fd == -1) 47 { 48 printf ("Cannot open input file: %m"); 49 exit (1); 50 } 51 52 /* Set the ELF version. */ 53 elf_version (EV_CURRENT); 54 55 /* Create an ELF descriptor. */ 56 cmd = ELF_C_READ; 57 elf = elf_begin (fd, cmd, NULL); 58 if (elf == NULL) 59 { 60 printf ("Cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 61 exit (1); 62 } 63 64 /* If it is no archive punt. */ 65 if (elf_kind (elf) != ELF_K_AR) 66 { 67 printf ("`%s' is no archive\n", argv[1]); 68 exit (1); 69 } 70 71 /* Get the elements of the archive one after the other. */ 72 while ((subelf = elf_begin (fd, cmd, elf)) != NULL) 73 { 74 /* The the header for this element. */ 75 Elf_Arhdr *arhdr = elf_getarhdr (subelf); 76 77 if (arhdr == NULL) 78 { 79 printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); 80 exit (1); 81 } 82 83 if (strcmp (arhdr->ar_name, argv[2]) == 0) 84 { 85 int outfd; 86 87 /* Get the offset of the file in the archive. */ 88 offset = elf_getbase (subelf); 89 if (offset == -1) 90 { 91 printf ("\ 92Failed to get base address for the archive element: %s\n", 93 elf_errmsg (-1)); 94 exit (1); 95 } 96 97 /* Open the output file. */ 98 outfd = open (argv[3], O_CREAT | O_TRUNC | O_RDWR, 0666); 99 if (outfd == -1) 100 { 101 printf ("cannot open output file: %m"); 102 exit (1); 103 } 104 105 /* Now write out the data. */ 106 todo = arhdr->ar_size; 107 while (todo > 0) 108 { 109 char buf[1024]; 110 ssize_t n = pread (fd, buf, MIN (sizeof buf, todo), offset); 111 if (n == 0) 112 break; 113 114 if (write (outfd, buf, n) != n) 115 { 116 puts ("Writing output failed"); 117 exit (1); 118 } 119 120 offset += n; 121 todo -= n; 122 } 123 124 /* Check whether all the date was read and written out. */ 125 if (todo != 0) 126 { 127 puts ("Reading archive member failed."); 128 exit (1); 129 } 130 131 /* Close the descriptors. */ 132 if (elf_end (subelf) != 0 || elf_end (elf) != 0) 133 { 134 printf ("Freeing ELF descriptors failed: %s", elf_errmsg (-1)); 135 exit (1); 136 } 137 138 close (outfd); 139 close (fd); 140 141 /* All went well. */ 142 exit (0); 143 } 144 145 /* Get next archive element. */ 146 cmd = elf_next (subelf); 147 if (elf_end (subelf) != 0) 148 { 149 printf ("error while freeing sub-ELF descriptor: %s\n", 150 elf_errmsg (-1)); 151 exit (1); 152 } 153 } 154 155 /* When we reach this point we haven't found the given file in the 156 archive. */ 157 printf ("File `%s' not found in archive\n", argv[2]); 158 exit (1); 159} 160