From b6f39cc51c4be15fbc5f8623bcc775e23d0160af Mon Sep 17 00:00:00 2001 From: Den Ilin Date: Sun, 11 Oct 2026 00:46:00 +0700 Subject: [PATCH] fix(updater): don't fail AppImage installs when the temp dir is another mount of the same file system (#3688) * fix(updater): skip a backup location the AppImage cannot be renamed into Two mounts of one file system share st_dev, so install_appimage could pick a bind-mounted or private temp dir and then fail every install with EXDEV. Move on to the next location instead; the last one is the AppImage's own directory. * Apply suggestion from @lucasfernog --------- Co-authored-by: Lucas Fernandes Nogueira --- .changes/updater-appimage-cross-mount.md | 6 ++++++ plugins/updater/src/updater.rs | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 .changes/updater-appimage-cross-mount.md diff --git a/.changes/updater-appimage-cross-mount.md b/.changes/updater-appimage-cross-mount.md new file mode 100644 index 000000000..f8cf4e2f5 --- /dev/null +++ b/.changes/updater-appimage-cross-mount.md @@ -0,0 +1,6 @@ +--- +updater: patch +updater-js: patch +--- + +On Linux, installing an AppImage update no longer fails with `Invalid cross-device link (os error 18)` when the temp or cache directory is a separate mount of the AppImage's file system, such as a bind-mounted or private `/tmp`. The backup now moves on to the next location, ending with the AppImage's own directory. diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index a34f4c031..d850ee3fb 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -1234,7 +1234,11 @@ impl Update { let permissions = std::fs::metadata(&self.extract_path)?.permissions(); // create a backup of our current app image - std::fs::rename(&self.extract_path, tmp_app_image)?; + match std::fs::rename(&self.extract_path, tmp_app_image) { + Ok(()) => {} + Err(err) if err.kind() == std::io::ErrorKind::CrossesDevices => continue, + Err(err) => return Err(err.into()), + } #[cfg(feature = "zip")] if infer::archive::is_gz(bytes) {