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