From 34b27c85a008825f67096f39cab3013f1adf1434 Mon Sep 17 00:00:00 2001 From: Niracha Janavatara Date: Sun, 4 Oct 2026 04:12:56 +0700 Subject: [PATCH 1/3] console: fix the sub-second field of log timestamps ConsoleLogger printed `uptime.as_micros()` (total microseconds since boot) as the fractional part, so after the first second the timestamps are wrong, e.g. "[ 4.4015238]" instead of "[ 4.401523]". Use `subsec_micros()`, matching Linux's printk format. --- src/console/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/console/mod.rs b/src/console/mod.rs index 42d22f97..df7a842f 100644 --- a/src/console/mod.rs +++ b/src/console/mod.rs @@ -91,7 +91,7 @@ impl Log for ConsoleLogger { let _ = write_fmt(format_args!( "[{:5}.{:06}] {}: {}\r\n", uptime.as_secs(), - uptime.as_micros(), + uptime.subsec_micros(), record .module_path() .map(|x| x.strip_prefix("moss::").unwrap_or(x)) From 5cd8f419d525c29c3ebf1fbbfa2f3bb7af280568 Mon Sep 17 00:00:00 2001 From: Niracha Janavatara Date: Sun, 4 Oct 2026 04:12:56 +0700 Subject: [PATCH 2/3] fs: reg: honour O_APPEND OpenFlags::O_APPEND was defined but never checked, so every write went to the current file position. As a result, shell `>>` overwrote files instead of appending to them: / # echo a > /tmp/t; echo b >> /tmp/t; cat /tmp/t b RegFile::write now moves the cursor to the end of the file before each write when the file was opened with O_APPEND. writev goes through write, so it is covered too; pwrite keeps its explicit offset. Add a usertest that also checks that a seek before the write doesn't stop the append. --- src/fs/reg.rs | 13 ++++++++++++- usertest/src/fs.rs | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/fs/reg.rs b/src/fs/reg.rs index 71860af7..bc9ed141 100644 --- a/src/fs/reg.rs +++ b/src/fs/reg.rs @@ -12,7 +12,7 @@ use async_trait::async_trait; use core::{cmp::min, pin::Pin}; use libkernel::{ error::Result, - fs::{Inode, SeekFrom}, + fs::{Inode, OpenFlags, SeekFrom}, memory::{PAGE_SIZE, address::UA}, }; @@ -63,6 +63,17 @@ impl FileOps for RegFile { Ok(total_bytes_read) } + /// Writes at the cursor, or at the end of the file if it was opened with + /// `O_APPEND`, and advances the cursor past the data written. + async fn write(&mut self, ctx: &mut FileCtx, buf: UA, count: usize) -> Result { + if ctx.flags.contains(OpenFlags::O_APPEND) { + ctx.pos = self.inode.getattr().await?.size; + } + let bytes_written = self.writeat(buf, count, ctx.pos).await?; + ctx.pos += bytes_written as u64; + Ok(bytes_written) + } + /// Writes data from `buf` to the current file position. /// The file's cursor is advanced by the number of bytes written. async fn writeat(&mut self, mut buf: UA, mut count: usize, mut offset: u64) -> Result { diff --git a/usertest/src/fs.rs b/usertest/src/fs.rs index a3f62543..83c73609 100644 --- a/usertest/src/fs.rs +++ b/usertest/src/fs.rs @@ -612,3 +612,18 @@ fn test_rust_dir() { } register_test!(test_rust_dir); + +fn test_o_append() { + use std::io::{Seek, SeekFrom, Write}; + let path = "/tmp/o_append_test"; + fs::write(path, "first\n").unwrap(); + let mut file = fs::OpenOptions::new().append(true).open(path).unwrap(); + file.write_all(b"second\n").unwrap(); + // O_APPEND writes always go to the end, even after seeking elsewhere. + file.seek(SeekFrom::Start(0)).unwrap(); + file.write_all(b"third\n").unwrap(); + assert_eq!(fs::read_to_string(path).unwrap(), "first\nsecond\nthird\n"); + fs::remove_file(path).unwrap(); +} + +register_test!(test_o_append); From 9a175b3dcf792fc421f60240440073168d5c37a0 Mon Sep 17 00:00:00 2001 From: Niracha Janavatara Date: Sun, 4 Oct 2026 04:13:09 +0700 Subject: [PATCH 3/3] fs: getcwd: return ERANGE when the buffer is too small sys_getcwd returned KernelError::TooLarge when the cwd didn't fit in the user's buffer. TooLarge has no errno mapping, so kern_err_to_syscall() reached its `todo!()` and panicked the kernel. Any process could trigger this with getcwd(buf, 1). Return RangeError (ERANGE), which is what Linux returns in this case, and add a usertest. --- src/fs/syscalls/chdir.rs | 2 +- usertest/src/fs.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/fs/syscalls/chdir.rs b/src/fs/syscalls/chdir.rs index b116da5a..71bc3968 100644 --- a/src/fs/syscalls/chdir.rs +++ b/src/fs/syscalls/chdir.rs @@ -20,7 +20,7 @@ pub async fn sys_getcwd(ctx: &ProcessCtx, buf: UA, len: usize) -> Result let slice = cstr.as_bytes_with_nul(); if slice.len() > len { - return Err(KernelError::TooLarge); + return Err(KernelError::RangeError); } copy_to_user_slice(slice, buf).await?; diff --git a/usertest/src/fs.rs b/usertest/src/fs.rs index 83c73609..38969d42 100644 --- a/usertest/src/fs.rs +++ b/usertest/src/fs.rs @@ -627,3 +627,15 @@ fn test_o_append() { } register_test!(test_o_append); + +fn test_getcwd_buffer_too_small() { + let mut buf = [0 as libc::c_char; 1]; + let ret = unsafe { libc::getcwd(buf.as_mut_ptr(), buf.len()) }; + assert!(ret.is_null()); + assert_eq!( + std::io::Error::last_os_error().raw_os_error(), + Some(libc::ERANGE) + ); +} + +register_test!(test_getcwd_buffer_too_small);