Skip to content

Commit

Permalink
Merge pull request #49 from Kijewski/pr-rel-link
Browse files Browse the repository at this point in the history
"/etc/localtime" may be relative link
  • Loading branch information
astraw authored Aug 11, 2022
2 parents 5073000 + 985df4b commit 2090e32
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 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)
}
23 changes: 15 additions & 8 deletions src/tz_netbsd.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
use std::fs::read_link;

const PREFIX: &str = "/usr/share/zoneinfo/";

pub(crate) fn get_timezone_inner() -> Result<String, crate::GetTimezoneError> {
// see https://www.cyberciti.biz/faq/openbsd-time-zone-howto/

// This is a backport of the Linux implementation.
// NetBSDs is less than thorough how the softlink should be set up.

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 2090e32

Please sign in to comment.