Home | History | Annotate | Download | only in tests
      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