1#include <ar.h>
2#include <fcntl.h>
3#include <libelf.h>
4#include <stdio.h>
5#include <unistd.h>
6
7
8static int handle (const char *fname);
9
10
11int
12main (int argc, char *argv[])
13{
14  elf_version (EV_CURRENT);
15
16  int result = 0;
17  if (argc == 1)
18    result = handle ("a.out");
19  else
20    for (int i = 1; i < argc; ++i)
21      result |= handle (argv[1]);
22
23  return result;
24}
25
26
27static int
28handle (const char *fname)
29{
30  int fd = open (fname, O_RDONLY);
31  if (fd == -1)
32    {
33      printf ("cannot open '%s': %m\n", fname);
34      return 1;
35    }
36
37  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
38  if (elf == NULL)
39    {
40      printf ("cannot get ELF handling for '%s': %s\n",
41	      fname, elf_errmsg (-1));
42      close (fd);
43      return 1;
44    }
45
46  if (elf_kind (elf) != ELF_K_AR)
47    {
48      printf ("'%s' is no archive\n", fname);
49      elf_end (elf);
50      close (fd);
51      return 1;
52    }
53
54  printf ("%s:\n", fname);
55  Elf *subelf = NULL;
56  Elf_Cmd cmd = ELF_C_READ_MMAP;
57  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
58    {
59      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
60      if (arhdr == NULL)
61	{
62	  printf ("cannot get archive header in '%s': %s\n",
63		  fname, elf_errmsg (-1));
64	  elf_end (subelf);
65	  elf_end (elf);
66	  close (fd);
67	  return 1;
68	}
69
70      off_t off = elf_getaroff (subelf);
71
72      printf ("\nOffset    %llu\n"
73	      "  Name    %s\n"
74	      "  Date    %ld\n"
75	      "  UID     %d\n"
76	      "  GID     %d\n"
77	      "  Mode    %o\n"
78	      "  Size    %lld\n",
79	      (unsigned long long int) off,
80	      arhdr->ar_name, (long int) arhdr->ar_date, (int) arhdr->ar_uid,
81	      (int) arhdr->ar_gid,
82	      (int) arhdr->ar_mode, (long long int) arhdr->ar_size);
83
84      cmd = elf_next (subelf);
85      elf_end (subelf);
86    }
87
88  close (fd);
89
90  return 0;
91}
92