From b8e034cd10cff676d8cbbeab0d33f93b6a2aaae4 Mon Sep 17 00:00:00 2001 From: Jean-Charles Campagne Date: Thu, 28 Jul 2022 10:57:34 +0100 Subject: [PATCH] Ignore broken symlinks for LocalFileSystem object store (#2195) * Re-enable test_list_root test for MacOS * LocalFileSystem: ignore broken links in convert_walkdir_result --- object_store/src/local.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/object_store/src/local.rs b/object_store/src/local.rs index 798edef6f37..e2f133e84d7 100644 --- a/object_store/src/local.rs +++ b/object_store/src/local.rs @@ -27,7 +27,7 @@ use futures::future::BoxFuture; use futures::FutureExt; use futures::{stream::BoxStream, StreamExt}; use snafu::{ensure, OptionExt, ResultExt, Snafu}; -use std::fs::File; +use std::fs::{metadata, symlink_metadata, File}; use std::io::{Read, Seek, SeekFrom, Write}; use std::ops::Range; use std::pin::Pin; @@ -804,11 +804,36 @@ fn convert_metadata(metadata: std::fs::Metadata, location: Path) -> Result, ) -> Result> { match res { - Ok(entry) => Ok(Some(entry)), + Ok(entry) => { + // To check for broken symlink: call symlink_metadata() - it does not traverse symlinks); + // if ok: check if entry is symlink; and try to read it by calling metadata(). + match symlink_metadata(entry.path()) { + Ok(attr) => { + if attr.is_symlink() { + let target_metadata = metadata(entry.path()); + match target_metadata { + Ok(_) => { + // symlink is valid + Ok(Some(entry)) + } + Err(_) => { + // this is a broken symlink, return None + Ok(None) + } + } + } else { + Ok(Some(entry)) + } + } + Err(_) => Ok(None), + } + } + Err(walkdir_err) => match walkdir_err.io_error() { Some(io_err) => match io_err.kind() { io::ErrorKind::NotFound => Ok(None), @@ -990,8 +1015,6 @@ mod tests { } #[tokio::test] - #[cfg(target_os = "linux")] - // macos has some magic in its root '/.VolumeIcon.icns"' which causes this test to fail async fn test_list_root() { let integration = LocalFileSystem::new(); let result = integration.list_with_delimiter(None).await;