mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 11:16:47 +00:00
移植sqlite3,并修复一些bug (#323)
* bugfix: 程序加载器映射内存时,计算要映射的大小不正确的问题。 * 修正brk系统调用不符合规范的地方 * bugfix: 修正fat文件系统未能正确的扩展文件大小的bug * 增加fcntl系统调用 * 移植sqlite3
This commit is contained in:
parent
26887c6334
commit
6d81180b3b
@ -1,11 +1,5 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use core::cmp::min;
|
use core::{cmp::min, intrinsics::unlikely};
|
||||||
|
|
||||||
use alloc::{
|
|
||||||
string::{String, ToString},
|
|
||||||
sync::Arc,
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
io::{device::LBA_SIZE, SeekFrom},
|
io::{device::LBA_SIZE, SeekFrom},
|
||||||
@ -13,6 +7,11 @@ use crate::{
|
|||||||
libs::vec_cursor::VecCursor,
|
libs::vec_cursor::VecCursor,
|
||||||
syscall::SystemError,
|
syscall::SystemError,
|
||||||
};
|
};
|
||||||
|
use alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
|
sync::Arc,
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
fs::{Cluster, FATFileSystem, MAX_FILE_SIZE},
|
fs::{Cluster, FATFileSystem, MAX_FILE_SIZE},
|
||||||
@ -166,7 +165,6 @@ impl FATFile {
|
|||||||
|
|
||||||
// 要写入的第一个簇的簇号
|
// 要写入的第一个簇的簇号
|
||||||
let start_cluster_num = offset / fs.bytes_per_cluster();
|
let start_cluster_num = offset / fs.bytes_per_cluster();
|
||||||
|
|
||||||
// 获取要写入的第一个簇
|
// 获取要写入的第一个簇
|
||||||
let mut current_cluster: Cluster = if let Some(c) =
|
let mut current_cluster: Cluster = if let Some(c) =
|
||||||
fs.get_cluster_by_relative(self.first_cluster, start_cluster_num as usize)
|
fs.get_cluster_by_relative(self.first_cluster, start_cluster_num as usize)
|
||||||
@ -239,22 +237,26 @@ impl FATFile {
|
|||||||
return Ok(());
|
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,证明它还没有分配簇,因此分配一个簇给它
|
// 如果文件大小为0,证明它还没有分配簇,因此分配一个簇给它
|
||||||
if self.size() == 0 {
|
if self.size() == 0 {
|
||||||
// first_cluster应当为0,否则将产生空间泄露的错误
|
// first_cluster应当为0,否则将产生空间泄露的错误
|
||||||
assert_eq!(self.first_cluster, Cluster::default());
|
assert_eq!(self.first_cluster, Cluster::default());
|
||||||
self.first_cluster = fs.allocate_cluster(None)?;
|
self.first_cluster = fs.allocate_cluster(None)?;
|
||||||
self.short_dir_entry.set_first_cluster(self.first_cluster);
|
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 {
|
if bytes_remain_in_cluster < extra_bytes {
|
||||||
let clusters_to_allocate =
|
let clusters_to_allocate =
|
||||||
@ -343,17 +345,24 @@ impl FATFile {
|
|||||||
return Ok(());
|
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) =
|
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);
|
self.set_size(new_size as u32);
|
||||||
// 计算短目录项在磁盘内的字节偏移量
|
// 计算短目录项在磁盘内的字节偏移量
|
||||||
let short_entry_offset = fs.cluster_bytes_offset((self.loc.1).0) + (self.loc.1).1;
|
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)?;
|
self.short_dir_entry.flush(fs, short_entry_offset)?;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1406,6 +1415,10 @@ impl FATDirIter {
|
|||||||
/// @return Err(错误码) 可能出现了内部错误,或者是磁盘错误等。具体原因看错误码。
|
/// @return Err(错误码) 可能出现了内部错误,或者是磁盘错误等。具体原因看错误码。
|
||||||
fn get_dir_entry(&mut self) -> Result<(Cluster, u64, Option<FATDirEntry>), SystemError> {
|
fn get_dir_entry(&mut self) -> Result<(Cluster, u64, Option<FATDirEntry>), SystemError> {
|
||||||
loop {
|
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 {
|
if self.offset >= self.fs.bytes_per_cluster() && !self.is_root {
|
||||||
match self.fs.get_fat_entry(self.current_cluster)? {
|
match self.fs.get_fat_entry(self.current_cluster)? {
|
||||||
|
@ -350,6 +350,10 @@ impl FATFileSystem {
|
|||||||
/// @return Err(SystemError) 错误码
|
/// @return Err(SystemError) 错误码
|
||||||
pub fn get_fat_entry(&self, cluster: Cluster) -> Result<FATEntry, SystemError> {
|
pub fn get_fat_entry(&self, cluster: Cluster) -> Result<FATEntry, SystemError> {
|
||||||
let current_cluster = cluster.cluster_num;
|
let current_cluster = cluster.cluster_num;
|
||||||
|
if current_cluster < 2 {
|
||||||
|
// 0号簇和1号簇是保留簇,不允许用户使用
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
let fat_type: FATType = self.bpb.fat_type;
|
let fat_type: FATType = self.bpb.fat_type;
|
||||||
// 获取FAT表的起始扇区(相对分区起始扇区的偏移量)
|
// 获取FAT表的起始扇区(相对分区起始扇区的偏移量)
|
||||||
@ -1460,6 +1464,44 @@ impl IndexNode for LockedFATInode {
|
|||||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
fn metadata(&self) -> Result<Metadata, SystemError> {
|
||||||
return Ok(self.0.lock().metadata.clone());
|
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> {
|
fn list(&self) -> Result<Vec<String>, SystemError> {
|
||||||
let mut guard: SpinLockGuard<FATInode> = self.0.lock();
|
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 {
|
if buf.len() < len {
|
||||||
return Err(SystemError::ENOBUFS);
|
return Err(SystemError::ENOBUFS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果文件指针已经超过了文件大小,则返回0
|
||||||
|
if self.offset > self.inode.metadata()?.size as usize {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
let len = self
|
let len = self
|
||||||
.inode
|
.inode
|
||||||
.read_at(self.offset, len, buf, &mut self.private_data)?;
|
.read_at(self.offset, len, buf, &mut self.private_data)?;
|
||||||
@ -152,6 +158,12 @@ impl File {
|
|||||||
if buf.len() < len {
|
if buf.len() < len {
|
||||||
return Err(SystemError::ENOBUFS);
|
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
|
let len = self
|
||||||
.inode
|
.inode
|
||||||
.write_at(self.offset, len, buf, &mut self.private_data)?;
|
.write_at(self.offset, len, buf, &mut self.private_data)?;
|
||||||
@ -197,8 +209,9 @@ impl File {
|
|||||||
return Err(SystemError::EINVAL);
|
return Err(SystemError::EINVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 根据linux man page, lseek允许超出文件末尾,并且不改变文件大小
|
||||||
if pos < 0 || pos > self.metadata()?.size {
|
// 当pos超出文件末尾时,read返回0。直到开始写入数据时,才会改变文件大小
|
||||||
|
if pos < 0 {
|
||||||
return Err(SystemError::EOVERFLOW);
|
return Err(SystemError::EOVERFLOW);
|
||||||
}
|
}
|
||||||
self.offset = pos as usize;
|
self.offset = pos as usize;
|
||||||
@ -301,6 +314,53 @@ impl File {
|
|||||||
pub fn file_type(&self) -> FileType {
|
pub fn file_type(&self) -> FileType {
|
||||||
return self.file_type;
|
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 {
|
impl Drop for File {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
pub mod core;
|
pub mod core;
|
||||||
|
pub mod fcntl;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod mount;
|
pub mod mount;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
@ -162,6 +163,9 @@ pub trait IndexNode: Any + Sync + Send + Debug {
|
|||||||
|
|
||||||
/// @brief 重新设置文件的大小
|
/// @brief 重新设置文件的大小
|
||||||
///
|
///
|
||||||
|
/// 如果文件大小增加,则文件内容不变,但是文件的空洞部分会被填充为0
|
||||||
|
/// 如果文件大小减小,则文件内容会被截断
|
||||||
|
///
|
||||||
/// @return 成功:Ok()
|
/// @return 成功:Ok()
|
||||||
/// 失败:Err(错误码)
|
/// 失败:Err(错误码)
|
||||||
fn resize(&self, _len: usize) -> Result<(), SystemError> {
|
fn resize(&self, _len: usize) -> Result<(), SystemError> {
|
||||||
|
@ -11,6 +11,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
core::{do_mkdir, do_remove_dir, do_unlink_at},
|
core::{do_mkdir, do_remove_dir, do_unlink_at},
|
||||||
|
fcntl::{FcntlCommand, FD_CLOEXEC},
|
||||||
file::{File, FileMode},
|
file::{File, FileMode},
|
||||||
utils::rsplit_path,
|
utils::rsplit_path,
|
||||||
Dirent, FileType, IndexNode, ROOT_INODE,
|
Dirent, FileType, IndexNode, ROOT_INODE,
|
||||||
@ -29,6 +30,7 @@ impl Syscall {
|
|||||||
///
|
///
|
||||||
/// @return 文件描述符编号,或者是错误码
|
/// @return 文件描述符编号,或者是错误码
|
||||||
pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
|
pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
|
||||||
|
// kdebug!("open: path: {}, mode: {:?}", path, mode);
|
||||||
// 文件名过长
|
// 文件名过长
|
||||||
if path.len() > PAGE_4K_SIZE as usize {
|
if path.len() > PAGE_4K_SIZE as usize {
|
||||||
return Err(SystemError::ENAMETOOLONG);
|
return Err(SystemError::ENAMETOOLONG);
|
||||||
@ -82,7 +84,9 @@ impl Syscall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 把文件对象存入pcb
|
// 把文件对象存入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 关闭文件
|
/// @brief 关闭文件
|
||||||
@ -91,6 +95,7 @@ impl Syscall {
|
|||||||
///
|
///
|
||||||
/// @return 成功返回0,失败返回错误码
|
/// @return 成功返回0,失败返回错误码
|
||||||
pub fn close(fd: usize) -> Result<usize, SystemError> {
|
pub fn close(fd: usize) -> Result<usize, SystemError> {
|
||||||
|
// kdebug!("syscall::close: fd: {}", fd);
|
||||||
return current_pcb().drop_fd(fd as i32).map(|_| 0);
|
return current_pcb().drop_fd(fd as i32).map(|_| 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +107,7 @@ impl Syscall {
|
|||||||
/// @return Ok(usize) 成功读取的数据的字节数
|
/// @return Ok(usize) 成功读取的数据的字节数
|
||||||
/// @return Err(SystemError) 读取失败,返回posix错误码
|
/// @return Err(SystemError) 读取失败,返回posix错误码
|
||||||
pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
|
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);
|
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||||
if file.is_none() {
|
if file.is_none() {
|
||||||
return Err(SystemError::EBADF);
|
return Err(SystemError::EBADF);
|
||||||
@ -119,6 +125,7 @@ impl Syscall {
|
|||||||
/// @return Ok(usize) 成功写入的数据的字节数
|
/// @return Ok(usize) 成功写入的数据的字节数
|
||||||
/// @return Err(SystemError) 写入失败,返回posix错误码
|
/// @return Err(SystemError) 写入失败,返回posix错误码
|
||||||
pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
|
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);
|
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||||
if file.is_none() {
|
if file.is_none() {
|
||||||
return Err(SystemError::EBADF);
|
return Err(SystemError::EBADF);
|
||||||
@ -136,6 +143,7 @@ impl Syscall {
|
|||||||
/// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
|
/// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
|
||||||
/// @return Err(SystemError) 调整失败,返回posix错误码
|
/// @return Err(SystemError) 调整失败,返回posix错误码
|
||||||
pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
|
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);
|
let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
|
||||||
if file.is_none() {
|
if file.is_none() {
|
||||||
return Err(SystemError::EBADF);
|
return Err(SystemError::EBADF);
|
||||||
@ -343,6 +351,129 @@ impl Syscall {
|
|||||||
// 从pcb获取文件描述符数组失败
|
// 从pcb获取文件描述符数组失败
|
||||||
return Err(SystemError::EMFILE);
|
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)]
|
#[repr(C)]
|
||||||
|
@ -93,7 +93,6 @@ impl ElfLoader {
|
|||||||
) -> Result<(), ExecError> {
|
) -> Result<(), ExecError> {
|
||||||
let start = self.elf_page_start(start);
|
let start = self.elf_page_start(start);
|
||||||
let end = self.elf_page_align_up(end);
|
let end = self.elf_page_align_up(end);
|
||||||
// kdebug!("set_elf_brk: start={:?}, end={:?}", start, end);
|
|
||||||
if end > start {
|
if end > start {
|
||||||
let r = user_vm_guard.map_anonymous(
|
let r = user_vm_guard.map_anonymous(
|
||||||
start,
|
start,
|
||||||
@ -177,9 +176,7 @@ impl ElfLoader {
|
|||||||
let beginning_page_offset = self.elf_page_offset(addr_to_map);
|
let beginning_page_offset = self.elf_page_offset(addr_to_map);
|
||||||
addr_to_map = self.elf_page_start(addr_to_map);
|
addr_to_map = self.elf_page_start(addr_to_map);
|
||||||
// 计算要映射的内存的大小
|
// 计算要映射的内存的大小
|
||||||
let map_size = phent.p_filesz as usize
|
let map_size = phent.p_filesz as usize + beginning_page_offset;
|
||||||
+ self.elf_page_offset(VirtAddr::new(phent.p_vaddr as usize))
|
|
||||||
+ beginning_page_offset;
|
|
||||||
let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data();
|
let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data();
|
||||||
// 当前段在文件中的大小
|
// 当前段在文件中的大小
|
||||||
let seg_in_file_size = phent.p_filesz as usize;
|
let seg_in_file_size = phent.p_filesz as usize;
|
||||||
|
@ -72,6 +72,13 @@ impl Syscall {
|
|||||||
let address_space = AddressSpace::current()?;
|
let address_space = AddressSpace::current()?;
|
||||||
let mut address_space = address_space.write();
|
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 {
|
unsafe {
|
||||||
address_space
|
address_space
|
||||||
.set_brk(VirtAddr::new(page_align_up(new_addr.data())))
|
.set_brk(VirtAddr::new(page_align_up(new_addr.data())))
|
||||||
|
@ -9,6 +9,7 @@ use crate::{
|
|||||||
arch::{cpu::cpu_reset, MMArch},
|
arch::{cpu::cpu_reset, MMArch},
|
||||||
filesystem::syscall::PosixKstat,
|
filesystem::syscall::PosixKstat,
|
||||||
filesystem::vfs::{
|
filesystem::vfs::{
|
||||||
|
fcntl::FcntlCommand,
|
||||||
file::FileMode,
|
file::FileMode,
|
||||||
syscall::{SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
|
syscall::{SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
|
||||||
MAX_PATHLEN,
|
MAX_PATHLEN,
|
||||||
@ -363,9 +364,18 @@ pub const SYS_GETPEERNAME: usize = 42;
|
|||||||
pub const SYS_GETTIMEOFDAY: usize = 43;
|
pub const SYS_GETTIMEOFDAY: usize = 43;
|
||||||
pub const SYS_MMAP: usize = 44;
|
pub const SYS_MMAP: usize = 44;
|
||||||
pub const SYS_MUNMAP: usize = 45;
|
pub const SYS_MUNMAP: usize = 45;
|
||||||
pub const SYS_MPROTECT: usize = 46;
|
|
||||||
|
|
||||||
|
pub const SYS_MPROTECT: usize = 46;
|
||||||
pub const SYS_FSTAT: usize = 47;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct Syscall;
|
pub struct Syscall;
|
||||||
@ -413,7 +423,7 @@ impl Syscall {
|
|||||||
|
|
||||||
Self::open(path, open_flags)
|
Self::open(path, open_flags)
|
||||||
};
|
};
|
||||||
// kdebug!("open: {:?}, res: {:?}", path, res);
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
SYS_CLOSE => {
|
SYS_CLOSE => {
|
||||||
@ -433,9 +443,10 @@ impl Syscall {
|
|||||||
let buf: &mut [u8] = unsafe {
|
let buf: &mut [u8] = unsafe {
|
||||||
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
|
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::read(fd, buf)
|
Self::read(fd, buf)
|
||||||
};
|
};
|
||||||
|
// kdebug!("sys read, fd: {}, len: {}, res: {:?}", fd, len, res);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
SYS_WRITE => {
|
SYS_WRITE => {
|
||||||
@ -451,9 +462,12 @@ impl Syscall {
|
|||||||
let buf: &[u8] = unsafe {
|
let buf: &[u8] = unsafe {
|
||||||
core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *const u8, len)
|
core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *const u8, len)
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::write(fd, buf)
|
Self::write(fd, buf)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// kdebug!("sys write, fd: {}, len: {}, res: {:?}", fd, len, res);
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,6 +490,7 @@ impl Syscall {
|
|||||||
let w = w.unwrap();
|
let w = w.unwrap();
|
||||||
Self::lseek(fd, w)
|
Self::lseek(fd, w)
|
||||||
};
|
};
|
||||||
|
// kdebug!("sys lseek, fd: {}, offset: {}, whence: {}, res: {:?}", fd, offset, whence, res);
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -674,6 +689,7 @@ impl Syscall {
|
|||||||
if pathname.is_err() {
|
if pathname.is_err() {
|
||||||
Err(pathname.unwrap_err())
|
Err(pathname.unwrap_err())
|
||||||
} else {
|
} else {
|
||||||
|
// kdebug!("sys unlinkat: dirfd: {}, pathname: {}", dirfd, pathname.as_ref().unwrap());
|
||||||
Self::unlinkat(dirfd, pathname.unwrap(), flags)
|
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),
|
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,14 +48,17 @@ ifneq ($(shell printf '%s\n%s' "$(DADK_VERSION)" "$(MIN_DADK_VERSION)" | sort -V
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
.PHONY: dadk_run
|
||||||
dadk_run: install_dadk
|
dadk_run: install_dadk
|
||||||
mkdir -p $(DADK_CACHE_DIR)
|
mkdir -p $(DADK_CACHE_DIR)
|
||||||
# 之所以在这里临时设置ARCH为空,是因为如果要设置这个环境变量,应当在DADK的配置文件中设置
|
# 之所以在这里临时设置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 build
|
||||||
ARCH= dadk --config-dir dadk/config --cache-dir $(DADK_CACHE_DIR) --dragonos-dir $(ROOT_PATH)/bin/sysroot install
|
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_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
|
$(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/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/)
|
$(shell cp -r $(ROOT_PATH)/user/libs/libc/src/arch/x86_64/c*.o $(OLD_LIBC_INSTALL_PATH)/lib/)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(GARBAGE)
|
rm -rf $(GARBAGE)
|
||||||
$(MAKE) dadk_clean
|
$(MAKE) dadk_clean
|
||||||
|
2
user/apps/test_sqlite3/.gitignore
vendored
Normal file
2
user/apps/test_sqlite3/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
sqlite*.zip
|
||||||
|
sqlite-*/
|
44
user/apps/test_sqlite3/Makefile
Normal file
44
user/apps/test_sqlite3/Makefile
Normal 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
|
99
user/apps/test_sqlite3/main.c
Normal file
99
user/apps/test_sqlite3/main.c
Normal 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;
|
||||||
|
}
|
28
user/dadk/config/test_sqlite3-3.42.0.dadk
Normal file
28
user/dadk/config/test_sqlite3-3.42.0.dadk
Normal 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": []
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user