Fix windows compilation issues

This commit is contained in:
Jeremy Soller 2026-04-17 13:31:55 -06:00
parent 8c57060db2
commit 4afacccc8a
5 changed files with 59 additions and 22 deletions

View file

@ -189,6 +189,8 @@ fn zip_extract<R: io::Read + io::Seek, P: AsRef<Path>>(
if file.is_symlink() && (cfg!(unix) || cfg!(windows)) { if file.is_symlink() && (cfg!(unix) || cfg!(windows)) {
let mut target = Vec::with_capacity(file.size() as usize); let mut target = Vec::with_capacity(file.size() as usize);
file.read_to_end(&mut target)?; file.read_to_end(&mut target)?;
// File no longer needed, drop to allow reading target on windows
drop(file);
#[cfg(unix)] #[cfg(unix)]
{ {
@ -199,11 +201,15 @@ fn zip_extract<R: io::Read + io::Seek, P: AsRef<Path>>(
#[cfg(windows)] #[cfg(windows)]
{ {
let Ok(target) = String::from_utf8(target) else { let Ok(target) = String::from_utf8(target) else {
return Err(ZipError::InvalidArchive("Invalid UTF-8 as symlink target")); return Err(ZipError::InvalidArchive(
"Invalid UTF-8 as symlink target".into(),
));
}; };
let target = target.into_boxed_str(); let target_is_dir_from_archive = match password {
let target_is_dir_from_archive = None => archive.by_name(&target),
archive.shared.files.contains_key(&target) && is_dir(&target); Some(pwd) => archive.by_name_decrypt(&target, pwd.as_bytes()),
}
.map_or(false, |x| x.is_dir());
let target_path = directory.as_ref().join(OsString::from(target.to_string())); let target_path = directory.as_ref().join(OsString::from(target.to_string()));
let target_is_dir = if target_is_dir_from_archive { let target_is_dir = if target_is_dir_from_archive {
true true

View file

@ -19,6 +19,7 @@ struct MimeIconKey {
struct MimeIconCache { struct MimeIconCache {
cache: FxHashMap<MimeIconKey, Option<icon::Handle>>, cache: FxHashMap<MimeIconKey, Option<icon::Handle>>,
#[cfg(unix)]
shared_mime_info: xdg_mime::SharedMimeInfo, shared_mime_info: xdg_mime::SharedMimeInfo,
} }
@ -26,10 +27,17 @@ impl MimeIconCache {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
cache: FxHashMap::default(), cache: FxHashMap::default(),
#[cfg(unix)]
shared_mime_info: xdg_mime::SharedMimeInfo::new(), shared_mime_info: xdg_mime::SharedMimeInfo::new(),
} }
} }
#[cfg(not(unix))]
pub fn get(&mut self, _key: MimeIconKey) -> Option<icon::Handle> {
None
}
#[cfg(unix)]
pub fn get(&mut self, key: MimeIconKey) -> Option<icon::Handle> { pub fn get(&mut self, key: MimeIconKey) -> Option<icon::Handle> {
self.cache self.cache
.entry(key) .entry(key)
@ -53,6 +61,16 @@ impl MimeIconCache {
static MIME_ICON_CACHE: LazyLock<Mutex<MimeIconCache>> = static MIME_ICON_CACHE: LazyLock<Mutex<MimeIconCache>> =
LazyLock::new(|| Mutex::new(MimeIconCache::new())); LazyLock::new(|| Mutex::new(MimeIconCache::new()));
#[cfg(not(unix))]
pub fn mime_for_path(
path: impl AsRef<Path>,
metadata_opt: Option<&fs::Metadata>,
remote: bool,
) -> Mime {
mime_guess::from_path(path).first_or_octet_stream()
}
#[cfg(unix)]
pub fn mime_for_path( pub fn mime_for_path(
path: impl AsRef<Path>, path: impl AsRef<Path>,
metadata_opt: Option<&fs::Metadata>, metadata_opt: Option<&fs::Metadata>,
@ -100,8 +118,13 @@ pub fn mime_icon(mime: Mime, size: u16) -> icon::Handle {
} }
} }
#[cfg(not(unix))]
pub fn parent_mime_types(_mime: &Mime) -> Option<Vec<Mime>> {
None
}
#[cfg(unix)]
pub fn parent_mime_types(mime: &Mime) -> Option<Vec<Mime>> { pub fn parent_mime_types(mime: &Mime) -> Option<Vec<Mime>> {
let mime_icon_cache = MIME_ICON_CACHE.lock().unwrap(); let mime_icon_cache = MIME_ICON_CACHE.lock().unwrap();
mime_icon_cache.shared_mime_info.get_parents_aliased(mime) mime_icon_cache.shared_mime_info.get_parents_aliased(mime)
} }

View file

@ -41,6 +41,8 @@ use jiff_icu::ConvertFrom;
use mime_guess::{Mime, mime}; use mime_guess::{Mime, mime};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
use std::{ use std::{
borrow::Cow, borrow::Cow,
cell::Cell, cell::Cell,
@ -51,7 +53,6 @@ use std::{
fs::{self, File, Metadata}, fs::{self, File, Metadata},
hash::Hash, hash::Hash,
io::{BufRead, BufReader}, io::{BufRead, BufReader},
os::unix::fs::MetadataExt,
path::{self, Path, PathBuf}, path::{self, Path, PathBuf},
sync::{Arc, LazyLock, RwLock, atomic}, sync::{Arc, LazyLock, RwLock, atomic},
time::{Duration, Instant, SystemTime}, time::{Duration, Instant, SystemTime},
@ -4339,6 +4340,7 @@ impl Tab {
for item in self.items_opt().map_or(Vec::new(), |items| { for item in self.items_opt().map_or(Vec::new(), |items| {
items.iter().filter(|item| item.selected).collect() items.iter().filter(|item| item.selected).collect()
}) { }) {
#[cfg(unix)]
if let (Some(path), Some(mode)) = ( if let (Some(path), Some(mode)) = (
item.path_opt(), item.path_opt(),
item.file_metadata() item.file_metadata()
@ -6356,22 +6358,23 @@ impl Tab {
} else { } else {
total_size = total_size.saturating_add(metadata.len()); total_size = total_size.saturating_add(metadata.len());
} }
let mode = metadata.mode();
#[cfg(unix)] #[cfg(unix)]
user_name.insert( {
uzers::get_user_by_uid(metadata.uid()) let mode = metadata.mode();
.and_then(|user| user.name().to_str().map(ToOwned::to_owned)) user_name.insert(
.unwrap_or_default(), uzers::get_user_by_uid(metadata.uid())
); .and_then(|user| user.name().to_str().map(ToOwned::to_owned))
mode_user.insert(get_mode_part(mode, MODE_SHIFT_USER)); .unwrap_or_default(),
#[cfg(unix)] );
group_name.insert( mode_user.insert(get_mode_part(mode, MODE_SHIFT_USER));
uzers::get_group_by_gid(metadata.gid()) group_name.insert(
.and_then(|group| group.name().to_str().map(ToOwned::to_owned)) uzers::get_group_by_gid(metadata.gid())
.unwrap_or_default(), .and_then(|group| group.name().to_str().map(ToOwned::to_owned))
); .unwrap_or_default(),
mode_group.insert(get_mode_part(mode, MODE_SHIFT_GROUP)); );
mode_other.insert(get_mode_part(mode, MODE_SHIFT_OTHER)); mode_group.insert(get_mode_part(mode, MODE_SHIFT_GROUP));
mode_other.insert(get_mode_part(mode, MODE_SHIFT_OTHER));
}
} }
} }
let mut mime_types: Vec<(String, u64)> = mime_type_counts.into_iter().collect(); let mut mime_types: Vec<(String, u64)> = mime_type_counts.into_iter().collect();

View file

@ -1,11 +1,12 @@
use image::DynamicImage; use image::DynamicImage;
use md5::{Digest, Md5}; use md5::{Digest, Md5};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::{ use std::{
error::Error, error::Error,
fs::{self, File}, fs::{self, File},
io::{self, BufReader, BufWriter}, io::{self, BufReader, BufWriter},
os::unix::fs::PermissionsExt,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::LazyLock, sync::LazyLock,
time::UNIX_EPOCH, time::UNIX_EPOCH,
@ -93,6 +94,7 @@ impl ThumbnailCacher {
} }
pub fn update_with_temp_file(&self, temp_file: NamedTempFile) -> Result<&Path, Box<dyn Error>> { pub fn update_with_temp_file(&self, temp_file: NamedTempFile) -> Result<&Path, Box<dyn Error>> {
#[cfg(unix)]
fs::set_permissions(temp_file.path(), fs::Permissions::from_mode(0o600))?; fs::set_permissions(temp_file.path(), fs::Permissions::from_mode(0o600))?;
self.update_thumbnail_text_metadata(temp_file.path())?; self.update_thumbnail_text_metadata(temp_file.path())?;
fs::rename(temp_file.path(), &self.thumbnail_path)?; fs::rename(temp_file.path(), &self.thumbnail_path)?;
@ -127,6 +129,7 @@ impl ThumbnailCacher {
pub fn create_fail_marker(&self) -> Result<(), Box<dyn Error>> { pub fn create_fail_marker(&self) -> Result<(), Box<dyn Error>> {
if let Some(dir) = self.thumbnail_fail_marker_path.parent() { if let Some(dir) = self.thumbnail_fail_marker_path.parent() {
fs::create_dir_all(dir)?; fs::create_dir_all(dir)?;
#[cfg(unix)]
fs::set_permissions(dir, fs::Permissions::from_mode(0o700))?; fs::set_permissions(dir, fs::Permissions::from_mode(0o700))?;
} }

View file

@ -74,6 +74,8 @@ impl TrashExt for Trash {
} }
} }
// Not available on Windows only
#[cfg(not(target_os = "windows"))]
fn folders() -> Result<HashSet<PathBuf>, trash::Error> { fn folders() -> Result<HashSet<PathBuf>, trash::Error> {
trash::os_limited::trash_folders() trash::os_limited::trash_folders()
} }