Skip to content

Commit d8cfd53

Browse files
committed
xinstall: apply fixes from vendor/install
See ea247a7.
1 parent 204be40 commit d8cfd53

File tree

1 file changed

+60
-41
lines changed

1 file changed

+60
-41
lines changed

src/pextlib1.0/xinstall.c

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ static int copy(Tcl_Interp *interp, int, const char *, int, const char *, off_t)
146146
static int compare(int, const char *, size_t, int, const char *, size_t);
147147
static int create_newfile(Tcl_Interp *interp, const char *, int, struct stat *);
148148
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
149154
static int install(Tcl_Interp *interp, const char *, const char *, u_long, u_int);
150155
static int install_dir(Tcl_Interp *interp, char *);
151156
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
448453
int tempcopy, temp_fd = -1, to_fd = -1;
449454
char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
450455
#if defined(HAVE_CLONEFILE) && defined(CLONE_NOOWNERCOPY)
451-
const int tryclone = 1;
456+
int tryclone = 1;
452457
#else
453458
const int tryclone = 0;
454459
#endif
@@ -537,7 +542,12 @@ install(Tcl_Interp *interp, const char *from_name, const char *to_name, u_long f
537542
int done_clone = 0;
538543
#if defined(HAVE_CLONEFILE) && defined(CLONE_NOOWNERCOPY)
539544
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+
}
541551
}
542552
if (done_clone &&
543553
(((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)
905915
return (mkstemp(temp));
906916
}
907917

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+
908964
/*
909965
* create_newfile --
910966
* create a new file, overwriting an existing one if necessary
911967
*/
912968
static int
913-
#if defined(UF_IMMUTABLE) && defined(SF_IMMUTABLE)
914969
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
918970
{
919-
char backup[MAXPATHLEN];
920971
int saved_errno = 0;
921972
int newfd;
922973

923974
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);
957976
}
958977

959978
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,
10541073
mktemp(temp_name);
10551074
to_name = temp_name;
10561075
}
1057-
return clonefile(from_name, to_name, CLONE_NOFOLLOW|CLONE_NOOWNERCOPY);
1076+
return clonefile(from_name, to_name, CLONE_NOOWNERCOPY);
10581077
}
10591078
#endif
10601079

0 commit comments

Comments
 (0)