mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 12:16:31 +00:00
feat: 实现并测试 newfstatat 系统调用 (#1153)
* feat: 实现并测试 newfstatat 系统调用 新增了 newfstatat 系统调用的实现,并添加了相应的测试应用。 Signed-off-by: longjin <longjin@DragonOS.org> * feat(loongarch64/riscv64): 添加文件系统模块并实现GenericPosixStat结构 为loongarch64和riscv64架构添加filesystem模块,包含stat子模块,并实现GenericPosixStat结构用于处理文件状态信息。 Signed-off-by: longjin <longjin@DragonOS.org> --------- Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
1
kernel/src/arch/loongarch64/filesystem/mod.rs
Normal file
1
kernel/src/arch/loongarch64/filesystem/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod stat;
|
1
kernel/src/arch/loongarch64/filesystem/stat.rs
Normal file
1
kernel/src/arch/loongarch64/filesystem/stat.rs
Normal file
@ -0,0 +1 @@
|
||||
pub use crate::filesystem::vfs::stat::GenericPosixStat as PosixStat;
|
@ -1,6 +1,7 @@
|
||||
pub mod asm;
|
||||
pub mod cpu;
|
||||
pub mod elf;
|
||||
pub mod filesystem;
|
||||
pub mod init;
|
||||
pub mod interrupt;
|
||||
pub mod ipc;
|
||||
|
1
kernel/src/arch/riscv64/filesystem/mod.rs
Normal file
1
kernel/src/arch/riscv64/filesystem/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod stat;
|
1
kernel/src/arch/riscv64/filesystem/stat.rs
Normal file
1
kernel/src/arch/riscv64/filesystem/stat.rs
Normal file
@ -0,0 +1 @@
|
||||
pub use crate::filesystem::vfs::stat::GenericPosixStat as PosixStat;
|
@ -2,6 +2,7 @@ pub mod asm;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
pub mod elf;
|
||||
pub mod filesystem;
|
||||
pub mod init;
|
||||
pub mod interrupt;
|
||||
pub mod ipc;
|
||||
|
1
kernel/src/arch/x86_64/filesystem/mod.rs
Normal file
1
kernel/src/arch/x86_64/filesystem/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod stat;
|
72
kernel/src/arch/x86_64/filesystem/stat.rs
Normal file
72
kernel/src/arch/x86_64/filesystem/stat.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::filesystem::vfs::stat::KStat;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub struct PosixStat {
|
||||
pub st_dev: usize,
|
||||
pub st_ino: usize,
|
||||
pub st_nlink: usize,
|
||||
pub st_mode: u32,
|
||||
pub st_uid: u32,
|
||||
pub st_gid: u32,
|
||||
pub __pad0: u32,
|
||||
pub st_rdev: usize,
|
||||
pub st_size: isize,
|
||||
pub st_blksize: isize,
|
||||
/// number of 512B blocks allocated
|
||||
pub st_blocks: isize,
|
||||
pub st_atime: usize,
|
||||
pub st_atime_nsec: usize,
|
||||
pub st_mtime: usize,
|
||||
pub st_mtime_nsec: usize,
|
||||
pub st_ctime: usize,
|
||||
pub st_ctime_nsec: usize,
|
||||
pub __unused: [isize; 3],
|
||||
}
|
||||
|
||||
/// 转换的代码参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#393
|
||||
impl TryFrom<KStat> for PosixStat {
|
||||
type Error = SystemError;
|
||||
|
||||
fn try_from(kstat: KStat) -> Result<Self, Self::Error> {
|
||||
let mut tmp = PosixStat::default();
|
||||
if core::mem::size_of_val(&tmp.st_dev) < 4 && !kstat.dev.old_valid_dev() {
|
||||
return Err(SystemError::EOVERFLOW);
|
||||
}
|
||||
if core::mem::size_of_val(&tmp.st_rdev) < 4 && !kstat.rdev.old_valid_dev() {
|
||||
return Err(SystemError::EOVERFLOW);
|
||||
}
|
||||
|
||||
tmp.st_dev = kstat.dev.new_encode_dev() as usize;
|
||||
tmp.st_ino = kstat.ino as usize;
|
||||
|
||||
if core::mem::size_of_val(&tmp.st_ino) < core::mem::size_of_val(&kstat.ino)
|
||||
&& tmp.st_ino != kstat.ino as usize
|
||||
{
|
||||
return Err(SystemError::EOVERFLOW);
|
||||
}
|
||||
|
||||
tmp.st_mode = kstat.mode.bits();
|
||||
tmp.st_nlink = kstat.nlink.try_into().map_err(|_| SystemError::EOVERFLOW)?;
|
||||
|
||||
// todo: 处理user namespace (https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#415)
|
||||
tmp.st_uid = kstat.uid;
|
||||
tmp.st_gid = kstat.gid;
|
||||
|
||||
tmp.st_rdev = kstat.rdev.data() as usize;
|
||||
tmp.st_size = kstat.size as isize;
|
||||
|
||||
tmp.st_atime = kstat.atime.tv_sec as usize;
|
||||
tmp.st_mtime = kstat.mtime.tv_sec as usize;
|
||||
tmp.st_ctime = kstat.ctime.tv_sec as usize;
|
||||
tmp.st_atime_nsec = kstat.atime.tv_nsec as usize;
|
||||
tmp.st_mtime_nsec = kstat.mtime.tv_nsec as usize;
|
||||
tmp.st_ctime_nsec = kstat.ctime.tv_nsec as usize;
|
||||
tmp.st_blocks = kstat.blocks as isize;
|
||||
tmp.st_blksize = kstat.blksize as isize;
|
||||
|
||||
Ok(tmp)
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ mod acpi;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
pub mod elf;
|
||||
pub mod filesystem;
|
||||
pub mod fpu;
|
||||
pub mod init;
|
||||
pub mod interrupt;
|
||||
|
@ -60,6 +60,17 @@ impl DeviceNumber {
|
||||
pub const fn data(&self) -> u32 {
|
||||
self.data
|
||||
}
|
||||
|
||||
/// acceptable for old filesystems
|
||||
pub const fn old_valid_dev(&self) -> bool {
|
||||
(self.major().data() < 256) && (self.minor() < 256)
|
||||
}
|
||||
|
||||
pub const fn new_encode_dev(&self) -> u32 {
|
||||
let major = self.major().data();
|
||||
let minor = self.minor();
|
||||
return (minor & 0xff) | (major << 8) | ((minor & !0xff) << 12);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DeviceNumber {
|
||||
|
@ -803,6 +803,7 @@ impl dyn IndexNode {
|
||||
#[builder(no_std, setter(into))]
|
||||
pub struct Metadata {
|
||||
/// 当前inode所在的文件系统的设备号
|
||||
/// todo:更改为DeviceNumber结构体
|
||||
pub dev_id: usize,
|
||||
|
||||
/// inode号
|
||||
|
@ -1,7 +1,10 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::filesystem::stat::PosixStat,
|
||||
driver::base::device::device_number::DeviceNumber,
|
||||
filesystem::vfs::{mount::is_mountpoint_root, vcore::do_file_lookup_at},
|
||||
process::ProcessManager,
|
||||
syscall::user_access::UserBufferWriter,
|
||||
time::PosixTimeSpec,
|
||||
};
|
||||
@ -22,8 +25,8 @@ pub struct KStat {
|
||||
pub attributes: StxAttributes,
|
||||
pub attributes_mask: StxAttributes,
|
||||
pub ino: u64,
|
||||
pub dev: i64, // dev_t
|
||||
pub rdev: i64, // dev_t
|
||||
pub dev: DeviceNumber, // dev_t
|
||||
pub rdev: DeviceNumber, // dev_t
|
||||
pub uid: u32, // kuid_t
|
||||
pub gid: u32, // kgid_t
|
||||
pub size: usize, // loff_t
|
||||
@ -257,8 +260,8 @@ pub fn vfs_getattr(
|
||||
kstat.attributes = StxAttributes::STATX_ATTR_APPEND;
|
||||
kstat.attributes_mask |=
|
||||
StxAttributes::STATX_ATTR_AUTOMOUNT | StxAttributes::STATX_ATTR_DAX;
|
||||
kstat.dev = metadata.dev_id as i64;
|
||||
kstat.rdev = metadata.raw_dev.data() as i64;
|
||||
kstat.dev = DeviceNumber::from(metadata.dev_id as u32);
|
||||
kstat.rdev = metadata.raw_dev;
|
||||
}
|
||||
|
||||
// 把文件类型加入mode里面 (todo: 在具体的文件系统里面去实现这个操作。这里只是权宜之计)
|
||||
@ -267,6 +270,67 @@ pub fn vfs_getattr(
|
||||
return Ok(kstat);
|
||||
}
|
||||
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#274
|
||||
#[inline(never)]
|
||||
pub fn vfs_fstatat(dfd: i32, filename: &str, flags: AtFlags) -> Result<KStat, SystemError> {
|
||||
let statx_flags = flags | AtFlags::AT_NO_AUTOMOUNT;
|
||||
if dfd >= 0 && flags == AtFlags::AT_EMPTY_PATH {
|
||||
return vfs_fstat(dfd);
|
||||
}
|
||||
|
||||
return vfs_statx(
|
||||
dfd,
|
||||
filename,
|
||||
statx_flags,
|
||||
PosixStatxMask::STATX_BASIC_STATS,
|
||||
);
|
||||
}
|
||||
|
||||
/// vfs_fstat - Get the basic attributes by file descriptor
|
||||
///
|
||||
/// # Arguments
|
||||
/// - fd: The file descriptor referring to the file of interest
|
||||
///
|
||||
/// This function is a wrapper around vfs_getattr(). The main difference is
|
||||
/// that it uses a file descriptor to determine the file location.
|
||||
///
|
||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#190
|
||||
pub fn vfs_fstat(dfd: i32) -> Result<KStat, SystemError> {
|
||||
// Get the file from the file descriptor
|
||||
let pcb = ProcessManager::current_pcb();
|
||||
let fd_table = pcb.fd_table();
|
||||
let file = fd_table
|
||||
.read()
|
||||
.get_file_by_fd(dfd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
let inode = file.inode();
|
||||
|
||||
// Get attributes using vfs_getattr with basic stats mask
|
||||
vfs_getattr(&inode, PosixStatxMask::STATX_BASIC_STATS, AtFlags::empty())
|
||||
}
|
||||
|
||||
pub(super) fn do_newfstatat(
|
||||
dfd: i32,
|
||||
filename: &str,
|
||||
user_stat_buf_ptr: usize,
|
||||
flags: u32,
|
||||
) -> Result<(), SystemError> {
|
||||
let kstat = vfs_fstatat(dfd, filename, AtFlags::from_bits_truncate(flags as i32))?;
|
||||
|
||||
cp_new_stat(kstat, user_stat_buf_ptr)
|
||||
}
|
||||
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#393
|
||||
#[inline(never)]
|
||||
fn cp_new_stat(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> {
|
||||
let posix_stat = PosixStat::try_from(kstat)?;
|
||||
let mut ubuf_writer =
|
||||
UserBufferWriter::new(user_buf_ptr as *mut PosixStat, size_of::<PosixStat>(), true)?;
|
||||
ubuf_writer
|
||||
.copy_one_to_user(&posix_stat, 0)
|
||||
.map_err(|_| SystemError::EFAULT)
|
||||
}
|
||||
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#660
|
||||
pub(super) fn do_statx(
|
||||
dfd: i32,
|
||||
@ -319,10 +383,10 @@ fn cp_statx(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> {
|
||||
statx.stx_mtime = kstat.mtime;
|
||||
|
||||
// Convert device numbers
|
||||
statx.stx_rdev_major = ((kstat.rdev >> 32) & 0xffff_ffff) as u32; // MAJOR equivalent
|
||||
statx.stx_rdev_minor = (kstat.rdev & 0xffff_ffff) as u32; // MINOR equivalent
|
||||
statx.stx_dev_major = ((kstat.dev >> 32) & 0xffff_ffff) as u32; // MAJOR equivalent
|
||||
statx.stx_dev_minor = (kstat.dev & 0xffff_ffff) as u32; // MINOR equivalent
|
||||
statx.stx_rdev_major = kstat.rdev.major().data();
|
||||
statx.stx_rdev_minor = kstat.rdev.minor();
|
||||
statx.stx_dev_major = kstat.dev.major().data();
|
||||
statx.stx_dev_minor = kstat.dev.minor();
|
||||
|
||||
statx.stx_mnt_id = kstat.mnt_id;
|
||||
statx.stx_dio_mem_align = kstat.dio_mem_align;
|
||||
@ -396,3 +460,95 @@ impl PosixKstat {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 通用的PosixStat
|
||||
#[allow(unused)]
|
||||
#[repr(C)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub struct GenericPosixStat {
|
||||
/// Device ID
|
||||
pub st_dev: u64,
|
||||
/// File serial number (inode)
|
||||
pub st_ino: u64,
|
||||
/// File mode
|
||||
pub st_mode: u32,
|
||||
/// Link count
|
||||
pub st_nlink: u32,
|
||||
/// User ID of the file's owner
|
||||
pub st_uid: u32,
|
||||
/// Group ID of the file's group
|
||||
pub st_gid: u32,
|
||||
/// Device number, if device
|
||||
pub st_rdev: u64,
|
||||
/// Padding
|
||||
pub __pad1: u64,
|
||||
/// Size of file, in bytes
|
||||
pub st_size: i64,
|
||||
/// Optimal block size for I/O
|
||||
pub st_blksize: i32,
|
||||
/// Padding
|
||||
pub __pad2: i32,
|
||||
/// Number 512-byte blocks allocated
|
||||
pub st_blocks: i64,
|
||||
/// Time of last access (seconds)
|
||||
pub st_atime: i64,
|
||||
/// Time of last access (nanoseconds)
|
||||
pub st_atime_nsec: u64,
|
||||
/// Time of last modification (seconds)
|
||||
pub st_mtime: i64,
|
||||
/// Time of last modification (nanoseconds)
|
||||
pub st_mtime_nsec: u64,
|
||||
/// Time of last status change (seconds)
|
||||
pub st_ctime: i64,
|
||||
/// Time of last status change (nanoseconds)
|
||||
pub st_ctime_nsec: u64,
|
||||
/// Unused
|
||||
pub __unused4: u32,
|
||||
/// Unused
|
||||
pub __unused5: u32,
|
||||
}
|
||||
|
||||
/// 转换的代码参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#393
|
||||
impl TryFrom<KStat> for GenericPosixStat {
|
||||
type Error = SystemError;
|
||||
|
||||
fn try_from(kstat: KStat) -> Result<Self, Self::Error> {
|
||||
let mut tmp = GenericPosixStat::default();
|
||||
if core::mem::size_of_val(&tmp.st_dev) < 4 && !kstat.dev.old_valid_dev() {
|
||||
return Err(SystemError::EOVERFLOW);
|
||||
}
|
||||
if core::mem::size_of_val(&tmp.st_rdev) < 4 && !kstat.rdev.old_valid_dev() {
|
||||
return Err(SystemError::EOVERFLOW);
|
||||
}
|
||||
|
||||
tmp.st_dev = kstat.dev.new_encode_dev() as u64;
|
||||
tmp.st_ino = kstat.ino;
|
||||
|
||||
if core::mem::size_of_val(&tmp.st_ino) < core::mem::size_of_val(&kstat.ino)
|
||||
&& tmp.st_ino != kstat.ino
|
||||
{
|
||||
return Err(SystemError::EOVERFLOW);
|
||||
}
|
||||
|
||||
tmp.st_mode = kstat.mode.bits();
|
||||
tmp.st_nlink = kstat.nlink;
|
||||
|
||||
// todo: 处理user namespace (https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#415)
|
||||
tmp.st_uid = kstat.uid;
|
||||
tmp.st_gid = kstat.gid;
|
||||
|
||||
tmp.st_rdev = kstat.rdev.data() as u64;
|
||||
tmp.st_size = kstat.size as i64;
|
||||
|
||||
tmp.st_atime = kstat.atime.tv_sec;
|
||||
tmp.st_mtime = kstat.mtime.tv_sec;
|
||||
tmp.st_ctime = kstat.ctime.tv_sec;
|
||||
tmp.st_atime_nsec = kstat.atime.tv_nsec as u64;
|
||||
tmp.st_mtime_nsec = kstat.mtime.tv_nsec as u64;
|
||||
tmp.st_ctime_nsec = kstat.ctime.tv_nsec as u64;
|
||||
tmp.st_blocks = kstat.blocks as i64;
|
||||
tmp.st_blksize = kstat.blksize as i32;
|
||||
|
||||
Ok(tmp)
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
time::{syscall::PosixTimeval, PosixTimeSpec},
|
||||
};
|
||||
|
||||
use super::stat::{do_statx, PosixKstat};
|
||||
use super::stat::{do_newfstatat, do_statx, PosixKstat};
|
||||
use super::vcore::do_symlinkat;
|
||||
use super::{
|
||||
fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC},
|
||||
@ -1376,6 +1376,23 @@ impl Syscall {
|
||||
do_statx(dfd, filename_str, flags, mask, user_kstat_ptr).map(|_| 0)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn newfstatat(
|
||||
dfd: i32,
|
||||
filename_ptr: usize,
|
||||
user_stat_buf_ptr: usize,
|
||||
flags: u32,
|
||||
) -> Result<usize, SystemError> {
|
||||
if user_stat_buf_ptr == 0 {
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
|
||||
let filename = check_and_clone_cstr(filename_ptr as *const u8, Some(MAX_PATHLEN))?;
|
||||
let filename_str = filename.to_str().map_err(|_| SystemError::EINVAL)?;
|
||||
|
||||
do_newfstatat(dfd, filename_str, user_stat_buf_ptr, flags).map(|_| 0)
|
||||
}
|
||||
|
||||
pub fn mknod(
|
||||
path: *const u8,
|
||||
mode: ModeType,
|
||||
|
@ -1133,11 +1133,7 @@ impl Syscall {
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
|
||||
SYS_NEWFSTATAT => {
|
||||
// todo: 这个系统调用还没有实现
|
||||
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
SYS_NEWFSTATAT => Self::newfstatat(args[0] as i32, args[1], args[2], args[3] as u32),
|
||||
|
||||
// SYS_SCHED_YIELD => Self::sched_yield(),
|
||||
SYS_UNAME => {
|
||||
|
1
user/apps/test_newfstatat/.gitignore
vendored
Normal file
1
user/apps/test_newfstatat/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
test_newfstatat
|
20
user/apps/test_newfstatat/Makefile
Normal file
20
user/apps/test_newfstatat/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
ifeq ($(ARCH), x86_64)
|
||||
CROSS_COMPILE=x86_64-linux-musl-
|
||||
else ifeq ($(ARCH), riscv64)
|
||||
CROSS_COMPILE=riscv64-linux-musl-
|
||||
endif
|
||||
|
||||
CC=$(CROSS_COMPILE)gcc
|
||||
|
||||
.PHONY: all
|
||||
all: main.c
|
||||
$(CC) -static -o test_newfstatat main.c
|
||||
|
||||
.PHONY: install clean
|
||||
install: all
|
||||
mv test_newfstatat $(DADK_CURRENT_BUILD_DIR)/test_newfstatat
|
||||
|
||||
clean:
|
||||
rm test_newfstatat *.o
|
||||
|
||||
fmt:
|
65
user/apps/test_newfstatat/main.c
Normal file
65
user/apps/test_newfstatat/main.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
|
||||
|
||||
#define TEST_DIR "test_dir"
|
||||
#define TEST_FILE "test_file"
|
||||
|
||||
void create_test_files() {
|
||||
mkdir(TEST_DIR, 0755);
|
||||
int fd = open(TEST_FILE, O_CREAT | O_RDWR, 0644);
|
||||
if (fd >= 0) close(fd);
|
||||
}
|
||||
|
||||
void cleanup_test_files() {
|
||||
unlink(TEST_FILE);
|
||||
rmdir(TEST_DIR);
|
||||
}
|
||||
|
||||
void run_test(const char *name, int (*test_func)(), int expected) {
|
||||
printf("Testing %s... ", name);
|
||||
int result = test_func();
|
||||
if (result == expected) {
|
||||
printf("[PASS]\n");
|
||||
} else {
|
||||
printf("[FAILED] (expected %d, got %d)\n", expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
int test_normal_file() {
|
||||
struct stat st;
|
||||
return syscall(__NR_newfstatat, AT_FDCWD, TEST_FILE, &st, 0);
|
||||
}
|
||||
|
||||
int test_directory() {
|
||||
struct stat st;
|
||||
return syscall(__NR_newfstatat, AT_FDCWD, TEST_DIR, &st, 0);
|
||||
}
|
||||
|
||||
int test_invalid_fd() {
|
||||
struct stat st;
|
||||
return syscall(__NR_newfstatat, -1, TEST_FILE, &st, 0);
|
||||
}
|
||||
|
||||
int test_nonexistent_path() {
|
||||
struct stat st;
|
||||
return syscall(__NR_newfstatat, AT_FDCWD, "nonexistent_file", &st, 0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
create_test_files();
|
||||
|
||||
run_test("normal file stat", test_normal_file, 0);
|
||||
run_test("directory stat", test_directory, 0);
|
||||
run_test("invalid file descriptor", test_invalid_fd, -1);
|
||||
run_test("nonexistent path", test_nonexistent_path, -1);
|
||||
|
||||
cleanup_test_files();
|
||||
return 0;
|
||||
}
|
36
user/dadk/config/test_newfstatat-0.1.0.toml
Normal file
36
user/dadk/config/test_newfstatat-0.1.0.toml
Normal file
@ -0,0 +1,36 @@
|
||||
# 用户程序名称
|
||||
name = "test_newfstatat"
|
||||
# 版本号
|
||||
version = "0.1.0"
|
||||
# 用户程序描述信息
|
||||
description = "一个用来测试 newfstatat 能够正常运行的app"
|
||||
# (可选)默认: false 是否只构建一次,如果为true,DADK会在构建成功后,将构建结果缓存起来,下次构建时,直接使用缓存的构建结果
|
||||
build-once = false
|
||||
# (可选) 默认: false 是否只安装一次,如果为true,DADK会在安装成功后,不再重复安装
|
||||
install-once = false
|
||||
# 目标架构
|
||||
# 可选值:"x86_64", "aarch64", "riscv64", "loongarch64"
|
||||
target-arch = ["x86_64", "riscv64"]
|
||||
# 任务源
|
||||
[task-source]
|
||||
# 构建类型
|
||||
# 可选值:"build-from_source", "install-from-prebuilt"
|
||||
type = "build-from-source"
|
||||
# 构建来源
|
||||
# "build_from_source" 可选值:"git", "local", "archive"
|
||||
# "install_from_prebuilt" 可选值:"local", "archive"
|
||||
source = "local"
|
||||
# 路径或URL
|
||||
source-path = "user/apps/test_newfstatat"
|
||||
# 构建相关信息
|
||||
[build]
|
||||
# (可选)构建命令
|
||||
build-command = "make install"
|
||||
# 安装相关信息
|
||||
[install]
|
||||
# (可选)安装到DragonOS的路径
|
||||
in-dragonos-path = "/bin"
|
||||
# 清除相关信息
|
||||
[clean]
|
||||
# (可选)清除命令
|
||||
clean-command = "make clean"
|
Reference in New Issue
Block a user