From fcf104f124163c2073a486b178b3e0822a3cec47 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Sun, 14 Jul 2024 20:50:53 +0800 Subject: [PATCH 01/10] buildtools: feat #135: Check the version of QEMU ahead --- os/Makefile | 13 ++++++++----- os/scripts/qemu-ver-check.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 os/scripts/qemu-ver-check.sh diff --git a/os/Makefile b/os/Makefile index 9815cee..ff109f0 100644 --- a/os/Makefile +++ b/os/Makefile @@ -74,20 +74,23 @@ QEMU_ARGS := -machine virt \ -drive file=$(FS_IMG),if=none,format=raw,id=x0 \ -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 -run-inner: build +QEMU_NAME := qemu-system-riscv64 +qemu-version-check: + @sh scripts/qemu-ver-check.sh $(QEMU_NAME) + +run-inner: qemu-version-check build @qemu-system-riscv64 $(QEMU_ARGS) -debug: build +debug: qemu-version-check build @tmux new-session -d \ "qemu-system-riscv64 $(QEMU_ARGS) -s -S" && \ tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \ tmux -2 attach-session -d - -gdbserver: build +gdbserver: qemu-version-check build @qemu-system-riscv64 $(QEMU_ARGS) -s -S gdbclient: @riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234' -.PHONY: build env kernel clean disasm disasm-vim run-inner fs-img gdbserver gdbclient +.PHONY: build env kernel clean disasm disasm-vim run-inner fs-img gdbserver gdbclient qemu-version-check diff --git a/os/scripts/qemu-ver-check.sh b/os/scripts/qemu-ver-check.sh new file mode 100644 index 0000000..8c20456 --- /dev/null +++ b/os/scripts/qemu-ver-check.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Argument1: The filename of qemu executable, e.g. qemu-system-riscv64 +QEMU_PATH=$(which $1) +RET=$? +MINIMUM_MAJOR_VERSION=7 +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' +if [ $RET != 0 ] +then + echo "$1 not found" + exit 1 +else + QEMU_VERSION=$($1 --version|head -n 1|awk '{print $4}') + MAJOR_VERSION=$(echo $QEMU_VERSION|cut -c1-1) + if [ $MAJOR_VERSION -lt $MINIMUM_MAJOR_VERSION ] + then + echo "${RED}Error: Required major version of QEMU is ${MINIMUM_MAJOR_VERSION}, " \ + "but current is ${QEMU_VERSION}.${NC}" + exit 1 + else + echo "${GREEN}QEMU version is ${QEMU_VERSION}(>=${MINIMUM_MAJOR_VERSION}), OK!${NC}" + exit 0 + fi +fi From 6699e80a30f9a479ca9a0b4e76e0dccc4e860a26 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Mon, 10 Feb 2025 00:29:05 +0800 Subject: [PATCH 02/10] logging: bugfix #137: Init log module to enable logging macros --- os/src/logging.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ os/src/main.rs | 6 +++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 os/src/logging.rs diff --git a/os/src/logging.rs b/os/src/logging.rs new file mode 100644 index 0000000..b5421f1 --- /dev/null +++ b/os/src/logging.rs @@ -0,0 +1,47 @@ +/*! + +本模块利用 log crate 为你提供了日志功能,使用方式见 main.rs. + +*/ + +use log::{self, Level, LevelFilter, Log, Metadata, Record}; + +struct SimpleLogger; + +impl Log for SimpleLogger { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + fn log(&self, record: &Record) { + if !self.enabled(record.metadata()) { + return; + } + let color = match record.level() { + Level::Error => 31, // Red + Level::Warn => 93, // BrightYellow + Level::Info => 34, // Blue + Level::Debug => 32, // Green + Level::Trace => 90, // BrightBlack + }; + println!( + "\u{1B}[{}m[{:>5}] {}\u{1B}[0m", + color, + record.level(), + record.args(), + ); + } + fn flush(&self) {} +} + +pub fn init() { + static LOGGER: SimpleLogger = SimpleLogger; + log::set_logger(&LOGGER).unwrap(); + log::set_max_level(match option_env!("LOG") { + Some("ERROR") => LevelFilter::Error, + Some("WARN") => LevelFilter::Warn, + Some("INFO") => LevelFilter::Info, + Some("DEBUG") => LevelFilter::Debug, + Some("TRACE") => LevelFilter::Trace, + _ => LevelFilter::Info, + }); +} diff --git a/os/src/main.rs b/os/src/main.rs index cc58958..ad60a70 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -31,6 +31,8 @@ extern crate alloc; #[macro_use] extern crate bitflags; +use log::*; + #[path = "boards/qemu.rs"] mod board; @@ -40,6 +42,7 @@ mod config; mod drivers; pub mod fs; pub mod lang_items; +mod logging; pub mod mm; pub mod sbi; pub mod sync; @@ -67,7 +70,8 @@ fn clear_bss() { /// the rust entry-point of os pub fn rust_main() -> ! { clear_bss(); - println!("[kernel] Hello, world!"); + logging::init(); + info!("[kernel] Hello, world!"); mm::init(); mm::remap_test(); trap::init(); From 123595601d02abf6b154f3b6858897be8f67cf70 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Tue, 11 Feb 2025 23:10:55 +0800 Subject: [PATCH 03/10] Update doc-and-test.yml --- .github/workflows/doc-and-test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/doc-and-test.yml b/.github/workflows/doc-and-test.yml index 0a05371..72f124b 100644 --- a/.github/workflows/doc-and-test.yml +++ b/.github/workflows/doc-and-test.yml @@ -49,7 +49,10 @@ jobs: - name: Install QEMU run: | sudo apt-get update - sudo apt-get install ninja-build -y + sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \ + gawk build-essential bison flex texinfo gperf libtool patchutils bc \ + zlib1g-dev libexpat-dev pkg-config libglib2.0-dev libpixman-1-dev libsdl2-dev libslirp-dev \ + python3 python3-pip ninja-build -y if [ ! -d qemu-7.0.0 ]; then wget https://download.qemu.org/qemu-7.0.0.tar.xz tar -xf qemu-7.0.0.tar.xz From 5b846fce6a826da3eb19417adf73df9d315088b2 Mon Sep 17 00:00:00 2001 From: Yifan Wu Date: Wed, 19 Feb 2025 21:27:17 +0800 Subject: [PATCH 04/10] Bump Rust version to nightly-2025-02-18(2024 Edition) --- .github/workflows/doc-and-test.yml | 2 +- os/Cargo.toml | 2 +- os/src/drivers/block/virtio_blk.rs | 4 +- os/src/fs/mod.rs | 2 +- os/src/lang_items.rs | 4 +- os/src/main.rs | 9 ++--- os/src/mm/frame_allocator.rs | 4 +- os/src/mm/heap_allocator.rs | 9 +++-- os/src/mm/memory_set.rs | 61 +++++++++++++++++------------- os/src/mm/mod.rs | 8 ++-- os/src/mm/page_table.rs | 3 +- os/src/sbi.rs | 2 +- os/src/syscall/fs.rs | 4 +- os/src/syscall/process.rs | 2 +- os/src/task/mod.rs | 10 ++--- os/src/task/pid.rs | 2 +- os/src/task/processor.rs | 2 +- os/src/task/switch.rs | 9 ++++- os/src/task/task.rs | 6 +-- os/src/trap/context.rs | 2 +- os/src/trap/mod.rs | 12 +++--- rust-toolchain.toml | 2 +- user/Cargo.toml | 2 +- user/src/bin/cat_filea.rs | 4 +- user/src/bin/exit.rs | 2 +- user/src/bin/fantastic_text.rs | 6 +-- user/src/bin/filetest_simple.rs | 4 +- user/src/bin/forktest.rs | 2 +- user/src/bin/forktest2.rs | 2 +- user/src/bin/forktest_simple.rs | 2 +- user/src/bin/forktree.rs | 2 +- user/src/bin/hello_world.rs | 2 +- user/src/bin/huge_write.rs | 4 +- user/src/bin/initproc.rs | 2 +- user/src/bin/matrix.rs | 2 +- user/src/bin/sleep.rs | 2 +- user/src/bin/sleep_simple.rs | 2 +- user/src/bin/stack_overflow.rs | 2 +- user/src/bin/user_shell.rs | 2 +- user/src/bin/usertests.rs | 2 +- user/src/bin/usertests_simple.rs | 2 +- user/src/bin/yield.rs | 2 +- user/src/lang_items.rs | 2 +- user/src/lib.rs | 10 ++--- 44 files changed, 118 insertions(+), 105 deletions(-) diff --git a/.github/workflows/doc-and-test.yml b/.github/workflows/doc-and-test.yml index 72f124b..9fee30e 100644 --- a/.github/workflows/doc-and-test.yml +++ b/.github/workflows/doc-and-test.yml @@ -4,7 +4,7 @@ on: [push] env: CARGO_TERM_COLOR: always - rust_toolchain: nightly-2024-01-18 + rust_toolchain: nightly-2025-02-18 jobs: build-doc: diff --git a/os/Cargo.toml b/os/Cargo.toml index b65ed6e..d621557 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -2,7 +2,7 @@ name = "os" version = "0.1.0" authors = ["Yifan Wu "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/os/src/drivers/block/virtio_blk.rs b/os/src/drivers/block/virtio_blk.rs index 9755250..5097831 100644 --- a/os/src/drivers/block/virtio_blk.rs +++ b/os/src/drivers/block/virtio_blk.rs @@ -1,7 +1,7 @@ use super::BlockDevice; use crate::mm::{ - frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum, - StepByOne, VirtAddr, + FrameTracker, PageTable, PhysAddr, PhysPageNum, StepByOne, VirtAddr, frame_alloc, + frame_dealloc, kernel_token, }; use crate::sync::UPSafeCell; use alloc::vec::Vec; diff --git a/os/src/fs/mod.rs b/os/src/fs/mod.rs index 6c790fe..c3cc1e7 100644 --- a/os/src/fs/mod.rs +++ b/os/src/fs/mod.rs @@ -15,5 +15,5 @@ pub trait File: Send + Sync { fn write(&self, buf: UserBuffer) -> usize; } -pub use inode::{list_apps, open_file, OSInode, OpenFlags}; +pub use inode::{OSInode, OpenFlags, list_apps, open_file}; pub use stdio::{Stdin, Stdout}; diff --git a/os/src/lang_items.rs b/os/src/lang_items.rs index 26951f8..79cd51e 100644 --- a/os/src/lang_items.rs +++ b/os/src/lang_items.rs @@ -10,10 +10,10 @@ fn panic(info: &PanicInfo) -> ! { "[kernel] Panicked at {}:{} {}", location.file(), location.line(), - info.message().unwrap() + info.message() ); } else { - error!("[kernel] Panicked: {}", info.message().unwrap()); + error!("[kernel] Panicked: {}", info.message()); } shutdown(true) } diff --git a/os/src/main.rs b/os/src/main.rs index ad60a70..46161de 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -23,7 +23,6 @@ #![allow(unused_imports)] #![no_std] #![no_main] -#![feature(panic_info_message)] #![feature(alloc_error_handler)] extern crate alloc; @@ -56,9 +55,9 @@ use core::arch::global_asm; global_asm!(include_str!("entry.asm")); /// clear BSS segment fn clear_bss() { - extern "C" { - fn sbss(); - fn ebss(); + unsafe extern "C" { + safe fn sbss(); + safe fn ebss(); } unsafe { core::slice::from_raw_parts_mut(sbss as usize as *mut u8, ebss as usize - sbss as usize) @@ -66,8 +65,8 @@ fn clear_bss() { } } -#[no_mangle] /// the rust entry-point of os +#[unsafe(no_mangle)] pub fn rust_main() -> ! { clear_bss(); logging::init(); diff --git a/os/src/mm/frame_allocator.rs b/os/src/mm/frame_allocator.rs index f3d18ea..28b519c 100644 --- a/os/src/mm/frame_allocator.rs +++ b/os/src/mm/frame_allocator.rs @@ -94,8 +94,8 @@ lazy_static! { } /// initiate the frame allocator using `ekernel` and `MEMORY_END` pub fn init_frame_allocator() { - extern "C" { - fn ekernel(); + unsafe extern "C" { + safe fn ekernel(); } FRAME_ALLOCATOR.exclusive_access().init( PhysAddr::from(ekernel as usize).ceil(), diff --git a/os/src/mm/heap_allocator.rs b/os/src/mm/heap_allocator.rs index e5f8b30..a6b413b 100644 --- a/os/src/mm/heap_allocator.rs +++ b/os/src/mm/heap_allocator.rs @@ -1,6 +1,7 @@ //! The global allocator use crate::config::KERNEL_HEAP_SIZE; use buddy_system_allocator::LockedHeap; +use core::ptr::addr_of_mut; #[global_allocator] /// heap allocator instance @@ -18,7 +19,7 @@ pub fn init_heap() { unsafe { HEAP_ALLOCATOR .lock() - .init(HEAP_SPACE.as_ptr() as usize, KERNEL_HEAP_SIZE); + .init(addr_of_mut!(HEAP_SPACE) as usize, KERNEL_HEAP_SIZE); } } @@ -26,9 +27,9 @@ pub fn init_heap() { pub fn heap_test() { use alloc::boxed::Box; use alloc::vec::Vec; - extern "C" { - fn sbss(); - fn ebss(); + unsafe extern "C" { + safe fn sbss(); + safe fn ebss(); } let bss_range = sbss as usize..ebss as usize; let a = Box::new(5); diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index a2c31cd..b1e5072 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -1,5 +1,6 @@ //! Implementation of [`MapArea`] and [`MemorySet`]. -use super::{frame_alloc, FrameTracker}; + +use super::{FrameTracker, frame_alloc}; use super::{PTEFlags, PageTable, PageTableEntry}; use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum}; use super::{StepByOne, VPNRange}; @@ -12,17 +13,17 @@ use core::arch::asm; use lazy_static::*; use riscv::register::satp; -extern "C" { - fn stext(); - fn etext(); - fn srodata(); - fn erodata(); - fn sdata(); - fn edata(); - fn sbss_with_stack(); - fn ebss(); - fn ekernel(); - fn strampoline(); +unsafe extern "C" { + safe fn stext(); + safe fn etext(); + safe fn srodata(); + safe fn erodata(); + safe fn sdata(); + safe fn edata(); + safe fn sbss_with_stack(); + safe fn ebss(); + safe fn ekernel(); + safe fn strampoline(); } lazy_static! { @@ -389,20 +390,26 @@ pub fn remap_test() { let mid_text: VirtAddr = ((stext as usize + etext as usize) / 2).into(); let mid_rodata: VirtAddr = ((srodata as usize + erodata as usize) / 2).into(); let mid_data: VirtAddr = ((sdata as usize + edata as usize) / 2).into(); - assert!(!kernel_space - .page_table - .translate(mid_text.floor()) - .unwrap() - .writable(),); - assert!(!kernel_space - .page_table - .translate(mid_rodata.floor()) - .unwrap() - .writable(),); - assert!(!kernel_space - .page_table - .translate(mid_data.floor()) - .unwrap() - .executable(),); + assert!( + !kernel_space + .page_table + .translate(mid_text.floor()) + .unwrap() + .writable(), + ); + assert!( + !kernel_space + .page_table + .translate(mid_rodata.floor()) + .unwrap() + .writable(), + ); + assert!( + !kernel_space + .page_table + .translate(mid_data.floor()) + .unwrap() + .executable(), + ); println!("remap_test passed!"); } diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 65f1e9a..3255725 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -13,13 +13,13 @@ mod page_table; use address::VPNRange; pub use address::{PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum}; -pub use frame_allocator::{frame_alloc, frame_dealloc, FrameTracker}; +pub use frame_allocator::{FrameTracker, frame_alloc, frame_dealloc}; pub use memory_set::remap_test; -pub use memory_set::{kernel_token, MapPermission, MemorySet, KERNEL_SPACE}; +pub use memory_set::{KERNEL_SPACE, MapPermission, MemorySet, kernel_token}; use page_table::PTEFlags; pub use page_table::{ - translated_byte_buffer, translated_ref, translated_refmut, translated_str, PageTable, - PageTableEntry, UserBuffer, UserBufferIterator, + PageTable, PageTableEntry, UserBuffer, UserBufferIterator, translated_byte_buffer, + translated_ref, translated_refmut, translated_str, }; /// initiate heap allocator, frame allocator and kernel space pub fn init() { diff --git a/os/src/mm/page_table.rs b/os/src/mm/page_table.rs index 9fbd21b..f5fdf2b 100644 --- a/os/src/mm/page_table.rs +++ b/os/src/mm/page_table.rs @@ -1,5 +1,6 @@ //! Implementation of [`PageTableEntry`] and [`PageTable`]. -use super::{frame_alloc, FrameTracker, PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum}; + +use super::{FrameTracker, PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum, frame_alloc}; use alloc::string::String; use alloc::vec; use alloc::vec::Vec; diff --git a/os/src/sbi.rs b/os/src/sbi.rs index eb79f67..a73476f 100644 --- a/os/src/sbi.rs +++ b/os/src/sbi.rs @@ -20,7 +20,7 @@ pub fn set_timer(timer: usize) { /// use sbi call to shutdown the kernel pub fn shutdown(failure: bool) -> ! { - use sbi_rt::{system_reset, NoReason, Shutdown, SystemFailure}; + use sbi_rt::{NoReason, Shutdown, SystemFailure, system_reset}; if !failure { system_reset(Shutdown, NoReason); } else { diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index aecc790..ff68ee9 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -1,6 +1,6 @@ //! File and filesystem-related syscalls -use crate::fs::{open_file, OpenFlags}; -use crate::mm::{translated_byte_buffer, translated_str, UserBuffer}; +use crate::fs::{OpenFlags, open_file}; +use crate::mm::{UserBuffer, translated_byte_buffer, translated_str}; use crate::task::{current_task, current_user_token}; pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index 3d62cbb..61e78d6 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -1,4 +1,4 @@ -use crate::fs::{open_file, OpenFlags}; +use crate::fs::{OpenFlags, open_file}; use crate::mm::{translated_refmut, translated_str}; use crate::task::{ add_task, current_task, current_user_token, exit_current_and_run_next, diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index e4837cb..47c13cd 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -23,20 +23,20 @@ mod switch; #[allow(rustdoc::private_intra_doc_links)] mod task; -use crate::fs::{open_file, OpenFlags}; +use crate::fs::{OpenFlags, open_file}; use crate::sbi::shutdown; use alloc::sync::Arc; pub use context::TaskContext; use lazy_static::*; -pub use manager::{fetch_task, TaskManager}; +pub use manager::{TaskManager, fetch_task}; use switch::__switch; use task::{TaskControlBlock, TaskStatus}; pub use manager::add_task; -pub use pid::{pid_alloc, KernelStack, PidAllocator, PidHandle}; +pub use pid::{KernelStack, PidAllocator, PidHandle, pid_alloc}; pub use processor::{ - current_task, current_trap_cx, current_user_token, run_tasks, schedule, take_current_task, - Processor, + Processor, current_task, current_trap_cx, current_user_token, run_tasks, schedule, + take_current_task, }; /// Suspend the current 'Running' task and run the next task in task list. pub fn suspend_current_and_run_next() { diff --git a/os/src/task/pid.rs b/os/src/task/pid.rs index a7bdea9..f0a5e2a 100644 --- a/os/src/task/pid.rs +++ b/os/src/task/pid.rs @@ -1,6 +1,6 @@ //!Implementation of [`PidAllocator`] use crate::config::{KERNEL_STACK_SIZE, PAGE_SIZE, TRAMPOLINE}; -use crate::mm::{MapPermission, VirtAddr, KERNEL_SPACE}; +use crate::mm::{KERNEL_SPACE, MapPermission, VirtAddr}; use crate::sync::UPSafeCell; use alloc::vec::Vec; use lazy_static::*; diff --git a/os/src/task/processor.rs b/os/src/task/processor.rs index 1d9c0f2..7c05a21 100644 --- a/os/src/task/processor.rs +++ b/os/src/task/processor.rs @@ -1,7 +1,7 @@ //!Implementation of [`Processor`] and Intersection of control flow use super::__switch; -use super::{fetch_task, TaskStatus}; use super::{TaskContext, TaskControlBlock}; +use super::{TaskStatus, fetch_task}; use crate::sync::UPSafeCell; use crate::trap::TrapContext; use alloc::sync::Arc; diff --git a/os/src/task/switch.rs b/os/src/task/switch.rs index 7d194f5..8f69fdf 100644 --- a/os/src/task/switch.rs +++ b/os/src/task/switch.rs @@ -4,6 +4,11 @@ use core::arch::global_asm; global_asm!(include_str!("switch.S")); -extern "C" { - pub fn __switch(current_task_cx_ptr: *mut TaskContext, next_task_cx_ptr: *const TaskContext); +unsafe extern "C" { + /// Switch to the context of `next_task_cx_ptr`, saving the current context + /// in `current_task_cx_ptr`. + pub unsafe fn __switch( + current_task_cx_ptr: *mut TaskContext, + next_task_cx_ptr: *const TaskContext, + ); } diff --git a/os/src/task/task.rs b/os/src/task/task.rs index 6e38b92..7b02cd6 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -1,11 +1,11 @@ //!Implementation of [`TaskControlBlock`] use super::TaskContext; -use super::{pid_alloc, KernelStack, PidHandle}; +use super::{KernelStack, PidHandle, pid_alloc}; use crate::config::TRAP_CONTEXT; use crate::fs::{File, Stdin, Stdout}; -use crate::mm::{MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE}; +use crate::mm::{KERNEL_SPACE, MemorySet, PhysPageNum, VirtAddr}; use crate::sync::UPSafeCell; -use crate::trap::{trap_handler, TrapContext}; +use crate::trap::{TrapContext, trap_handler}; use alloc::sync::{Arc, Weak}; use alloc::vec; use alloc::vec::Vec; diff --git a/os/src/trap/context.rs b/os/src/trap/context.rs index 0cae492..5f968e5 100644 --- a/os/src/trap/context.rs +++ b/os/src/trap/context.rs @@ -1,5 +1,5 @@ //! Implementation of [`TrapContext`] -use riscv::register::sstatus::{self, Sstatus, SPP}; +use riscv::register::sstatus::{self, SPP, Sstatus}; #[repr(C)] #[derive(Debug)] diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index 49b85ec..26e7895 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -50,7 +50,7 @@ pub fn enable_timer_interrupt() { } } -#[no_mangle] +#[unsafe(no_mangle)] /// handle an interrupt, exception, or system call from user space pub fn trap_handler() -> ! { set_kernel_trap_entry(); @@ -103,7 +103,7 @@ pub fn trap_handler() -> ! { trap_return(); } -#[no_mangle] +#[unsafe(no_mangle)] /// set the new addr of __restore asm function in TRAMPOLINE page, /// set the reg a0 = trap_cx_ptr, reg a1 = phy addr of usr page table, /// finally, jump to new addr of __restore asm function @@ -111,9 +111,9 @@ pub fn trap_return() -> ! { set_user_trap_entry(); let trap_cx_ptr = TRAP_CONTEXT; let user_satp = current_user_token(); - extern "C" { - fn __alltraps(); - fn __restore(); + unsafe extern "C" { + unsafe fn __alltraps(); + unsafe fn __restore(); } let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE; unsafe { @@ -128,7 +128,7 @@ pub fn trap_return() -> ! { } } -#[no_mangle] +#[unsafe(no_mangle)] /// Unimplement: traps/interrupts/exceptions from kernel mode /// Todo: Chapter 9: I/O device pub fn trap_from_kernel() -> ! { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c65d258..e6f10a1 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] profile = "minimal" # use the nightly version of the last stable toolchain, see -channel = "nightly-2024-05-01" +channel = "nightly-2025-02-18" components = ["rust-src", "llvm-tools", "rustfmt", "clippy"] targets = ["riscv64gc-unknown-none-elf"] diff --git a/user/Cargo.toml b/user/Cargo.toml index 3bc82dc..92f3f7e 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -2,7 +2,7 @@ name = "user_lib" version = "0.1.0" authors = ["Yifan Wu "] -edition = "2018" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/user/src/bin/cat_filea.rs b/user/src/bin/cat_filea.rs index 6307ecd..20daf77 100644 --- a/user/src/bin/cat_filea.rs +++ b/user/src/bin/cat_filea.rs @@ -5,9 +5,9 @@ extern crate user_lib; extern crate alloc; -use user_lib::{close, open, read, OpenFlags}; +use user_lib::{OpenFlags, close, open, read}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { let fd = open("filea\0", OpenFlags::RDONLY); if fd == -1 { diff --git a/user/src/bin/exit.rs b/user/src/bin/exit.rs index 60510c9..8e19542 100644 --- a/user/src/bin/exit.rs +++ b/user/src/bin/exit.rs @@ -7,7 +7,7 @@ use user_lib::{exit, fork, wait, waitpid, yield_}; const MAGIC: i32 = -0x10384; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { println!("I am the parent. Forking the child..."); let pid = fork(); diff --git a/user/src/bin/fantastic_text.rs b/user/src/bin/fantastic_text.rs index a3402ff..0850162 100644 --- a/user/src/bin/fantastic_text.rs +++ b/user/src/bin/fantastic_text.rs @@ -5,12 +5,12 @@ extern crate user_lib; macro_rules! color_text { - ($text:expr, $color:expr) => {{ + ($text:expr, $color:expr) => { format_args!("\x1b[{}m{}\x1b[0m", $color, $text) - }}; + }; } -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { println!( "{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}", diff --git a/user/src/bin/filetest_simple.rs b/user/src/bin/filetest_simple.rs index 3406d55..b192156 100644 --- a/user/src/bin/filetest_simple.rs +++ b/user/src/bin/filetest_simple.rs @@ -4,9 +4,9 @@ #[macro_use] extern crate user_lib; -use user_lib::{close, open, read, write, OpenFlags}; +use user_lib::{OpenFlags, close, open, read, write}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { let test_str = "Hello, world!"; let filea = "filea\0"; diff --git a/user/src/bin/forktest.rs b/user/src/bin/forktest.rs index 5374a56..f6003c5 100644 --- a/user/src/bin/forktest.rs +++ b/user/src/bin/forktest.rs @@ -8,7 +8,7 @@ use user_lib::{exit, fork, wait}; const MAX_CHILD: usize = 30; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { for i in 0..MAX_CHILD { let pid = fork(); diff --git a/user/src/bin/forktest2.rs b/user/src/bin/forktest2.rs index c91ce15..ee452cc 100644 --- a/user/src/bin/forktest2.rs +++ b/user/src/bin/forktest2.rs @@ -8,7 +8,7 @@ use user_lib::{exit, fork, get_time, getpid, sleep, wait}; static NUM: usize = 30; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { for _ in 0..NUM { let pid = fork(); diff --git a/user/src/bin/forktest_simple.rs b/user/src/bin/forktest_simple.rs index 29a624b..b9cf587 100644 --- a/user/src/bin/forktest_simple.rs +++ b/user/src/bin/forktest_simple.rs @@ -6,7 +6,7 @@ extern crate user_lib; use user_lib::{fork, getpid, wait}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { assert_eq!(wait(&mut 0i32), -1); println!("sys_wait without child process test passed!"); diff --git a/user/src/bin/forktree.rs b/user/src/bin/forktree.rs index bfcfc4c..bcca4e6 100644 --- a/user/src/bin/forktree.rs +++ b/user/src/bin/forktree.rs @@ -29,7 +29,7 @@ fn fork_tree(cur: &str) { fork_child(cur, '1'); } -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { fork_tree(""); sleep(3000); diff --git a/user/src/bin/hello_world.rs b/user/src/bin/hello_world.rs index 10d3f26..cc651e7 100644 --- a/user/src/bin/hello_world.rs +++ b/user/src/bin/hello_world.rs @@ -4,7 +4,7 @@ #[macro_use] extern crate user_lib; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { println!("Hello world from user mode program!"); 0 diff --git a/user/src/bin/huge_write.rs b/user/src/bin/huge_write.rs index e93f8b8..9327261 100644 --- a/user/src/bin/huge_write.rs +++ b/user/src/bin/huge_write.rs @@ -4,9 +4,9 @@ #[macro_use] extern crate user_lib; -use user_lib::{close, get_time, open, write, OpenFlags}; +use user_lib::{OpenFlags, close, get_time, open, write}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { let mut buffer = [0u8; 1024]; // 1KiB for (i, ch) in buffer.iter_mut().enumerate() { diff --git a/user/src/bin/initproc.rs b/user/src/bin/initproc.rs index 71bed27..d522b77 100644 --- a/user/src/bin/initproc.rs +++ b/user/src/bin/initproc.rs @@ -6,7 +6,7 @@ extern crate user_lib; use user_lib::{exec, fork, wait, yield_}; -#[no_mangle] +#[unsafe(no_mangle)] fn main() -> i32 { if fork() == 0 { exec("user_shell\0"); diff --git a/user/src/bin/matrix.rs b/user/src/bin/matrix.rs index 9ebf48f..846f4c6 100644 --- a/user/src/bin/matrix.rs +++ b/user/src/bin/matrix.rs @@ -44,7 +44,7 @@ fn work(times: isize) { exit(0); } -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { for _ in 0..NUM { let pid = fork(); diff --git a/user/src/bin/sleep.rs b/user/src/bin/sleep.rs index 641a4f9..e02b3ed 100644 --- a/user/src/bin/sleep.rs +++ b/user/src/bin/sleep.rs @@ -15,7 +15,7 @@ fn sleepy() { exit(0); } -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { let current_time = get_time(); let pid = fork(); diff --git a/user/src/bin/sleep_simple.rs b/user/src/bin/sleep_simple.rs index 7015a3d..9f6e2e4 100644 --- a/user/src/bin/sleep_simple.rs +++ b/user/src/bin/sleep_simple.rs @@ -6,7 +6,7 @@ extern crate user_lib; use user_lib::{get_time, sleep}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { println!("into sleep test!"); let start = get_time(); diff --git a/user/src/bin/stack_overflow.rs b/user/src/bin/stack_overflow.rs index 3bec557..731982a 100644 --- a/user/src/bin/stack_overflow.rs +++ b/user/src/bin/stack_overflow.rs @@ -12,7 +12,7 @@ fn f(depth: usize) { f(depth + 1); } -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { println!("It should trigger segmentation fault!"); f(0); diff --git a/user/src/bin/user_shell.rs b/user/src/bin/user_shell.rs index cdcb972..1ca120b 100644 --- a/user/src/bin/user_shell.rs +++ b/user/src/bin/user_shell.rs @@ -16,7 +16,7 @@ use alloc::string::String; use user_lib::console::getchar; use user_lib::{exec, fork, waitpid}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { println!("Rust user shell"); let mut line: String = String::new(); diff --git a/user/src/bin/usertests.rs b/user/src/bin/usertests.rs index 20cbbe9..d47dc20 100644 --- a/user/src/bin/usertests.rs +++ b/user/src/bin/usertests.rs @@ -84,7 +84,7 @@ fn run_tests(tests: &[(&str, &str, &str, &str, i32)]) -> i32 { pass_num } -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { let succ_num = run_tests(SUCC_TESTS); let err_num = run_tests(FAIL_TESTS); diff --git a/user/src/bin/usertests_simple.rs b/user/src/bin/usertests_simple.rs index 62bc838..0a73edd 100644 --- a/user/src/bin/usertests_simple.rs +++ b/user/src/bin/usertests_simple.rs @@ -20,7 +20,7 @@ static TESTS: &[&str] = &[ use user_lib::{exec, fork, waitpid}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { for test in TESTS { println!("Usertests: Running {}", test); diff --git a/user/src/bin/yield.rs b/user/src/bin/yield.rs index 78b1468..b9558ef 100644 --- a/user/src/bin/yield.rs +++ b/user/src/bin/yield.rs @@ -5,7 +5,7 @@ extern crate user_lib; use user_lib::{getpid, yield_}; -#[no_mangle] +#[unsafe(no_mangle)] pub fn main() -> i32 { println!("Hello, I am process {}.", getpid()); for i in 0..5 { diff --git a/user/src/lang_items.rs b/user/src/lang_items.rs index c65aa42..b03e8eb 100644 --- a/user/src/lang_items.rs +++ b/user/src/lang_items.rs @@ -2,7 +2,7 @@ use super::exit; #[panic_handler] fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! { - let err = panic_info.message().unwrap(); + let err = panic_info.message(); if let Some(location) = panic_info.location() { println!( "Panicked at {}:{}, {}", diff --git a/user/src/lib.rs b/user/src/lib.rs index c3b2cb9..a5584c2 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -1,6 +1,5 @@ #![no_std] #![feature(linkage)] -#![feature(panic_info_message)] #![feature(alloc_error_handler)] #[macro_use] @@ -13,6 +12,7 @@ extern crate alloc; extern crate bitflags; use buddy_system_allocator::LockedHeap; +use core::ptr::addr_of_mut; use syscall::*; const USER_HEAP_SIZE: usize = 32768; @@ -27,18 +27,18 @@ pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! { panic!("Heap allocation error, layout = {:?}", layout); } -#[no_mangle] -#[link_section = ".text.entry"] +#[unsafe(no_mangle)] +#[unsafe(link_section = ".text.entry")] pub extern "C" fn _start() -> ! { unsafe { HEAP.lock() - .init(HEAP_SPACE.as_ptr() as usize, USER_HEAP_SIZE); + .init(addr_of_mut!(HEAP_SPACE) as usize, USER_HEAP_SIZE); } exit(main()); } #[linkage = "weak"] -#[no_mangle] +#[unsafe(no_mangle)] fn main() -> i32 { panic!("Cannot find main!"); } From f9fc2a538cf95b4406549b3682652d6d91be70f0 Mon Sep 17 00:00:00 2001 From: Luv-Ray Date: Tue, 11 Mar 2025 17:14:57 +0800 Subject: [PATCH 05/10] fix alignment -------- Cherry-picked from #158. --- easy-fs/src/block_cache.rs | 54 +++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/easy-fs/src/block_cache.rs b/easy-fs/src/block_cache.rs index c9bfa26..67a3b89 100644 --- a/easy-fs/src/block_cache.rs +++ b/easy-fs/src/block_cache.rs @@ -1,12 +1,40 @@ use super::{BlockDevice, BLOCK_SZ}; use alloc::collections::VecDeque; use alloc::sync::Arc; +use alloc::vec; +use alloc::vec::Vec; +use core::ptr::{addr_of, addr_of_mut}; +use core::slice; use lazy_static::*; use spin::Mutex; + +/// use `Vec` to ensure the alignment of addr is `8` +struct CacheData(Vec); + +impl CacheData { + fn new() -> Self { + Self(vec![0u64; BLOCK_SZ / 8]) + } +} + +impl AsRef<[u8]> for CacheData { + fn as_ref(&self) -> &[u8] { + let ptr = self.0.as_ptr() as *const u8; + unsafe { slice::from_raw_parts(ptr, BLOCK_SZ) } + } +} + +impl AsMut<[u8]> for CacheData { + fn as_mut(&mut self) -> &mut [u8] { + let ptr = self.0.as_mut_ptr() as *mut u8; + unsafe { slice::from_raw_parts_mut(ptr, BLOCK_SZ) } + } +} + /// Cached block inside memory pub struct BlockCache { /// cached block data - cache: [u8; BLOCK_SZ], + cache: CacheData, /// underlying block id block_id: usize, /// underlying block device @@ -18,8 +46,9 @@ pub struct BlockCache { impl BlockCache { /// Load a new BlockCache from disk. pub fn new(block_id: usize, block_device: Arc) -> Self { - let mut cache = [0u8; BLOCK_SZ]; - block_device.read_block(block_id, &mut cache); + // for alignment and move effciency + let mut cache = CacheData::new(); + block_device.read_block(block_id, cache.as_mut()); Self { cache, block_id, @@ -28,8 +57,12 @@ impl BlockCache { } } /// Get the address of an offset inside the cached block data - fn addr_of_offset(&self, offset: usize) -> usize { - &self.cache[offset] as *const _ as usize + fn addr_of_offset(&self, offset: usize) -> *const u8 { + addr_of!(self.cache.as_ref()[offset]) + } + + fn addr_of_offset_mut(&mut self, offset: usize) -> *mut u8 { + addr_of_mut!(self.cache.as_mut()[offset]) } pub fn get_ref(&self, offset: usize) -> &T @@ -38,8 +71,8 @@ impl BlockCache { { let type_size = core::mem::size_of::(); assert!(offset + type_size <= BLOCK_SZ); - let addr = self.addr_of_offset(offset); - unsafe { &*(addr as *const T) } + let addr = self.addr_of_offset(offset) as *const T; + unsafe { &*addr } } pub fn get_mut(&mut self, offset: usize) -> &mut T @@ -49,8 +82,8 @@ impl BlockCache { let type_size = core::mem::size_of::(); assert!(offset + type_size <= BLOCK_SZ); self.modified = true; - let addr = self.addr_of_offset(offset); - unsafe { &mut *(addr as *mut T) } + let addr = self.addr_of_offset_mut(offset) as *mut T; + unsafe { &mut *addr } } pub fn read(&self, offset: usize, f: impl FnOnce(&T) -> V) -> V { @@ -64,7 +97,8 @@ impl BlockCache { pub fn sync(&mut self) { if self.modified { self.modified = false; - self.block_device.write_block(self.block_id, &self.cache); + self.block_device + .write_block(self.block_id, self.cache.as_ref()); } } } From 1f2b9a2fafedb8c0c144a49fa21314bad1f25308 Mon Sep 17 00:00:00 2001 From: Luv-Ray Date: Fri, 14 Mar 2025 10:08:55 +0800 Subject: [PATCH 06/10] alignment 512 -------- Cherry-picked from #158. --- easy-fs/src/block_cache.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/easy-fs/src/block_cache.rs b/easy-fs/src/block_cache.rs index 67a3b89..786f9e0 100644 --- a/easy-fs/src/block_cache.rs +++ b/easy-fs/src/block_cache.rs @@ -1,19 +1,35 @@ use super::{BlockDevice, BLOCK_SZ}; +use alloc::boxed::Box; use alloc::collections::VecDeque; use alloc::sync::Arc; -use alloc::vec; -use alloc::vec::Vec; +use core::alloc::Layout; +use core::mem::ManuallyDrop; use core::ptr::{addr_of, addr_of_mut}; use core::slice; use lazy_static::*; use spin::Mutex; -/// use `Vec` to ensure the alignment of addr is `8` -struct CacheData(Vec); +/// Use `ManuallyDrop` to ensure data is deallocated with an alignment of `BLOCK_SZ` +struct CacheData(ManuallyDrop>); impl CacheData { - fn new() -> Self { - Self(vec![0u64; BLOCK_SZ / 8]) + pub fn new() -> Self { + let data = unsafe { + let raw = alloc::alloc::alloc(Self::layout()); + Box::from_raw(raw as *mut [u8; BLOCK_SZ]) + }; + Self(ManuallyDrop::new(data)) + } + + fn layout() -> Layout { + Layout::from_size_align(BLOCK_SZ, BLOCK_SZ).unwrap() + } +} + +impl Drop for CacheData { + fn drop(&mut self) { + let ptr = self.0.as_mut_ptr(); + unsafe { alloc::alloc::dealloc(ptr, Self::layout()) }; } } From 493e373bcd4490bea8a0a62b9f825b11a6c91f54 Mon Sep 17 00:00:00 2001 From: lxc Date: Sat, 29 Mar 2025 13:21:55 +0800 Subject: [PATCH 07/10] Update efs.rs -------- Cherry-picked from #160. --- easy-fs/src/efs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easy-fs/src/efs.rs b/easy-fs/src/efs.rs index 202b9eb..e28f6b2 100644 --- a/easy-fs/src/efs.rs +++ b/easy-fs/src/efs.rs @@ -36,7 +36,7 @@ impl EasyFileSystem { let data_bitmap_blocks = (data_total_blocks + 4096) / 4097; let data_area_blocks = data_total_blocks - data_bitmap_blocks; let data_bitmap = Bitmap::new( - (1 + inode_bitmap_blocks + inode_area_blocks) as usize, + (1 + inode_total_blocks) as usize, data_bitmap_blocks as usize, ); let mut efs = Self { From cec2f1589668179c2583aa4254521821f1cf199c Mon Sep 17 00:00:00 2001 From: saying Date: Fri, 25 Apr 2025 21:14:51 +0800 Subject: [PATCH 08/10] fix(scripts): get correct major version --- os/scripts/qemu-ver-check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 os/scripts/qemu-ver-check.sh diff --git a/os/scripts/qemu-ver-check.sh b/os/scripts/qemu-ver-check.sh old mode 100644 new mode 100755 index 8c20456..40ef766 --- a/os/scripts/qemu-ver-check.sh +++ b/os/scripts/qemu-ver-check.sh @@ -13,7 +13,7 @@ then exit 1 else QEMU_VERSION=$($1 --version|head -n 1|awk '{print $4}') - MAJOR_VERSION=$(echo $QEMU_VERSION|cut -c1-1) + MAJOR_VERSION=$(echo $QEMU_VERSION | awk -F '.' '{print $1}') if [ $MAJOR_VERSION -lt $MINIMUM_MAJOR_VERSION ] then echo "${RED}Error: Required major version of QEMU is ${MINIMUM_MAJOR_VERSION}, " \ From b7612e38d7f2713f28ce9b81d36f01d21b337a44 Mon Sep 17 00:00:00 2001 From: Tateisi Date: Wed, 13 Aug 2025 14:46:46 +0800 Subject: [PATCH 09/10] FS init --- os/src/syscall/fs.rs | 8 ++++++++ os/src/task/task.rs | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index ff68ee9..8d46fad 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -47,6 +47,13 @@ pub fn sys_open(path: *const u8, flags: u32) -> isize { let task = current_task().unwrap(); let token = current_user_token(); let path = translated_str(token, path); + + // 简单用户检查示例:非 root 用户不能打开 /root 下文件 + let username = task.inner_exclusive_access().user.clone(); + if path.starts_with("/root") && username != "root" { + return -1; // Permission denied + } + if let Some(inode) = open_file(path.as_str(), OpenFlags::from_bits(flags).unwrap()) { let mut inner = task.inner_exclusive_access(); let fd = inner.alloc_fd(); @@ -57,6 +64,7 @@ pub fn sys_open(path: *const u8, flags: u32) -> isize { } } + pub fn sys_close(fd: usize) -> isize { let task = current_task().unwrap(); let mut inner = task.inner_exclusive_access(); diff --git a/os/src/task/task.rs b/os/src/task/task.rs index 7b02cd6..87d287a 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -30,6 +30,9 @@ pub struct TaskControlBlockInner { pub children: Vec>, pub exit_code: i32, pub fd_table: Vec>>, + + // New: User + pub user: String, } impl TaskControlBlockInner { @@ -166,6 +169,7 @@ impl TaskControlBlock { children: Vec::new(), exit_code: 0, fd_table: new_fd_table, + user: username.to_string(), // Init User name }) }, }); From 3a57c25f668d9bfbf721b11d2ef08647e2fcc585 Mon Sep 17 00:00:00 2001 From: Tateisi Date: Wed, 13 Aug 2025 15:01:59 +0800 Subject: [PATCH 10/10] add easyfs fuse mac test --- easy-fs-fuse/src/main.rs | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/easy-fs-fuse/src/main.rs b/easy-fs-fuse/src/main.rs index 09016c3..39b9eaf 100644 --- a/easy-fs-fuse/src/main.rs +++ b/easy-fs-fuse/src/main.rs @@ -149,3 +149,59 @@ fn efs_test() -> std::io::Result<()> { Ok(()) } + +#[test] +fn mac_test() -> std::io::Result<()> { + const BLOCK_SZ: usize = 512; + + let block_file = Arc::new(BlockFile(Mutex::new({ + let f = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open("target/fs_mac.img")?; + f.set_len(8192 * BLOCK_SZ).unwrap(); + f + }))); + + EasyFileSystem::create(block_file.clone(), 4096, 1); + let efs = EasyFileSystem::open(block_file.clone()); + let root_inode = EasyFileSystem::root_inode(&efs); + + root_inode.create("root_file"); + root_inode.create("public_file"); + + let secret_inode = root_inode.find("root_file").unwrap(); + secret_inode.write_at(0, b"TOP SECRET: root only!"); + let public_inode = root_inode.find("public_file").unwrap(); + public_inode.write_at(0, b"This file is public."); + + let check_permission = |user: &str, filename: &str| -> bool { + if filename == "root_file" && user != "root" { + false + } else { + true + } + }; + + let users = ["root", "nonroot"]; + for user in users.iter() { + println!("{} task:", user); + + for filename in ["root_file", "public_file"].iter() { + if check_permission(user, filename) { + let inode = root_inode.find(filename).unwrap(); + let mut buf = [0u8; 128]; + let len = inode.read_at(0, &mut buf); + let content = core::str::from_utf8(&buf[..len]).unwrap(); + println!("{}: Opened successfully"); + } else { + println!("{}: Permission denied"); + } + } + + println!(); + } + + Ok(()) +}