vendor/install: correct file handling

Handle existing target files and source symlinks in the expected way.

Closes: https://trac.macports.org/ticket/72850
This commit is contained in:
Joshua Root
2025-08-18 10:21:00 +10:00
parent 05122e1f46
commit ea247a70af
2 changed files with 115 additions and 36 deletions
+36 -25
View File
@@ -93,6 +93,7 @@ mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
char *suffix = BACKUP_SUFFIX;
static int clone __P((const char *, const char *, int, char *, size_t));
static void handle_existing_file __P((char *path, struct stat *sbp));
void copy __P((int, char *, int, char *, off_t));
int compare __P((int, const char *, size_t, int, const char *, size_t));
int create_newfile __P((char *, int, struct stat *));
@@ -339,6 +340,9 @@ install(char *from_name, char *to_name,
if (!files_match) {
int done_clone = 0;
if (tryclone && !devnull && !dostrip) {
if (!tempcopy && target) {
handle_existing_file(to_name, &to_sb);
}
done_clone = (clone(from_name, to_name, tempcopy, tempfile, sizeof(tempfile)) == 0);
}
if (done_clone &&
@@ -640,6 +644,36 @@ create_tempfile(char *path,
return (mkstemp(temp));
}
/* unlink or move (backup) an existing file */
static void
handle_existing_file(char *path, struct stat *sbp)
{
char backup[MAXPATHLEN];
/*
* Unlink now... avoid ETXTBSY errors later. Try to turn
* off the append/immutable bits -- if we fail, go ahead,
* it might work.
*/
if (sbp->st_flags & NOCHANGEBITS)
(void)chflags(path, sbp->st_flags & ~NOCHANGEBITS);
if (dobackup) {
if (snprintf(backup, MAXPATHLEN, "%s%s",
path, suffix) != strlen(path) + strlen(suffix))
errx(EX_OSERR, "%s: backup filename too long",
path);
(void)snprintf(backup, MAXPATHLEN, "%s%s",
path, suffix);
if (verbose)
(void)printf("install: %s -> %s\n",
path, backup);
if (rename(path, backup) < 0)
err(EX_OSERR, "rename: %s to %s", path, backup);
} else {
(void)unlink(path);
}
}
/*
* create_newfile --
* create a new file, overwriting an existing one if necessary
@@ -649,31 +683,8 @@ create_newfile(char *path,
int target,
struct stat *sbp)
{
char backup[MAXPATHLEN];
if (target) {
/*
* Unlink now... avoid ETXTBSY errors later. Try to turn
* off the append/immutable bits -- if we fail, go ahead,
* it might work.
*/
if (sbp->st_flags & NOCHANGEBITS)
(void)chflags(path, sbp->st_flags & ~NOCHANGEBITS);
if (dobackup) {
if (snprintf(backup, MAXPATHLEN, "%s%s",
path, suffix) != strlen(path) + strlen(suffix))
errx(EX_OSERR, "%s: backup filename too long",
path);
(void)snprintf(backup, MAXPATHLEN, "%s%s",
path, suffix);
if (verbose)
(void)printf("install: %s -> %s\n",
path, backup);
if (rename(path, backup) < 0)
err(EX_OSERR, "rename: %s to %s", path, backup);
} else
(void)unlink(path);
handle_existing_file(path, sbp);
}
return (open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR));
@@ -775,7 +786,7 @@ clone(const char *from_name, const char *to_name,
mktemp(temp_name);
to_name = temp_name;
}
return clonefile(from_name, to_name, CLONE_NOFOLLOW|CLONE_NOOWNERCOPY);
return clonefile(from_name, to_name, CLONE_NOOWNERCOPY);
}
/*
+79 -11
View File
@@ -1,8 +1,8 @@
Applied to original from file_cmds-430.140.2
--- xinstall.c.orig 2024-08-20 16:07:42
+++ xinstall.c 2024-08-27 16:58:56
@@ -70,9 +70,9 @@
+++ xinstall.c 2025-08-18 10:03:32
@@ -70,9 +70,9 @@ __used static const char rcsid[] =
#ifdef __APPLE__
#include <TargetConditionals.h>
#include <copyfile.h>
@@ -14,15 +14,16 @@ Applied to original from file_cmds-430.140.2
/* Bootstrap aid - this doesn't exist in most older releases */
#ifndef MAP_FAILED
@@ -92,6 +92,7 @@
@@ -92,6 +92,8 @@ char *suffix = BACKUP_SUFFIX;
mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
char *suffix = BACKUP_SUFFIX;
+static int clone __P((const char *, const char *, int, char *, size_t));
+static void handle_existing_file __P((char *path, struct stat *sbp));
void copy __P((int, char *, int, char *, off_t));
int compare __P((int, const char *, size_t, int, const char *, size_t));
int create_newfile __P((char *, int, struct stat *));
@@ -100,6 +101,7 @@
@@ -100,6 +102,7 @@ void strip __P((char *));
void install_dir __P((char *));
u_long numeric_id __P((char *, char *));
void strip __P((char *));
@@ -30,7 +31,7 @@ Applied to original from file_cmds-430.140.2
int trymmap __P((int));
void usage __P((void));
@@ -276,9 +278,10 @@
@@ -276,9 +279,10 @@ install(char *from_name, char *to_name,
{
struct stat from_sb, temp_sb, to_sb;
struct utimbuf utb;
@@ -43,12 +44,15 @@ Applied to original from file_cmds-430.140.2
files_match = 0;
@@ -334,6 +337,17 @@
@@ -334,6 +338,20 @@ install(char *from_name, char *to_name,
}
if (!files_match) {
+ int done_clone = 0;
+ if (tryclone && !devnull && !dostrip) {
+ if (!tempcopy && target) {
+ handle_existing_file(to_name, &to_sb);
+ }
+ done_clone = (clone(from_name, to_name, tempcopy, tempfile, sizeof(tempfile)) == 0);
+ }
+ if (done_clone &&
@@ -61,7 +65,7 @@ Applied to original from file_cmds-430.140.2
if (tempcopy) {
to_fd = create_tempfile(to_name, tempfile,
sizeof(tempfile));
@@ -350,6 +364,7 @@
@@ -350,6 +368,7 @@ install(char *from_name, char *to_name,
if (!devnull)
copy(from_fd, from_name, to_fd,
tempcopy ? tempfile : to_name, from_sb.st_size);
@@ -69,7 +73,7 @@ Applied to original from file_cmds-430.140.2
}
if (dostrip) {
@@ -592,11 +607,11 @@
@@ -592,11 +611,11 @@ compare(int from_fd, const char *from_name, size_t fro
}
/*
@@ -85,7 +89,7 @@ Applied to original from file_cmds-430.140.2
char *temp,
size_t tsize)
{
@@ -610,6 +625,18 @@
@@ -610,7 +629,49 @@ create_tempfile(char *path,
p = temp;
(void)strncpy(p, "INS@XXXX", &temp[tsize - 1] - p);
temp[tsize - 1] = '\0';
@@ -102,9 +106,73 @@ Applied to original from file_cmds-430.140.2
+{
+ tempfile_template(path, temp, tsize);
return (mkstemp(temp));
+}
+
+/* unlink or move (backup) an existing file */
+static void
+handle_existing_file(char *path, struct stat *sbp)
+{
+ char backup[MAXPATHLEN];
+ /*
+ * Unlink now... avoid ETXTBSY errors later. Try to turn
+ * off the append/immutable bits -- if we fail, go ahead,
+ * it might work.
+ */
+ if (sbp->st_flags & NOCHANGEBITS)
+ (void)chflags(path, sbp->st_flags & ~NOCHANGEBITS);
+
+ if (dobackup) {
+ if (snprintf(backup, MAXPATHLEN, "%s%s",
+ path, suffix) != strlen(path) + strlen(suffix))
+ errx(EX_OSERR, "%s: backup filename too long",
+ path);
+ (void)snprintf(backup, MAXPATHLEN, "%s%s",
+ path, suffix);
+ if (verbose)
+ (void)printf("install: %s -> %s\n",
+ path, backup);
+ if (rename(path, backup) < 0)
+ err(EX_OSERR, "rename: %s to %s", path, backup);
+ } else {
+ (void)unlink(path);
+ }
}
@@ -736,6 +763,22 @@
/*
@@ -622,31 +683,8 @@ create_newfile(char *path,
int target,
struct stat *sbp)
{
- char backup[MAXPATHLEN];
-
if (target) {
- /*
- * Unlink now... avoid ETXTBSY errors later. Try to turn
- * off the append/immutable bits -- if we fail, go ahead,
- * it might work.
- */
- if (sbp->st_flags & NOCHANGEBITS)
- (void)chflags(path, sbp->st_flags & ~NOCHANGEBITS);
-
- if (dobackup) {
- if (snprintf(backup, MAXPATHLEN, "%s%s",
- path, suffix) != strlen(path) + strlen(suffix))
- errx(EX_OSERR, "%s: backup filename too long",
- path);
- (void)snprintf(backup, MAXPATHLEN, "%s%s",
- path, suffix);
- if (verbose)
- (void)printf("install: %s -> %s\n",
- path, backup);
- if (rename(path, backup) < 0)
- err(EX_OSERR, "rename: %s to %s", path, backup);
- } else
- (void)unlink(path);
+ handle_existing_file(path, sbp);
}
return (open(path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR));
@@ -736,6 +774,22 @@ copy(int from_fd, char *from_name,
}
/*
@@ -120,7 +188,7 @@ Applied to original from file_cmds-430.140.2
+ mktemp(temp_name);
+ to_name = temp_name;
+ }
+ return clonefile(from_name, to_name, CLONE_NOFOLLOW|CLONE_NOOWNERCOPY);
+ return clonefile(from_name, to_name, CLONE_NOOWNERCOPY);
+}
+
+/*