33// SPDX-License-Identifier: MIT
44
55use super :: error:: { Error , Result } ;
6- #[ cfg( feature = "updater" ) ]
76use crate :: api:: file:: { ArchiveFormat , Extract , Move } ;
87use crate :: {
98 api:: http:: { ClientBuilder , HttpRequestBuilder } ,
@@ -21,7 +20,6 @@ use tauri_utils::{platform::current_exe, Env};
2120use time:: OffsetDateTime ;
2221use url:: Url ;
2322
24- #[ cfg( feature = "updater" ) ]
2523use std:: io:: Seek ;
2624use std:: {
2725 collections:: HashMap ,
@@ -33,7 +31,6 @@ use std::{
3331 time:: Duration ,
3432} ;
3533
36- #[ cfg( feature = "updater" ) ]
3734#[ cfg( not( target_os = "macos" ) ) ]
3835use std:: ffi:: OsStr ;
3936
@@ -602,29 +599,27 @@ impl<R: Runtime> Update<R> {
602599 // if there is no signature, bail out.
603600 verify_signature ( & mut archive_buffer, & self . signature , & pub_key) ?;
604601
605- #[ cfg( feature = "updater" ) ]
606- {
607- // we copy the files depending of the operating system
608- // we run the setup, appimage re-install or overwrite the
609- // macos .app
610- #[ cfg( target_os = "windows" ) ]
611- copy_files_and_run (
612- archive_buffer,
613- & self . extract_path ,
614- self . with_elevated_task ,
615- self
616- . app
617- . config ( )
618- . tauri
619- . updater
620- . windows
621- . install_mode
622- . clone ( )
623- . msiexec_args ( ) ,
624- ) ?;
625- #[ cfg( not( target_os = "windows" ) ) ]
626- copy_files_and_run ( archive_buffer, & self . extract_path ) ?;
627- }
602+ // we copy the files depending of the operating system
603+ // we run the setup, appimage re-install or overwrite the
604+ // macos .app
605+ #[ cfg( target_os = "windows" ) ]
606+ copy_files_and_run (
607+ archive_buffer,
608+ & self . extract_path ,
609+ self . with_elevated_task ,
610+ self
611+ . app
612+ . config ( )
613+ . tauri
614+ . updater
615+ . windows
616+ . install_mode
617+ . clone ( )
618+ . msiexec_args ( ) ,
619+ ) ?;
620+ #[ cfg( not( target_os = "windows" ) ) ]
621+ copy_files_and_run ( archive_buffer, & self . extract_path ) ?;
622+
628623 // We are done!
629624 Ok ( ( ) )
630625 }
@@ -640,42 +635,60 @@ impl<R: Runtime> Update<R> {
640635// We should have an AppImage already installed to be able to copy and install
641636// the extract_path is the current AppImage path
642637// tmp_dir is where our new AppImage is found
643- #[ cfg( feature = "updater" ) ]
644638#[ cfg( target_os = "linux" ) ]
645639fn copy_files_and_run < R : Read + Seek > ( archive_buffer : R , extract_path : & Path ) -> Result {
646- use std:: os:: unix:: fs:: PermissionsExt ;
647- let tmp_dir = tempfile:: Builder :: new ( )
648- . prefix ( "tauri_current_app" )
649- . tempdir ( ) ?;
650- let mut perms = std:: fs:: metadata ( tmp_dir. path ( ) ) ?. permissions ( ) ;
651- perms. set_mode ( 0o700 ) ;
652- std:: fs:: set_permissions ( tmp_dir. path ( ) , perms) ?;
653-
654- let tmp_app_image = & tmp_dir. path ( ) . join ( "current_app.AppImage" ) ;
655-
656- // create a backup of our current app image
657- Move :: from_source ( extract_path) . to_dest ( tmp_app_image) ?;
658-
659- // extract the buffer to the tmp_dir
660- // we extract our signed archive into our final directory without any temp file
661- let mut extractor =
662- Extract :: from_cursor ( archive_buffer, ArchiveFormat :: Tar ( Some ( Compression :: Gz ) ) ) ;
663-
664- extractor. with_files ( |entry| {
665- let path = entry. path ( ) ?;
666- if path. extension ( ) == Some ( OsStr :: new ( "AppImage" ) ) {
667- // if something went wrong during the extraction, we should restore previous app
668- if let Err ( err) = entry. extract ( extract_path) {
669- Move :: from_source ( tmp_app_image) . to_dest ( extract_path) ?;
670- return Err ( crate :: api:: Error :: Extract ( err. to_string ( ) ) ) ;
640+ use std:: os:: unix:: fs:: { MetadataExt , PermissionsExt } ;
641+
642+ let extract_path_metadata = extract_path. metadata ( ) ?;
643+
644+ let tmp_dir_locations = vec ! [
645+ Box :: new( || Some ( env:: temp_dir( ) ) ) as Box <dyn FnOnce ( ) -> Option <PathBuf >>,
646+ Box :: new( dirs_next:: cache_dir) ,
647+ Box :: new( || Some ( extract_path. parent( ) . unwrap( ) . to_path_buf( ) ) ) ,
648+ ] ;
649+
650+ for tmp_dir_location in tmp_dir_locations {
651+ if let Some ( tmp_dir_location) = tmp_dir_location ( ) {
652+ let tmp_dir = tempfile:: Builder :: new ( )
653+ . prefix ( "tauri_current_app" )
654+ . tempdir_in ( tmp_dir_location) ?;
655+ let tmp_dir_metadata = tmp_dir. path ( ) . metadata ( ) ?;
656+
657+ if extract_path_metadata. dev ( ) == tmp_dir_metadata. dev ( ) {
658+ let mut perms = tmp_dir_metadata. permissions ( ) ;
659+ perms. set_mode ( 0o700 ) ;
660+ std:: fs:: set_permissions ( tmp_dir. path ( ) , perms) ?;
661+
662+ let tmp_app_image = & tmp_dir. path ( ) . join ( "current_app.AppImage" ) ;
663+
664+ // create a backup of our current app image
665+ Move :: from_source ( extract_path) . to_dest ( tmp_app_image) ?;
666+
667+ // extract the buffer to the tmp_dir
668+ // we extract our signed archive into our final directory without any temp file
669+ let mut extractor =
670+ Extract :: from_cursor ( archive_buffer, ArchiveFormat :: Tar ( Some ( Compression :: Gz ) ) ) ;
671+
672+ return extractor
673+ . with_files ( |entry| {
674+ let path = entry. path ( ) ?;
675+ if path. extension ( ) == Some ( OsStr :: new ( "AppImage" ) ) {
676+ // if something went wrong during the extraction, we should restore previous app
677+ if let Err ( err) = entry. extract ( extract_path) {
678+ Move :: from_source ( tmp_app_image) . to_dest ( extract_path) ?;
679+ return Err ( crate :: api:: Error :: Extract ( err. to_string ( ) ) ) ;
680+ }
681+ // early finish we have everything we need here
682+ return Ok ( true ) ;
683+ }
684+ Ok ( false )
685+ } )
686+ . map_err ( Into :: into) ;
671687 }
672- // early finish we have everything we need here
673- return Ok ( true ) ;
674688 }
675- Ok ( false )
676- } ) ?;
689+ }
677690
678- Ok ( ( ) )
691+ Err ( Error :: TempDirNotOnSameMountPoint )
679692}
680693
681694// Windows
@@ -692,7 +705,6 @@ fn copy_files_and_run<R: Read + Seek>(archive_buffer: R, extract_path: &Path) ->
692705
693706// ## EXE
694707// Update server can provide a custom EXE (installer) who can run any task.
695- #[ cfg( feature = "updater" ) ]
696708#[ cfg( target_os = "windows" ) ]
697709#[ allow( clippy:: unnecessary_wraps) ]
698710fn copy_files_and_run < R : Read + Seek > (
@@ -795,7 +807,6 @@ fn copy_files_and_run<R: Read + Seek>(
795807// │ └── Contents # Application contents...
796808// │ └── ...
797809// └── ...
798- #[ cfg( feature = "updater" ) ]
799810#[ cfg( target_os = "macos" ) ]
800811fn copy_files_and_run < R : Read + Seek > ( archive_buffer : R , extract_path : & Path ) -> Result {
801812 let mut extracted_files: Vec < PathBuf > = Vec :: new ( ) ;
0 commit comments