git: 06a6d0259fe5 - stable/14 - Revert "tzsetup: symlink /etc/localtime instead of copying"
Date: Sat, 21 Sep 2024 11:10:34 UTC
The branch stable/14 has been updated by emaste:
URL: https://cgit.FreeBSD.org/src/commit/?id=06a6d0259fe5721bfb3b745b231ecf7cf3a5e28e
commit 06a6d0259fe5721bfb3b745b231ecf7cf3a5e28e
Author: Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2024-09-21 11:06:02 +0000
Commit: Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-09-21 11:06:39 +0000
Revert "tzsetup: symlink /etc/localtime instead of copying"
This failed when used with tzsetup's -C option (for example, when using
etcupdate -D to update a jail from the host). Revert the stable/14 MFC
for now; will be reapplied after being fixed in main..
This reverts commit fc43a1b6842afa806dfd7ba48de5bece63d04456.
This reverts commit 87f7f0389f8b7bf30ef12df5c0d337cb2789883e.
---
usr.sbin/etcupdate/tests/tzsetup_test.sh | 5 +-
usr.sbin/tzsetup/tzsetup.8 | 2 +-
usr.sbin/tzsetup/tzsetup.c | 119 ++++++++++++++++++++++++-------
3 files changed, 96 insertions(+), 30 deletions(-)
diff --git a/usr.sbin/etcupdate/tests/tzsetup_test.sh b/usr.sbin/etcupdate/tests/tzsetup_test.sh
index 155830bddae7..dd76884e13eb 100644
--- a/usr.sbin/etcupdate/tests/tzsetup_test.sh
+++ b/usr.sbin/etcupdate/tests/tzsetup_test.sh
@@ -232,8 +232,7 @@ echo "Differences for real update:"
diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
|| FAILED=yes
-# XXX tzsetup installs a symlink as of 5e16809c953f
-#file /etc/localtime "foo"
-#file /var/db/zoneinfo "foo"
+file /etc/localtime "foo"
+file /var/db/zoneinfo "foo"
[ "${FAILED}" = no ]
diff --git a/usr.sbin/tzsetup/tzsetup.8 b/usr.sbin/tzsetup/tzsetup.8
index 499d25765541..bfa625a1af3a 100644
--- a/usr.sbin/tzsetup/tzsetup.8
+++ b/usr.sbin/tzsetup/tzsetup.8
@@ -52,7 +52,7 @@ The following options are available:
Open all files and directories relative to
.Ar chroot_directory .
.It Fl n
-Do not create or symlink files.
+Do not create or copy files.
.It Fl r
Reinstall the zoneinfo file installed last time.
The name is obtained from
diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c
index 617de4efb765..6cd2e16b607c 100644
--- a/usr.sbin/tzsetup/tzsetup.c
+++ b/usr.sbin/tzsetup/tzsetup.c
@@ -744,42 +744,109 @@ static void message_zoneinfo_file(const char *title, char *prompt)
static int
install_zoneinfo_file(const char *zoneinfo_file)
{
+ char buf[1024];
char prompt[SILLY_BUFFER_SIZE];
+ struct stat sb;
+ ssize_t len;
+ int fd1, fd2, copymode;
+
+ if (lstat(path_localtime, &sb) < 0) {
+ /* Nothing there yet... */
+ copymode = 1;
+ } else if (S_ISLNK(sb.st_mode))
+ copymode = 0;
+ else
+ copymode = 1;
#ifdef VERBOSE
- snprintf(prompt, sizeof(prompt), "Creating symbolic link %s to %s",
- path_localtime, zoneinfo_file);
+ if (copymode)
+ snprintf(prompt, sizeof(prompt),
+ "Copying %s to %s", zoneinfo_file, path_localtime);
+ else
+ snprintf(prompt, sizeof(prompt),
+ "Creating symbolic link %s to %s",
+ path_localtime, zoneinfo_file);
message_zoneinfo_file("Info", prompt);
#endif
if (reallydoit) {
- if (access(zoneinfo_file, R_OK) != 0) {
- snprintf(prompt, sizeof(prompt),
- "Cannot access %s: %s", zoneinfo_file,
- strerror(errno));
- message_zoneinfo_file("Error", prompt);
- return (DITEM_FAILURE | DITEM_RECREATE);
- }
- if (unlink(path_localtime) < 0 && errno != ENOENT) {
- snprintf(prompt, sizeof(prompt),
- "Could not delete %s: %s",
- path_localtime, strerror(errno));
- message_zoneinfo_file("Error", prompt);
- return (DITEM_FAILURE | DITEM_RECREATE);
- }
- if (symlink(zoneinfo_file, path_localtime) < 0) {
- snprintf(prompt, sizeof(prompt),
- "Cannot create symbolic link %s to %s: %s",
- path_localtime, zoneinfo_file,
- strerror(errno));
- message_zoneinfo_file("Error", prompt);
- return (DITEM_FAILURE | DITEM_RECREATE);
+ if (copymode) {
+ fd1 = open(zoneinfo_file, O_RDONLY, 0);
+ if (fd1 < 0) {
+ snprintf(prompt, sizeof(prompt),
+ "Could not open %s: %s", zoneinfo_file,
+ strerror(errno));
+ message_zoneinfo_file("Error", prompt);
+ return (DITEM_FAILURE | DITEM_RECREATE);
+ }
+
+ if (unlink(path_localtime) < 0 && errno != ENOENT) {
+ snprintf(prompt, sizeof(prompt),
+ "Could not delete %s: %s",
+ path_localtime, strerror(errno));
+ message_zoneinfo_file("Error", prompt);
+ return (DITEM_FAILURE | DITEM_RECREATE);
+ }
+
+ fd2 = open(path_localtime, O_CREAT | O_EXCL | O_WRONLY,
+ S_IRUSR | S_IRGRP | S_IROTH);
+ if (fd2 < 0) {
+ snprintf(prompt, sizeof(prompt),
+ "Could not open %s: %s",
+ path_localtime, strerror(errno));
+ message_zoneinfo_file("Error", prompt);
+ return (DITEM_FAILURE | DITEM_RECREATE);
+ }
+
+ while ((len = read(fd1, buf, sizeof(buf))) > 0)
+ if ((len = write(fd2, buf, len)) < 0)
+ break;
+
+ if (len == -1) {
+ snprintf(prompt, sizeof(prompt),
+ "Error copying %s to %s %s", zoneinfo_file,
+ path_localtime, strerror(errno));
+ message_zoneinfo_file("Error", prompt);
+ /* Better to leave none than a corrupt one. */
+ unlink(path_localtime);
+ return (DITEM_FAILURE | DITEM_RECREATE);
+ }
+ close(fd1);
+ close(fd2);
+ } else {
+ if (access(zoneinfo_file, R_OK) != 0) {
+ snprintf(prompt, sizeof(prompt),
+ "Cannot access %s: %s", zoneinfo_file,
+ strerror(errno));
+ message_zoneinfo_file("Error", prompt);
+ return (DITEM_FAILURE | DITEM_RECREATE);
+ }
+ if (unlink(path_localtime) < 0 && errno != ENOENT) {
+ snprintf(prompt, sizeof(prompt),
+ "Could not delete %s: %s",
+ path_localtime, strerror(errno));
+ message_zoneinfo_file("Error", prompt);
+ return (DITEM_FAILURE | DITEM_RECREATE);
+ }
+ if (symlink(zoneinfo_file, path_localtime) < 0) {
+ snprintf(prompt, sizeof(prompt),
+ "Cannot create symbolic link %s to %s: %s",
+ path_localtime, zoneinfo_file,
+ strerror(errno));
+ message_zoneinfo_file("Error", prompt);
+ return (DITEM_FAILURE | DITEM_RECREATE);
+ }
}
#ifdef VERBOSE
- snprintf(prompt, sizeof(prompt),
- "Created symbolic link from %s to %s", zoneinfo_file,
- path_localtime);
+ if (copymode)
+ snprintf(prompt, sizeof(prompt),
+ "Copied timezone file from %s to %s",
+ zoneinfo_file, path_localtime);
+ else
+ snprintf(prompt, sizeof(prompt),
+ "Created symbolic link from %s to %s",
+ zoneinfo_file, path_localtime);
message_zoneinfo_file("Done", prompt);
#endif
} /* reallydoit */