]> git.proxmox.com Git - proxmox-backup.git/blame - src/api2/node/time.rs
update to proxmox-sys 0.2 crate
[proxmox-backup.git] / src / api2 / node / time.rs
CommitLineData
30f57724 1use anyhow::{bail, format_err, Error};
f3a8d1d7
WB
2use serde_json::{json, Value};
3
25877d05 4use proxmox_sys::fs::{file_read_firstline, replace_file, CreateOptions};
6ef1b649
WB
5use proxmox_router::{Router, Permission};
6use proxmox_schema::api;
b2b3485d 7
8cc3760e 8use pbs_api_types::{NODE_SCHEMA, TIME_ZONE_SCHEMA, PRIV_SYS_MODIFY};
0463602a
DM
9
10fn read_etc_localtime() -> Result<String, Error> {
13f8310c 11 // use /etc/timezone
e18a6c9e 12 if let Ok(line) = file_read_firstline("/etc/timezone") {
13f8310c
WB
13 return Ok(line.trim().to_owned());
14 }
0463602a 15
13f8310c 16 // otherwise guess from the /etc/localtime symlink
30f57724
DM
17 let link = std::fs::read_link("/etc/localtime").
18 map_err(|err| format_err!("failed to guess timezone - {}", err))?;
19
20 let link = link.to_string_lossy();
13f8310c
WB
21 match link.rfind("/zoneinfo/") {
22 Some(pos) => Ok(link[(pos + 10)..].to_string()),
23 None => Ok(link.to_string()),
24 }
0463602a 25}
b2b3485d 26
4b40148c
DM
27#[api(
28 input: {
29 properties: {
30 node: {
31 schema: NODE_SCHEMA,
32 },
33 },
34 },
35 returns: {
36 description: "Returns server time and timezone.",
37 properties: {
38 timezone: {
39 schema: TIME_ZONE_SCHEMA,
40 },
41 time: {
42 type: i64,
43 description: "Seconds since 1970-01-01 00:00:00 UTC.",
44 minimum: 1_297_163_644,
45 },
46 localtime: {
47 type: i64,
48 description: "Seconds since 1970-01-01 00:00:00 UTC. (local time)",
49 minimum: 1_297_163_644,
50 },
51 }
52 },
53 access: {
54 permission: &Permission::Anybody,
55 },
56)]
57/// Read server time and time zone settings.
58fn get_time(_param: Value) -> Result<Value, Error> {
6ef1b649
WB
59 let time = proxmox_time::epoch_i64();
60 let tm = proxmox_time::localtime(time)?;
6a7be83e
DM
61 let offset = tm.tm_gmtoff;
62
63 let localtime = time + offset;
0463602a 64
b2b3485d 65 Ok(json!({
0463602a
DM
66 "timezone": read_etc_localtime()?,
67 "time": time,
68 "localtime": localtime,
b2b3485d
DM
69 }))
70}
71
4b40148c
DM
72#[api(
73 protected: true,
74 reload_timezone: true,
75 input: {
76 properties: {
77 node: {
78 schema: NODE_SCHEMA,
79 },
80 timezone: {
81 schema: TIME_ZONE_SCHEMA,
82 },
83 },
84 },
74c08a57
DM
85 access: {
86 permission: &Permission::Privilege(&["system", "time"], PRIV_SYS_MODIFY, false),
87 },
4b40148c
DM
88)]
89/// Set time zone
6049b71f 90fn set_timezone(
4b40148c
DM
91 timezone: String,
92 _param: Value,
6049b71f 93) -> Result<Value, Error> {
e6ffeb91
DM
94 let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
95
96 if !path.exists() {
97 bail!("No such timezone.");
98 }
99
e0a19d33 100 replace_file("/etc/timezone", timezone.as_bytes(), CreateOptions::new(), true)?;
e6ffeb91
DM
101
102 let _ = std::fs::remove_file("/etc/localtime");
103
104 use std::os::unix::fs::symlink;
105 symlink(path, "/etc/localtime")?;
106
e6ffeb91
DM
107 Ok(Value::Null)
108}
109
255f378a 110pub const ROUTER: Router = Router::new()
4b40148c
DM
111 .get(&API_METHOD_GET_TIME)
112 .put(&API_METHOD_SET_TIMEZONE);