Skip to content

Instantly share code, notes, and snippets.

@hshimamoto
Last active September 5, 2018 21:39
Show Gist options
  • Save hshimamoto/6a38ab58ace5f9f990e0364284bd85bd to your computer and use it in GitHub Desktop.
Save hshimamoto/6a38ab58ace5f9f990e0364284bd85bd to your computer and use it in GitHub Desktop.

FUSE test

$ ./elfs elfs tmp

$ ls tmp
Elf64  sections

$ ls tmp/sections
0  10  12  14  16  18  2   21  23  25  27  29  30  5  7  9
1  11  13  15  17  19  20  22  24  26  28  3   4   6  8

$ cat tmp/sections/1
.interp
#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;
}
#ifndef BITS
#error "No BITS"
#endif
#define STR0(x,y) x ## y
#define STR(x,y) STR0(x,y)
#define E(x) STR(STR(STR(Elf, BITS), _), x)
#define Elf_Ehdr E(Ehdr)
#define Elf_Shdr E(Shdr)
static int elfs_elf_init(int bits)
{
Elf_Ehdr *e = ptr;
if (bits != BITS)
return -1;
sections = e->e_shnum;
return 0;
}
static int elfs_getattr_sections(const char *path, struct stat *st)
{
if (*path == 0 || !strcmp(path, "/")) {
st->st_mode = S_IFDIR | 0755;
st->st_nlink = 2;
return 0;
}
st->st_mode = S_IFREG | 0444;
st->st_nlink = 1;
st->st_size = 4096;
return 0;
}
static int elfs_readdir_sections(const char *path, void *buf,
fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
char tmp[64];
int i;
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
for (i = 0; i < sections; i++) {
sprintf(tmp, "%d", i);
filler(buf, tmp, NULL, 0);
}
return 0;
}
static int elfs_open_sections(const char *path, struct fuse_file_info *fi)
{
int n = atoi(path + 1);
if (n < 0 || sections < n)
return -ENOENT;
if ((fi->flags & 3) != O_RDONLY)
return -EACCES;
return 0;
}
static int elfs_read_sections(const char *path, char *buf, size_t size,
off_t offset, struct fuse_file_info *fi)
{
Elf_Ehdr *e = ptr;
Elf_Shdr *sh = ptr + e->e_shoff;
int stidx = e->e_shstrndx;
int n = atoi(path + 1);
int len;
char tmp[4096];
char *str;
if (n < 0 || sections < n)
return -ENOENT;
str = ptr + sh[stidx].sh_offset;
sprintf(tmp, "%s\n", str + sh[n].sh_name);
len = strlen(tmp);
if (offset >= len)
return 0;
if (offset + size > len)
size = len - offset;
memcpy(buf, tmp + offset, size);
return size;
}
all:
gcc -Wall `pkg-config fuse --cflags --libs` -DFUSE_USE_VERSION=26 elfs.c -o elfs
clean:
rm -f elfs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment