diff --git a/ecstore/src/disk/endpoint.rs b/ecstore/src/disk/endpoint.rs index 254a1213b..f764baa4a 100644 --- a/ecstore/src/disk/endpoint.rs +++ b/ecstore/src/disk/endpoint.rs @@ -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 { - /// check whether given path is not empty. - fn is_empty_path(path: impl AsRef) -> 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:/ 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. diff --git a/ecstore/src/disk/local.rs b/ecstore/src/disk/local.rs index 8a559477e..7f8bd1cc6 100644 --- a/ecstore/src/disk/local.rs +++ b/ecstore/src/disk/local.rs @@ -114,7 +114,7 @@ impl Debug for LocalDisk { impl LocalDisk { pub async fn new(ep: &Endpoint, cleanup: bool) -> Result { - let root = fs::canonicalize(ep.url.path()).await?; + let root = fs::canonicalize(ep.get_file_path()).await?; if cleanup { // TODO: 删除tmp数据 diff --git a/ecstore/src/disk/remote.rs b/ecstore/src/disk/remote.rs index 9b6597d65..68a5ab31e 100644 --- a/ecstore/src/disk/remote.rs +++ b/ecstore/src/disk/remote.rs @@ -52,7 +52,7 @@ pub struct RemoteDisk { impl RemoteDisk { pub async fn new(ep: &Endpoint, _opt: &DiskOption) -> Result { // 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), diff --git a/ecstore/src/endpoints.rs b/ecstore/src/endpoints.rs index 5a0cac5cc..8dbee9928 100644 --- a/ecstore/src/endpoints.rs +++ b/ecstore/src/endpoints.rs @@ -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());