Browse Source

移植sqlite3,并修复一些bug (#323)

* bugfix: 程序加载器映射内存时,计算要映射的大小不正确的问题。

* 修正brk系统调用不符合规范的地方

* bugfix: 修正fat文件系统未能正确的扩展文件大小的bug

* 增加fcntl系统调用

* 移植sqlite3
LoGin 1 year ago
parent
commit
6d81180b3b

+ 32 - 19
kernel/src/filesystem/fat/entry.rs

@@ -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)? {

+ 42 - 0
kernel/src/filesystem/fat/fs.rs

@@ -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 - 0
kernel/src/filesystem/vfs/fcntl.rs

@@ -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;

+ 62 - 2
kernel/src/filesystem/vfs/file.rs

@@ -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 {

+ 4 - 0
kernel/src/filesystem/vfs/mod.rs

@@ -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(错误码)

+ 132 - 1
kernel/src/filesystem/vfs/syscall.rs

@@ -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)]

+ 1 - 4
kernel/src/libs/elf.rs

@@ -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;

+ 7 - 0
kernel/src/mm/syscall.rs

@@ -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())))

+ 42 - 3
kernel/src/syscall/mod.rs

@@ -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),
         };
 

+ 5 - 1
user/Makefile

@@ -48,14 +48,17 @@ ifneq ($(shell printf '%s\n%s' "$(DADK_VERSION)" "$(MIN_DADK_VERSION)" | sort -V
 endif
 endif
 
+.PHONY: dadk_run
 dadk_run: install_dadk
 	mkdir -p $(DADK_CACHE_DIR)
 # 之所以在这里临时设置ARCH为空,是因为如果要设置这个环境变量,应当在DADK的配置文件中设置
 	ARCH= dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot build
 	ARCH= dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot install
 
+.PHONY: dadk_clean
 dadk_clean: install_dadk
-	dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot clean
+	dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot clean src
+	dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot clean target
 
 $(user_sub_dirs): ECHO sys_api_lib 
 
@@ -99,6 +102,7 @@ sys_api_lib: sys_api_lib_stage_1
 	$(shell cp -r $(ROOT_PATH)/user/libs/libc/src/include/export/* $(OLD_LIBC_INSTALL_PATH)/include/)
 	$(shell cp -r $(ROOT_PATH)/user/libs/libc/src/arch/x86_64/c*.o $(OLD_LIBC_INSTALL_PATH)/lib/)
 
+.PHONY: clean
 clean: 
 	rm -rf $(GARBAGE)
 	$(MAKE) dadk_clean

+ 2 - 0
user/apps/test_sqlite3/.gitignore

@@ -0,0 +1,2 @@
+sqlite*.zip
+sqlite-*/

+ 44 - 0
user/apps/test_sqlite3/Makefile

@@ -0,0 +1,44 @@
+CC=$(DragonOS_GCC)/x86_64-elf-gcc
+LD=ld
+OBJCOPY=objcopy
+SQLITE_FILENAME=sqlite-amalgamation-3420000
+SQLITE3_DIR=$(shell pwd)/$(SQLITE_FILENAME)
+
+RELIBC_OPT=$(DADK_BUILD_CACHE_DIR_RELIBC_0_1_0)
+CFLAGS=-I $(RELIBC_OPT)/include -I $(SQLITE3_DIR) -D__dragonos__ -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_FLOATING_POINT -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DEBUG
+
+tmp_output_dir=$(ROOT_PATH)/bin/tmp/user
+output_dir=$(DADK_BUILD_CACHE_DIR_TEST_SQLITE3_3_42_0)
+
+LIBC_OBJS:=$(shell find $(RELIBC_OPT)/lib -name "*.o" | sort )
+LIBC_OBJS+=$(RELIBC_OPT)/lib/libc.a
+
+.PHONY: all clean download_sqlite3 __download_sqlite3
+
+
+all: main.o sqlite3.o
+	mkdir -p $(tmp_output_dir)
+	
+	$(LD) -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test_sqlite3  $(shell find . -name "*.o") $(LIBC_OBJS)
+
+	$(OBJCOPY) -I elf64-x86-64 -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/test_sqlite3 $(output_dir)/test_sqlite3.elf
+	mv $(output_dir)/test_sqlite3.elf $(output_dir)/test_sqlite3
+
+main.o: main.c
+	$(CC) $(CFLAGS) -c main.c  -o main.o
+
+sqlite3.o: $(SQLITE3_DIR)/sqlite3.c
+	$(CC) $(CFLAGS) -c $(SQLITE3_DIR)/sqlite3.c -o sqlite3.o
+
+__download_sqlite3:
+	@echo "Download sqlite3 from https://mirrors.ringotek.cn/pub/third_party/sqlite/$(SQLITE_FILENAME).zip"
+	@wget https://mirrors.ringotek.cn/pub/third_party/sqlite/$(SQLITE_FILENAME).zip || (@echo "Download sqlite3 failed" && rm $(SQLITE_FILENAME).zip && exit 1)
+	@unzip -o $(SQLITE_FILENAME).zip || (@echo "Unzip sqlite3 failed" && exit 1)
+	@rm $(SQLITE_FILENAME).zip || (@echo "Remove $(SQLITE_FILENAME).zip failed" && exit 1)
+
+download_sqlite3:
+# 如果文件夹不存在,则下载,否则不下载
+	@test -d $(SQLITE3_DIR) || $(MAKE) __download_sqlite3
+
+clean:
+	rm -f *.o

+ 99 - 0
user/apps/test_sqlite3/main.c

@@ -0,0 +1,99 @@
+// This is a test program for sqlite3.
+// We take it from rcore-os/arceos, thanks to @rcore-os community.
+#include <sqlite3.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+int callback(void *NotUsed, int argc, char **argv, char **azColName)
+{
+    NotUsed = NULL;
+
+    for (int i = 0; i < argc; ++i) {
+        printf("%s = %s\n", azColName[i], (argv[i] ? argv[i] : "NULL"));
+    }
+
+    printf("\n");
+
+    return 0;
+}
+
+void exec(sqlite3 *db, char *sql)
+{
+    printf("sqlite exec:\n    %s\n", sql);
+    char *errmsg = NULL;
+    int rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
+    if (rc != SQLITE_OK) {
+        printf("sqlite exec error: %s\n", errmsg);
+    }
+}
+
+void query(sqlite3 *db, char *sql)
+{
+    printf("sqlite query:\n    %s\n", sql);
+    char *errmsg = NULL;
+    int rc = sqlite3_exec(db, sql, callback, NULL, &errmsg);
+
+    if (rc != SQLITE_OK) {
+        printf("%s\n", errmsg);
+    }
+}
+
+void query_test(sqlite3 *db, const char *args)
+{
+    puts("======== init user table ========");
+    exec(db, "create table user("
+             "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+             "username TEXT,"
+             "password TEXT"
+             ")");
+
+    puts("======== insert user 1, 2, 3 into user table ========");
+
+    char cmd[256] = {0};
+    sprintf(cmd,
+            "insert into user (username, password) VALUES ('%s_1', 'password1'), ('%s_2', "
+            "'password2'), ('%s_3', 'password3')",
+            args, args, args);
+    exec(db, cmd);
+
+    puts("======== select all ========");
+    query(db, "select * from user");
+
+    puts("======== select id = 2 ========");
+    query(db, "select * from user where id = 2");
+}
+
+void memory()
+{
+    sqlite3 *db;
+    printf("sqlite open memory\n");
+    int ret = sqlite3_open(":memory:", &db);
+    printf("sqlite open memory status %d \n", ret);
+
+    query_test(db, "memory");
+}
+
+void file()
+{
+    sqlite3 *db;
+    int ret = sqlite3_open("file.sqlite", &db);
+    printf("sqlite open /file.sqlite status %d \n", ret);
+
+    if (ret != 0) {
+        printf("sqlite open error");
+        return;
+    }
+
+    query_test(db, "file");
+    sqlite3_close(db);
+}
+
+int main()
+{
+    printf("sqlite version: %s\n", sqlite3_libversion());
+
+    memory();
+    file();
+    return 0;
+}

+ 28 - 0
user/dadk/config/test_sqlite3-3.42.0.dadk

@@ -0,0 +1,28 @@
+{
+  "name": "test_sqlite3",
+  "version": "3.42.0",
+  "description": "测试sqlite3",
+  "task_type": {
+    "BuildFromSource": {
+      "Local": {
+        "path": "apps/test_sqlite3"
+      }
+    }
+  },
+  "depends": [
+    {
+      "name": "relibc",
+      "version": "0.1.0"
+    }
+  ],
+  "build": {
+    "build_command": "make download_sqlite3 && make -j $(nproc)"
+  },
+  "install": {
+    "in_dragonos_path": "/bin"
+  },
+  "clean": {
+    "clean_command": "make clean"
+  },
+  "envs": []
+}