basic file sharing

This commit is contained in:
2025-08-29 15:32:23 +02:00
parent c8b52a5b3b
commit 284d805590
84 changed files with 3969 additions and 375 deletions

View File

@@ -1,8 +1,8 @@
use std::os::unix::fs::MetadataExt;
use std::{os::unix::fs::MetadataExt, path::PathBuf};
use anyhow::{Context, anyhow, bail};
use futures_util::TryStreamExt;
use rustix::fs::statx;
use rustix::fs::{Statx, statx};
use tokio::{
fs,
io::{self, AsyncWriteExt as _},
@@ -17,7 +17,8 @@ use crate::{
AbsoluteFilePath, CatError, CatRequest, CpError, CpRequest, CpResponse, File,
FileMimeType, FileName, FilePath, FileStream, FileType, LsError, LsRequest,
LsResponse, MkdirError, MkdirRequest, MvError, MvRequest, RelativeFilePath,
RmError, RmRequest, SaveError, SaveRequest, SaveResponse, TouchError, TouchRequest,
RmError, RmRequest, SaveError, SaveRequest, SaveResponse, StatError, StatRequest,
StatResponse, TouchError, TouchRequest,
},
warren::UploadFileStream,
},
@@ -242,7 +243,12 @@ impl FileSystem {
async fn touch(&self, path: &AbsoluteFilePath) -> io::Result<()> {
let path = self.get_target_path(path);
fs::File::create(&path).await.map(|_| ())
fs::OpenOptions::new()
.create(true)
.write(true)
.open(&path)
.await
.map(|_| ())
}
async fn cp(
@@ -257,6 +263,46 @@ impl FileSystem {
Ok(CpResponse::new(path, target_path))
}
async fn stat(&self, path: AbsoluteFilePath) -> anyhow::Result<File> {
let target_path = self.get_target_path(&path);
let fs_path = PathBuf::from(target_path.to_string());
let metadata = fs::metadata(&fs_path).await?;
let name = {
let file_name = fs_path
.clone()
.file_name()
.context("Failed to get file name")?
.to_owned()
.into_string()
.ok()
.context("Failed to get file name")?;
FileName::new(&file_name)?
};
let file_type = {
let file_type = metadata.file_type();
if file_type.is_dir() {
FileType::Directory
} else if file_type.is_file() {
FileType::File
} else {
bail!("Invalid file type");
}
};
let mime_type = match file_type {
FileType::File => FileMimeType::from_name(name.as_str()),
_ => None,
};
let created_at = get_btime(&fs_path);
Ok(File::new(name, file_type, mime_type, created_at))
}
}
impl FileSystemRepository for FileSystem {
@@ -333,11 +379,25 @@ impl FileSystemRepository for FileSystem {
.await
.map_err(|e| CpError::Unknown(e.into()))
}
async fn stat(&self, request: StatRequest) -> Result<StatResponse, StatError> {
let path = request.into_path();
Ok(self.stat(path).await.map(StatResponse::new)?)
}
}
// TODO: Use `DirEntry::metadata` once `target=x86_64-unknown-linux-musl` updates from musl 1.2.3 to 1.2.5
// https://github.com/rust-lang/rust/pull/142682
fn get_btime<P>(path: P) -> Option<u64>
where
P: rustix::path::Arg,
{
get_statx(path)
.ok()
.map(|statx| statx.stx_btime.tv_sec as u64)
}
fn get_statx<P>(path: P) -> rustix::io::Result<Statx>
where
P: rustix::path::Arg,
{
@@ -349,6 +409,4 @@ where
rustix::fs::StatxFlags::BTIME,
)
}
.ok()
.map(|statx| statx.stx_btime.tv_sec as u64)
}