feat: add klog
This commit is contained in:
74
backend/src/storage.rs
Normal file
74
backend/src/storage.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use std::{io, path::{Path, PathBuf}};
|
||||
use sha2::{Sha256, Digest};
|
||||
use klog_types::FileInfo;
|
||||
|
||||
pub fn files_root(data_dir: &Path) -> PathBuf {
|
||||
data_dir.join("files")
|
||||
}
|
||||
|
||||
pub fn validate_filename(name: &str) -> bool {
|
||||
!name.is_empty()
|
||||
&& name != "."
|
||||
&& name != ".."
|
||||
&& !name.contains('/')
|
||||
&& !name.contains('\\')
|
||||
&& !name.contains('\0')
|
||||
}
|
||||
|
||||
pub async fn list_all_files(data_dir: &Path) -> io::Result<Vec<FileInfo>> {
|
||||
let root = files_root(data_dir);
|
||||
let mut result = Vec::new();
|
||||
|
||||
let mut user_dirs = match tokio::fs::read_dir(&root).await {
|
||||
Ok(d) => d,
|
||||
Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(result),
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
while let Some(user_entry) = user_dirs.next_entry().await? {
|
||||
if !user_entry.file_type().await?.is_dir() {
|
||||
continue;
|
||||
}
|
||||
let username = user_entry.file_name().to_string_lossy().to_string();
|
||||
let user_dir = root.join(&username);
|
||||
|
||||
let mut files = tokio::fs::read_dir(&user_dir).await?;
|
||||
while let Some(file_entry) = files.next_entry().await? {
|
||||
if !file_entry.file_type().await?.is_file() {
|
||||
continue;
|
||||
}
|
||||
let filename = file_entry.file_name().to_string_lossy().to_string();
|
||||
let path = user_dir.join(&filename);
|
||||
let sha256 = hash_file(&path).await?;
|
||||
result.push(FileInfo { username: username.clone(), filename, sha256 });
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn hash_file(path: &Path) -> io::Result<String> {
|
||||
let data = tokio::fs::read(path).await?;
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&data);
|
||||
Ok(hex::encode(hasher.finalize()))
|
||||
}
|
||||
|
||||
pub async fn read_file(data_dir: &Path, username: &str, filename: &str) -> io::Result<Vec<u8>> {
|
||||
tokio::fs::read(files_root(data_dir).join(username).join(filename)).await
|
||||
}
|
||||
|
||||
pub async fn write_file(data_dir: &Path, username: &str, filename: &str, data: &[u8]) -> io::Result<()> {
|
||||
let dir = files_root(data_dir).join(username);
|
||||
tokio::fs::create_dir_all(&dir).await?;
|
||||
tokio::fs::write(dir.join(filename), data).await
|
||||
}
|
||||
|
||||
pub async fn delete_file(data_dir: &Path, username: &str, filename: &str) -> io::Result<bool> {
|
||||
let path = files_root(data_dir).join(username).join(filename);
|
||||
match tokio::fs::remove_file(&path).await {
|
||||
Ok(()) => Ok(true),
|
||||
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user