fix: Optimize the issue of obtaining path errors on Windows.

This commit is contained in:
shiro
2025-03-03 20:13:27 +08:00
parent 4ff452ffd2
commit ad30f0db89
4 changed files with 30 additions and 34 deletions
+25 -29
View File
@@ -29,7 +29,7 @@ pub struct Endpoint {
impl Display for Endpoint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.url.scheme() == "file" {
write!(f, "{}", self.url.path())
write!(f, "{}", self.get_file_path())
} else {
write!(f, "{}", self.url)
}
@@ -42,13 +42,9 @@ impl TryFrom<&str> for Endpoint {
/// Performs the conversion.
fn try_from(value: &str) -> Result<Self, Self::Error> {
/// check whether given path is not empty.
fn is_empty_path(path: impl AsRef<Path>) -> bool {
["", "/", "\\"].iter().any(|&v| Path::new(v).eq(path.as_ref()))
}
if is_empty_path(value) {
return Err(Error::from_string("empty or root endpoint is not supported"));
// check whether given path is not empty.
if ["", "/", "\\"].iter().any(|&v| v.eq(value)) {
return Err(ErrorCode::EmptyPath().with_message("empty or root endpoint is not supported"));
}
let mut is_local = false;
@@ -67,35 +63,26 @@ impl TryFrom<&str> for Endpoint {
return Err(Error::from_string("invalid URL endpoint format"));
}
let path = Path::new(url.path()).clean();
if is_empty_path(&path) {
return Err(Error::from_string("empty or root path is not supported in URL endpoint"));
}
let path = url.path().to_string();
if let Some(v) = path.to_str() {
url.set_path(v)
}
#[cfg(not(windows))]
let path = Path::new(&path).absolutize()?;
// On windows having a preceding SlashSeparator will cause problems, if the
// command line already has C:/<export-folder/ in it. Final resulting
// path on windows might become C:/C:/ this will cause problems
// of starting rustfs server properly in distributed mode on windows.
// As a special case make sure to trim the separator.
// NOTE: It is also perfectly fine for windows users to have a path
// without C:/ since at that point we treat it as relative path
// and obtain the full filesystem path as well. Providing C:/
// style is necessary to provide paths other than C:/,
// such as F:/, D:/ etc.
//
// Another additional benefit here is that this style also
// supports providing \\host\share support as well.
#[cfg(windows)]
{
let path = url.path().to_owned();
if Path::new(&path[1..]).is_absolute() {
url.set_path(&path[1..]);
}
let path = Path::new(&path[1..]).absolutize()?;
if path.parent().is_none() || Path::new("").eq(&path) {
return Err(Error::from_string("empty or root path is not supported in URL endpoint"));
}
match path.to_str() {
Some(v) => url.set_path(v),
None => return Err(Error::from_string("invalid path")),
}
url
@@ -182,6 +169,15 @@ impl Endpoint {
_ => String::new(),
}
}
pub fn get_file_path(&self) -> &str {
let path = self.url.path();
#[cfg(windows)]
let path = &path[1..];
path
}
}
/// parse a file path into an URL.
+1 -1
View File
@@ -114,7 +114,7 @@ impl Debug for LocalDisk {
impl LocalDisk {
pub async fn new(ep: &Endpoint, cleanup: bool) -> Result<Self> {
let root = fs::canonicalize(ep.url.path()).await?;
let root = fs::canonicalize(ep.get_file_path()).await?;
if cleanup {
// TODO: 删除tmp数据
+1 -1
View File
@@ -52,7 +52,7 @@ pub struct RemoteDisk {
impl RemoteDisk {
pub async fn new(ep: &Endpoint, _opt: &DiskOption) -> Result<Self> {
// let root = fs::canonicalize(ep.url.path()).await?;
let root = PathBuf::from(ep.url.path());
let root = PathBuf::from(ep.get_file_path());
let addr = format!("{}://{}:{}", ep.url.scheme(), ep.url.host_str().unwrap(), ep.url.port().unwrap());
Ok(Self {
id: Mutex::new(None),
+3 -3
View File
@@ -231,7 +231,7 @@ impl PoolEndpointList {
.map_err(|e| Error::from_string(format!("host '{}' cannot resolve: {}", host, e)))?
});
let path = ep.url.path();
let path = ep.get_file_path();
match path_ip_map.entry(path) {
Entry::Occupied(mut e) => {
if e.get().intersection(host_ip_set).count() > 0 {
@@ -255,7 +255,7 @@ impl PoolEndpointList {
continue;
}
let path = ep.url.path();
let path = ep.get_file_path();
if local_path_set.contains(path) {
return Err(Error::from_string(format!(
"path '{}' cannot be served by different address on same server",
@@ -272,7 +272,7 @@ impl PoolEndpointList {
let mut local_endpoint_count = 0;
for ep in endpoints.as_ref() {
ep_path_set.insert(ep.url.path());
ep_path_set.insert(ep.get_file_path());
if ep.is_local && ep.url.has_host() {
local_server_host_set.insert(ep.url.host());
local_port_set.insert(ep.url.port());