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

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

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

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

* 增加fcntl系统调用

* 移植sqlite3
This commit is contained in:
LoGin 2023-08-08 23:39:22 +08:00 committed by GitHub
parent 26887c6334
commit 6d81180b3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 562 additions and 30 deletions

View File

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

View File

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
user/apps/test_sqlite3/.gitignore vendored Normal file
View File

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

View File

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

View File

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

View File

@ -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": []
}