1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
From: Michael Stapelberg <stapelberg@debian.org>
Date: Wed, 27 Nov 2013 22:48:47 +0100
Subject: =?utf-8?q?timedated=3A_don=E2=80=99t_rely_on_/usr_being_mounted_i?=
=?utf-8?q?n_the_initrd?=
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
This reverts commit 92c4ef2d357baeef78b6f82f119b92f7ed12ac77
We don’t have /usr mounted in the initramfs yet in Debian, so let’s
support split usr by copying the file instead of symlinking if
necessary, for now.
Closes: #726256
---
src/timedate/timedated.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 89 insertions(+), 1 deletion(-)
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index c183438..467f567 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -153,6 +153,94 @@ static bool valid_timezone(const char *name) {
return true;
}
+static int symlink_or_copy(const char *from, const char *to) {
+ char *pf = NULL, *pt = NULL;
+ struct stat a, b;
+ int r;
+
+ assert(from);
+ assert(to);
+
+ if (path_get_parent(from, &pf) < 0 ||
+ path_get_parent(to, &pt) < 0) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (stat(pf, &a) < 0 ||
+ stat(pt, &b) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ if (a.st_dev != b.st_dev) {
+ free(pf);
+ free(pt);
+
+ return copy_file(from, to);
+ }
+
+ if (symlink(from, to) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ r = 0;
+
+finish:
+ free(pf);
+ free(pt);
+
+ return r;
+}
+
+static int symlink_or_copy_atomic(const char *from, const char *to) {
+ char *t, *x;
+ const char *fn;
+ size_t k;
+ unsigned long long ull;
+ unsigned i;
+ int r;
+
+ assert(from);
+ assert(to);
+
+ t = new(char, strlen(to) + 1 + 16 + 1);
+ if (!t)
+ return -ENOMEM;
+
+ fn = path_get_file_name(to);
+ k = fn-to;
+ memcpy(t, to, k);
+ t[k] = '.';
+ x = stpcpy(t+k+1, fn);
+
+ ull = random_ull();
+ for (i = 0; i < 16; i++) {
+ *(x++) = hexchar(ull & 0xF);
+ ull >>= 4;
+ }
+
+ *x = 0;
+
+ r = symlink_or_copy(from, t);
+ if (r < 0) {
+ unlink(t);
+ free(t);
+ return r;
+ }
+
+ if (rename(t, to) < 0) {
+ r = -errno;
+ unlink(t);
+ free(t);
+ return r;
+ }
+
+ free(t);
+ return r;
+}
+
static int read_data(void) {
int r;
_cleanup_free_ char *t = NULL;
@@ -220,7 +308,7 @@ static int write_data_timezone(void) {
if (!p)
return log_oom();
- r = symlink_atomic(p, "/etc/localtime");
+ r = symlink_or_copy_atomic(p, "/etc/localtime");
if (r < 0)
return r;
|