]> pd.if.org Git - zpackage/blob - elf/elftype.c
fixups
[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 printtype = 0;
29         int printname = 0;
30         int verbose = 0;
31         int perr = 0;
32         FILE *list = 0;
33         char fn[PATH_MAX];
34         
35         while ((option = getopt(ac, av, "vtnredclaqp0f:")) != -1) {
36                 switch (option) {
37                         case 'r': want |= RELOCATABLE; break;
38                         case 'e': want |= EXECUTABLE; break;
39                         case 'd': want |= DYNAMIC; break;
40                         case 'c': want |= CORE; break;
41                         case 'l': want |= SYMLINKS; break;
42                         case 'a': want = (RELOCATABLE|EXECUTABLE|DYNAMIC|CORE); break;
43                         case 'q': quiet++; break;
44                         case 't': printtype++; break;
45                         case 'n': printname++; break;
46                         case 'v': verbose++; break;
47                         case 'p': perr++; break;
48                         case '0': zeroterm = 1; break;
49                         case 'f':
50                                   if (optarg[0] == '-' && optarg[1] == 0) {
51                                           list = stdin;
52                                   } else {
53                                           list = fopen(optarg, "r");
54                                   }
55                                   break;
56                         default:
57                                   exit(1);
58                                   break;
59                 }
60         }
61
62         if (!want) want = (RELOCATABLE|EXECUTABLE|DYNAMIC|CORE);
63
64         if (list) {
65                 quiet = 2;
66                 perr = 0;
67                 while (readline(list, fn)) {
68                         if (checkfile(fn, want,perr,quiet)) {
69                                 printf("%s\n", fn);
70                         }
71                 }
72         } else {
73                 int type;
74                 char *fn;
75
76                 fn = av[optind];
77                 if (verbose) fprintf(stderr, "checking %s\n", av[optind]);
78                 type = checkfile(fn,want,perr,quiet);
79
80                 if (printtype) {
81                         switch (type) {
82                                 case RELOCATABLE:
83                                         printf("relocatable"); break;
84                                 case EXECUTABLE:
85                                         printf("executable"); break;
86                                 case DYNAMIC:
87                                         printf("dynamic"); break;
88                                 case CORE:
89                                         printf("core"); break;
90                                 default:
91                                         printf("notelf"); break;
92                         }
93                 }
94
95                 if (printname) {
96                         printf("%s%s", printtype ? " " : "", fn);
97                 }
98                 if (printtype || printname) printf("\n");
99
100                 return type & want ? 0 : 1;
101         }
102         return errors ? 1 : 0;
103 }
104
105 int readline(FILE *f, char *fn) {
106         int ch;
107         int i = 0;
108
109         do {
110                 ch = fgetc(f);
111                 switch (ch) {
112                         case EOF: break;
113                         case 0:
114                                   if (i == 0) continue;
115                                   break;
116                         case '\n':
117                                   if (!zeroterm) {
118                                           if (i == 0) continue;
119                                           break;
120                                   }
121                         default:
122                                   fn[i++] = ch;
123                                   continue;
124                 }
125                 if (i >= PATH_MAX) {
126                         /* TODO print an error */
127                         return 0;
128                 }
129                 fn[i] = 0;
130                 return i;
131         } while (ch != EOF);
132         return 0;
133 }
134
135 int checkfile(char *fn, unsigned int want, int perr, int quiet) {
136         Elf64_Ehdr hdr;
137         int fd, bytes;
138         int endian = 0;
139         struct stat st;
140
141         if (want & SYMLINKS) {
142                 lstat(fn, &st);
143         } else {
144                 stat(fn, &st);
145         }
146         if (!S_ISREG(st.st_mode)) {
147                 return 0;
148         }
149         
150         fd = open(fn, O_RDONLY);
151         if (fd == -1) {
152                 perror("elfcheck");
153                 errors++;
154                 return 0;
155         }
156         bytes = read(fd, &hdr, sizeof hdr);
157         close(fd);
158         if (bytes < sizeof hdr) {
159                 if (perr) fprintf(stderr, "could not read full elf header (wanted %zu got %d bytes)\n", sizeof hdr, bytes);
160                 return 0;
161         }
162         if (hdr.e_ident[EI_MAG0] != ELFMAG0
163                         || hdr.e_ident[EI_MAG1] != ELFMAG1
164                         || hdr.e_ident[EI_MAG2] != ELFMAG2
165                         || hdr.e_ident[EI_MAG3] != ELFMAG3
166            ) {
167                 if (perr) fprintf(stderr, "elf header magic wrong\n");
168                 return 0;
169         }
170         switch (hdr.e_ident[EI_CLASS]) {
171                 case ELFCLASS64:
172                 case ELFCLASS32:
173                 case ELFCLASSNONE:
174                         break;
175                 default:
176                         if (perr) fprintf(stderr, "elf header unknown class\n");
177                         return 0;
178         }
179
180         endian = hdr.e_ident[EI_DATA];
181         switch (endian) {
182                 case ELFDATA2LSB: break;
183                 case ELFDATA2MSB: break;
184                                   /* TODO swap endian if needed */
185                 default:
186                         if (perr) fprintf(stderr, "elf header unknown endian\n");
187                         return 0;
188         }
189
190         switch (hdr.e_type) {
191                 case ET_REL: return RELOCATABLE;
192                 case ET_EXEC: return EXECUTABLE;
193                 case ET_DYN: return DYNAMIC;
194                 case ET_CORE: return CORE;
195                 case ET_NONE:
196                 default:
197                         if (perr) fprintf(stderr, "unknown %s\n", fn);
198                         return 0;
199         }
200
201         return 0;
202 }