From 3886749b1c8d79d4701bf6b8e66249c4e1491648 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Sun, 4 Jan 2026 18:06:31 +0800 Subject: dev(shell): implement basic shell tools fixed(file-system): fixed read and write bugs --- src/fs/fat32.cc | 32 +++++++++++++++++++++++--------- src/fs/file.cc | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 9 deletions(-) (limited to 'src/fs') diff --git a/src/fs/fat32.cc b/src/fs/fat32.cc index 5c70f5a..17b543c 100644 --- a/src/fs/fat32.cc +++ b/src/fs/fat32.cc @@ -141,8 +141,6 @@ uint32 FAT32FileSystem::next_cluster(uint32 cluster) uint32 ent_offset = fat_offset % 512; // block = sector / 2 - // offset in block = (sector % 2) * 512 + ent_offset - struct Buf *b = BufferCache::bread(0, fat_sector / 2); uint32 block_offset = (fat_sector % 2) * 512 + ent_offset; @@ -177,6 +175,20 @@ int FAT32Inode::read(char *dst, uint32 off, uint32 n, int isUser) if (first_clus == 0) return 0; + // [FIX] 只有非目录文件才检查 size 边界 + // 目录文件 size 可能为 0,应允许读取直到簇链结束 + if (type != T_DIR) + { + if (off >= size) + { + return 0; + } + if (off + n > size) + { + n = size - off; + } + } + uint32 tot = 0; uint32 clus = first_clus; uint32 clus_sz = fs->bytes_per_cluster; @@ -303,7 +315,7 @@ uint32 FAT32FileSystem::alloc_cluster() uint32 current_fat_sec = fat_start_sector + i; struct Buf *b = BufferCache::bread(0, current_fat_sec / 2); uint32 *table = (uint32 *)(b->data + (current_fat_sec % 2) * 512); - for(uint32 j = 0; j < fat_entries_per_sector; j++) + for (uint32 j = 0; j < fat_entries_per_sector; j++) { if (i == 0 && j < 2) continue; @@ -359,7 +371,6 @@ void FAT32FileSystem::free_cluster_chain(uint32 cluster) cluster = next; } - } void FAT32Inode::update() @@ -654,7 +665,9 @@ int FAT32Inode::unlink(const char *name) uint32_t clus = first_clus; bool found = false; - struct Buf *target_buf = nullptr; + + // [FIX] Deadlock prevention: Do not hold buffer while looking up inode + uint32_t target_block = 0; uint32_t target_offset = 0; struct FAT32_DirEnt de; @@ -681,16 +694,16 @@ int FAT32Inode::unlink(const char *name) if (match_name(de.name, name)) { - target_buf = b; + target_block = (sec + i) / 2; target_offset = ((sec + i) % 2) * 512 + off; found = true; break; } } + BufferCache::brelse(b); // Always release buffer if (found) break; - BufferCache::brelse(b); } if (found) @@ -701,7 +714,7 @@ int FAT32Inode::unlink(const char *name) return -1; } - if (found && target_buf) + if (found) { Inode *target_ip = lookup(name); if (target_ip) @@ -710,7 +723,6 @@ int FAT32Inode::unlink(const char *name) if (target_ip->type == T_DIR) { VFS::iunlockput(target_ip); - BufferCache::brelse(target_buf); return -1; } @@ -719,6 +731,8 @@ int FAT32Inode::unlink(const char *name) VFS::iunlockput(target_ip); } + // Re-read buffer to mark deletion + struct Buf *target_buf = BufferCache::bread(dev, target_block); uint8_t *ptr = (uint8_t *)target_buf->data + target_offset; *ptr = 0xE5; diff --git a/src/fs/file.cc b/src/fs/file.cc index 623b535..9f12dc1 100644 --- a/src/fs/file.cc +++ b/src/fs/file.cc @@ -217,6 +217,16 @@ namespace FileTable if (f->type == FD_INODE) { VFS::ilock(f->ip); + + if (f->ip->type == T_DEVICE) + { + if (f->ip->major == 1) + { + VFS::iunlock(f->ip); + return Drivers::console_read(addr, n); + } + } + int r = f->ip->read((char*)addr, f->off, n, 1); if(r > 0) { @@ -240,6 +250,37 @@ namespace FileTable if (f->type == FD_INODE) { VFS::ilock(f->ip); + + if (f->ip->type == T_DEVICE) + { + if (f->ip->major == 1) // Console + { + VFS::iunlock(f->ip); + struct Proc *proc = myproc(); + constexpr int MAX_WRITE_BUF = 128; + char buf[MAX_WRITE_BUF]; + int i = 0; + while (i < n) + { + int len = n - i; + if (len > MAX_WRITE_BUF) + len = MAX_WRITE_BUF; + + if (VM::copyin(proc->pagetable, buf, addr + i, static_cast(len)) < 0) + { + return -1; + } + + for (int j = 0; j < len; j++) + { + Drivers::uart_putc(buf[j]); + } + i += len; + } + return n; + } + } + int r = f->ip->write((char *)addr, f->off, n, 1); if (r > 0) { -- cgit v1.2.3