]> pd.if.org Git - zpackage/blob - elf/elftype.c
added program to output the elf type of a file
[zpackage] / elf / elftype.c
1 #define _POSIX_C_SOURCE 200112L
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <limits.h>
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <elf.h>
11
12 #define RELOCATABLE 0x1
13 #define EXECUTABLE  0x2
14 #define DYNAMIC     0x4
15 #define CORE        0x8
16 #define SYMLINKS    0x10
17
18 int readline(FILE *f, char *fn);
19 int checkfile(char *fn, unsigned int want, int perr, int quiet);
20
21 int errors = 0;
22 int zeroterm = 0;
23
24 int main(int ac, char **av) {
25         int option;
26         unsigned int want = 0;
27         int quiet = 0;
28         int perr = 0;
29         FILE *list = 0;
30         char fn[PATH_MAX];
31         
32         while ((option = getopt(ac, av, "redclaqp0f:")) != -1) {
33                 switch (option) {
34                         case 'r': want |= RELOCATABLE; break;
35                         case 'e': want |= EXECUTABLE; break;
36                         case 'd': want |= DYNAMIC; break;
37                         case 'c': want |= CORE; break;
38                         case 'l': want |= SYMLINKS; break;
39                         case 'a': want = (RELOCATABLE|EXECUTABLE|DYNAMIC|CORE); break;
40                         case 'q': quiet++; break;
41                         case 'p': perr++; break;
42                         case '0': zeroterm = 1; break;
43                         case 'f':
44                                   if (optarg[0] == '-' && optarg[1] == 0) {
45                                           list = stdin;
46                                   } else {
47                                           list = fopen(optarg, "r");
48                                   }
49                                   break;
50                         default:
51                                   exit(1);
52                                   break;
53                 }
54         }
55         if (list) {
56                 quiet = 2;
57                 perr = 0;
58                 while (readline(list, fn)) {
59                         fprintf(stderr, "checking %s\n", fn);
60                         if (checkfile(fn, want,perr,quiet)) {
61                                 printf("%s\n", fn);
62                         }
63                 }
64         } else {
65                 fprintf(stderr, "checking %s\n", av[optind]);
66                 return !checkfile(av[optind], want,perr,quiet);
67         }
68         return errors ? 1 : 0;
69 }
70
71 int readline(FILE *f, char *fn) {
72         int ch;
73         int i = 0;
74
75         do {
76                 ch = fgetc(f);
77                 switch (ch) {
78                         case EOF: break;
79                         case 0:
80                                   if (i == 0) continue;
81                                   break;
82                         case '\n':
83                                   if (!zeroterm) {
84                                           if (i == 0) continue;
85                                           break;
86                                   }
87                         default:
88                                   fn[i++] = ch;
89                                   continue;
90                 }
91                 if (i >= PATH_MAX) {
92                         /* TODO print an error */
93                         return 0;
94                 }
95                 fn[i] = 0;
96                 return i;
97         } while (ch != EOF);
98         return 0;
99 }
100
101 int checkfile(char *fn, unsigned int want, int perr, int quiet) {
102         Elf64_Ehdr hdr;
103         int fd, bytes;
104         int endian = 0;
105         struct stat st;
106
107         if (want & SYMLINKS) {
108                 lstat(fn, &st);
109         } else {
110                 stat(fn, &st);
111         }
112         if (!S_ISREG(st.st_mode)) {
113                 return 0;
114         }
115         
116         fd = open(fn, O_RDONLY);
117         if (fd == -1) {
118                 perror("elfcheck");
119                 errors++;
120                 return 0;
121         }
122         bytes = read(fd, &hdr, sizeof hdr);
123         if (bytes < sizeof hdr) {
124                 if (perr) fprintf(stderr, "could not read full elf header (wanted %zu got %d bytes)\n", sizeof hdr, bytes);
125                 close(fd);
126                 return 0;
127         }
128         if (hdr.e_ident[EI_MAG0] != ELFMAG0
129                         || hdr.e_ident[EI_MAG1] != ELFMAG1
130                         || hdr.e_ident[EI_MAG2] != ELFMAG2
131                         || hdr.e_ident[EI_MAG3] != ELFMAG3
132            ) {
133                 if (perr) fprintf(stderr, "elf header magic wrong\n");
134                 close(fd);
135                 return 0;
136         }
137         switch (hdr.e_ident[EI_CLASS]) {
138                 case ELFCLASS64:
139                 case ELFCLASS32:
140                 case ELFCLASSNONE:
141                         break;
142                 default:
143                         if (perr) fprintf(stderr, "elf header unknown class\n");
144                 close(fd);
145                         return 0;
146         }
147
148         endian = hdr.e_ident[EI_DATA];
149         switch (endian) {
150                 case ELFDATA2LSB: break;
151                 case ELFDATA2MSB: break;
152                                   /* TODO swap endian if needed */
153                 default:
154                         if (perr) fprintf(stderr, "elf header unknown endian\n");
155                 close(fd);
156                         return 0;
157         }
158
159         switch (hdr.e_type) {
160                 case ET_REL:
161                         if (!quiet) printf("relocatable\n");
162                         close(fd);
163                         return want & RELOCATABLE ? 1 : 0;
164                 case ET_EXEC:
165                         if (!quiet) printf("executable\n");
166                         close(fd);
167                         return want & EXECUTABLE ? 1 : 0;
168                 case ET_DYN:
169                         if (!quiet) printf("dynamic\n");
170                         close(fd);
171                         return want & DYNAMIC ? 1 : 0;
172                 case ET_CORE:
173                         if (!quiet) printf("core\n");
174                         close(fd);
175                         return want & CORE ? 1 : 0;
176                 case ET_NONE:
177                 default:
178                         if (perr) fprintf(stderr, "unknown type\n");
179                         close(fd);
180                         return 0;
181         }
182
183         close(fd);
184         return 0;
185 }