blob: aa86fb4e176b7f1698e6ff24a83b305dbfc61dd0 [file] [log] [blame]
The Android Open Source Project441f72d2009-03-03 19:29:28 -08001/* Copyright (C) 1999, 2000, 2002 Red Hat, Inc.
2 Written by Ulrich Drepper <drepper@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
27int
28main (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 ("\
88Failed 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}