Home | History | Annotate | Download | only in tests
      1 /* Copyright (C) 1999, 2000, 2002 Red Hat, Inc.
      2    This file is part of elfutils.
      3    Written by Ulrich Drepper <drepper (at) 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 
     31 int
     32 main (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 ("\
     92 Failed 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