mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-01-30 17:11:47 -05:00
Merge pull request #138 from arihant2math/xattr
Implement xattr syscalls
This commit is contained in:
@@ -7,18 +7,18 @@
|
||||
| 0x2 (2) | io_submit | (aio_context_t ctx_id, long nr, struct iocb **iocbpp) | __arm64_sys_io_submit | false |
|
||||
| 0x3 (3) | io_cancel | (aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) | __arm64_sys_io_cancel | false |
|
||||
| 0x4 (4) | io_getevents | (aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) | __arm64_sys_io_getevents | false |
|
||||
| 0x5 (5) | setxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_setxattr | false |
|
||||
| 0x6 (6) | lsetxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_lsetxattr | false |
|
||||
| 0x7 (7) | fsetxattr | (int fd, const char *name, const void *value, size_t size, int flags) | __arm64_sys_fsetxattr | false |
|
||||
| 0x8 (8) | getxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_getxattr | false |
|
||||
| 0x9 (9) | lgetxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_lgetxattr | false |
|
||||
| 0xa (10) | fgetxattr | (int fd, const char *name, void *value, size_t size) | __arm64_sys_fgetxattr | false |
|
||||
| 0xb (11) | listxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_listxattr | false |
|
||||
| 0xc (12) | llistxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_llistxattr | false |
|
||||
| 0xd (13) | flistxattr | (int fd, char *list, size_t size) | __arm64_sys_flistxattr | false |
|
||||
| 0xe (14) | removexattr | (const char *pathname, const char *name) | __arm64_sys_removexattr | false |
|
||||
| 0xf (15) | lremovexattr | (const char *pathname, const char *name) | __arm64_sys_lremovexattr | false |
|
||||
| 0x10 (16) | fremovexattr | (int fd, const char *name) | __arm64_sys_fremovexattr | false |
|
||||
| 0x5 (5) | setxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_setxattr | true |
|
||||
| 0x6 (6) | lsetxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_lsetxattr | true |
|
||||
| 0x7 (7) | fsetxattr | (int fd, const char *name, const void *value, size_t size, int flags) | __arm64_sys_fsetxattr | true |
|
||||
| 0x8 (8) | getxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_getxattr | true |
|
||||
| 0x9 (9) | lgetxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_lgetxattr | true |
|
||||
| 0xa (10) | fgetxattr | (int fd, const char *name, void *value, size_t size) | __arm64_sys_fgetxattr | true |
|
||||
| 0xb (11) | listxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_listxattr | true |
|
||||
| 0xc (12) | llistxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_llistxattr | true |
|
||||
| 0xd (13) | flistxattr | (int fd, char *list, size_t size) | __arm64_sys_flistxattr | true |
|
||||
| 0xe (14) | removexattr | (const char *pathname, const char *name) | __arm64_sys_removexattr | true |
|
||||
| 0xf (15) | lremovexattr | (const char *pathname, const char *name) | __arm64_sys_lremovexattr | true |
|
||||
| 0x10 (16) | fremovexattr | (int fd, const char *name) | __arm64_sys_fremovexattr | true |
|
||||
| 0x11 (17) | getcwd | (char *buf, unsigned long size) | __arm64_sys_getcwd | true |
|
||||
| 0x13 (19) | eventfd2 | (unsigned int count, int flags) | __arm64_sys_eventfd2 | false |
|
||||
| 0x14 (20) | epoll_create1 | (int flags) | __arm64_sys_epoll_create1 | false |
|
||||
|
||||
@@ -186,6 +186,9 @@ pub enum KernelError {
|
||||
#[error("Operation timed out")]
|
||||
TimedOut,
|
||||
|
||||
#[error("Value out of range")]
|
||||
RangeError,
|
||||
|
||||
#[error("{0}")]
|
||||
Other(&'static str),
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ pub fn kern_err_to_syscall(err: KernelError) -> isize {
|
||||
KernelError::NotSupported => ENOSYS,
|
||||
KernelError::NoMemory => ENOMEM,
|
||||
KernelError::TimedOut => ETIMEDOUT,
|
||||
KernelError::RangeError => ERANGE,
|
||||
KernelError::NoChildProcess => ECHILD,
|
||||
e => todo!("{e}"),
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use alloc::string::ToString;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
sync::{Arc, Weak},
|
||||
|
||||
@@ -687,6 +687,7 @@ struct TmpFsSymlinkInode<C: CpuOps> {
|
||||
id: InodeId,
|
||||
target: PathBuf,
|
||||
attr: SpinLockIrq<FileAttr, C>,
|
||||
xattr: SpinLockIrq<Vec<(String, Vec<u8>)>, C>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -707,6 +708,48 @@ impl<C: CpuOps> Inode for TmpFsSymlinkInode<C> {
|
||||
async fn readlink(&self) -> Result<PathBuf> {
|
||||
Ok(self.target.clone())
|
||||
}
|
||||
|
||||
async fn getxattr(&self, name: &str) -> Result<Vec<u8>> {
|
||||
let guard = self.xattr.lock_save_irq();
|
||||
if let Some((_, value)) = guard.iter().find(|(key, _)| key == name) {
|
||||
Ok(value.clone())
|
||||
} else {
|
||||
Err(FsError::NotFound.into())
|
||||
}
|
||||
}
|
||||
|
||||
async fn removexattr(&self, _name: &str) -> Result<()> {
|
||||
let mut guard = self.xattr.lock_save_irq();
|
||||
if let Some(pos) = guard.iter().position(|(key, _)| key == _name) {
|
||||
guard.remove(pos);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(FsError::NotFound.into())
|
||||
}
|
||||
}
|
||||
|
||||
async fn listxattr(&self) -> Result<Vec<String>> {
|
||||
let guard = self.xattr.lock_save_irq();
|
||||
Ok(guard.iter().map(|(key, _)| key.clone()).collect())
|
||||
}
|
||||
|
||||
async fn setxattr(&self, name: &str, buf: &[u8], create: bool, replace: bool) -> Result<()> {
|
||||
let mut guard = self.xattr.lock_save_irq();
|
||||
|
||||
if let Some((_, value)) = guard.iter_mut().find(|(key, _)| key == name) {
|
||||
if create {
|
||||
return Err(FsError::AlreadyExists.into());
|
||||
}
|
||||
*value = buf.to_vec();
|
||||
Ok(())
|
||||
} else {
|
||||
if replace {
|
||||
return Err(FsError::NotFound.into());
|
||||
}
|
||||
guard.push((name.to_owned(), buf.to_vec()));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: CpuOps> TmpFsSymlinkInode<C> {
|
||||
@@ -720,6 +763,7 @@ impl<C: CpuOps> TmpFsSymlinkInode<C> {
|
||||
nlinks: 1,
|
||||
..Default::default()
|
||||
}),
|
||||
xattr: SpinLockIrq::new(Vec::new()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ use crate::{
|
||||
error::{FsError, KernelError, Result},
|
||||
fs::{path::Path, pathbuf::PathBuf},
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{boxed::Box, string::String, sync::Arc};
|
||||
use async_trait::async_trait;
|
||||
use attr::{FileAttr, FilePermissions};
|
||||
@@ -211,6 +212,34 @@ pub trait Inode: Send + Sync + Any {
|
||||
Err(KernelError::NotSupported)
|
||||
}
|
||||
|
||||
/// Gets an extended attribute.
|
||||
async fn getxattr(&self, _name: &str) -> Result<Vec<u8>> {
|
||||
Err(KernelError::NotSupported)
|
||||
}
|
||||
|
||||
/// Sets an extended attribute.
|
||||
/// Can only create an attribute if `create` is true.
|
||||
/// Can only replace an existing attribute if `replace` is true.
|
||||
async fn setxattr(
|
||||
&self,
|
||||
_name: &str,
|
||||
_buf: &[u8],
|
||||
_create: bool,
|
||||
_replace: bool,
|
||||
) -> Result<()> {
|
||||
Err(KernelError::NotSupported)
|
||||
}
|
||||
|
||||
/// Removes an extended attribute.
|
||||
async fn removexattr(&self, _name: &str) -> Result<()> {
|
||||
Err(KernelError::NotSupported)
|
||||
}
|
||||
|
||||
/// Lists all extended attribute names.
|
||||
async fn listxattr(&self) -> Result<Vec<String>> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
/// Looks up a name within a directory, returning the corresponding inode.
|
||||
async fn lookup(&self, _name: &str) -> Result<Arc<dyn Inode>> {
|
||||
Err(KernelError::NotSupported)
|
||||
|
||||
@@ -24,10 +24,14 @@ use crate::{
|
||||
chmod::sys_fchmod,
|
||||
chown::sys_fchown,
|
||||
close::sys_close,
|
||||
getxattr::{sys_fgetxattr, sys_getxattr, sys_lgetxattr},
|
||||
ioctl::sys_ioctl,
|
||||
iov::{sys_preadv, sys_preadv2, sys_pwritev, sys_pwritev2, sys_readv, sys_writev},
|
||||
listxattr::{sys_flistxattr, sys_listxattr, sys_llistxattr},
|
||||
removexattr::{sys_fremovexattr, sys_lremovexattr, sys_removexattr},
|
||||
rw::{sys_pread64, sys_pwrite64, sys_read, sys_write},
|
||||
seek::sys_lseek,
|
||||
setxattr::{sys_fsetxattr, sys_lsetxattr, sys_setxattr},
|
||||
splice::sys_sendfile,
|
||||
stat::sys_fstat,
|
||||
sync::{sys_fdatasync, sys_fsync, sys_sync, sys_syncfs},
|
||||
@@ -102,6 +106,83 @@ pub async fn handle_syscall() {
|
||||
};
|
||||
|
||||
let res = match nr {
|
||||
0x5 => {
|
||||
sys_setxattr(
|
||||
TUA::from_value(arg1 as _),
|
||||
TUA::from_value(arg2 as _),
|
||||
TUA::from_value(arg3 as _),
|
||||
arg4 as _,
|
||||
arg5 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x6 => {
|
||||
sys_lsetxattr(
|
||||
TUA::from_value(arg1 as _),
|
||||
TUA::from_value(arg2 as _),
|
||||
TUA::from_value(arg3 as _),
|
||||
arg4 as _,
|
||||
arg5 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x7 => {
|
||||
sys_fsetxattr(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
TUA::from_value(arg3 as _),
|
||||
arg4 as _,
|
||||
arg5 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x8 => {
|
||||
sys_getxattr(
|
||||
TUA::from_value(arg1 as _),
|
||||
TUA::from_value(arg2 as _),
|
||||
TUA::from_value(arg3 as _),
|
||||
arg4 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x9 => {
|
||||
sys_lgetxattr(
|
||||
TUA::from_value(arg1 as _),
|
||||
TUA::from_value(arg2 as _),
|
||||
TUA::from_value(arg3 as _),
|
||||
arg4 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0xa => {
|
||||
sys_fgetxattr(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
TUA::from_value(arg3 as _),
|
||||
arg4 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0xb => {
|
||||
sys_listxattr(
|
||||
TUA::from_value(arg1 as _),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0xc => {
|
||||
sys_llistxattr(
|
||||
TUA::from_value(arg1 as _),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0xd => sys_flistxattr(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
|
||||
0xe => sys_removexattr(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
|
||||
0xf => sys_lremovexattr(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
|
||||
0x10 => sys_fremovexattr(arg1.into(), TUA::from_value(arg2 as _)).await,
|
||||
0x11 => sys_getcwd(TUA::from_value(arg1 as _), arg2 as _).await,
|
||||
0x17 => sys_dup(arg1.into()),
|
||||
0x18 => sys_dup3(arg1.into(), arg2.into(), arg3 as _),
|
||||
|
||||
88
src/fs/syscalls/getxattr.rs
Normal file
88
src/fs/syscalls/getxattr.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
use crate::fs::VFS;
|
||||
use crate::memory::uaccess::copy_to_user_slice;
|
||||
use crate::memory::uaccess::cstr::UserCStr;
|
||||
use crate::process::fd_table::Fd;
|
||||
use crate::sched::current::current_task_shared;
|
||||
use alloc::sync::Arc;
|
||||
use core::ffi::c_char;
|
||||
use libkernel::error::{KernelError, Result};
|
||||
use libkernel::fs::Inode;
|
||||
use libkernel::fs::path::Path;
|
||||
use libkernel::memory::address::{TUA, UA};
|
||||
|
||||
async fn getxattr(node: Arc<dyn Inode>, name: &str, ua: UA, size: usize) -> Result<usize> {
|
||||
let value = node.getxattr(name).await?;
|
||||
if size < value.len() {
|
||||
Err(KernelError::RangeError)
|
||||
} else {
|
||||
copy_to_user_slice(&value, ua).await?;
|
||||
Ok(value.len())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sys_getxattr(
|
||||
path: TUA<c_char>,
|
||||
name: TUA<c_char>,
|
||||
value: UA,
|
||||
size: usize,
|
||||
) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS.resolve_path(path, VFS.root_inode(), &task).await?;
|
||||
let mut buf = [0; 1024];
|
||||
getxattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
value,
|
||||
size,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn sys_lgetxattr(
|
||||
path: TUA<c_char>,
|
||||
name: TUA<c_char>,
|
||||
value: UA,
|
||||
size: usize,
|
||||
) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS
|
||||
.resolve_path_nofollow(path, VFS.root_inode(), &task)
|
||||
.await?;
|
||||
let mut buf = [0; 1024];
|
||||
getxattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
value,
|
||||
size,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn sys_fgetxattr(fd: Fd, name: TUA<c_char>, value: UA, size: usize) -> Result<usize> {
|
||||
let node = {
|
||||
let task = current_task_shared();
|
||||
let file = task
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
file.inode().ok_or(KernelError::BadFd)?
|
||||
};
|
||||
let mut buf = [0; 1024];
|
||||
getxattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
value,
|
||||
size,
|
||||
)
|
||||
.await
|
||||
}
|
||||
59
src/fs/syscalls/listxattr.rs
Normal file
59
src/fs/syscalls/listxattr.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use crate::fs::VFS;
|
||||
use crate::memory::uaccess::copy_to_user_slice;
|
||||
use crate::memory::uaccess::cstr::UserCStr;
|
||||
use crate::process::fd_table::Fd;
|
||||
use crate::sched::current::current_task_shared;
|
||||
use alloc::sync::Arc;
|
||||
use libkernel::error::{KernelError, Result};
|
||||
use libkernel::fs::Inode;
|
||||
use libkernel::fs::path::Path;
|
||||
use libkernel::memory::address::{TUA, UA};
|
||||
|
||||
async fn listxattr(node: Arc<dyn Inode>, ua: UA, size: usize) -> Result<usize> {
|
||||
let list = node.listxattr().await?;
|
||||
// Join with \0
|
||||
let list = list.join("\0");
|
||||
let list_bytes = list.as_bytes();
|
||||
if size < list_bytes.len() {
|
||||
Err(KernelError::RangeError)
|
||||
} else {
|
||||
copy_to_user_slice(list_bytes, ua).await?;
|
||||
Ok(list_bytes.len())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sys_listxattr(path: TUA<core::ffi::c_char>, list: UA, size: usize) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS.resolve_path(path, VFS.root_inode(), &task).await?;
|
||||
listxattr(node, list, size).await
|
||||
}
|
||||
|
||||
pub async fn sys_llistxattr(path: TUA<core::ffi::c_char>, list: UA, size: usize) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS
|
||||
.resolve_path_nofollow(path, VFS.root_inode(), &task)
|
||||
.await?;
|
||||
listxattr(node, list, size).await
|
||||
}
|
||||
|
||||
pub async fn sys_flistxattr(fd: Fd, list: UA, size: usize) -> Result<usize> {
|
||||
let node = {
|
||||
let task = current_task_shared();
|
||||
let file = task
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
file.inode().ok_or(KernelError::BadFd)?
|
||||
};
|
||||
listxattr(node, list, size).await
|
||||
}
|
||||
@@ -3,11 +3,15 @@ pub mod chdir;
|
||||
pub mod chmod;
|
||||
pub mod chown;
|
||||
pub mod close;
|
||||
pub mod getxattr;
|
||||
pub mod ioctl;
|
||||
pub mod iov;
|
||||
pub mod listxattr;
|
||||
pub mod open;
|
||||
pub mod removexattr;
|
||||
pub mod rw;
|
||||
pub mod seek;
|
||||
pub mod setxattr;
|
||||
pub mod splice;
|
||||
pub mod stat;
|
||||
pub mod sync;
|
||||
|
||||
69
src/fs/syscalls/removexattr.rs
Normal file
69
src/fs/syscalls/removexattr.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
use crate::fs::VFS;
|
||||
use crate::memory::uaccess::cstr::UserCStr;
|
||||
use crate::process::fd_table::Fd;
|
||||
use crate::sched::current::current_task_shared;
|
||||
use alloc::sync::Arc;
|
||||
use core::ffi::c_char;
|
||||
use libkernel::error::{KernelError, Result};
|
||||
use libkernel::fs::Inode;
|
||||
use libkernel::fs::path::Path;
|
||||
use libkernel::memory::address::TUA;
|
||||
|
||||
async fn removexattr(node: Arc<dyn Inode>, name: &str) -> Result<()> {
|
||||
node.removexattr(name).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn sys_removexattr(path: TUA<c_char>, name: TUA<c_char>) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS.resolve_path(path, VFS.root_inode(), &task).await?;
|
||||
let mut buf = [0; 1024];
|
||||
removexattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
)
|
||||
.await?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub async fn sys_lremovexattr(path: TUA<c_char>, name: TUA<c_char>) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS
|
||||
.resolve_path_nofollow(path, VFS.root_inode(), &task)
|
||||
.await?;
|
||||
let mut buf = [0; 1024];
|
||||
removexattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
)
|
||||
.await?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub async fn sys_fremovexattr(fd: Fd, name: TUA<c_char>) -> Result<usize> {
|
||||
let node = {
|
||||
let task = current_task_shared();
|
||||
let file = task
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
file.inode().ok_or(KernelError::BadFd)?
|
||||
};
|
||||
let mut buf = [0; 1024];
|
||||
removexattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
)
|
||||
.await?;
|
||||
Ok(0)
|
||||
}
|
||||
129
src/fs/syscalls/setxattr.rs
Normal file
129
src/fs/syscalls/setxattr.rs
Normal file
@@ -0,0 +1,129 @@
|
||||
use crate::fs::VFS;
|
||||
use crate::memory::uaccess::copy_from_user_slice;
|
||||
use crate::memory::uaccess::cstr::UserCStr;
|
||||
use crate::process::fd_table::Fd;
|
||||
use crate::sched::current::current_task_shared;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec;
|
||||
use bitflags::bitflags;
|
||||
use core::ffi::c_char;
|
||||
use libkernel::error::{KernelError, Result};
|
||||
use libkernel::fs::Inode;
|
||||
use libkernel::fs::path::Path;
|
||||
use libkernel::memory::address::{TUA, UA};
|
||||
|
||||
bitflags! {
|
||||
pub struct SetXattrFlags: i32 {
|
||||
const CREATE = 0x1;
|
||||
const REPLACE = 0x2;
|
||||
}
|
||||
}
|
||||
|
||||
async fn setxattr(
|
||||
node: Arc<dyn Inode>,
|
||||
name: &str,
|
||||
value: UA,
|
||||
size: usize,
|
||||
flags: i32,
|
||||
) -> Result<usize> {
|
||||
let flags = match flags {
|
||||
0 => SetXattrFlags::all(),
|
||||
1 => SetXattrFlags::CREATE,
|
||||
2 => SetXattrFlags::REPLACE,
|
||||
_ => return Err(KernelError::InvalidValue),
|
||||
};
|
||||
if name.is_empty() || name.len() > 255 {
|
||||
return Err(KernelError::RangeError);
|
||||
}
|
||||
if size > 2 * 1024 * 1024 {
|
||||
return Err(KernelError::RangeError);
|
||||
}
|
||||
let mut value_vec = vec![0u8; size];
|
||||
copy_from_user_slice(value, &mut value_vec[..]).await?;
|
||||
node.setxattr(
|
||||
name,
|
||||
&value_vec,
|
||||
flags.contains(SetXattrFlags::CREATE),
|
||||
flags.contains(SetXattrFlags::REPLACE),
|
||||
)
|
||||
.await?;
|
||||
Ok(size)
|
||||
}
|
||||
|
||||
pub async fn sys_setxattr(
|
||||
path: TUA<c_char>,
|
||||
name: TUA<c_char>,
|
||||
value: UA,
|
||||
size: usize,
|
||||
flags: i32,
|
||||
) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS.resolve_path(path, VFS.root_inode(), &task).await?;
|
||||
let mut buf = [0; 1024];
|
||||
setxattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
value,
|
||||
size,
|
||||
flags,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn sys_lsetxattr(
|
||||
path: TUA<c_char>,
|
||||
name: TUA<c_char>,
|
||||
value: UA,
|
||||
size: usize,
|
||||
flags: i32,
|
||||
) -> Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let task = current_task_shared();
|
||||
|
||||
let node = VFS
|
||||
.resolve_path_nofollow(path, VFS.root_inode(), &task)
|
||||
.await?;
|
||||
let mut buf = [0; 1024];
|
||||
setxattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
value,
|
||||
size,
|
||||
flags,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn sys_fsetxattr(
|
||||
fd: Fd,
|
||||
name: TUA<c_char>,
|
||||
value: UA,
|
||||
size: usize,
|
||||
flags: i32,
|
||||
) -> Result<usize> {
|
||||
let node = {
|
||||
let task = current_task_shared();
|
||||
let file = task
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
file.inode().ok_or(KernelError::BadFd)?
|
||||
};
|
||||
let mut buf = [0; 1024];
|
||||
setxattr(
|
||||
node,
|
||||
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
|
||||
value,
|
||||
size,
|
||||
flags,
|
||||
)
|
||||
.await
|
||||
}
|
||||
Reference in New Issue
Block a user