X-Git-Url: https://pd.if.org/git/?p=zpackage;a=blobdiff_plain;f=elf%2Felftype.c;fp=elf%2Felftype.c;h=6dece5a471cef454326335f8a6b2f0ddd759f539;hp=0000000000000000000000000000000000000000;hb=3c05d0baf322f9f47b0894379509f5e3c67e492b;hpb=5a8b837accfa150d6d8aa9326f38aae9555e40d7 diff --git a/elf/elftype.c b/elf/elftype.c new file mode 100644 index 0000000..6dece5a --- /dev/null +++ b/elf/elftype.c @@ -0,0 +1,185 @@ +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include +#include + +#include +#include +#include + +#define RELOCATABLE 0x1 +#define EXECUTABLE 0x2 +#define DYNAMIC 0x4 +#define CORE 0x8 +#define SYMLINKS 0x10 + +int readline(FILE *f, char *fn); +int checkfile(char *fn, unsigned int want, int perr, int quiet); + +int errors = 0; +int zeroterm = 0; + +int main(int ac, char **av) { + int option; + unsigned int want = 0; + int quiet = 0; + int perr = 0; + FILE *list = 0; + char fn[PATH_MAX]; + + while ((option = getopt(ac, av, "redclaqp0f:")) != -1) { + switch (option) { + case 'r': want |= RELOCATABLE; break; + case 'e': want |= EXECUTABLE; break; + case 'd': want |= DYNAMIC; break; + case 'c': want |= CORE; break; + case 'l': want |= SYMLINKS; break; + case 'a': want = (RELOCATABLE|EXECUTABLE|DYNAMIC|CORE); break; + case 'q': quiet++; break; + case 'p': perr++; break; + case '0': zeroterm = 1; break; + case 'f': + if (optarg[0] == '-' && optarg[1] == 0) { + list = stdin; + } else { + list = fopen(optarg, "r"); + } + break; + default: + exit(1); + break; + } + } + if (list) { + quiet = 2; + perr = 0; + while (readline(list, fn)) { + fprintf(stderr, "checking %s\n", fn); + if (checkfile(fn, want,perr,quiet)) { + printf("%s\n", fn); + } + } + } else { + fprintf(stderr, "checking %s\n", av[optind]); + return !checkfile(av[optind], want,perr,quiet); + } + return errors ? 1 : 0; +} + +int readline(FILE *f, char *fn) { + int ch; + int i = 0; + + do { + ch = fgetc(f); + switch (ch) { + case EOF: break; + case 0: + if (i == 0) continue; + break; + case '\n': + if (!zeroterm) { + if (i == 0) continue; + break; + } + default: + fn[i++] = ch; + continue; + } + if (i >= PATH_MAX) { + /* TODO print an error */ + return 0; + } + fn[i] = 0; + return i; + } while (ch != EOF); + return 0; +} + +int checkfile(char *fn, unsigned int want, int perr, int quiet) { + Elf64_Ehdr hdr; + int fd, bytes; + int endian = 0; + struct stat st; + + if (want & SYMLINKS) { + lstat(fn, &st); + } else { + stat(fn, &st); + } + if (!S_ISREG(st.st_mode)) { + return 0; + } + + fd = open(fn, O_RDONLY); + if (fd == -1) { + perror("elfcheck"); + errors++; + return 0; + } + bytes = read(fd, &hdr, sizeof hdr); + if (bytes < sizeof hdr) { + if (perr) fprintf(stderr, "could not read full elf header (wanted %zu got %d bytes)\n", sizeof hdr, bytes); + close(fd); + return 0; + } + if (hdr.e_ident[EI_MAG0] != ELFMAG0 + || hdr.e_ident[EI_MAG1] != ELFMAG1 + || hdr.e_ident[EI_MAG2] != ELFMAG2 + || hdr.e_ident[EI_MAG3] != ELFMAG3 + ) { + if (perr) fprintf(stderr, "elf header magic wrong\n"); + close(fd); + return 0; + } + switch (hdr.e_ident[EI_CLASS]) { + case ELFCLASS64: + case ELFCLASS32: + case ELFCLASSNONE: + break; + default: + if (perr) fprintf(stderr, "elf header unknown class\n"); + close(fd); + return 0; + } + + endian = hdr.e_ident[EI_DATA]; + switch (endian) { + case ELFDATA2LSB: break; + case ELFDATA2MSB: break; + /* TODO swap endian if needed */ + default: + if (perr) fprintf(stderr, "elf header unknown endian\n"); + close(fd); + return 0; + } + + switch (hdr.e_type) { + case ET_REL: + if (!quiet) printf("relocatable\n"); + close(fd); + return want & RELOCATABLE ? 1 : 0; + case ET_EXEC: + if (!quiet) printf("executable\n"); + close(fd); + return want & EXECUTABLE ? 1 : 0; + case ET_DYN: + if (!quiet) printf("dynamic\n"); + close(fd); + return want & DYNAMIC ? 1 : 0; + case ET_CORE: + if (!quiet) printf("core\n"); + close(fd); + return want & CORE ? 1 : 0; + case ET_NONE: + default: + if (perr) fprintf(stderr, "unknown type\n"); + close(fd); + return 0; + } + + close(fd); + return 0; +}