mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 20:36:31 +00:00
移植sqlite3,并修复一些bug (#323)
* bugfix: 程序加载器映射内存时,计算要映射的大小不正确的问题。 * 修正brk系统调用不符合规范的地方 * bugfix: 修正fat文件系统未能正确的扩展文件大小的bug * 增加fcntl系统调用 * 移植sqlite3
This commit is contained in:
@ -1,11 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
use core::cmp::min;
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{cmp::min, intrinsics::unlikely};
|
||||
|
||||
use crate::{
|
||||
io::{device::LBA_SIZE, SeekFrom},
|
||||
@ -13,6 +7,11 @@ use crate::{
|
||||
libs::vec_cursor::VecCursor,
|
||||
syscall::SystemError,
|
||||
};
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use super::{
|
||||
fs::{Cluster, FATFileSystem, MAX_FILE_SIZE},
|
||||
@ -166,7 +165,6 @@ impl FATFile {
|
||||
|
||||
// 要写入的第一个簇的簇号
|
||||
let start_cluster_num = offset / fs.bytes_per_cluster();
|
||||
|
||||
// 获取要写入的第一个簇
|
||||
let mut current_cluster: Cluster = if let Some(c) =
|
||||
fs.get_cluster_by_relative(self.first_cluster, start_cluster_num as usize)
|
||||
@ -239,22 +237,26 @@ impl FATFile {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// 计算文件的最后一个簇中有多少空闲空间
|
||||
let in_cluster_offset = self.size() % fs.bytes_per_cluster();
|
||||
let mut bytes_remain_in_cluster = if in_cluster_offset == 0 {
|
||||
0
|
||||
} else {
|
||||
fs.bytes_per_cluster() - in_cluster_offset
|
||||
};
|
||||
|
||||
// 计算还需要申请多少空间
|
||||
let extra_bytes = min((offset + len) - self.size(), MAX_FILE_SIZE - self.size());
|
||||
|
||||
// 如果文件大小为0,证明它还没有分配簇,因此分配一个簇给它
|
||||
if self.size() == 0 {
|
||||
// first_cluster应当为0,否则将产生空间泄露的错误
|
||||
assert_eq!(self.first_cluster, Cluster::default());
|
||||
self.first_cluster = fs.allocate_cluster(None)?;
|
||||
self.short_dir_entry.set_first_cluster(self.first_cluster);
|
||||
bytes_remain_in_cluster = fs.bytes_per_cluster();
|
||||
}
|
||||
|
||||
// 计算文件的最后一个簇中有多少空闲空间
|
||||
|
||||
let in_cluster_offset = self.size() % fs.bytes_per_cluster();
|
||||
let bytes_remain_in_cluster = fs.bytes_per_cluster() - in_cluster_offset;
|
||||
|
||||
// 计算还需要申请多少空间
|
||||
let extra_bytes = min((offset + len) - self.size(), MAX_FILE_SIZE - self.size());
|
||||
|
||||
// 如果还需要更多的簇
|
||||
if bytes_remain_in_cluster < extra_bytes {
|
||||
let clusters_to_allocate =
|
||||
@ -343,17 +345,24 @@ impl FATFile {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let new_last_cluster = new_size / fs.bytes_per_cluster();
|
||||
let new_last_cluster = (new_size + fs.bytes_per_cluster() - 1) / fs.bytes_per_cluster();
|
||||
if let Some(begin_delete) =
|
||||
fs.get_cluster_by_relative(self.first_cluster, (new_last_cluster + 1) as usize)
|
||||
fs.get_cluster_by_relative(self.first_cluster, new_last_cluster as usize)
|
||||
{
|
||||
fs.deallocate_cluster(begin_delete)?;
|
||||
fs.deallocate_cluster_chain(begin_delete)?;
|
||||
};
|
||||
|
||||
if new_size == 0 {
|
||||
assert!(new_last_cluster == 0);
|
||||
self.short_dir_entry.set_first_cluster(Cluster::new(0));
|
||||
self.first_cluster = Cluster::new(0);
|
||||
}
|
||||
|
||||
self.set_size(new_size as u32);
|
||||
// 计算短目录项在磁盘内的字节偏移量
|
||||
let short_entry_offset = fs.cluster_bytes_offset((self.loc.1).0) + (self.loc.1).1;
|
||||
self.short_dir_entry.flush(fs, short_entry_offset)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -1406,6 +1415,10 @@ impl FATDirIter {
|
||||
/// @return Err(错误码) 可能出现了内部错误,或者是磁盘错误等。具体原因看错误码。
|
||||
fn get_dir_entry(&mut self) -> Result<(Cluster, u64, Option<FATDirEntry>), SystemError> {
|
||||
loop {
|
||||
if unlikely(self.current_cluster.cluster_num < 2) {
|
||||
return Ok((self.current_cluster, self.offset, None));
|
||||
}
|
||||
|
||||
// 如果当前簇已经被读完,那么尝试获取下一个簇
|
||||
if self.offset >= self.fs.bytes_per_cluster() && !self.is_root {
|
||||
match self.fs.get_fat_entry(self.current_cluster)? {
|
||||
|
@ -350,6 +350,10 @@ impl FATFileSystem {
|
||||
/// @return Err(SystemError) 错误码
|
||||
pub fn get_fat_entry(&self, cluster: Cluster) -> Result<FATEntry, SystemError> {
|
||||
let current_cluster = cluster.cluster_num;
|
||||
if current_cluster < 2 {
|
||||
// 0号簇和1号簇是保留簇,不允许用户使用
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let fat_type: FATType = self.bpb.fat_type;
|
||||
// 获取FAT表的起始扇区(相对分区起始扇区的偏移量)
|
||||
@ -1460,6 +1464,44 @@ impl IndexNode for LockedFATInode {
|
||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
||||
return Ok(self.0.lock().metadata.clone());
|
||||
}
|
||||
fn resize(&self, len: usize) -> Result<(), SystemError> {
|
||||
let mut guard: SpinLockGuard<FATInode> = self.0.lock();
|
||||
let fs: &Arc<FATFileSystem> = &guard.fs.upgrade().unwrap();
|
||||
let old_size = guard.metadata.size as usize;
|
||||
|
||||
match &mut guard.inode_type {
|
||||
FATDirEntry::File(file) | FATDirEntry::VolId(file) => {
|
||||
// 如果新的长度和旧的长度相同,那么就直接返回
|
||||
if len == old_size {
|
||||
return Ok(());
|
||||
} else if len > old_size {
|
||||
// 如果新的长度比旧的长度大,那么就在文件末尾添加空白
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
let mut remain_size = len - old_size;
|
||||
let buf_size = remain_size;
|
||||
// let buf_size = core::cmp::min(remain_size, 512 * 1024);
|
||||
buf.resize(buf_size, 0);
|
||||
|
||||
let mut offset = old_size;
|
||||
while remain_size > 0 {
|
||||
let write_size = core::cmp::min(remain_size, buf_size);
|
||||
file.write(fs, &buf[0..write_size], offset as u64)?;
|
||||
remain_size -= write_size;
|
||||
offset += write_size;
|
||||
}
|
||||
} else {
|
||||
file.truncate(fs, len as u64)?;
|
||||
}
|
||||
guard.update_metadata();
|
||||
return Ok(());
|
||||
}
|
||||
FATDirEntry::Dir(_) => return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP),
|
||||
FATDirEntry::UnInit => {
|
||||
kerror!("FATFS: param: Inode_type uninitialized.");
|
||||
return Err(SystemError::EROFS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn list(&self) -> Result<Vec<String>, SystemError> {
|
||||
let mut guard: SpinLockGuard<FATInode> = self.0.lock();
|
||||
|
62
kernel/src/filesystem/vfs/fcntl.rs
Normal file
62
kernel/src/filesystem/vfs/fcntl.rs
Normal file
@ -0,0 +1,62 @@
|
||||
const F_LINUX_SPECIFIC_BASE: u32 = 1024;
|
||||
|
||||
/// fcntl syscall command
|
||||
///
|
||||
/// for linux-specific fcntl commands, see:
|
||||
/// https://opengrok.ringotek.cn/xref/linux-5.19.10/tools/include/uapi/linux/fcntl.h#8
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
||||
#[repr(u32)]
|
||||
pub enum FcntlCommand {
|
||||
/// dup
|
||||
DupFd = 0,
|
||||
/// get close-on-exec
|
||||
GetFd = 1,
|
||||
/// set/clear close-on-exec
|
||||
SetFd = 2,
|
||||
/// get file flags
|
||||
GetFlags = 3,
|
||||
/// set file flags
|
||||
SetFlags = 4,
|
||||
/// get record locking info
|
||||
GetLock = 5,
|
||||
/// set record locking info (non-blocking)
|
||||
SetLock = 6,
|
||||
/// set record locking info (blocking)
|
||||
SetLockWait = 7,
|
||||
|
||||
SetLease = F_LINUX_SPECIFIC_BASE + 0,
|
||||
GetLease = F_LINUX_SPECIFIC_BASE + 1,
|
||||
|
||||
/// Request nofications on a directory.
|
||||
/// See below for events that may be notified.
|
||||
Notify = F_LINUX_SPECIFIC_BASE + 2,
|
||||
|
||||
/// Cancel a blocking posix lock; internal use only until we expose an
|
||||
/// asynchronous lock api to userspace
|
||||
CancelLock = F_LINUX_SPECIFIC_BASE + 5,
|
||||
/// Create a file descriptor with FD_CLOEXEC set.
|
||||
DupFdCloexec = F_LINUX_SPECIFIC_BASE + 6,
|
||||
|
||||
/// Set pipe page size array
|
||||
SetPipeSize = F_LINUX_SPECIFIC_BASE + 7,
|
||||
/// Get pipe page size array
|
||||
GetPipeSize = F_LINUX_SPECIFIC_BASE + 8,
|
||||
|
||||
/// Set seals
|
||||
AddSeals = F_LINUX_SPECIFIC_BASE + 9,
|
||||
/// Get seals
|
||||
GetSeals = F_LINUX_SPECIFIC_BASE + 10,
|
||||
|
||||
/**
|
||||
* Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
|
||||
* underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
|
||||
* the specific file.
|
||||
*/
|
||||
GetRwHint = F_LINUX_SPECIFIC_BASE + 11,
|
||||
SetRwHint = F_LINUX_SPECIFIC_BASE + 12,
|
||||
GetFileRwHint = F_LINUX_SPECIFIC_BASE + 13,
|
||||
SetFileRwHint = F_LINUX_SPECIFIC_BASE + 14,
|
||||
}
|
||||
|
||||
/// for F_[GET|SET]FL
|
||||
pub const FD_CLOEXEC: u32 = 1;
|
@ -132,6 +132,12 @@ impl File {
|
||||
if buf.len() < len {
|
||||
return Err(SystemError::ENOBUFS);
|
||||
}
|
||||
|
||||
// 如果文件指针已经超过了文件大小,则返回0
|
||||
if self.offset > self.inode.metadata()?.size as usize {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let len = self
|
||||
.inode
|
||||
.read_at(self.offset, len, buf, &mut self.private_data)?;
|
||||
@ -152,6 +158,12 @@ impl File {
|
||||
if buf.len() < len {
|
||||
return Err(SystemError::ENOBUFS);
|
||||
}
|
||||
|
||||
// 如果文件指针已经超过了文件大小,则需要扩展文件大小
|
||||
let file_size = self.inode.metadata()?.size as usize;
|
||||
if self.offset > file_size {
|
||||
self.inode.resize(self.offset)?;
|
||||
}
|
||||
let len = self
|
||||
.inode
|
||||
.write_at(self.offset, len, buf, &mut self.private_data)?;
|
||||
@ -197,8 +209,9 @@ impl File {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if pos < 0 || pos > self.metadata()?.size {
|
||||
// 根据linux man page, lseek允许超出文件末尾,并且不改变文件大小
|
||||
// 当pos超出文件末尾时,read返回0。直到开始写入数据时,才会改变文件大小
|
||||
if pos < 0 {
|
||||
return Err(SystemError::EOVERFLOW);
|
||||
}
|
||||
self.offset = pos as usize;
|
||||
@ -301,6 +314,53 @@ impl File {
|
||||
pub fn file_type(&self) -> FileType {
|
||||
return self.file_type;
|
||||
}
|
||||
|
||||
/// @brief 获取文件的打开模式
|
||||
#[inline]
|
||||
pub fn mode(&self) -> FileMode {
|
||||
return self.mode;
|
||||
}
|
||||
|
||||
/// 获取文件是否在execve时关闭
|
||||
#[inline]
|
||||
pub fn close_on_exec(&self) -> bool {
|
||||
return self.mode.contains(FileMode::O_CLOEXEC);
|
||||
}
|
||||
|
||||
/// 设置文件是否在execve时关闭
|
||||
#[inline]
|
||||
pub fn set_close_on_exec(&mut self, close_on_exec: bool) {
|
||||
if close_on_exec {
|
||||
self.mode.insert(FileMode::O_CLOEXEC);
|
||||
} else {
|
||||
self.mode.remove(FileMode::O_CLOEXEC);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_mode(&mut self, mode: FileMode) -> Result<(), SystemError> {
|
||||
// todo: 是否需要调用inode的open方法,以更新private data(假如它与mode有关的话)?
|
||||
// 也许需要加个更好的设计,让inode知晓文件的打开模式发生了变化,让它自己决定是否需要更新private data
|
||||
|
||||
// 直接修改文件的打开模式
|
||||
self.mode = mode;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// @brief 重新设置文件的大小
|
||||
///
|
||||
/// 如果文件大小增加,则文件内容不变,但是文件的空洞部分会被填充为0
|
||||
/// 如果文件大小减小,则文件内容会被截断
|
||||
///
|
||||
/// @return 成功:Ok()
|
||||
/// 失败:Err(错误码)
|
||||
pub fn ftruncate(&mut self, len: usize) -> Result<(), SystemError> {
|
||||
// 如果文件不可写,返回错误
|
||||
self.writeable()?;
|
||||
|
||||
// 调用inode的truncate方法
|
||||
self.inode.resize(len)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for File {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub mod core;
|
||||
pub mod fcntl;
|
||||
pub mod file;
|
||||
pub mod mount;
|
||||
pub mod syscall;
|
||||
@ -161,6 +162,9 @@ pub trait IndexNode: Any + Sync + Send + Debug {
|
||||
}
|
||||
|
||||
/// @brief 重新设置文件的大小
|
||||
///
|
||||
/// 如果文件大小增加,则文件内容不变,但是文件的空洞部分会被填充为0
|
||||
/// 如果文件大小减小,则文件内容会被截断
|
||||
///
|
||||
/// @return 成功:Ok()
|
||||
/// 失败:Err(错误码)
|
||||
|
@ -11,6 +11,7 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
core::{do_mkdir, do_remove_dir, do_unlink_at},
|
||||
fcntl::{FcntlCommand, FD_CLOEXEC},
|
||||
file::{File, FileMode},
|
||||
utils::rsplit_path,
|
||||
Dirent, FileType, IndexNode, ROOT_INODE,
|
||||
@ -29,6 +30,7 @@ impl Syscall {
|
||||
///
|
||||
/// @return 文件描述符编号,或者是错误码
|
||||
pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
|
||||
// kdebug!("open: path: {}, mode: {:?}", path, mode);
|
||||
// 文件名过长
|
||||
if path.len() > PAGE_4K_SIZE as usize {
|
||||
return Err(SystemError::ENAMETOOLONG);
|
||||
@ -82,7 +84,9 @@ impl Syscall {
|
||||
}
|
||||
|
||||
// 把文件对象存入pcb
|
||||
return current_pcb().alloc_fd(file, None).map(|fd| fd as usize);
|
||||
let r = current_pcb().alloc_fd(file, None).map(|fd| fd as usize);
|
||||
// kdebug!("open: fd: {:?}", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/// @brief 关闭文件
|
||||
@ -91,6 +95,7 @@ impl Syscall {
|
||||
///
|
||||
/// @return 成功返回0,失败返回错误码
|
||||
pub fn close(fd: usize) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::close: fd: {}", fd);
|
||||
return current_pcb().drop_fd(fd as i32).map(|_| 0);
|
||||
}
|
||||
|
||||
@ -102,6 +107,7 @@ impl Syscall {
|
||||
/// @return Ok(usize) 成功读取的数据的字节数
|
||||
/// @return Err(SystemError) 读取失败,返回posix错误码
|
||||
pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::read: fd: {}, len={}", fd, buf.len());
|
||||
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||
if file.is_none() {
|
||||
return Err(SystemError::EBADF);
|
||||
@ -119,6 +125,7 @@ impl Syscall {
|
||||
/// @return Ok(usize) 成功写入的数据的字节数
|
||||
/// @return Err(SystemError) 写入失败,返回posix错误码
|
||||
pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::write: fd: {}, len={}", fd, buf.len());
|
||||
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||
if file.is_none() {
|
||||
return Err(SystemError::EBADF);
|
||||
@ -136,6 +143,7 @@ impl Syscall {
|
||||
/// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
|
||||
/// @return Err(SystemError) 调整失败,返回posix错误码
|
||||
pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
|
||||
// kdebug!("syscall::lseek: fd: {}, seek={:?}", fd, seek);
|
||||
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||
if file.is_none() {
|
||||
return Err(SystemError::EBADF);
|
||||
@ -343,6 +351,129 @@ impl Syscall {
|
||||
// 从pcb获取文件描述符数组失败
|
||||
return Err(SystemError::EMFILE);
|
||||
}
|
||||
|
||||
/// # fcntl
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `fd`:文件描述符
|
||||
/// - `cmd`:命令
|
||||
/// - `arg`:参数
|
||||
pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> {
|
||||
match cmd {
|
||||
FcntlCommand::DupFd => {
|
||||
if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
let arg = arg as usize;
|
||||
for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if fds.fds[i as usize].is_none() {
|
||||
return Self::dup2(fd, i as i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EMFILE);
|
||||
}
|
||||
FcntlCommand::GetFd => {
|
||||
// Get file descriptor flags.
|
||||
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &fds.fds[fd as usize] {
|
||||
if file.close_on_exec() {
|
||||
return Ok(FD_CLOEXEC as usize);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
FcntlCommand::SetFd => {
|
||||
// Set file descriptor flags.
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &mut fds.fds[fd as usize] {
|
||||
let arg = arg as u32;
|
||||
if arg & FD_CLOEXEC != 0 {
|
||||
file.set_close_on_exec(true);
|
||||
} else {
|
||||
file.set_close_on_exec(false);
|
||||
}
|
||||
return Ok(0);
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
|
||||
FcntlCommand::GetFlags => {
|
||||
// Get file status flags.
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &fds.fds[fd as usize] {
|
||||
return Ok(file.mode().bits() as usize);
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
FcntlCommand::SetFlags => {
|
||||
// Set file status flags.
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &mut fds.fds[fd as usize] {
|
||||
let arg = arg as u32;
|
||||
let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?;
|
||||
file.set_mode(mode)?;
|
||||
return Ok(0);
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
_ => {
|
||||
// TODO: unimplemented
|
||||
// 未实现的命令,返回0,不报错。
|
||||
|
||||
// kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd);
|
||||
return Ok(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # ftruncate
|
||||
///
|
||||
/// ## 描述
|
||||
///
|
||||
/// 改变文件大小.
|
||||
/// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充.
|
||||
/// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小.
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `fd`:文件描述符
|
||||
/// - `len`:文件大小
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 如果成功,返回0,否则返回错误码.
|
||||
pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> {
|
||||
if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
|
||||
if FileDescriptorVec::validate_fd(fd) {
|
||||
if let Some(file) = &mut fds.fds[fd as usize] {
|
||||
let r = file.ftruncate(len).map(|_| 0);
|
||||
return r;
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -93,7 +93,6 @@ impl ElfLoader {
|
||||
) -> Result<(), ExecError> {
|
||||
let start = self.elf_page_start(start);
|
||||
let end = self.elf_page_align_up(end);
|
||||
// kdebug!("set_elf_brk: start={:?}, end={:?}", start, end);
|
||||
if end > start {
|
||||
let r = user_vm_guard.map_anonymous(
|
||||
start,
|
||||
@ -177,9 +176,7 @@ impl ElfLoader {
|
||||
let beginning_page_offset = self.elf_page_offset(addr_to_map);
|
||||
addr_to_map = self.elf_page_start(addr_to_map);
|
||||
// 计算要映射的内存的大小
|
||||
let map_size = phent.p_filesz as usize
|
||||
+ self.elf_page_offset(VirtAddr::new(phent.p_vaddr as usize))
|
||||
+ beginning_page_offset;
|
||||
let map_size = phent.p_filesz as usize + beginning_page_offset;
|
||||
let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data();
|
||||
// 当前段在文件中的大小
|
||||
let seg_in_file_size = phent.p_filesz as usize;
|
||||
|
@ -72,6 +72,13 @@ impl Syscall {
|
||||
let address_space = AddressSpace::current()?;
|
||||
let mut address_space = address_space.write();
|
||||
|
||||
if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR {
|
||||
return Ok(address_space.brk);
|
||||
}
|
||||
if new_addr == address_space.brk {
|
||||
return Ok(address_space.brk);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
address_space
|
||||
.set_brk(VirtAddr::new(page_align_up(new_addr.data())))
|
||||
|
@ -9,6 +9,7 @@ use crate::{
|
||||
arch::{cpu::cpu_reset, MMArch},
|
||||
filesystem::syscall::PosixKstat,
|
||||
filesystem::vfs::{
|
||||
fcntl::FcntlCommand,
|
||||
file::FileMode,
|
||||
syscall::{SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
|
||||
MAX_PATHLEN,
|
||||
@ -363,9 +364,18 @@ pub const SYS_GETPEERNAME: usize = 42;
|
||||
pub const SYS_GETTIMEOFDAY: usize = 43;
|
||||
pub const SYS_MMAP: usize = 44;
|
||||
pub const SYS_MUNMAP: usize = 45;
|
||||
pub const SYS_MPROTECT: usize = 46;
|
||||
|
||||
pub const SYS_MPROTECT: usize = 46;
|
||||
pub const SYS_FSTAT: usize = 47;
|
||||
#[allow(dead_code)]
|
||||
pub const SYS_GETCWD: usize = 48;
|
||||
#[allow(dead_code)]
|
||||
pub const SYS_GETPPID: usize = 49;
|
||||
#[allow(dead_code)]
|
||||
pub const SYS_GETPGID: usize = 50;
|
||||
|
||||
pub const SYS_FCNTL: usize = 51;
|
||||
pub const SYS_FTRUNCATE: usize = 52;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Syscall;
|
||||
@ -413,7 +423,7 @@ impl Syscall {
|
||||
|
||||
Self::open(path, open_flags)
|
||||
};
|
||||
// kdebug!("open: {:?}, res: {:?}", path, res);
|
||||
|
||||
res
|
||||
}
|
||||
SYS_CLOSE => {
|
||||
@ -433,9 +443,10 @@ impl Syscall {
|
||||
let buf: &mut [u8] = unsafe {
|
||||
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
|
||||
};
|
||||
|
||||
Self::read(fd, buf)
|
||||
};
|
||||
|
||||
// kdebug!("sys read, fd: {}, len: {}, res: {:?}", fd, len, res);
|
||||
res
|
||||
}
|
||||
SYS_WRITE => {
|
||||
@ -451,9 +462,12 @@ impl Syscall {
|
||||
let buf: &[u8] = unsafe {
|
||||
core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *const u8, len)
|
||||
};
|
||||
|
||||
Self::write(fd, buf)
|
||||
};
|
||||
|
||||
// kdebug!("sys write, fd: {}, len: {}, res: {:?}", fd, len, res);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
@ -476,6 +490,7 @@ impl Syscall {
|
||||
let w = w.unwrap();
|
||||
Self::lseek(fd, w)
|
||||
};
|
||||
// kdebug!("sys lseek, fd: {}, offset: {}, whence: {}, res: {:?}", fd, offset, whence, res);
|
||||
|
||||
res
|
||||
}
|
||||
@ -674,6 +689,7 @@ impl Syscall {
|
||||
if pathname.is_err() {
|
||||
Err(pathname.unwrap_err())
|
||||
} else {
|
||||
// kdebug!("sys unlinkat: dirfd: {}, pathname: {}", dirfd, pathname.as_ref().unwrap());
|
||||
Self::unlinkat(dirfd, pathname.unwrap(), flags)
|
||||
}
|
||||
}
|
||||
@ -952,6 +968,29 @@ impl Syscall {
|
||||
}
|
||||
}
|
||||
|
||||
SYS_FCNTL => {
|
||||
let fd = args[0] as i32;
|
||||
let cmd: Option<FcntlCommand> =
|
||||
<FcntlCommand as FromPrimitive>::from_u32(args[1] as u32);
|
||||
let arg = args[2] as i32;
|
||||
let res = if let Some(cmd) = cmd {
|
||||
Self::fcntl(fd, cmd, arg)
|
||||
} else {
|
||||
Err(SystemError::EINVAL)
|
||||
};
|
||||
|
||||
// kdebug!("FCNTL: fd: {}, cmd: {:?}, arg: {}, res: {:?}", fd, cmd, arg, res);
|
||||
res
|
||||
}
|
||||
|
||||
SYS_FTRUNCATE => {
|
||||
let fd = args[0] as i32;
|
||||
let len = args[1] as usize;
|
||||
let res = Self::ftruncate(fd, len);
|
||||
// kdebug!("FTRUNCATE: fd: {}, len: {}, res: {:?}", fd, len, res);
|
||||
res
|
||||
}
|
||||
|
||||
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user