blob: 202917903457d001328d646292c4f8afe4b44eea [file] [log] [blame] [edit]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::{
auth::FsCred,
device::DeviceMode,
fs::{
kobject::DeviceMetadata, tmpfs::TmpFs, DirEntryHandle, FileSystemHandle, FsStr, MountInfo,
},
task::Kernel,
types::{mode, DeviceType, Errno},
};
use std::sync::Arc;
pub fn dev_tmp_fs(kernel: &Arc<Kernel>) -> &FileSystemHandle {
kernel.dev_tmp_fs.get_or_init(|| init_devtmpfs(kernel))
}
fn init_devtmpfs(kernel: &Arc<Kernel>) -> FileSystemHandle {
let fs = TmpFs::new_fs(kernel);
let root = fs.root();
let current_task = kernel.kthreads.system_task();
let mkdir = |name| {
// This creates content inside the temporary FS. This doesn't depend on the mount
// information.
root.create_entry(current_task, &MountInfo::detached(), name, |dir, mount, name| {
dir.mknod(
current_task,
mount,
name,
mode!(IFDIR, 0o755),
DeviceType::NONE,
FsCred::root(),
)
})
.unwrap();
};
mkdir(b"shm");
create_symlink(kernel, root, b"fd", b"/proc/self/fd").unwrap();
fs
}
pub fn devtmpfs_create_device(
kernel: &Arc<Kernel>,
device: DeviceMetadata,
) -> Result<DirEntryHandle, Errno> {
let current_task = kernel.kthreads.system_task();
let mode = match device.mode {
DeviceMode::Char => mode!(IFCHR, 0o666),
DeviceMode::Block => mode!(IFBLK, 0o666),
};
// This creates content inside the temporary FS. This doesn't depend on the mount
// information.
dev_tmp_fs(kernel).root().create_entry(
current_task,
&MountInfo::detached(),
&device.name,
|dir, mount, name| {
dir.mknod(current_task, mount, name, mode, device.device_type, FsCred::root())
},
)
}
pub fn devtmpfs_mkdir(kernel: &Arc<Kernel>, name: &FsStr) -> Result<DirEntryHandle, Errno> {
let current_task = kernel.kthreads.system_task();
// This creates content inside the temporary FS. This doesn't depend on the mount
// information.
dev_tmp_fs(kernel).root().create_entry(
current_task,
&MountInfo::detached(),
name,
|dir, mount, name| {
dir.mknod(
current_task,
mount,
name,
mode!(IFDIR, 0o755),
DeviceType::NONE,
FsCred::root(),
)
},
)
}
pub fn devtmpfs_remove_child(kernel: &Arc<Kernel>, name: &FsStr) {
dev_tmp_fs(kernel).root().remove_child(name);
}
pub fn devtmpfs_create_symlink(
kernel: &Arc<Kernel>,
name: &FsStr,
target: &FsStr,
) -> Result<DirEntryHandle, Errno> {
create_symlink(kernel, dev_tmp_fs(kernel).root(), name, target)
}
fn create_symlink(
kernel: &Arc<Kernel>,
entry: &DirEntryHandle,
name: &FsStr,
target: &FsStr,
) -> Result<DirEntryHandle, Errno> {
let current_task = kernel.kthreads.system_task();
// This creates content inside the temporary FS. This doesn't depend on the mount
// information.
entry.create_entry(current_task, &MountInfo::detached(), name, |dir, mount, name| {
dir.create_symlink(current_task, mount, name, target, FsCred::root())
})
}