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