mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-25 13:36:50 +00:00
refactor: Restructure project layout and clean up dependencies (#30)
This commit introduces a significant reorganization of the project structure to improve maintainability and clarity. Key changes include: - Adjusted the directory layout for a more logical module organization. - Removed unused crate dependencies, reducing the overall project size and potentially speeding up build times. - Updated import paths and configuration files to reflect the structural changes.
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
// Copyright 2024 RustFS Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::{
|
||||
io,
|
||||
path::{Component, Path},
|
||||
};
|
||||
|
||||
use super::error::Result;
|
||||
use crate::disk::error_conv::to_file_error;
|
||||
use rustfs_utils::path::SLASH_SEPARATOR;
|
||||
use tokio::fs;
|
||||
use tracing::warn;
|
||||
|
||||
use super::error::DiskError;
|
||||
|
||||
pub fn check_path_length(path_name: &str) -> Result<()> {
|
||||
// Apple OS X path length is limited to 1016
|
||||
if cfg!(target_os = "macos") && path_name.len() > 1016 {
|
||||
return Err(DiskError::FileNameTooLong);
|
||||
}
|
||||
|
||||
// Disallow more than 1024 characters on windows, there
|
||||
// are no known name_max limits on Windows.
|
||||
if cfg!(target_os = "windows") && path_name.len() > 1024 {
|
||||
return Err(DiskError::FileNameTooLong);
|
||||
}
|
||||
|
||||
// On Unix we reject paths if they are just '.', '..' or '/'
|
||||
let invalid_paths = [".", "..", "/"];
|
||||
if invalid_paths.contains(&path_name) {
|
||||
return Err(DiskError::FileAccessDenied);
|
||||
}
|
||||
|
||||
// Check each path segment length is > 255 on all Unix
|
||||
// platforms, look for this value as NAME_MAX in
|
||||
// /usr/include/linux/limits.h
|
||||
let mut count = 0usize;
|
||||
for c in path_name.chars() {
|
||||
match c {
|
||||
'/' | '\\' if cfg!(target_os = "windows") => count = 0, // Reset
|
||||
_ => {
|
||||
count += 1;
|
||||
if count > 255 {
|
||||
return Err(DiskError::FileNameTooLong);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Success.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_root_disk(disk_path: &str, root_disk: &str) -> Result<bool> {
|
||||
if cfg!(target_os = "windows") {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
rustfs_utils::os::same_disk(disk_path, root_disk).map_err(|e| to_file_error(e).into())
|
||||
}
|
||||
|
||||
pub async fn make_dir_all(path: impl AsRef<Path>, base_dir: impl AsRef<Path>) -> Result<()> {
|
||||
check_path_length(path.as_ref().to_string_lossy().to_string().as_str())?;
|
||||
|
||||
reliable_mkdir_all(path.as_ref(), base_dir.as_ref())
|
||||
.await
|
||||
.map_err(to_file_error)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn is_empty_dir(path: impl AsRef<Path>) -> bool {
|
||||
read_dir(path.as_ref(), 1).await.is_ok_and(|v| v.is_empty())
|
||||
}
|
||||
|
||||
// read_dir count read limit. when count == 0 unlimit.
|
||||
pub async fn read_dir(path: impl AsRef<Path>, count: i32) -> std::io::Result<Vec<String>> {
|
||||
let mut entries = fs::read_dir(path.as_ref()).await?;
|
||||
|
||||
let mut volumes = Vec::new();
|
||||
|
||||
let mut count = count;
|
||||
|
||||
while let Some(entry) = entries.next_entry().await? {
|
||||
let name = entry.file_name().to_string_lossy().to_string();
|
||||
|
||||
if name.is_empty() || name == "." || name == ".." {
|
||||
continue;
|
||||
}
|
||||
|
||||
let file_type = entry.file_type().await?;
|
||||
|
||||
if file_type.is_file() {
|
||||
volumes.push(name);
|
||||
} else if file_type.is_dir() {
|
||||
volumes.push(format!("{name}{SLASH_SEPARATOR}"));
|
||||
}
|
||||
count -= 1;
|
||||
if count == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(volumes)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn rename_all(
|
||||
src_file_path: impl AsRef<Path>,
|
||||
dst_file_path: impl AsRef<Path>,
|
||||
base_dir: impl AsRef<Path>,
|
||||
) -> Result<()> {
|
||||
reliable_rename(src_file_path, dst_file_path.as_ref(), base_dir)
|
||||
.await
|
||||
.map_err(to_file_error)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn reliable_rename(
|
||||
src_file_path: impl AsRef<Path>,
|
||||
dst_file_path: impl AsRef<Path>,
|
||||
base_dir: impl AsRef<Path>,
|
||||
) -> io::Result<()> {
|
||||
if let Some(parent) = dst_file_path.as_ref().parent() {
|
||||
if !file_exists(parent) {
|
||||
// info!("reliable_rename reliable_mkdir_all parent: {:?}", parent);
|
||||
reliable_mkdir_all(parent, base_dir.as_ref()).await?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if let Err(e) = super::fs::rename_std(src_file_path.as_ref(), dst_file_path.as_ref()) {
|
||||
if e.kind() == io::ErrorKind::NotFound {
|
||||
break;
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
warn!(
|
||||
"reliable_rename failed. src_file_path: {:?}, dst_file_path: {:?}, base_dir: {:?}, err: {:?}",
|
||||
src_file_path.as_ref(),
|
||||
dst_file_path.as_ref(),
|
||||
base_dir.as_ref(),
|
||||
e
|
||||
);
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn reliable_mkdir_all(path: impl AsRef<Path>, base_dir: impl AsRef<Path>) -> io::Result<()> {
|
||||
let mut i = 0;
|
||||
|
||||
let mut base_dir = base_dir.as_ref();
|
||||
loop {
|
||||
if let Err(e) = os_mkdir_all(path.as_ref(), base_dir).await {
|
||||
if e.kind() == io::ErrorKind::NotFound && i == 0 {
|
||||
i += 1;
|
||||
|
||||
if let Some(base_parent) = base_dir.parent() {
|
||||
if let Some(c) = base_parent.components().next() {
|
||||
if c != Component::RootDir {
|
||||
base_dir = base_parent
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn os_mkdir_all(dir_path: impl AsRef<Path>, base_dir: impl AsRef<Path>) -> io::Result<()> {
|
||||
if !base_dir.as_ref().to_string_lossy().is_empty() && base_dir.as_ref().starts_with(dir_path.as_ref()) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(parent) = dir_path.as_ref().parent() {
|
||||
// 不支持递归,直接 create_dir_all 了
|
||||
if let Err(e) = super::fs::make_dir_all(&parent).await {
|
||||
if e.kind() == io::ErrorKind::AlreadyExists {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
return Err(e);
|
||||
}
|
||||
// Box::pin(os_mkdir_all(&parent, &base_dir)).await?;
|
||||
}
|
||||
|
||||
if let Err(e) = super::fs::mkdir(dir_path.as_ref()).await {
|
||||
if e.kind() == io::ErrorKind::AlreadyExists {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn file_exists(path: impl AsRef<Path>) -> bool {
|
||||
std::fs::metadata(path.as_ref()).map(|_| true).unwrap_or(false)
|
||||
}
|
||||
Reference in New Issue
Block a user