From 4adb65d4ecdfa175fcf208d1ce4f318cac5cbb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Thu, 11 Aug 2022 10:16:39 +0200 Subject: [PATCH] "/etc/localtime" may be relative link C.f. --- src/tz_linux.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/tz_linux.rs b/src/tz_linux.rs index 6cff285..e2f7d28 100644 --- a/src/tz_linux.rs +++ b/src/tz_linux.rs @@ -13,19 +13,31 @@ fn etc_timezone() -> Result { } fn etc_localtime() -> Result { - // https://www.man7.org/linux/man-pages/man5/localtime.5.html - // https://www.cyberciti.biz/faq/openbsd-time-zone-howto/ - const PREFIX: &str = "/usr/share/zoneinfo/"; + // Per : + // “ The /etc/localtime file configures the system-wide timezone of the local system that is + // used by applications for presentation to the user. It should be an absolute or relative + // symbolic link pointing to /usr/share/zoneinfo/, followed by a timezone identifier such as + // "Europe/Berlin" or "Etc/UTC". The resulting link should lead to the corresponding binary + // tzfile(5) timezone data for the configured timezone. ” + // Systemd does not canonicalize the link, but only checks if it is prefixed by + // "/usr/share/zoneinfo/" or "../usr/share/zoneinfo/". So we do the same. + // + + const PREFIXES: &[&str] = &[ + "/usr/share/zoneinfo/", // absolute path + "../usr/share/zoneinfo/", // relative path + ]; let mut s = read_link("/etc/localtime")? .into_os_string() .into_string() .map_err(|_| crate::GetTimezoneError::FailedParsingString)?; - if !s.starts_with(PREFIX) { - return Err(crate::GetTimezoneError::FailedParsingString); + for &prefix in PREFIXES { + if s.starts_with(prefix) { + // Trim to the correct length without allocating. + s.replace_range(..prefix.len(), ""); + return Ok(s); + } } - - // Trim to the correct length without allocating. - s.replace_range(..PREFIX.len(), ""); - Ok(s) + Err(crate::GetTimezoneError::FailedParsingString) }