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