|
#include <unistd.h> |
|
#include <sys/mman.h> |
|
#include <elf.h> |
|
#include <fuse.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <errno.h> |
|
#include <fcntl.h> |
|
#include <string.h> |
|
|
|
static void *ptr; |
|
|
|
static int sections; |
|
static int bits; |
|
|
|
#ifdef __i386__ |
|
#define BITS 32 |
|
#endif |
|
#ifdef __x86_64__ |
|
#define BITS 64 |
|
#endif |
|
|
|
#include "elfs_elf.c" |
|
|
|
static int map(const char *path) |
|
{ |
|
struct stat st; |
|
int fd; |
|
|
|
fd = open(path, O_RDONLY); |
|
if (fd == -1 || fstat(fd, &st) == -1) |
|
return -1; |
|
|
|
ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
|
|
|
close(fd); |
|
|
|
return !!(ptr == MAP_FAILED); |
|
} |
|
|
|
static int init(const char *path) |
|
{ |
|
const char *e; |
|
|
|
if (map(path)) |
|
return -1; |
|
|
|
e = ptr; |
|
|
|
/* check ELF header */ |
|
if (memcmp(e, ELFMAG, SELFMAG)) |
|
return -1; |
|
/* support 32 or 64 */ |
|
switch (e[EI_CLASS]) { |
|
case ELFCLASS32: |
|
bits = 32; |
|
break; |
|
case ELFCLASS64: |
|
bits = 64; |
|
break; |
|
default: |
|
return -1; |
|
} |
|
|
|
return elfs_elf_init(bits); |
|
} |
|
|
|
static int elfs_getattr(const char *path, struct stat *st) |
|
{ |
|
int len = strlen("/sections"); |
|
|
|
memset(st, 0, sizeof(struct stat)); |
|
|
|
if (!strncmp(path, "/sections", len)) |
|
return elfs_getattr_sections(path + len, st); |
|
|
|
if (!strcmp(path, "/")) { |
|
st->st_mode = S_IFDIR | 0755; |
|
st->st_nlink = 2; |
|
return 0; |
|
} |
|
|
|
st->st_mode = S_IFREG | 0444; |
|
st->st_nlink = 1; |
|
|
|
return 0; |
|
} |
|
|
|
static int elfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, |
|
off_t offset, struct fuse_file_info *fi) |
|
{ |
|
char tmp[32]; |
|
int len = strlen("/sections"); |
|
|
|
if (!strncmp(path, "/sections", len)) |
|
return elfs_readdir_sections(path + len, buf, filler, offset, fi); |
|
|
|
if (strcmp(path, "/")) |
|
return -ENOENT; |
|
|
|
filler(buf, ".", NULL, 0); |
|
filler(buf, "..", NULL, 0); |
|
|
|
sprintf(tmp, "Elf%d", bits); |
|
filler(buf, tmp, NULL, 0); |
|
filler(buf, "sections", NULL, 0); |
|
|
|
return 0; |
|
} |
|
|
|
static int elfs_open(const char *path, struct fuse_file_info *fi) |
|
{ |
|
int len = strlen("/sections"); |
|
char tmp[32]; |
|
|
|
if (!strncmp(path, "/sections", len)) |
|
return elfs_open_sections(path + len, fi); |
|
|
|
sprintf(tmp, "/Elf%d", bits); |
|
if (strcmp(path, tmp)) |
|
return -ENOENT; |
|
|
|
if ((fi->flags & 3) != O_RDONLY) |
|
return -EACCES; |
|
|
|
return 0; |
|
} |
|
|
|
static int elfs_read(const char *path, char *buf, size_t size, off_t offset, |
|
struct fuse_file_info *fi) |
|
{ |
|
int len = strlen("/sections"); |
|
char tmp[32]; |
|
|
|
if (!strncmp(path, "/sections", len)) |
|
return elfs_read_sections(path + len, buf, size, offset, fi); |
|
|
|
sprintf(tmp, "/Elf%d", bits); |
|
if (strcmp(path, tmp)) |
|
return -ENOENT; |
|
|
|
return 0; |
|
} |
|
|
|
static struct fuse_operations elfs_op = { |
|
.getattr = elfs_getattr, |
|
.readdir = elfs_readdir, |
|
.open = elfs_open, |
|
.read = elfs_read, |
|
}; |
|
|
|
int main(int argc, char **argv) |
|
{ |
|
struct fuse_args args = FUSE_ARGS_INIT(0, NULL); |
|
|
|
if (argc != 3) |
|
goto err; |
|
|
|
if (init(argv[1])) |
|
goto err; |
|
|
|
fuse_opt_add_arg(&args, argv[0]); |
|
fuse_opt_add_arg(&args, argv[2]); |
|
|
|
return fuse_main(args.argc, args.argv, &elfs_op, NULL); |
|
|
|
err: |
|
fprintf(stderr, "error\n"); |
|
|
|
return 1; |
|
} |