]> pd.if.org Git - zpackage/commitdiff
added program to output the elf type of a file
authorNathan Wagner <nw@hydaspes.if.org>
Sat, 28 Feb 2015 19:14:17 +0000 (19:14 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Sat, 28 Feb 2015 19:14:17 +0000 (19:14 +0000)
Makefile
elf/elftype.c [new file with mode: 0644]

index 8f84c9d29b0060d709815792875fe862f84072bc..fb3494ed7d3b0ef98be93f0445304574bdf79924 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,9 @@
-install:
+CFLAGS=-Wall -std=c99
+
+elftype: elf/elftype.c
+       $(CC) $(CFLAGS) -o $@ $+
+
+install: elftype
        install -D zpm $(DESTDIR)/bin/zpm
        install -D zpm-note $(DESTDIR)/bin/zpm-note
        install -D zpm-sequence $(DESTDIR)/bin/zpm-sequence
@@ -6,4 +11,5 @@ install:
        install -d -m2770 -o root -g adm $(DESTDIR)/var/lib/admin/notes
        install -d -m2770 -o root -g adm $(DESTDIR)/var/lib/admin/notes/open
        install -d -m2770 -o root -g adm $(DESTDIR)/var/lib/admin/notes/ack
+       install -D elftype $(DESTDIR)/usr/sbin/elftype
        #SPOOL=$(DESTDIR)/var/lib/admin/notes ./zpm-sequence -c notes
diff --git a/elf/elftype.c b/elf/elftype.c
new file mode 100644 (file)
index 0000000..6dece5a
--- /dev/null
@@ -0,0 +1,185 @@
+#define _POSIX_C_SOURCE 200112L
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <elf.h>
+
+#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;
+}