@@ -146,6 +146,11 @@ static int copy(Tcl_Interp *interp, int, const char *, int, const char *, off_t)
146
146
static int compare (int , const char * , size_t , int , const char * , size_t );
147
147
static int create_newfile (Tcl_Interp * interp , const char * , int , struct stat * );
148
148
static int create_tempfile (const char * , char * , size_t );
149
+ #if defined(UF_IMMUTABLE ) && defined(SF_IMMUTABLE )
150
+ static int handle_existing_file (Tcl_Interp * interp , const char * path , struct stat * sbp );
151
+ #else
152
+ static int handle_existing_file (Tcl_Interp * interp , const char * path , struct stat * sbp UNUSED );
153
+ #endif
149
154
static int install (Tcl_Interp * interp , const char * , const char * , u_long , u_int );
150
155
static int install_dir (Tcl_Interp * interp , char * );
151
156
static u_long numeric_id (Tcl_Interp * interp , const char * , const char * , int * rval );
@@ -448,7 +453,7 @@ install(Tcl_Interp *interp, const char *from_name, const char *to_name, u_long f
448
453
int tempcopy , temp_fd = -1 , to_fd = -1 ;
449
454
char backup [MAXPATHLEN ], * p , pathbuf [MAXPATHLEN ], tempfile [MAXPATHLEN ];
450
455
#if defined(HAVE_CLONEFILE ) && defined(CLONE_NOOWNERCOPY )
451
- const int tryclone = 1 ;
456
+ int tryclone = 1 ;
452
457
#else
453
458
const int tryclone = 0 ;
454
459
#endif
@@ -537,7 +542,12 @@ install(Tcl_Interp *interp, const char *from_name, const char *to_name, u_long f
537
542
int done_clone = 0 ;
538
543
#if defined(HAVE_CLONEFILE ) && defined(CLONE_NOOWNERCOPY )
539
544
if (tryclone && !devnull && !dostrip ) {
540
- done_clone = (clone (from_name , to_name , tempcopy , tempfile , sizeof (tempfile )) == 0 );
545
+ if (!tempcopy && target && handle_existing_file (interp , to_name , & to_sb ) != 0 ) {
546
+ tryclone = 0 ;
547
+ }
548
+ if (tryclone ) {
549
+ done_clone = (clone (from_name , to_name , tempcopy , tempfile , sizeof (tempfile )) == 0 );
550
+ }
541
551
}
542
552
if (done_clone &&
543
553
(((to_fd = open (tempcopy ? tempfile : to_name , O_RDONLY , 0 )) < 0 )
@@ -905,55 +915,64 @@ create_tempfile(const char *path, char *temp, size_t tsize)
905
915
return (mkstemp (temp ));
906
916
}
907
917
918
+ /* unlink or move (backup) an existing file */
919
+ static int
920
+ #if defined(UF_IMMUTABLE ) && defined(SF_IMMUTABLE )
921
+ handle_existing_file (Tcl_Interp * interp , const char * path , struct stat * sbp )
922
+ #else
923
+ handle_existing_file (Tcl_Interp * interp , const char * path , struct stat * sbp UNUSED )
924
+ #endif
925
+ {
926
+ char backup [MAXPATHLEN ];
927
+ /*
928
+ * Unlink now... avoid ETXTBSY errors later. Try to turn
929
+ * off the append/immutable bits -- if we fail, go ahead,
930
+ * it might work.
931
+ */
932
+ #if defined(UF_IMMUTABLE ) && defined(SF_IMMUTABLE )
933
+ if (sbp -> st_flags & NOCHANGEBITS )
934
+ (void )chflags (path , sbp -> st_flags & ~NOCHANGEBITS );
935
+ #endif
936
+
937
+ if (dobackup ) {
938
+ if ((size_t )snprintf (backup , MAXPATHLEN , "%s%s" ,
939
+ path , suffix ) != strlen (path ) + strlen (suffix )) {
940
+ char errmsg [255 ];
941
+
942
+ snprintf (errmsg , sizeof errmsg , "%s: Backup filename %s too long" ,
943
+ funcname , path );
944
+ Tcl_SetResult (interp , errmsg , TCL_VOLATILE );
945
+ return EINVAL ;
946
+ }
947
+ (void )snprintf (backup , MAXPATHLEN , "%s%s" , path , suffix );
948
+ ui_info (interp , "%s: %s -> %s" , funcname , path , backup );
949
+ if (rename (path , backup ) < 0 ) {
950
+ char errmsg [255 ];
951
+ int saved_errno = errno ;
952
+
953
+ snprintf (errmsg , sizeof errmsg , "%s: Rename: %s to %s, %s" ,
954
+ funcname , path , backup , strerror (errno ));
955
+ Tcl_SetResult (interp , errmsg , TCL_VOLATILE );
956
+ return saved_errno ;
957
+ }
958
+ } else if (unlink (path ) < 0 ) {
959
+ return errno ;
960
+ }
961
+ return 0 ;
962
+ }
963
+
908
964
/*
909
965
* create_newfile --
910
966
* create a new file, overwriting an existing one if necessary
911
967
*/
912
968
static int
913
- #if defined(UF_IMMUTABLE ) && defined(SF_IMMUTABLE )
914
969
create_newfile (Tcl_Interp * interp , const char * path , int target , struct stat * sbp )
915
- #else
916
- create_newfile (Tcl_Interp * interp , const char * path , int target , struct stat * sbp UNUSED )
917
- #endif
918
970
{
919
- char backup [MAXPATHLEN ];
920
971
int saved_errno = 0 ;
921
972
int newfd ;
922
973
923
974
if (target ) {
924
- /*
925
- * Unlink now... avoid ETXTBSY errors later. Try to turn
926
- * off the append/immutable bits -- if we fail, go ahead,
927
- * it might work.
928
- */
929
- #if defined(UF_IMMUTABLE ) && defined(SF_IMMUTABLE )
930
- if (sbp -> st_flags & NOCHANGEBITS )
931
- (void )chflags (path , sbp -> st_flags & ~NOCHANGEBITS );
932
- #endif
933
-
934
- if (dobackup ) {
935
- if ((size_t )snprintf (backup , MAXPATHLEN , "%s%s" ,
936
- path , suffix ) != strlen (path ) + strlen (suffix )) {
937
- char errmsg [255 ];
938
-
939
- snprintf (errmsg , sizeof errmsg , "%s: Backup filename %s too long" ,
940
- funcname , path );
941
- Tcl_SetResult (interp , errmsg , TCL_VOLATILE );
942
- return -1 ;
943
- }
944
- (void )snprintf (backup , MAXPATHLEN , "%s%s" , path , suffix );
945
- ui_info (interp , "%s: %s -> %s" , funcname , path , backup );
946
- if (rename (path , backup ) < 0 ) {
947
- char errmsg [255 ];
948
-
949
- snprintf (errmsg , sizeof errmsg , "%s: Rename: %s to %s, %s" ,
950
- funcname , path , backup , strerror (errno ));
951
- Tcl_SetResult (interp , errmsg , TCL_VOLATILE );
952
- return -1 ;
953
- }
954
- } else
955
- if (unlink (path ) < 0 )
956
- saved_errno = errno ;
975
+ saved_errno = handle_existing_file (interp , path , sbp );
957
976
}
958
977
959
978
newfd = open (path , O_CREAT | O_RDWR | O_TRUNC , S_IRUSR | S_IWUSR );
@@ -1054,7 +1073,7 @@ clone(const char *from_name, const char *to_name,
1054
1073
mktemp (temp_name );
1055
1074
to_name = temp_name ;
1056
1075
}
1057
- return clonefile (from_name , to_name , CLONE_NOFOLLOW | CLONE_NOOWNERCOPY );
1076
+ return clonefile (from_name , to_name , CLONE_NOOWNERCOPY );
1058
1077
}
1059
1078
#endif
1060
1079
0 commit comments