static telf_status defaultfs_readdir(void *ctx_hdl, const char *path, void *data, fuse_fill_dir_t fill) { telf_ctx *ctx = ctx_hdl; telf_obj *obj = NULL; telf_status ret; int rc; telf_dir_hdl *dir_hdl = NULL; telf_dirent dirent; int locked = 0; DEBUG("%s", path); elf_ctx_lock(ctx); rc = elf_namei(ctx, path, &obj); if (ELF_SUCCESS != rc) { ERR("can't find object with key '%s': %s", path, elf_status_to_str(rc)); ret = ELF_ENOENT; goto end; } elf_obj_lock(obj); locked = 1; dir_hdl = alloca(sizeof *dir_hdl); if (! dir_hdl) { ERR("alloca: %s", strerror(errno)); ret = ELF_ENOMEM; goto end; } memset(&dirent, 0, sizeof dirent); dir_ctor(obj->ctx, obj, dir_hdl); while (0 == readdir_getdirent(dir_hdl, &dirent)) { if (fill(data, dirent.name, NULL, 0)) break; } ret = ELF_SUCCESS; end: if (locked) elf_obj_unlock(obj); elf_ctx_unlock(ctx); return ret; }
static telf_status defaultfs_read(void *ctx_hdl, const char *path, char *buf, size_t size, off_t offset, ssize_t *sizep) { telf_ctx *ctx = ctx_hdl; telf_obj *obj = NULL; telf_default_content *content = NULL; telf_status ret; telf_status rc; int locked = 0; DEBUG("path=%s", path); elf_ctx_lock(ctx); rc = elf_namei(ctx, path, &obj); if (ELF_SUCCESS != rc) { ERR("namei(%s) failed: %d", path, rc); ret = ELF_ENOENT; goto end; } elf_obj_lock(obj); locked = 1; DEBUG("name:%s data=%p", obj->name, obj->data); content = obj->data; if (content->buf) { if (size > content->buf_len - offset) size = content->buf_len - offset; memcpy(buf, content->buf + offset, size); } ret = ELF_SUCCESS; end: if (sizep) *sizep = size; if (locked) elf_obj_unlock(obj); elf_ctx_unlock(ctx); DEBUG("path=%s, ret=%s (%d)", path, elf_status_to_str(ret), ret); return ret; }
static telf_status defaultfs_getattr(void *ctx_hdl, const char *path, telf_stat *st) { telf_ctx *ctx = ctx_hdl; telf_status ret; telf_status rc; telf_obj *obj = NULL; int locked = 0; DEBUG("path=%s", path); elf_ctx_lock(ctx); rc = elf_namei(ctx, path, &obj); if (ELF_SUCCESS != rc) { ERR("namei(%s) failed: %d", path, rc); ret = ELF_ENOENT; goto end; } elf_obj_lock(obj); locked = 1; DEBUG("name:%s data=%p", obj->name, obj->data); memcpy(st, &obj->st, sizeof *st); st->mode |= ELF_S_IRUSR|ELF_S_IWUSR | ELF_S_IRGRP | ELF_S_IROTH; st->nlink = 1; st->atime = st->mtime = st->ctime = time(NULL); if (ELF_S_ISREG(obj->st.mode)) { if (obj->fill_func) { rc = obj->fill_func(obj, NULL, &st->size); if (ELF_SUCCESS != rc) { ret = rc; goto end; } } } ret = ELF_SUCCESS; end: if (locked) elf_obj_unlock(obj); elf_ctx_unlock(ctx); DEBUG("path=%s, ret=%s (%d)", path, elf_status_to_str(ret), ret); return ret; }
static telf_status defaultfs_release(void *ctx_hdl, const char *path) { telf_ctx *ctx = ctx_hdl; telf_obj *obj = NULL; telf_status ret; telf_status rc; int locked = 0; DEBUG("path=%s", path); elf_ctx_lock(ctx); rc = elf_namei(ctx, path, &obj); if (ELF_SUCCESS != rc) { ERR("namei(%s) failed: %d", path, rc); ret = ELF_ENOENT; goto end; } elf_obj_lock(obj); locked = 1; elf_obj_unref_nolock(obj); DEBUG("name:%s data=%p", obj->name, obj->data); if (0 == obj->refcount) { if (obj->free_func) { obj->free_func(obj->data); obj->data = NULL; } } ret = ELF_SUCCESS; end: if (locked) elf_obj_unlock(obj); elf_ctx_unlock(ctx); DEBUG("path=%s, ret=%s (%d)", path, elf_status_to_str(ret), ret); return ELF_SUCCESS; }
telf_status headerfs_build(telf_ctx *ctx) { telf_obj *header_obj = NULL; telf_status ret; telf_status rc; rc = elf_namei(ctx, "/header", &header_obj); if (ELF_SUCCESS != rc) { ERR("can't find '/header' object: %s", elf_status_to_str(rc)); ret = rc; goto end; } /* now add the pseudo files */ for (size_t i = 0; i < N_ELEMS(headerfs_fcb); i++) { telf_obj *entry = NULL; telf_fcb *fcb = headerfs_fcb + i; entry = elf_obj_new(ctx, fcb->str, header_obj, ELF_HEADER_ENTRY, ELF_S_IFREG); if (! entry) { ERR("can't build entry '%s'", fcb->str); continue; } headerfs_override_driver(entry->driver); entry->free_func = fcb->freecontent_func; entry->fill_func = fcb->fillcontent_func; list_add(header_obj->entries, entry); } ret = ELF_SUCCESS; end: return ret; }
static telf_status headerfs_release(void *ctx_hdl, const char *path) { telf_ctx *ctx = ctx_hdl; telf_obj *obj = NULL; telf_fcb *fcb = NULL; telf_status ret; telf_status rc; int locked = 0; elf_ctx_lock(ctx); rc = elf_namei(ctx, path, &obj); if (ELF_SUCCESS != rc) { ERR("namei(%s) failed: %d", path, rc); ret = -ENOENT; goto end; } elf_obj_lock(obj); locked = 1; elf_obj_unref_nolock(obj); DEBUG("name:%s data=%p", obj->name, obj->data); fcb = elf_get_fcb(headerfs_fcb, N_ELEMS(headerfs_fcb), obj->name); if (! fcb) { ERR("no fcb matching obj '%s'", obj->name); ret = ELF_ENOENT; goto end; } if (fcb->release_func) { rc = fcb->release_func(obj); if (ELF_SUCCESS != rc) { ERR("release ('%s') failed: %s", obj->name, elf_status_to_str(rc)); ret = rc; goto end; } } if (0 == obj->refcount) { if (obj->free_func) { obj->free_func(obj->data); obj->data = NULL; } } ret = ELF_SUCCESS; end: if (locked) elf_obj_unlock(obj); elf_ctx_unlock(ctx); return ret; }
static telf_status defaultfs_open(void *ctx_hdl, const char *path, void **obj_hdlp) { telf_ctx *ctx = ctx_hdl; telf_obj *obj = NULL; telf_status ret; telf_status rc; telf_default_content *content; int locked = 0; DEBUG("path=%s", path); elf_ctx_lock(ctx); rc = elf_namei(ctx, path, &obj); if (ELF_SUCCESS != rc) { ERR("namei(%s) failed: %d", path, rc); ret = ELF_ENOENT; goto end; } elf_obj_lock(obj); locked = 1; elf_obj_ref_nolock(obj); content = malloc(sizeof *content); if (! content) { ERR("malloc: %s", strerror(errno)); ret = ELF_ENOMEM; goto end; } if (obj->fill_func) { rc = obj->fill_func(obj, &content->buf, &content->buf_len); if (ELF_SUCCESS != rc) { ret = rc; goto end; } } if (obj->data && obj->free_func) obj->free_func(obj->data); obj->data = content; ret = ELF_SUCCESS; end: if (obj_hdlp) *obj_hdlp = obj; if (locked) elf_obj_unlock(obj); elf_ctx_unlock(ctx); DEBUG("path=%s, ret=%s (%d)", path, elf_status_to_str(ret), ret); return ret; }
telf_status libfs_build(telf_ctx *ctx) { telf_status ret; telf_status rc; telf_obj *libfs_obj = NULL; telf_obj *entry = NULL; int i; Elf64_Shdr *shdr = NULL; Elf64_Dyn *dyn = NULL; /* sanity check */ rc = elf_namei(ctx, "/libs", &libfs_obj); if (ELF_SUCCESS != rc) { ERR("can't find '/libfs' object: %s", elf_status_to_str(rc)); ret = rc; goto end; } shdr = elf_getsectionbytype(ctx, SHT_DYNAMIC); if (! shdr) { ERR("can't find any SHT_DYNAMIC section"); ret = ELF_ENOENT; goto end; } /* get all DT_NEEDED strings. */ for (i = 0; i < shdr->sh_size / sizeof(Elf64_Dyn); i++) { telf_obj *entry = NULL; char *libname = NULL; dyn = (Elf64_Dyn *) (ctx->addr + shdr->sh_offset) + i; if (DT_NEEDED != dyn->d_tag) continue; libname = strdup(ctx->dstrtab + dyn->d_un.d_val); if (! libname) { ERR("strdup(%s): %s", libname, strerror(errno)); ret = ELF_ENOMEM; goto end; } entry = elf_obj_new(ctx, libname, libfs_obj, ELF_LIBS_ENTRY, ELF_S_IFLNK); if (! entry) { ERR("can't build entry '%s'", libname); continue; } libfs_override_driver(entry->driver); list_add(libfs_obj->entries, entry); } rc = elf_set_default_libpath(ctx); if (ELF_SUCCESS != rc) { ERR("Can't set libpath list"); ret = rc; goto end; } ret = ELF_SUCCESS; end: return ret; }