1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <inttypes.h> 6#include <fcntl.h> 7#include <stdlib.h> 8#include <string.h> 9#include <sys/stat.h> 10 11#include <fbl/ref_ptr.h> 12#include <fbl/unique_ptr.h> 13#include <lib/fdio/namespace.h> 14#include <lib/fdio/vfs.h> 15#include <fs/vfs.h> 16#include <lib/async/dispatcher.h> 17#include <lib/memfs/cpp/vnode.h> 18#include <lib/memfs/memfs.h> 19#include <lib/sync/completion.h> 20#include <zircon/device/vfs.h> 21 22#include "dnode.h" 23 24struct memfs_filesystem { 25 memfs::Vfs vfs; 26 27 explicit memfs_filesystem(size_t pages_limit): vfs(pages_limit) { } 28}; 29 30zx_status_t memfs_create_filesystem(async_dispatcher_t* dispatcher, 31 memfs_filesystem_t** out_fs, 32 zx_handle_t* out_root) { 33 return memfs_create_filesystem_with_page_limit(dispatcher, UINT64_MAX, out_fs, out_root); 34} 35 36zx_status_t memfs_create_filesystem_with_page_limit(async_dispatcher_t* dispatcher, 37 size_t max_num_pages, 38 memfs_filesystem_t** out_fs, 39 zx_handle_t* out_root) { 40 ZX_DEBUG_ASSERT(dispatcher != nullptr); 41 ZX_DEBUG_ASSERT(out_fs != nullptr); 42 ZX_DEBUG_ASSERT(out_root != nullptr); 43 44 zx::channel client, server; 45 zx_status_t status = zx::channel::create(0, &client, &server); 46 if (status != ZX_OK) { 47 return status; 48 } 49 50 fbl::unique_ptr<memfs_filesystem_t> fs = fbl::make_unique<memfs_filesystem_t>(max_num_pages); 51 fs->vfs.SetDispatcher(dispatcher); 52 53 fbl::RefPtr<memfs::VnodeDir> root; 54 if ((status = memfs::CreateFilesystem("<tmp>", &fs->vfs, &root)) != ZX_OK) { 55 return status; 56 } 57 if ((status = fs->vfs.ServeDirectory(fbl::move(root), fbl::move(server))) != ZX_OK) { 58 return status; 59 } 60 61 *out_fs = fs.release(); 62 *out_root = client.release(); 63 return ZX_OK; 64} 65 66zx_status_t memfs_install_at(async_dispatcher_t* dispatcher, const char* path) { 67 return memfs_install_at_with_page_limit(dispatcher, UINT64_MAX, path); 68} 69 70zx_status_t memfs_install_at_with_page_limit(async_dispatcher_t* dispatcher, 71 size_t max_num_pages, const char* path) { 72 fdio_ns_t* ns; 73 zx_status_t status = fdio_ns_get_installed(&ns); 74 if (status != ZX_OK) { 75 return status; 76 } 77 78 memfs_filesystem_t* fs; 79 zx_handle_t root; 80 status = memfs_create_filesystem_with_page_limit(dispatcher, max_num_pages, &fs, &root); 81 if (status != ZX_OK) { 82 return status; 83 } 84 85 status = fdio_ns_bind(ns, path, root); 86 if (status != ZX_OK) { 87 memfs_free_filesystem(fs, nullptr); 88 zx_handle_close(root); 89 return status; 90 } 91 92 return ZX_OK; 93} 94 95void memfs_free_filesystem(memfs_filesystem_t* fs, sync_completion_t* unmounted) { 96 ZX_DEBUG_ASSERT(fs != nullptr); 97 fs->vfs.Shutdown([fs, unmounted](zx_status_t status) { 98 delete fs; 99 if (unmounted) { 100 sync_completion_signal(unmounted); 101 } 102 }); 103} 104