Skip to content

Commit

Permalink
"/etc/localtime" may be relative link
Browse files Browse the repository at this point in the history
  • Loading branch information
Kijewski committed Aug 11, 2022
1 parent 175791e commit 4adb65d
Showing 1 changed file with 21 additions and 9 deletions.
30 changes: 21 additions & 9 deletions src/tz_linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,31 @@ fn etc_timezone() -> Result<String, crate::GetTimezoneError> {
}

fn etc_localtime() -> Result<String, crate::GetTimezoneError> {
// 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 <https://www.man7.org/linux/man-pages/man5/localtime.5.html>:
// “ 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.
// <https://github.com/systemd/systemd/blob/9102c625a673a3246d7e73d8737f3494446bad4e/src/basic/time-util.c#L1493>

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)
}

0 comments on commit 4adb65d

Please sign in to comment.