11/*
22This file is part of rmw<https://theimpossibleastronaut.github.io/rmw-website/>
33
4- Copyright (C) 2012-2023 Andy Alt (arch_stanton5995@proton.me)
4+ Copyright (C) 2012-2025 Andy Alt (arch_stanton5995@proton.me)
55Other authors: https://github.com/theimpossibleastronaut/rmw/blob/master/AUTHORS.md
66
77This program is free software: you can redistribute it and/or modify
@@ -63,6 +63,67 @@ get_waste_parent(char *waste_parent, const char *src)
6363 return ;
6464}
6565
66+ static int
67+ move_back (const char * src , const char * dest , bool want_dry_run )
68+ {
69+ int rename_res = 0 ;
70+ int save_errno = 0 ;
71+ int clone_errno = 0 ;
72+
73+ if (want_dry_run )
74+ return 0 ;
75+
76+ rename_res = rename (src , dest );
77+ if (rename_res == 0 )
78+ return 0 ; /* success */
79+
80+ /* rename failed; preserve errno immediately */
81+ save_errno = errno ;
82+
83+ struct stat st_src ;
84+
85+ /* rename already failed and save_errno == errno from rename() */
86+ if (save_errno == EXDEV )
87+ {
88+ /* get file type without following symlinks */
89+ if (lstat (src , & st_src ) != 0 )
90+ {
91+ /* cannot stat. restore rename's errno and fail */
92+ errno = save_errno ;
93+ return -1 ;
94+ }
95+
96+ if (S_ISDIR (st_src .st_mode ))
97+ {
98+ /* directory on different device -> execv mv */
99+ int mv_ret = safe_mv_via_exec (src , dest , & clone_errno );
100+ if (mv_ret == 0 )
101+ {
102+ errno = 0 ;
103+ return 0 ;
104+ }
105+ errno = clone_errno ? clone_errno : save_errno ;
106+ return -1 ;
107+ }
108+ else
109+ {
110+ /* regular file on different device -> try btrfs clone */
111+ int clone_res = do_btrfs_clone (src , dest , & clone_errno );
112+ if (clone_res == 0 )
113+ {
114+ errno = 0 ;
115+ return 0 ;
116+ }
117+ errno = clone_errno ? clone_errno : save_errno ;
118+ return -1 ;
119+ }
120+ }
121+
122+ /* other rename error */
123+ errno = save_errno ;
124+ return -1 ;
125+ }
126+
66127
67128int
68129restore (const char * src , st_time * st_time_var ,
@@ -171,16 +232,10 @@ Duplicate filename at destination - appending time string...\n"));
171232 return p_state_parent ;
172233 }
173234
174- int rename_res = 0 ;
175- int save_errno = errno ;
176- if (cli_user_options -> want_dry_run == false)
177- {
178- rename_res = rename (src , dest );
179- if (errno == EXDEV )
180- rename_res = do_btrfs_clone (src , dest , & save_errno );
181- }
235+ int res = move_back (src , dest , cli_user_options -> want_dry_run );
236+
182237
183- if (!rename_res )
238+ if (!res )
184239 {
185240 printf ("+'%s' -> '%s'\n" , src , dest );
186241
@@ -199,7 +254,7 @@ Duplicate filename at destination - appending time string...\n"));
199254 else
200255 {
201256 msg_err_rename (src , dest );
202- return rename_res ;
257+ return res ;
203258 }
204259 }
205260 else
0 commit comments