mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-31 17:28:12 +00:00
fix: Optimize the issue of obtaining path errors on Windows.
This commit is contained in:
@@ -29,7 +29,7 @@ pub struct Endpoint {
|
|||||||
impl Display for Endpoint {
|
impl Display for Endpoint {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if self.url.scheme() == "file" {
|
if self.url.scheme() == "file" {
|
||||||
write!(f, "{}", self.url.path())
|
write!(f, "{}", self.get_file_path())
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}", self.url)
|
write!(f, "{}", self.url)
|
||||||
}
|
}
|
||||||
@@ -42,13 +42,9 @@ impl TryFrom<&str> for Endpoint {
|
|||||||
|
|
||||||
/// Performs the conversion.
|
/// Performs the conversion.
|
||||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
/// check whether given path is not empty.
|
// check whether given path is not empty.
|
||||||
fn is_empty_path(path: impl AsRef<Path>) -> bool {
|
if ["", "/", "\\"].iter().any(|&v| v.eq(value)) {
|
||||||
["", "/", "\\"].iter().any(|&v| Path::new(v).eq(path.as_ref()))
|
return Err(ErrorCode::EmptyPath().with_message("empty or root endpoint is not supported"));
|
||||||
}
|
|
||||||
|
|
||||||
if is_empty_path(value) {
|
|
||||||
return Err(Error::from_string("empty or root endpoint is not supported"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut is_local = false;
|
let mut is_local = false;
|
||||||
@@ -67,35 +63,26 @@ impl TryFrom<&str> for Endpoint {
|
|||||||
return Err(Error::from_string("invalid URL endpoint format"));
|
return Err(Error::from_string("invalid URL endpoint format"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = Path::new(url.path()).clean();
|
let path = url.path().to_string();
|
||||||
if is_empty_path(&path) {
|
|
||||||
return Err(Error::from_string("empty or root path is not supported in URL endpoint"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(v) = path.to_str() {
|
#[cfg(not(windows))]
|
||||||
url.set_path(v)
|
let path = Path::new(&path).absolutize()?;
|
||||||
}
|
|
||||||
|
|
||||||
// On windows having a preceding SlashSeparator will cause problems, if the
|
// On windows having a preceding SlashSeparator will cause problems, if the
|
||||||
// command line already has C:/<export-folder/ in it. Final resulting
|
// command line already has C:/<export-folder/ in it. Final resulting
|
||||||
// path on windows might become C:/C:/ this will cause problems
|
// path on windows might become C:/C:/ this will cause problems
|
||||||
// of starting rustfs server properly in distributed mode on windows.
|
// of starting rustfs server properly in distributed mode on windows.
|
||||||
// As a special case make sure to trim the separator.
|
// 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)]
|
#[cfg(windows)]
|
||||||
{
|
let path = Path::new(&path[1..]).absolutize()?;
|
||||||
let path = url.path().to_owned();
|
|
||||||
if Path::new(&path[1..]).is_absolute() {
|
if path.parent().is_none() || Path::new("").eq(&path) {
|
||||||
url.set_path(&path[1..]);
|
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
|
url
|
||||||
@@ -182,6 +169,15 @@ impl Endpoint {
|
|||||||
_ => String::new(),
|
_ => 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.
|
/// parse a file path into an URL.
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl Debug for LocalDisk {
|
|||||||
|
|
||||||
impl LocalDisk {
|
impl LocalDisk {
|
||||||
pub async fn new(ep: &Endpoint, cleanup: bool) -> Result<Self> {
|
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 {
|
if cleanup {
|
||||||
// TODO: 删除tmp数据
|
// TODO: 删除tmp数据
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ pub struct RemoteDisk {
|
|||||||
impl RemoteDisk {
|
impl RemoteDisk {
|
||||||
pub async fn new(ep: &Endpoint, _opt: &DiskOption) -> Result<Self> {
|
pub async fn new(ep: &Endpoint, _opt: &DiskOption) -> Result<Self> {
|
||||||
// let root = fs::canonicalize(ep.url.path()).await?;
|
// 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());
|
let addr = format!("{}://{}:{}", ep.url.scheme(), ep.url.host_str().unwrap(), ep.url.port().unwrap());
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: Mutex::new(None),
|
id: Mutex::new(None),
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ impl PoolEndpointList {
|
|||||||
.map_err(|e| Error::from_string(format!("host '{}' cannot resolve: {}", host, e)))?
|
.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) {
|
match path_ip_map.entry(path) {
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
if e.get().intersection(host_ip_set).count() > 0 {
|
if e.get().intersection(host_ip_set).count() > 0 {
|
||||||
@@ -255,7 +255,7 @@ impl PoolEndpointList {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = ep.url.path();
|
let path = ep.get_file_path();
|
||||||
if local_path_set.contains(path) {
|
if local_path_set.contains(path) {
|
||||||
return Err(Error::from_string(format!(
|
return Err(Error::from_string(format!(
|
||||||
"path '{}' cannot be served by different address on same server",
|
"path '{}' cannot be served by different address on same server",
|
||||||
@@ -272,7 +272,7 @@ impl PoolEndpointList {
|
|||||||
let mut local_endpoint_count = 0;
|
let mut local_endpoint_count = 0;
|
||||||
|
|
||||||
for ep in endpoints.as_ref() {
|
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() {
|
if ep.is_local && ep.url.has_host() {
|
||||||
local_server_host_set.insert(ep.url.host());
|
local_server_host_set.insert(ep.url.host());
|
||||||
local_port_set.insert(ep.url.port());
|
local_port_set.insert(ep.url.port());
|
||||||
|
|||||||
Reference in New Issue
Block a user