mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-25 05:53:22 +00:00
feat:添加chown系统调用 (#962)
* 添加chown系统调用 --------- Co-authored-by: sparkzky <sparkhhhhhhhhh@outlook.com> Co-authored-by: longjin <longjin@DragonOS.org>
This commit is contained in:
160
user/apps/test-chown/src/main.rs
Normal file
160
user/apps/test-chown/src/main.rs
Normal file
@ -0,0 +1,160 @@
|
||||
use core::ffi::{c_char, c_void};
|
||||
use libc::{
|
||||
chown, fchown, fchownat, getgrnam, getpwnam, gid_t, lchown, mount, uid_t, umount, AT_FDCWD,
|
||||
AT_SYMLINK_NOFOLLOW,
|
||||
};
|
||||
use nix::errno::Errno;
|
||||
use std::{
|
||||
ffi::CString,
|
||||
fs::{self, metadata, File},
|
||||
io::{self, Error, Write},
|
||||
os::unix::{
|
||||
fs::{MetadataExt, PermissionsExt},
|
||||
io::AsRawFd,
|
||||
},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
fn print_file_owner_group(filename: &str) -> Result<(), Error> {
|
||||
let metadata = std::fs::metadata(filename)?;
|
||||
let uid = metadata.uid();
|
||||
let gid = metadata.gid();
|
||||
|
||||
// 确保 UID 和 GID 打印正确
|
||||
assert!(uid > 0, "UID should be greater than 0");
|
||||
assert!(gid > 0, "GID should be greater than 0");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_fchownat(filename: &str, new_uid: uid_t, new_gid: gid_t, flags: i32) -> Result<(), Error> {
|
||||
let c_filename = CString::new(filename)?;
|
||||
let result = unsafe { fchownat(AT_FDCWD, c_filename.as_ptr(), new_uid, new_gid, flags) };
|
||||
|
||||
// 确保 fchownat 成功
|
||||
assert!(result != -1, "fchownat failed");
|
||||
|
||||
print_file_owner_group(filename)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_chown(filename: &str, new_uid: uid_t, new_gid: gid_t) -> Result<(), Error> {
|
||||
let c_filename = CString::new(filename)?;
|
||||
let result = unsafe { chown(c_filename.as_ptr(), new_uid, new_gid) };
|
||||
|
||||
// 确保 chown 成功
|
||||
assert!(result != -1, "chown failed");
|
||||
|
||||
print_file_owner_group(filename)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_fchown(fd: i32, new_uid: uid_t, new_gid: gid_t) -> Result<(), Error> {
|
||||
let result = unsafe { fchown(fd, new_uid, new_gid) };
|
||||
|
||||
// 确保 fchown 成功
|
||||
assert!(result != -1, "fchown failed");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_lchown(symlink_name: &str, new_uid: uid_t, new_gid: gid_t) -> Result<(), Error> {
|
||||
let c_symlink = CString::new(symlink_name)?;
|
||||
let result = unsafe { lchown(c_symlink.as_ptr(), new_uid, new_gid) };
|
||||
|
||||
// 确保 lchown 成功
|
||||
assert!(result != -1, "lchown failed");
|
||||
|
||||
print_file_owner_group(symlink_name)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
mount_test_ramfs();
|
||||
|
||||
let filename = "/mnt/myramfs/testfile.txt";
|
||||
let symlink_name = "/mnt/myramfs/testsymlink";
|
||||
let new_owner = "nobody"; // 替换为你测试系统中的有效用户名
|
||||
let new_group = "nogroup"; // 替换为你测试系统中的有效组名
|
||||
|
||||
// 获取新的 UID 和 GID
|
||||
let pw = unsafe { getpwnam(CString::new(new_owner)?.as_ptr()) };
|
||||
let gr = unsafe { getgrnam(CString::new(new_group)?.as_ptr()) };
|
||||
|
||||
assert!(!pw.is_null(), "Invalid user name");
|
||||
assert!(!gr.is_null(), "Invalid group name");
|
||||
|
||||
let new_uid = unsafe { (*pw).pw_uid };
|
||||
let new_gid = unsafe { (*gr).gr_gid };
|
||||
|
||||
// 创建测试文件
|
||||
let mut file = File::create(filename)?;
|
||||
println!("Created test file: {}", filename);
|
||||
writeln!(file, "This is a test file for chown system call")?;
|
||||
|
||||
// 创建符号链接
|
||||
std::os::unix::fs::symlink(filename, symlink_name)?;
|
||||
println!("Created symlink: {}", symlink_name);
|
||||
|
||||
// 打开文件以测试 fchown
|
||||
let fd = file.as_raw_fd();
|
||||
|
||||
// 测试 chown
|
||||
test_chown(filename, new_uid, new_gid)?;
|
||||
|
||||
// 测试 fchown
|
||||
test_fchown(fd, new_uid, new_gid)?;
|
||||
|
||||
// 测试 lchown
|
||||
test_lchown(symlink_name, new_uid, new_gid)?;
|
||||
|
||||
// 测试 fchownat,带 AT_SYMLINK_NOFOLLOW 标志(不会跟随符号链接)
|
||||
test_fchownat(symlink_name, new_uid, new_gid, AT_SYMLINK_NOFOLLOW)?;
|
||||
|
||||
// 清理测试文件
|
||||
std::fs::remove_file(filename)?;
|
||||
|
||||
umount_test_ramfs();
|
||||
|
||||
println!("All tests passed!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mount_test_ramfs() {
|
||||
let path = Path::new("mnt/myramfs");
|
||||
let dir = fs::create_dir_all(path);
|
||||
assert!(dir.is_ok(), "mkdir /mnt/myramfs failed");
|
||||
|
||||
let source = b"\0".as_ptr() as *const c_char;
|
||||
let target = b"/mnt/myramfs\0".as_ptr() as *const c_char;
|
||||
let fstype = b"ramfs\0".as_ptr() as *const c_char;
|
||||
// let flags = MS_BIND;
|
||||
let flags = 0;
|
||||
let data = std::ptr::null() as *const c_void;
|
||||
let result = unsafe { mount(source, target, fstype, flags, data) };
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
0,
|
||||
"Mount myramfs failed, errno: {}",
|
||||
Errno::last().desc()
|
||||
);
|
||||
println!("Mount myramfs for test success!");
|
||||
}
|
||||
|
||||
fn umount_test_ramfs() {
|
||||
let path = b"/mnt/myramfs\0".as_ptr() as *const c_char;
|
||||
let result = unsafe { umount(path) };
|
||||
if result != 0 {
|
||||
let err = Errno::last();
|
||||
println!("Errno: {}", err);
|
||||
println!("Infomation: {}", err.desc());
|
||||
} else {
|
||||
// 删除mnt/myramfs
|
||||
let path = Path::new("mnt/myramfs");
|
||||
let _ = fs::remove_dir(path);
|
||||
}
|
||||
assert_eq!(result, 0, "Umount myramfs failed");
|
||||
println!("Umount myramfs for test success!");
|
||||
}
|
Reference in New Issue
Block a user