2019-01-23 12:05:32 +00:00
|
|
|
use failure::*;
|
|
|
|
|
|
|
|
use crate::tools;
|
2019-02-17 09:16:33 +00:00
|
|
|
use crate::api_schema::*;
|
2019-02-17 08:59:20 +00:00
|
|
|
use crate::api_schema::router::*;
|
2019-05-09 05:44:09 +00:00
|
|
|
use crate::api2::types::*;
|
|
|
|
|
2019-01-23 12:05:32 +00:00
|
|
|
use serde_json::{json, Value};
|
|
|
|
|
2019-01-23 14:14:14 +00:00
|
|
|
use chrono::prelude::*;
|
|
|
|
|
|
|
|
fn read_etc_localtime() -> Result<String, Error> {
|
2019-01-30 13:55:43 +00:00
|
|
|
// use /etc/timezone
|
|
|
|
if let Ok(line) = tools::file_read_firstline("/etc/timezone") {
|
|
|
|
return Ok(line.trim().to_owned());
|
|
|
|
}
|
2019-01-23 14:14:14 +00:00
|
|
|
|
2019-01-30 13:55:43 +00:00
|
|
|
// otherwise guess from the /etc/localtime symlink
|
|
|
|
let mut buf: [u8; 64] = unsafe { std::mem::uninitialized() };
|
|
|
|
let len = unsafe {
|
|
|
|
libc::readlink("/etc/localtime".as_ptr() as *const _, buf.as_mut_ptr() as *mut _, buf.len())
|
|
|
|
};
|
|
|
|
if len <= 0 {
|
|
|
|
bail!("failed to guess timezone");
|
|
|
|
}
|
|
|
|
let len = len as usize;
|
|
|
|
buf[len] = 0;
|
|
|
|
let link = std::str::from_utf8(&buf[..len])?;
|
|
|
|
match link.rfind("/zoneinfo/") {
|
|
|
|
Some(pos) => Ok(link[(pos + 10)..].to_string()),
|
|
|
|
None => Ok(link.to_string()),
|
|
|
|
}
|
2019-01-23 14:14:14 +00:00
|
|
|
}
|
2019-01-23 12:05:32 +00:00
|
|
|
|
2019-01-26 13:50:37 +00:00
|
|
|
fn get_time(
|
|
|
|
_param: Value,
|
|
|
|
_info: &ApiMethod,
|
2019-06-07 11:10:56 +00:00
|
|
|
_rpcenv: &mut dyn RpcEnvironment,
|
2019-01-26 13:50:37 +00:00
|
|
|
) -> Result<Value, Error> {
|
2019-01-23 12:05:32 +00:00
|
|
|
|
2019-01-23 14:14:14 +00:00
|
|
|
let datetime = Local::now();
|
|
|
|
let offset = datetime.offset();
|
|
|
|
let time = datetime.timestamp();
|
|
|
|
let localtime = time + (offset.fix().local_minus_utc() as i64);
|
|
|
|
|
2019-01-23 12:05:32 +00:00
|
|
|
Ok(json!({
|
2019-01-23 14:14:14 +00:00
|
|
|
"timezone": read_etc_localtime()?,
|
|
|
|
"time": time,
|
|
|
|
"localtime": localtime,
|
2019-01-23 12:05:32 +00:00
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2019-01-26 13:50:37 +00:00
|
|
|
fn set_timezone(
|
|
|
|
param: Value,
|
|
|
|
_info: &ApiMethod,
|
2019-06-07 11:10:56 +00:00
|
|
|
_rpcenv: &mut dyn RpcEnvironment,
|
2019-01-26 13:50:37 +00:00
|
|
|
) -> Result<Value, Error> {
|
2019-01-24 11:05:06 +00:00
|
|
|
|
|
|
|
let timezone = tools::required_string_param(¶m, "timezone")?;
|
|
|
|
|
|
|
|
let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
|
|
|
|
|
|
|
|
if !path.exists() {
|
|
|
|
bail!("No such timezone.");
|
|
|
|
}
|
|
|
|
|
2019-01-25 09:15:32 +00:00
|
|
|
tools::file_set_contents("/etc/timezone", timezone.as_bytes(), None)?;
|
2019-01-24 11:05:06 +00:00
|
|
|
|
|
|
|
let _ = std::fs::remove_file("/etc/localtime");
|
|
|
|
|
|
|
|
use std::os::unix::fs::symlink;
|
|
|
|
symlink(path, "/etc/localtime")?;
|
|
|
|
|
|
|
|
Ok(Value::Null)
|
|
|
|
}
|
|
|
|
|
2019-01-23 12:05:32 +00:00
|
|
|
pub fn router() -> Router {
|
|
|
|
|
|
|
|
let route = Router::new()
|
2019-01-24 10:07:11 +00:00
|
|
|
.get(
|
|
|
|
ApiMethod::new(
|
2019-01-24 11:05:06 +00:00
|
|
|
get_time,
|
|
|
|
ObjectSchema::new("Read server time and time zone settings.")
|
2019-05-09 05:44:09 +00:00
|
|
|
.required("node", NODE_SCHEMA.clone())
|
2019-04-09 12:43:30 +00:00
|
|
|
).returns(
|
2019-01-24 11:05:06 +00:00
|
|
|
ObjectSchema::new("Returns server time and timezone.")
|
|
|
|
.required("timezone", StringSchema::new("Time zone"))
|
|
|
|
.required("time", IntegerSchema::new("Seconds since 1970-01-01 00:00:00 UTC.")
|
|
|
|
.minimum(1297163644))
|
|
|
|
.required("localtime", IntegerSchema::new("Seconds since 1970-01-01 00:00:00 UTC. (local time)")
|
|
|
|
.minimum(1297163644))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.put(
|
|
|
|
ApiMethod::new(
|
|
|
|
set_timezone,
|
|
|
|
ObjectSchema::new("Set time zone.")
|
2019-05-09 05:44:09 +00:00
|
|
|
.required("node", NODE_SCHEMA.clone())
|
2019-04-09 12:43:30 +00:00
|
|
|
.required("timezone", StringSchema::new(
|
|
|
|
"Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names."))
|
2019-02-01 08:54:56 +00:00
|
|
|
).protected(true).reload_timezone(true)
|
2019-01-24 10:07:11 +00:00
|
|
|
);
|
|
|
|
|
2019-01-23 12:05:32 +00:00
|
|
|
|
|
|
|
route
|
|
|
|
}
|