basic file sharing
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user