mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 20:33:10 +00:00
LibTimeZone: Use /etc/timezone as the basis for the system time zone
This changes LibTimeZone to read the current time zone from the file /etc/timezone rather than using tzset/tzname. Instead, in a subsequent commit, LibC's time methods will be changed to used LibTimeZone to retrieve the system time zone. Also add an API to set the system time zone. This method is only allowed when running within Serenity.
This commit is contained in:
parent
bcf4ec9c61
commit
7f1404b870
1
Base/etc/timezone
Normal file
1
Base/etc/timezone
Normal file
|
@ -0,0 +1 @@
|
||||||
|
UTC
|
|
@ -4,8 +4,10 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/Array.h>
|
||||||
|
#include <AK/String.h>
|
||||||
#include <LibTimeZone/TimeZone.h>
|
#include <LibTimeZone/TimeZone.h>
|
||||||
#include <time.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
namespace TimeZone {
|
namespace TimeZone {
|
||||||
|
|
||||||
|
@ -20,15 +22,77 @@ enum class TimeZone : u16 {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
StringView current_time_zone()
|
class TimeZoneFile {
|
||||||
|
public:
|
||||||
|
TimeZoneFile(char const* mode)
|
||||||
|
: m_file(fopen("/etc/timezone", mode))
|
||||||
{
|
{
|
||||||
static bool initialized_time_zone = false;
|
if (m_file)
|
||||||
if (!initialized_time_zone) {
|
flockfile(m_file);
|
||||||
initialized_time_zone = true;
|
|
||||||
tzset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return canonicalize_time_zone(tzname[0]).value_or("UTC"sv);
|
~TimeZoneFile()
|
||||||
|
{
|
||||||
|
if (m_file) {
|
||||||
|
funlockfile(m_file);
|
||||||
|
fclose(m_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<String> read_time_zone()
|
||||||
|
{
|
||||||
|
if (!m_file)
|
||||||
|
return Error::from_string_literal("Could not open /etc/timezone");
|
||||||
|
|
||||||
|
Array<u8, 128> buffer;
|
||||||
|
size_t bytes = fread(buffer.data(), 1, buffer.size(), m_file);
|
||||||
|
|
||||||
|
if (bytes == 0)
|
||||||
|
return Error::from_string_literal("Could not read time zone from /etc/timezone");
|
||||||
|
|
||||||
|
return String(buffer.span().slice(0, bytes)).trim_whitespace();
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> write_time_zone(StringView time_zone)
|
||||||
|
{
|
||||||
|
if (!m_file)
|
||||||
|
return Error::from_string_literal("Could not open /etc/timezone");
|
||||||
|
|
||||||
|
auto bytes = fwrite(time_zone.characters_without_null_termination(), 1, time_zone.length(), m_file);
|
||||||
|
if (bytes != time_zone.length())
|
||||||
|
return Error::from_string_literal("Could not write new time zone to /etc/timezone");
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE* m_file { nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
StringView current_time_zone()
|
||||||
|
{
|
||||||
|
TimeZoneFile time_zone_file("r");
|
||||||
|
|
||||||
|
// FIXME: Propagate the error to existing callers.
|
||||||
|
if (auto time_zone = time_zone_file.read_time_zone(); !time_zone.is_error())
|
||||||
|
return canonicalize_time_zone(time_zone.value()).value_or("UTC"sv);
|
||||||
|
|
||||||
|
return "UTC"sv;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> change_time_zone([[maybe_unused]] StringView time_zone)
|
||||||
|
{
|
||||||
|
#ifdef __serenity__
|
||||||
|
TimeZoneFile time_zone_file("w");
|
||||||
|
|
||||||
|
if (auto new_time_zone = canonicalize_time_zone(time_zone); new_time_zone.has_value())
|
||||||
|
return time_zone_file.write_time_zone(*new_time_zone);
|
||||||
|
|
||||||
|
return Error::from_string_literal("Provided time zone is not supported");
|
||||||
|
#else
|
||||||
|
// Do not even attempt to change the time zone of someone's host machine.
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<StringView const> __attribute__((weak)) all_time_zones()
|
Span<StringView const> __attribute__((weak)) all_time_zones()
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Error.h>
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <AK/Time.h>
|
#include <AK/Time.h>
|
||||||
|
@ -25,6 +26,7 @@ struct Offset {
|
||||||
};
|
};
|
||||||
|
|
||||||
StringView current_time_zone();
|
StringView current_time_zone();
|
||||||
|
ErrorOr<void> change_time_zone(StringView time_zone);
|
||||||
Span<StringView const> all_time_zones();
|
Span<StringView const> all_time_zones();
|
||||||
|
|
||||||
Optional<TimeZone> time_zone_from_string(StringView time_zone);
|
Optional<TimeZone> time_zone_from_string(StringView time_zone);
|
||||||
|
|
Loading…
Reference in a new issue