refactor: is_dir only needs to look at the filename

This commit is contained in:
Chris Hennick 2024-05-15 16:44:59 -07:00
parent 09676e7bee
commit b7ac989013
No known key found for this signature in database
GPG key ID: DA47AABA4961C509
3 changed files with 23 additions and 25 deletions

View file

@ -85,7 +85,7 @@ pub(crate) mod zip_archive {
#[cfg(feature = "lzma")]
use crate::read::lzma::LzmaDecoder;
use crate::result::ZipError::{InvalidPassword, UnsupportedArchive};
use crate::spec::path_to_string;
use crate::spec::{is_dir, path_to_string};
use crate::types::ffi::S_IFLNK;
use crate::unstable::LittleEndianReadExt;
pub use zip_archive::ZipArchive;
@ -689,26 +689,28 @@ impl<R: Read + Seek> ZipArchive<R> {
if file.is_symlink() && (cfg!(unix) || cfg!(windows)) {
let mut target = Vec::with_capacity(file.size() as usize);
file.read_exact(&mut target)?;
let Ok(target) = try_utf8_to_os_string(target) else {
return Err(ZipError::InvalidArchive("Invalid UTF-8 as symlink target"));
};
#[cfg(unix)]
{
use std::os::unix::ffi::OsStringExt;
let target = OsString::from_vec(target);
let target_path = directory.as_ref().join(target);
std::os::unix::fs::symlink(target_path, outpath.as_path())?;
}
#[cfg(windows)]
{
let Ok(target) = String::from_utf8(target) else {
return Err(ZipError::InvalidArchive(
"Invalid UTF-8 as symlink target",
));
};
let target_is_dir_from_archive =
self.shared.files.contains_key(&target) && is_dir(&target);
let target_internal_path: PathBuf = target.into();
let target_path = directory.as_ref().join(target_internal_path.clone());
let target_is_dir = if let Ok(meta) = std::fs::metadata(&target_path) {
let target_is_dir = if target_is_dir_from_archive {
true
} else if let Ok(meta) = std::fs::metadata(&target_path) {
meta.is_dir()
} else if let Some(target_in_archive) =
self.index_for_path(&target_internal_path)
{
let (_, target_in_archive) =
self.shared.files.get_index(target_in_archive).unwrap();
target_in_archive.is_dir()
} else {
false
};
@ -930,12 +932,6 @@ impl<R: Read + Seek> ZipArchive<R> {
}
}
#[cfg(unix)]
fn try_utf8_to_os_string(utf8_bytes: Vec<u8>) -> Result<OsString, std::convert::Infallible> {
use std::os::unix::ffi::OsStringExt;
Ok(OsString::from_vec(utf8_bytes))
}
#[cfg(windows)]
fn try_utf8_to_os_string(utf8_bytes: Vec<u8>) -> Result<OsString, std::string::FromUtf8Error> {
Ok(OsString::from(String::from_utf8(utf8_bytes)?))
@ -1260,10 +1256,7 @@ impl<'a> ZipFile<'a> {
}
/// Returns whether the file is actually a directory
pub fn is_dir(&self) -> bool {
self.name()
.chars()
.next_back()
.map_or(false, |c| c == '/' || c == '\\')
is_dir(self.name())
}
/// Returns whether the file is actually a symbolic link

View file

@ -227,6 +227,13 @@ impl Zip64CentralDirectoryEnd {
}
}
pub(crate) fn is_dir(filename: &str) -> bool {
filename
.chars()
.next_back()
.map_or(false, |c| c == '/' || c == '\\')
}
/// Converts a path to the ZIP format (forward-slash-delimited and normalized).
pub(crate) fn path_to_string<T: AsRef<Path>>(path: T) -> Box<str> {
let mut maybe_original = None;

View file

@ -16,6 +16,7 @@ pub(crate) mod ffi {
use crate::extra_fields::ExtraField;
use crate::result::DateTimeRangeError;
use crate::spec::is_dir;
use crate::types::ffi::S_IFDIR;
use crate::CompressionMethod;
#[cfg(feature = "time")]
@ -364,10 +365,7 @@ pub struct ZipFileData {
impl ZipFileData {
#[allow(dead_code)]
pub fn is_dir(&self) -> bool {
self.file_name
.chars()
.next_back()
.map_or(false, |c| c == '/' || c == '\\')
is_dir(&self.file_name)
}
pub fn file_name_sanitized(&self) -> PathBuf {