Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ make remove #remove from /bin/
- Images: BMP, PNG, JPEG, QOI, GIF, TIFF, WEBP
- Audio: WAV, MP3, OGG, QOA, AIFF, MIDI, FLAC
- Video: MP4, AVI
- Multimedia: PDF, Blender, glTF, MD2
- Multimedia: PDF, XCF, Blender, glTF, MD2
- Fonts: WOFF, WOFF2, OpenType
- Executables: ELF, EXE, WebAssembly, JAR, Luac
- Executables: ELF, EXE, WebAssembly, Luac
- Archives: Tar, ZIP, GZIP, XZ, LZIP, 7-Zip, RAR, BZip, CPIO, PAK, .deb, .rpm
- Binary Data: qcow, ISO
- Other: XML, Shebang scripts, SSH keys, Shortcuts
1 change: 1 addition & 0 deletions src/ext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "ext/elf.h"
108 changes: 108 additions & 0 deletions src/ext/elf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
typedef struct
{
unsigned char magic[4]; // 7F E L F
unsigned char bitclass;
unsigned char endian;
unsigned char elfversion; // Must be 1
unsigned char abi;
unsigned char abiversion; // ignore
unsigned char padding[7];
uint16_t type;
uint16_t machine;
uint32_t version;
// ... there's more we don't really care about in this context
}
elf_header_t;

enum {
ELF_BITCLASS_NONE,
ELF_BITCLASS_32,
ELF_BITCLASS_64,
ELF_BITCLASS_OOB
};
enum {
ELF_ENDIAN_NONE,
ELF_ENDIAN_LITTLE,
ELF_ENDIAN_BIG,
ELF_ENDIAN_OOB
};
enum {
ELF_ABI_NONE,
ELF_ABI_SYSV,
ELF_ABI_HPUX,
ELF_ABI_NETBSD,
ELF_ABI_LINUX,
ELF_ABI_SOLARIS,
ELF_ABI_IRIX,
ELF_ABI_FREEBSD,
ELF_ABI_TRU64,
ELF_ABI_ARM,
ELF_ABI_STANDALONE,
ELF_ABI_OOB
};
enum {
ELF_TYPE_NONE,
ELF_TYPE_RELOCATABLE,
ELF_TYPE_EXECUTABLE,
ELF_TYPE_DYNAMIC,
ELF_TYPE_CORE,
ELF_TYPE_OOB,
};
enum {
ELF_MACH_NONE,
ELF_MACH_X86 = 0x03,
ELF_MACH_IA64 = 0x32,
ELF_MACH_AMDX86 = 0x3E,
ELF_MACH_ARM = 0x28,
ELF_MACH_AARM = 0xB7,
ELF_MACH_RISCV = 0xF3,
ELF_MACH_Z80 = 0xDC
};

char elf_endians[][8] = {
"Invalid", "Little", "Big" };

char elf_bitclasses[][8] = {
"Invalid", "32", "64" };

char elf_types[][16] = {
"Other", "Relocatable", "Executable", "Dynamic Object", "Core File" };

char elf_abis[][16] = {
"Generic", "SYS-V", "HPUX", "NetBSD", "Linux", "Solaris", "Irix", "FreeBSD", "Tru64", "ARM", "Standalone" };

char elf_machs[0xFF][16] = {
[ELF_MACH_NONE] = "None",
[ELF_MACH_X86] = "x86",
[ELF_MACH_IA64] = "IA-64 (Itanium)",
[ELF_MACH_AMDX86] = "x86 (AMD)",
[ELF_MACH_ARM] = "ARM",
[ELF_MACH_AARM] = "ARM (AArch64)",
[ELF_MACH_RISCV] = "RISC-V",
[ELF_MACH_Z80] = "Zilog Z80",
};

void elf_printer (void *filetype, char *in) {
static char buffer[128];
elf_header_t * header = (elf_header_t *) in;
filetype_t * self = (filetype_t *) filetype;

if ( header->abi >= ELF_ABI_OOB ) { header->abi = 0; }
if ( header->bitclass >= ELF_BITCLASS_OOB ) { header->bitclass = 0; }
if ( header->endian >= ELF_ENDIAN_OOB ) { header->endian = 0; }
if ( header->abi >= ELF_ABI_OOB ) { header->abi = 0; }
if ( header->type >= ELF_TYPE_OOB ) { header->type = 0; }
if ( header->machine >= 0xFF ) { header->type = 0; } // Prevent overflow
if ( elf_machs[header->machine][0] == 0 ) { header->type = 0; } // Prevent nulls

char * abi = elf_abis[header->abi];
char * bitclass = elf_bitclasses[header->bitclass];
char * endian = elf_endians[header->endian];
char * type = elf_types[header->type];
char * mach = elf_machs[header->machine];

snprintf(buffer, sizeof(buffer),
"ELF %.16s-bit %.16s endian %.16s, %.16s %.16s",
bitclass, endian, type, mach, abi
); self->info = buffer;
}
3 changes: 3 additions & 0 deletions src/magic.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ int parse_magic(char *in) {
if ( status == 0 ) { type = test; break; }
}

if ( type != NULL && type->printer != NULL )
{ type->printer(type, (char *)buffer); }

fclose(target);
return 0;
}
Expand Down
18 changes: 10 additions & 8 deletions src/magic.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
#ifndef MAGIC_H
#define MAGIC_H
#include <stdio.h>
#include <string.h>

// Allows overriding the default printer function for certain types
typedef void *type_parser(void *type, char *in);
typedef void type_parser(void *type, char *in);
void parser_default(void *type, char *in);
int parse_magic(char *in);
long parse_size(char *in);
long get_size(FILE *f);
int parse_scale(long in);

typedef struct
{ char * name; char * magic; char * ext; int off; int len; type_parser *printer; }
{ char * name; char * magic; char * ext; int off; int len; type_parser *printer; char * info; }
filetype_t;
// the type_parser printer is used to set *info for file formats with important subtypes.
// they are passed in the first 32 bytes of the input file,
// which can be changed later if some formats (such as MacOS dmg files)
// require more data (and bounds checking logic)

extern filetype_t * type;
#include "ext.h"

// https://en.wikipedia.org/wiki/List_of_file_formats
#define magic_table_size ( sizeof(magic_table) / sizeof(magic_table[0]) )
Expand All @@ -35,8 +38,6 @@ filetype_t magic_table [] = {
{ .name = "Windows Shell Link",
.magic = "\x4C\x00\x00\x00\x01\x14\x02\x00\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x00\x00\x46", .len = 20, .ext = "lnk" },
// Raster Image Formats
// { .name = "PNG Image",
// .magic = "\x89\x50\x4E\x47\x0D\x0A\x1A\xA0", .len = 8, .ext = "png" },
{ .name = "PNG Image",
.magic = "\x89\x50\x4E\x47", .len = 4, .ext = "png" },
{ .name = "JPEG Image",
Expand Down Expand Up @@ -101,16 +102,17 @@ filetype_t magic_table [] = {
.magic = "FLhd", .len = 4, .ext = "flp" },
{ .name = "Quake 2 Model",
.magic = "IDP2\x08\x00\x00\x00", .len = 8, .ext = ".md2" },
{ .name = "GIMP Project",
.magic = "gimp xcf ", .len = 9, .ext = "xcf" },
// Executable Formats
// TODO: ELF Format Printer, checks header for subtype information
{ .name = "MachO Binary (32-bit x86)",
.magic = "\xCE\xFA\xED\xFE\x07\x00\x00\x00", .len = 8, .ext = NULL },
{ .name = "MachO Binary (64-bit x86)",
.magic = "\xCF\xFA\xED\xFE\x07\x00\x00\x00", .len = 8, .ext = NULL },
{ .name = "MachO Binary (64-bit ARM)",
.magic = "\xCF\xFA\xED\xFE\x0C\x00\x00\x00", .len = 8, .ext = NULL },
{ .name = "ELF Binary",
.magic = "\x7F" "ELF", .len = 4, .ext = "bin" },
.magic = "\x7F" "ELF", .len = 4, .ext = "bin", .printer = elf_printer },
{ .name = "Portable Executable Binary",
.magic = "\x4D\x5A", .len = 2, .ext = "exe" },
{ .name = "WebAssembly Binary",
Expand Down
4 changes: 4 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "magic.h"
#include "magic.c"
#include "license.h"
Expand Down Expand Up @@ -25,6 +28,7 @@ int main(int argc, char* argv[]) {
outname = (char *)(argv[1] + arglen - maxlen );
outname[0] = '.'; outname[1] = '.'; outname[2] = '.'; }
if ( type == NULL ) { printf("%s: Unknown file type\n", outname); }
else if ( type->info != NULL ) { printf("%s:%s\n", outname, type->info); }
else { printf("%s: %s\n", outname, type->name); }
// Scale the filesize then print
char prefix[] = " KMGTP";
Expand Down
Loading