update to nix 0.14, use code from proxmox:tools
This commit is contained in:
parent
b86f263ced
commit
e18a6c9ee5
|
@ -32,7 +32,7 @@ hyper-openssl = "0.7"
|
||||||
lazy_static = "1.1"
|
lazy_static = "1.1"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
nix = "0.13"
|
nix = "0.14"
|
||||||
shellwords = "1.0"
|
shellwords = "1.0"
|
||||||
uuid = { version = "0.7", features = ["v4"] }
|
uuid = { version = "0.7", features = ["v4"] }
|
||||||
chrono = "0.4" # Date and time library for Rust
|
chrono = "0.4" # Date and time library for Rust
|
||||||
|
|
|
@ -12,6 +12,8 @@ use chrono::{DateTime, Datelike, TimeZone, Local};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use proxmox::tools::{try_block, fs::file_set_contents};
|
||||||
|
|
||||||
use crate::config::datastore;
|
use crate::config::datastore;
|
||||||
|
|
||||||
use crate::backup::*;
|
use crate::backup::*;
|
||||||
|
@ -510,7 +512,7 @@ fn upload_backup_log(
|
||||||
// always comput CRC at server side
|
// always comput CRC at server side
|
||||||
blob.set_crc(blob.compute_crc());
|
blob.set_crc(blob.compute_crc());
|
||||||
let raw_data = blob.raw_data();
|
let raw_data = blob.raw_data();
|
||||||
crate::tools::file_set_contents(&path, raw_data, None)?;
|
file_set_contents(&path, raw_data, None)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.and_then(move |_| {
|
.and_then(move |_| {
|
||||||
|
|
|
@ -4,7 +4,10 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use proxmox::tools;
|
use proxmox::tools::{
|
||||||
|
digest_to_hex,
|
||||||
|
fs::file_set_contents,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::api_schema::router::{RpcEnvironment, RpcEnvironmentType};
|
use crate::api_schema::router::{RpcEnvironment, RpcEnvironmentType};
|
||||||
use crate::server::WorkerTask;
|
use crate::server::WorkerTask;
|
||||||
|
@ -298,8 +301,8 @@ impl BackupEnvironment {
|
||||||
|
|
||||||
fn log_upload_stat(&self, archive_name: &str, csum: &[u8; 32], uuid: &[u8; 16], size: u64, chunk_count: u64, upload_stat: &UploadStatistic) {
|
fn log_upload_stat(&self, archive_name: &str, csum: &[u8; 32], uuid: &[u8; 16], size: u64, chunk_count: u64, upload_stat: &UploadStatistic) {
|
||||||
self.log(format!("Upload statistics for '{}'", archive_name));
|
self.log(format!("Upload statistics for '{}'", archive_name));
|
||||||
self.log(format!("UUID: {}", tools::digest_to_hex(uuid)));
|
self.log(format!("UUID: {}", digest_to_hex(uuid)));
|
||||||
self.log(format!("Checksum: {}", tools::digest_to_hex(csum)));
|
self.log(format!("Checksum: {}", digest_to_hex(csum)));
|
||||||
self.log(format!("Size: {}", size));
|
self.log(format!("Size: {}", size));
|
||||||
self.log(format!("Chunk count: {}", chunk_count));
|
self.log(format!("Chunk count: {}", chunk_count));
|
||||||
|
|
||||||
|
@ -402,7 +405,7 @@ impl BackupEnvironment {
|
||||||
blob.set_crc(blob.compute_crc());
|
blob.set_crc(blob.compute_crc());
|
||||||
|
|
||||||
let raw_data = blob.raw_data();
|
let raw_data = blob.raw_data();
|
||||||
crate::tools::file_set_contents(&path, raw_data, None)?;
|
file_set_contents(&path, raw_data, None)?;
|
||||||
|
|
||||||
self.log(format!("add blob {:?} ({} bytes, comp: {})", path, orig_len, blob_len));
|
self.log(format!("add blob {:?} ({} bytes, comp: {})", path, orig_len, blob_len));
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
|
use proxmox::tools::fs::{file_get_contents, file_set_contents};
|
||||||
use crate::tools;
|
|
||||||
use crate::api2::*;
|
use crate::api2::*;
|
||||||
use crate::api_schema::*;
|
use crate::api_schema::*;
|
||||||
//use crate::api_schema::router::*;
|
//use crate::api_schema::router::*;
|
||||||
|
@ -23,7 +22,7 @@ fn read_etc_resolv_conf() -> Result<Value, Error> {
|
||||||
|
|
||||||
let mut nscount = 0;
|
let mut nscount = 0;
|
||||||
|
|
||||||
let raw = tools::file_get_contents(RESOLV_CONF_FN)?;
|
let raw = file_get_contents(RESOLV_CONF_FN)?;
|
||||||
|
|
||||||
result["digest"] = Value::from(proxmox::tools::digest_to_hex(&sha::sha256(&raw)));
|
result["digest"] = Value::from(proxmox::tools::digest_to_hex(&sha::sha256(&raw)));
|
||||||
|
|
||||||
|
@ -63,13 +62,13 @@ fn update_dns(
|
||||||
|
|
||||||
let _guard = MUTEX.lock();
|
let _guard = MUTEX.lock();
|
||||||
|
|
||||||
let search = tools::required_string_param(¶m, "search")?;
|
let search = crate::tools::required_string_param(¶m, "search")?;
|
||||||
|
|
||||||
let raw = tools::file_get_contents(RESOLV_CONF_FN)?;
|
let raw = file_get_contents(RESOLV_CONF_FN)?;
|
||||||
let old_digest = proxmox::tools::digest_to_hex(&sha::sha256(&raw));
|
let old_digest = proxmox::tools::digest_to_hex(&sha::sha256(&raw));
|
||||||
|
|
||||||
if let Some(digest) = param["digest"].as_str() {
|
if let Some(digest) = param["digest"].as_str() {
|
||||||
tools::assert_if_modified(&old_digest, &digest)?;
|
crate::tools::assert_if_modified(&old_digest, &digest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let old_data = String::from_utf8(raw)?;
|
let old_data = String::from_utf8(raw)?;
|
||||||
|
@ -92,7 +91,7 @@ fn update_dns(
|
||||||
data.push('\n');
|
data.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
tools::file_set_contents(RESOLV_CONF_FN, data.as_bytes(), None)?;
|
file_set_contents(RESOLV_CONF_FN, data.as_bytes(), None)?;
|
||||||
|
|
||||||
Ok(Value::Null)
|
Ok(Value::Null)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use failure::*;
|
use failure::*;
|
||||||
|
use proxmox::tools::fs::{file_read_firstline, file_set_contents};
|
||||||
|
|
||||||
use crate::tools;
|
|
||||||
use crate::api_schema::*;
|
use crate::api_schema::*;
|
||||||
use crate::api_schema::router::*;
|
use crate::api_schema::router::*;
|
||||||
use crate::api2::types::*;
|
use crate::api2::types::*;
|
||||||
|
@ -11,7 +11,7 @@ use chrono::prelude::*;
|
||||||
|
|
||||||
fn read_etc_localtime() -> Result<String, Error> {
|
fn read_etc_localtime() -> Result<String, Error> {
|
||||||
// use /etc/timezone
|
// use /etc/timezone
|
||||||
if let Ok(line) = tools::file_read_firstline("/etc/timezone") {
|
if let Ok(line) = file_read_firstline("/etc/timezone") {
|
||||||
return Ok(line.trim().to_owned());
|
return Ok(line.trim().to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ fn set_timezone(
|
||||||
_rpcenv: &mut dyn RpcEnvironment,
|
_rpcenv: &mut dyn RpcEnvironment,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
|
|
||||||
let timezone = tools::required_string_param(¶m, "timezone")?;
|
let timezone = crate::tools::required_string_param(¶m, "timezone")?;
|
||||||
|
|
||||||
let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
|
let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ fn set_timezone(
|
||||||
bail!("No such timezone.");
|
bail!("No such timezone.");
|
||||||
}
|
}
|
||||||
|
|
||||||
tools::file_set_contents("/etc/timezone", timezone.as_bytes(), None)?;
|
file_set_contents("/etc/timezone", timezone.as_bytes(), None)?;
|
||||||
|
|
||||||
let _ = std::fs::remove_file("/etc/localtime");
|
let _ = std::fs::remove_file("/etc/localtime");
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use crate::tools;
|
|
||||||
|
|
||||||
use failure::*;
|
use failure::*;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
@ -9,6 +7,11 @@ use openssl::sha;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use proxmox::tools::{
|
||||||
|
try_block,
|
||||||
|
fs::{file_get_contents, file_set_contents, file_set_contents_full},
|
||||||
|
};
|
||||||
|
|
||||||
fn compute_csrf_secret_digest(
|
fn compute_csrf_secret_digest(
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
secret: &[u8],
|
secret: &[u8],
|
||||||
|
@ -94,11 +97,11 @@ pub fn generate_csrf_key() -> Result<(), Error> {
|
||||||
|
|
||||||
use nix::sys::stat::Mode;
|
use nix::sys::stat::Mode;
|
||||||
|
|
||||||
let (_, backup_gid) = tools::getpwnam_ugid("backup")?;
|
let (_, backup_gid) = crate::tools::getpwnam_ugid("backup")?;
|
||||||
let uid = Some(nix::unistd::ROOT);
|
let uid = Some(nix::unistd::ROOT);
|
||||||
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
||||||
|
|
||||||
tools::file_set_contents_full(
|
file_set_contents_full(
|
||||||
&path, &pem, Some(Mode::from_bits_truncate(0o0640)), uid, gid)?;
|
&path, &pem, Some(Mode::from_bits_truncate(0o0640)), uid, gid)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -119,13 +122,13 @@ pub fn generate_auth_key() -> Result<(), Error> {
|
||||||
|
|
||||||
use nix::sys::stat::Mode;
|
use nix::sys::stat::Mode;
|
||||||
|
|
||||||
tools::file_set_contents(
|
file_set_contents(
|
||||||
&priv_path, &priv_pem, Some(Mode::from_bits_truncate(0o0600)))?;
|
&priv_path, &priv_pem, Some(Mode::from_bits_truncate(0o0600)))?;
|
||||||
|
|
||||||
|
|
||||||
let public_pem = rsa.public_key_to_pem()?;
|
let public_pem = rsa.public_key_to_pem()?;
|
||||||
|
|
||||||
tools::file_set_contents(&public_path, &public_pem, None)?;
|
file_set_contents(&public_path, &public_pem, None)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -134,7 +137,7 @@ pub fn csrf_secret() -> &'static [u8] {
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SECRET: Vec<u8> =
|
static ref SECRET: Vec<u8> =
|
||||||
tools::file_get_contents(configdir!("/csrf.key")).unwrap();
|
file_get_contents(configdir!("/csrf.key")).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
&SECRET
|
&SECRET
|
||||||
|
@ -142,7 +145,7 @@ pub fn csrf_secret() -> &'static [u8] {
|
||||||
|
|
||||||
fn load_private_auth_key() -> Result<PKey<Private>, Error> {
|
fn load_private_auth_key() -> Result<PKey<Private>, Error> {
|
||||||
|
|
||||||
let pem = tools::file_get_contents(configdir!("/authkey.key"))?;
|
let pem = file_get_contents(configdir!("/authkey.key"))?;
|
||||||
let rsa = Rsa::private_key_from_pem(&pem)?;
|
let rsa = Rsa::private_key_from_pem(&pem)?;
|
||||||
let key = PKey::from_rsa(rsa)?;
|
let key = PKey::from_rsa(rsa)?;
|
||||||
|
|
||||||
|
@ -160,7 +163,7 @@ pub fn private_auth_key() -> &'static PKey<Private> {
|
||||||
|
|
||||||
fn load_public_auth_key() -> Result<PKey<Public>, Error> {
|
fn load_public_auth_key() -> Result<PKey<Public>, Error> {
|
||||||
|
|
||||||
let pem = tools::file_get_contents(configdir!("/authkey.pub"))?;
|
let pem = file_get_contents(configdir!("/authkey.pub"))?;
|
||||||
let rsa = Rsa::public_key_from_pem(&pem)?;
|
let rsa = Rsa::public_key_from_pem(&pem)?;
|
||||||
let key = PKey::from_rsa(rsa)?;
|
let key = PKey::from_rsa(rsa)?;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,11 @@ use failure::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use chrono::{Local, TimeZone, DateTime};
|
use chrono::{Local, TimeZone, DateTime};
|
||||||
|
|
||||||
|
use proxmox::tools::{
|
||||||
|
try_block,
|
||||||
|
fs::{file_get_contents, file_set_contents},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub enum KeyDerivationConfig {
|
pub enum KeyDerivationConfig {
|
||||||
Scrypt {
|
Scrypt {
|
||||||
|
@ -79,7 +84,7 @@ pub fn store_key_config(
|
||||||
try_block!({
|
try_block!({
|
||||||
if replace {
|
if replace {
|
||||||
let mode = nix::sys::stat::Mode::S_IRUSR | nix::sys::stat::Mode::S_IWUSR;
|
let mode = nix::sys::stat::Mode::S_IRUSR | nix::sys::stat::Mode::S_IWUSR;
|
||||||
crate::tools::file_set_contents(&path, data.as_bytes(), Some(mode))?;
|
file_set_contents(&path, data.as_bytes(), Some(mode))?;
|
||||||
} else {
|
} else {
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
|
|
||||||
|
@ -145,7 +150,7 @@ pub fn encrypt_key_with_passphrase(
|
||||||
|
|
||||||
pub fn load_and_decrtypt_key(path: &std::path::Path, passphrase: fn() -> Result<Vec<u8>, Error>) -> Result<([u8;32], DateTime<Local>), Error> {
|
pub fn load_and_decrtypt_key(path: &std::path::Path, passphrase: fn() -> Result<Vec<u8>, Error>) -> Result<([u8;32], DateTime<Local>), Error> {
|
||||||
|
|
||||||
let raw = crate::tools::file_get_contents(&path)?;
|
let raw = file_get_contents(&path)?;
|
||||||
let data = String::from_utf8(raw)?;
|
let data = String::from_utf8(raw)?;
|
||||||
|
|
||||||
let key_config: KeyConfig = serde_json::from_str(&data)?;
|
let key_config: KeyConfig = serde_json::from_str(&data)?;
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl ReadChunk for LocalChunkReader {
|
||||||
println!("READ CHUNK {}", digest_str);
|
println!("READ CHUNK {}", digest_str);
|
||||||
|
|
||||||
let (path, _) = self.store.chunk_path(digest);
|
let (path, _) = self.store.chunk_path(digest);
|
||||||
let raw_data = crate::tools::file_get_contents(&path)?;
|
let raw_data = proxmox::tools::fs::file_get_contents(&path)?;
|
||||||
let chunk = DataChunk::from_raw(raw_data, *digest)?;
|
let chunk = DataChunk::from_raw(raw_data, *digest)?;
|
||||||
chunk.verify_crc()?;
|
chunk.verify_crc()?;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//use proxmox_backup::tools;
|
//use proxmox_backup::tools;
|
||||||
use proxmox_backup::try_block;
|
|
||||||
use proxmox_backup::api_schema::router::*;
|
use proxmox_backup::api_schema::router::*;
|
||||||
use proxmox_backup::api_schema::config::*;
|
use proxmox_backup::api_schema::config::*;
|
||||||
use proxmox_backup::server::rest::*;
|
use proxmox_backup::server::rest::*;
|
||||||
|
@ -10,6 +9,7 @@ use proxmox_backup::config;
|
||||||
|
|
||||||
use failure::*;
|
use failure::*;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
use proxmox::tools::try_block;
|
||||||
|
|
||||||
use futures::*;
|
use futures::*;
|
||||||
use futures::future::Future;
|
use futures::future::Future;
|
||||||
|
|
|
@ -7,6 +7,7 @@ use chrono::{Local, Utc, TimeZone};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use proxmox::tools::fs::{file_get_contents, file_get_json, file_set_contents, image_size};
|
||||||
|
|
||||||
use proxmox_backup::tools;
|
use proxmox_backup::tools;
|
||||||
use proxmox_backup::cli::*;
|
use proxmox_backup::cli::*;
|
||||||
|
@ -86,7 +87,7 @@ fn record_repository(repo: &BackupRepository) {
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut data = tools::file_get_json(&path, None).unwrap_or(json!({}));
|
let mut data = file_get_json(&path, None).unwrap_or(json!({}));
|
||||||
|
|
||||||
let repo = repo.to_string();
|
let repo = repo.to_string();
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ fn record_repository(repo: &BackupRepository) {
|
||||||
|
|
||||||
let new_data = json!(map);
|
let new_data = json!(map);
|
||||||
|
|
||||||
let _ = tools::file_set_contents(path, new_data.to_string().as_bytes(), None);
|
let _ = file_set_contents(path, new_data.to_string().as_bytes(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_repository(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
|
fn complete_repository(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
|
||||||
|
@ -136,7 +137,7 @@ fn complete_repository(_arg: &str, _param: &HashMap<String, String>) -> Vec<Stri
|
||||||
_ => return result,
|
_ => return result,
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = tools::file_get_json(&path, None).unwrap_or(json!({}));
|
let data = file_get_json(&path, None).unwrap_or(json!({}));
|
||||||
|
|
||||||
if let Some(map) = data.as_object() {
|
if let Some(map) = data.as_object() {
|
||||||
for (repo, _count) in map {
|
for (repo, _count) in map {
|
||||||
|
@ -521,7 +522,7 @@ fn create_backup(
|
||||||
bail!("got unexpected file type (expected file or block device)");
|
bail!("got unexpected file type (expected file or block device)");
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = tools::image_size(&PathBuf::from(filename))?;
|
let size = image_size(&PathBuf::from(filename))?;
|
||||||
|
|
||||||
if size == 0 { bail!("got zero-sized file '{}'", filename); }
|
if size == 0 { bail!("got zero-sized file '{}'", filename); }
|
||||||
|
|
||||||
|
@ -567,7 +568,7 @@ fn create_backup(
|
||||||
|
|
||||||
let path = master_pubkey_path()?;
|
let path = master_pubkey_path()?;
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
let pem_data = proxmox_backup::tools::file_get_contents(&path)?;
|
let pem_data = file_get_contents(&path)?;
|
||||||
let rsa = openssl::rsa::Rsa::public_key_from_pem(&pem_data)?;
|
let rsa = openssl::rsa::Rsa::public_key_from_pem(&pem_data)?;
|
||||||
let enc_key = crypt_config.generate_rsa_encoded_key(rsa, created)?;
|
let enc_key = crypt_config.generate_rsa_encoded_key(rsa, created)?;
|
||||||
(Some(Arc::new(crypt_config)), Some(enc_key))
|
(Some(Arc::new(crypt_config)), Some(enc_key))
|
||||||
|
@ -632,7 +633,7 @@ fn create_backup(
|
||||||
// openssl rsautl -decrypt -inkey master-private.pem -in rsa-encrypted.key -out t
|
// openssl rsautl -decrypt -inkey master-private.pem -in rsa-encrypted.key -out t
|
||||||
/*
|
/*
|
||||||
let mut buffer2 = vec![0u8; rsa.size() as usize];
|
let mut buffer2 = vec![0u8; rsa.size() as usize];
|
||||||
let pem_data = proxmox_backup::tools::file_get_contents("master-private.pem")?;
|
let pem_data = file_get_contents("master-private.pem")?;
|
||||||
let rsa = openssl::rsa::Rsa::private_key_from_pem(&pem_data)?;
|
let rsa = openssl::rsa::Rsa::private_key_from_pem(&pem_data)?;
|
||||||
let len = rsa.private_decrypt(&buffer, &mut buffer2, openssl::rsa::Padding::PKCS1)?;
|
let len = rsa.private_decrypt(&buffer, &mut buffer2, openssl::rsa::Padding::PKCS1)?;
|
||||||
println!("TEST {} {:?}", len, buffer2);
|
println!("TEST {} {:?}", len, buffer2);
|
||||||
|
@ -777,7 +778,7 @@ fn restore(
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
crate::tools::file_set_contents(target, &raw_data, None)?;
|
file_set_contents(target, &raw_data, None)?;
|
||||||
} else {
|
} else {
|
||||||
let stdout = std::io::stdout();
|
let stdout = std::io::stdout();
|
||||||
let mut writer = stdout.lock();
|
let mut writer = stdout.lock();
|
||||||
|
@ -878,7 +879,7 @@ fn upload_log(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = crate::tools::file_get_contents(logfile)?;
|
let data = file_get_contents(logfile)?;
|
||||||
|
|
||||||
let blob = if let Some(ref crypt_config) = crypt_config {
|
let blob = if let Some(ref crypt_config) = crypt_config {
|
||||||
DataBlob::encode(&data, Some(crypt_config), true)?
|
DataBlob::encode(&data, Some(crypt_config), true)?
|
||||||
|
@ -1200,7 +1201,7 @@ fn key_import_master_pubkey(
|
||||||
let path = tools::required_string_param(¶m, "path")?;
|
let path = tools::required_string_param(¶m, "path")?;
|
||||||
let path = PathBuf::from(path);
|
let path = PathBuf::from(path);
|
||||||
|
|
||||||
let pem_data = proxmox_backup::tools::file_get_contents(&path)?;
|
let pem_data = file_get_contents(&path)?;
|
||||||
|
|
||||||
if let Err(err) = openssl::pkey::PKey::public_key_from_pem(&pem_data) {
|
if let Err(err) = openssl::pkey::PKey::public_key_from_pem(&pem_data) {
|
||||||
bail!("Unable to decode PEM data - {}", err);
|
bail!("Unable to decode PEM data - {}", err);
|
||||||
|
@ -1208,7 +1209,7 @@ fn key_import_master_pubkey(
|
||||||
|
|
||||||
let target_path = master_pubkey_path()?;
|
let target_path = master_pubkey_path()?;
|
||||||
|
|
||||||
proxmox_backup::tools::file_set_contents(&target_path, &pem_data, None)?;
|
file_set_contents(&target_path, &pem_data, None)?;
|
||||||
|
|
||||||
println!("Imported public master key to {:?}", target_path);
|
println!("Imported public master key to {:?}", target_path);
|
||||||
|
|
||||||
|
@ -1243,14 +1244,14 @@ fn key_create_master_key(
|
||||||
let pub_key: Vec<u8> = pkey.public_key_to_pem()?;
|
let pub_key: Vec<u8> = pkey.public_key_to_pem()?;
|
||||||
let filename_pub = "master-public.pem";
|
let filename_pub = "master-public.pem";
|
||||||
println!("Writing public master key to {}", filename_pub);
|
println!("Writing public master key to {}", filename_pub);
|
||||||
proxmox_backup::tools::file_set_contents(filename_pub, pub_key.as_slice(), None)?;
|
file_set_contents(filename_pub, pub_key.as_slice(), None)?;
|
||||||
|
|
||||||
let cipher = openssl::symm::Cipher::aes_256_cbc();
|
let cipher = openssl::symm::Cipher::aes_256_cbc();
|
||||||
let priv_key: Vec<u8> = pkey.private_key_to_pem_pkcs8_passphrase(cipher, new_pw.as_bytes())?;
|
let priv_key: Vec<u8> = pkey.private_key_to_pem_pkcs8_passphrase(cipher, new_pw.as_bytes())?;
|
||||||
|
|
||||||
let filename_priv = "master-private.pem";
|
let filename_priv = "master-private.pem";
|
||||||
println!("Writing private master key to {}", filename_priv);
|
println!("Writing private master key to {}", filename_priv);
|
||||||
proxmox_backup::tools::file_set_contents(filename_priv, priv_key.as_slice(), None)?;
|
file_set_contents(filename_priv, priv_key.as_slice(), None)?;
|
||||||
|
|
||||||
Ok(Value::Null)
|
Ok(Value::Null)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use proxmox_backup::try_block;
|
|
||||||
use proxmox_backup::configdir;
|
use proxmox_backup::configdir;
|
||||||
use proxmox_backup::server;
|
use proxmox_backup::server;
|
||||||
use proxmox_backup::tools::daemon;
|
use proxmox_backup::tools::daemon;
|
||||||
|
@ -8,6 +7,7 @@ use proxmox_backup::server::rest::*;
|
||||||
use proxmox_backup::auth_helpers::*;
|
use proxmox_backup::auth_helpers::*;
|
||||||
|
|
||||||
use failure::*;
|
use failure::*;
|
||||||
|
use proxmox::tools::try_block;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use futures::*;
|
use futures::*;
|
||||||
|
|
|
@ -21,6 +21,11 @@ use openssl::ssl::{SslConnector, SslMethod};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use url::percent_encoding::{percent_encode, DEFAULT_ENCODE_SET};
|
use url::percent_encoding::{percent_encode, DEFAULT_ENCODE_SET};
|
||||||
|
|
||||||
|
use proxmox::tools::{
|
||||||
|
digest_to_hex,
|
||||||
|
fs::{file_get_json, file_set_contents},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::tools::{self, BroadcastFuture, tty};
|
use crate::tools::{self, BroadcastFuture, tty};
|
||||||
use crate::tools::futures::{cancellable, Canceller};
|
use crate::tools::futures::{cancellable, Canceller};
|
||||||
use super::pipe_to_stream::*;
|
use super::pipe_to_stream::*;
|
||||||
|
@ -51,7 +56,7 @@ fn store_ticket_info(server: &str, username: &str, ticket: &str, token: &str) ->
|
||||||
|
|
||||||
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0600);
|
let mode = nix::sys::stat::Mode::from_bits_truncate(0o0600);
|
||||||
|
|
||||||
let mut data = tools::file_get_json(&path, Some(json!({})))?;
|
let mut data = file_get_json(&path, Some(json!({})))?;
|
||||||
|
|
||||||
let now = Utc::now().timestamp();
|
let now = Utc::now().timestamp();
|
||||||
|
|
||||||
|
@ -73,7 +78,7 @@ fn store_ticket_info(server: &str, username: &str, ticket: &str, token: &str) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tools::file_set_contents(path, new_data.to_string().as_bytes(), Some(mode))?;
|
file_set_contents(path, new_data.to_string().as_bytes(), Some(mode))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -90,7 +95,7 @@ fn load_ticket_info(server: &str, username: &str) -> Option<(String, String)> {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = match tools::file_get_json(&path, None) {
|
let data = match file_get_json(&path, None) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
@ -536,7 +541,7 @@ impl BackupReader {
|
||||||
output: W,
|
output: W,
|
||||||
) -> impl Future<Item=W, Error=Error> {
|
) -> impl Future<Item=W, Error=Error> {
|
||||||
let path = "chunk";
|
let path = "chunk";
|
||||||
let param = json!({ "digest": proxmox::tools::digest_to_hex(digest) });
|
let param = json!({ "digest": digest_to_hex(digest) });
|
||||||
self.h2.download(path, Some(param), output)
|
self.h2.download(path, Some(param), output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,7 +786,7 @@ impl BackupClient {
|
||||||
let mut offset_list = vec![];
|
let mut offset_list = vec![];
|
||||||
for (offset, digest) in chunk_list {
|
for (offset, digest) in chunk_list {
|
||||||
//println!("append chunk {} (offset {})", proxmox::tools::digest_to_hex(&digest), offset);
|
//println!("append chunk {} (offset {})", proxmox::tools::digest_to_hex(&digest), offset);
|
||||||
digest_list.push(proxmox::tools::digest_to_hex(&digest));
|
digest_list.push(digest_to_hex(&digest));
|
||||||
offset_list.push(offset);
|
offset_list.push(offset);
|
||||||
}
|
}
|
||||||
println!("append chunks list len ({})", digest_list.len());
|
println!("append chunks list len ({})", digest_list.len());
|
||||||
|
@ -842,7 +847,7 @@ impl BackupClient {
|
||||||
DigestListDecoder::new(body.map_err(Error::from))
|
DigestListDecoder::new(body.map_err(Error::from))
|
||||||
.for_each(move |chunk| {
|
.for_each(move |chunk| {
|
||||||
let _ = release_capacity.release_capacity(chunk.len());
|
let _ = release_capacity.release_capacity(chunk.len());
|
||||||
println!("GOT DOWNLOAD {}", proxmox::tools::digest_to_hex(&chunk));
|
println!("GOT DOWNLOAD {}", digest_to_hex(&chunk));
|
||||||
known_chunks.lock().unwrap().insert(chunk);
|
known_chunks.lock().unwrap().insert(chunk);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -904,7 +909,7 @@ impl BackupClient {
|
||||||
if let MergedChunkInfo::New(chunk_info) = merged_chunk_info {
|
if let MergedChunkInfo::New(chunk_info) = merged_chunk_info {
|
||||||
let offset = chunk_info.offset;
|
let offset = chunk_info.offset;
|
||||||
let digest = *chunk_info.chunk.digest();
|
let digest = *chunk_info.chunk.digest();
|
||||||
let digest_str = proxmox::tools::digest_to_hex(&digest);
|
let digest_str = digest_to_hex(&digest);
|
||||||
let upload_queue = upload_queue.clone();
|
let upload_queue = upload_queue.clone();
|
||||||
|
|
||||||
println!("upload new chunk {} ({} bytes, offset {})", digest_str,
|
println!("upload new chunk {} ({} bytes, offset {})", digest_str,
|
||||||
|
|
|
@ -7,7 +7,8 @@ use failure::*;
|
||||||
|
|
||||||
pub mod datastore;
|
pub mod datastore;
|
||||||
|
|
||||||
use crate::tools;
|
use proxmox::tools::try_block;
|
||||||
|
|
||||||
use crate::buildcfg;
|
use crate::buildcfg;
|
||||||
|
|
||||||
/// Check configuration directory permissions
|
/// Check configuration directory permissions
|
||||||
|
@ -18,7 +19,7 @@ use crate::buildcfg;
|
||||||
pub fn check_configdir_permissions() -> Result<(), Error> {
|
pub fn check_configdir_permissions() -> Result<(), Error> {
|
||||||
|
|
||||||
let cfgdir = buildcfg::CONFIGDIR;
|
let cfgdir = buildcfg::CONFIGDIR;
|
||||||
let (backup_uid, backup_gid) = tools::getpwnam_ugid("backup")?;
|
let (backup_uid, backup_gid) = crate::tools::getpwnam_ugid("backup")?;
|
||||||
|
|
||||||
try_block!({
|
try_block!({
|
||||||
let stat = nix::sys::stat::stat(cfgdir)?;
|
let stat = nix::sys::stat::stat(cfgdir)?;
|
||||||
|
@ -43,7 +44,7 @@ pub fn create_configdir() -> Result<(), Error> {
|
||||||
use nix::sys::stat::Mode;
|
use nix::sys::stat::Mode;
|
||||||
|
|
||||||
let cfgdir = buildcfg::CONFIGDIR;
|
let cfgdir = buildcfg::CONFIGDIR;
|
||||||
let (backup_uid, backup_gid) = tools::getpwnam_ugid("backup")?;
|
let (backup_uid, backup_gid) = crate::tools::getpwnam_ugid("backup")?;
|
||||||
|
|
||||||
match nix::unistd::mkdir(cfgdir, Mode::from_bits_truncate(0o700)) {
|
match nix::unistd::mkdir(cfgdir, Mode::from_bits_truncate(0o700)) {
|
||||||
Ok(()) => {},
|
Ok(()) => {},
|
||||||
|
|
|
@ -5,7 +5,8 @@ use std::io::Read;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
//use std::sync::Arc;
|
//use std::sync::Arc;
|
||||||
use crate::tools;
|
use proxmox::tools::{try_block, fs::file_set_contents};
|
||||||
|
|
||||||
use crate::api_schema::*;
|
use crate::api_schema::*;
|
||||||
|
|
||||||
use crate::section_config::*;
|
use crate::section_config::*;
|
||||||
|
@ -61,7 +62,7 @@ pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
|
||||||
|
|
||||||
let raw = CONFIG.write(DATASTORE_CFG_FILENAME, &config)?;
|
let raw = CONFIG.write(DATASTORE_CFG_FILENAME, &config)?;
|
||||||
|
|
||||||
tools::file_set_contents(DATASTORE_CFG_FILENAME, raw.as_bytes(), None)?;
|
file_set_contents(DATASTORE_CFG_FILENAME, raw.as_bytes(), None)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@ use std::collections::VecDeque;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use proxmox::tools::try_block;
|
||||||
|
|
||||||
use crate::api_schema::*;
|
use crate::api_schema::*;
|
||||||
|
|
||||||
pub struct SectionConfigPlugin {
|
pub struct SectionConfigPlugin {
|
||||||
|
|
|
@ -14,6 +14,8 @@ use std::sync::Arc;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use nix::sys::socket;
|
use nix::sys::socket;
|
||||||
|
|
||||||
|
use proxmox::tools::try_block;
|
||||||
|
|
||||||
/// Listens on a Unix Socket to handle simple command asynchronously
|
/// Listens on a Unix Socket to handle simple command asynchronously
|
||||||
pub fn create_control_socket<P, F>(path: P, f: F) -> Result<impl Future<Item=(), Error=()>, Error>
|
pub fn create_control_socket<P, F>(path: P, f: F) -> Result<impl Future<Item=(), Error=()>, Error>
|
||||||
where P: Into<PathBuf>,
|
where P: Into<PathBuf>,
|
||||||
|
|
|
@ -13,9 +13,14 @@ use std::panic::UnwindSafe;
|
||||||
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
|
use proxmox::tools::{
|
||||||
|
try_block,
|
||||||
|
fs::{create_dir_chown, file_set_contents_full},
|
||||||
|
};
|
||||||
|
|
||||||
use super::UPID;
|
use super::UPID;
|
||||||
|
|
||||||
use crate::tools::{self, FileLogger};
|
use crate::tools::FileLogger;
|
||||||
|
|
||||||
macro_rules! PROXMOX_BACKUP_VAR_RUN_DIR_M { () => ("/var/run/proxmox-backup") }
|
macro_rules! PROXMOX_BACKUP_VAR_RUN_DIR_M { () => ("/var/run/proxmox-backup") }
|
||||||
macro_rules! PROXMOX_BACKUP_LOG_DIR_M { () => ("/var/log/proxmox-backup") }
|
macro_rules! PROXMOX_BACKUP_LOG_DIR_M { () => ("/var/log/proxmox-backup") }
|
||||||
|
@ -31,7 +36,7 @@ lazy_static! {
|
||||||
static ref WORKER_TASK_LIST: Mutex<HashMap<usize, Arc<WorkerTask>>> = Mutex::new(HashMap::new());
|
static ref WORKER_TASK_LIST: Mutex<HashMap<usize, Arc<WorkerTask>>> = Mutex::new(HashMap::new());
|
||||||
|
|
||||||
static ref MY_PID: i32 = unsafe { libc::getpid() };
|
static ref MY_PID: i32 = unsafe { libc::getpid() };
|
||||||
static ref MY_PID_PSTART: u64 = tools::procfs::read_proc_pid_stat(*MY_PID).unwrap().starttime;
|
static ref MY_PID_PSTART: u64 = crate::tools::procfs::read_proc_pid_stat(*MY_PID).unwrap().starttime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if the task is still running
|
/// Test if the task is still running
|
||||||
|
@ -44,7 +49,7 @@ pub fn worker_is_active(upid: &UPID) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match tools::procfs::check_process_running_pstart(upid.pid, upid.pstart) {
|
match crate::tools::procfs::check_process_running_pstart(upid.pid, upid.pstart) {
|
||||||
Some(_) => true,
|
Some(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -136,13 +141,13 @@ fn parse_worker_status_line(line: &str) -> Result<(String, UPID, Option<(i64, St
|
||||||
pub fn create_task_log_dirs() -> Result<(), Error> {
|
pub fn create_task_log_dirs() -> Result<(), Error> {
|
||||||
|
|
||||||
try_block!({
|
try_block!({
|
||||||
let (backup_uid, backup_gid) = tools::getpwnam_ugid("backup")?;
|
let (backup_uid, backup_gid) = crate::tools::getpwnam_ugid("backup")?;
|
||||||
let uid = Some(nix::unistd::Uid::from_raw(backup_uid));
|
let uid = Some(nix::unistd::Uid::from_raw(backup_uid));
|
||||||
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
||||||
|
|
||||||
tools::create_dir_chown(PROXMOX_BACKUP_LOG_DIR, None, uid, gid)?;
|
create_dir_chown(PROXMOX_BACKUP_LOG_DIR, None, uid, gid)?;
|
||||||
tools::create_dir_chown(PROXMOX_BACKUP_TASK_DIR, None, uid, gid)?;
|
create_dir_chown(PROXMOX_BACKUP_TASK_DIR, None, uid, gid)?;
|
||||||
tools::create_dir_chown(PROXMOX_BACKUP_VAR_RUN_DIR, None, uid, gid)?;
|
create_dir_chown(PROXMOX_BACKUP_VAR_RUN_DIR, None, uid, gid)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}).map_err(|err: Error| format_err!("unable to create task log dir - {}", err))?;
|
}).map_err(|err: Error| format_err!("unable to create task log dir - {}", err))?;
|
||||||
|
|
||||||
|
@ -204,11 +209,11 @@ pub struct TaskListInfo {
|
||||||
// Returns a sorted list of known tasks,
|
// Returns a sorted list of known tasks,
|
||||||
fn update_active_workers(new_upid: Option<&UPID>) -> Result<Vec<TaskListInfo>, Error> {
|
fn update_active_workers(new_upid: Option<&UPID>) -> Result<Vec<TaskListInfo>, Error> {
|
||||||
|
|
||||||
let (backup_uid, backup_gid) = tools::getpwnam_ugid("backup")?;
|
let (backup_uid, backup_gid) = crate::tools::getpwnam_ugid("backup")?;
|
||||||
let uid = Some(nix::unistd::Uid::from_raw(backup_uid));
|
let uid = Some(nix::unistd::Uid::from_raw(backup_uid));
|
||||||
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
||||||
|
|
||||||
let lock = tools::open_file_locked(PROXMOX_BACKUP_TASK_LOCK_FN, std::time::Duration::new(10, 0))?;
|
let lock = crate::tools::open_file_locked(PROXMOX_BACKUP_TASK_LOCK_FN, std::time::Duration::new(10, 0))?;
|
||||||
nix::unistd::chown(PROXMOX_BACKUP_TASK_LOCK_FN, uid, gid)?;
|
nix::unistd::chown(PROXMOX_BACKUP_TASK_LOCK_FN, uid, gid)?;
|
||||||
|
|
||||||
let reader = match File::open(PROXMOX_BACKUP_ACTIVE_TASK_FN) {
|
let reader = match File::open(PROXMOX_BACKUP_ACTIVE_TASK_FN) {
|
||||||
|
@ -303,7 +308,7 @@ fn update_active_workers(new_upid: Option<&UPID>) -> Result<Vec<TaskListInfo>, E
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tools::file_set_contents_full(PROXMOX_BACKUP_ACTIVE_TASK_FN, raw.as_bytes(), None, uid, gid)?;
|
file_set_contents_full(PROXMOX_BACKUP_ACTIVE_TASK_FN, raw.as_bytes(), None, uid, gid)?;
|
||||||
|
|
||||||
drop(lock);
|
drop(lock);
|
||||||
|
|
||||||
|
@ -363,11 +368,11 @@ impl WorkerTask {
|
||||||
|
|
||||||
path.push(format!("{:02X}", upid.pstart % 256));
|
path.push(format!("{:02X}", upid.pstart % 256));
|
||||||
|
|
||||||
let (backup_uid, backup_gid) = tools::getpwnam_ugid("backup")?;
|
let (backup_uid, backup_gid) = crate::tools::getpwnam_ugid("backup")?;
|
||||||
let uid = Some(nix::unistd::Uid::from_raw(backup_uid));
|
let uid = Some(nix::unistd::Uid::from_raw(backup_uid));
|
||||||
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
let gid = Some(nix::unistd::Gid::from_raw(backup_gid));
|
||||||
|
|
||||||
tools::create_dir_chown(&path, None, uid, gid)?;
|
create_dir_chown(&path, None, uid, gid)?;
|
||||||
|
|
||||||
path.push(upid.to_string());
|
path.push(upid.to_string());
|
||||||
|
|
||||||
|
|
220
src/tools.rs
220
src/tools.rs
|
@ -2,14 +2,9 @@
|
||||||
//!
|
//!
|
||||||
//! This is a collection of small and useful tools.
|
//! This is a collection of small and useful tools.
|
||||||
use failure::*;
|
use failure::*;
|
||||||
use nix::unistd;
|
|
||||||
use nix::sys::stat;
|
|
||||||
use nix::{convert_ioctl_res, request_code_read, ioc};
|
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::Write;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
|
@ -50,28 +45,6 @@ pub use file_logger::*;
|
||||||
mod broadcast_future;
|
mod broadcast_future;
|
||||||
pub use broadcast_future::*;
|
pub use broadcast_future::*;
|
||||||
|
|
||||||
/// Macro to write error-handling blocks (like perl eval {})
|
|
||||||
///
|
|
||||||
/// #### Example:
|
|
||||||
/// ```
|
|
||||||
/// # #[macro_use] extern crate proxmox_backup;
|
|
||||||
/// # use failure::*;
|
|
||||||
/// # let some_condition = false;
|
|
||||||
/// let result = try_block!({
|
|
||||||
/// if (some_condition) {
|
|
||||||
/// bail!("some error");
|
|
||||||
/// }
|
|
||||||
/// Ok(())
|
|
||||||
/// })
|
|
||||||
/// .map_err(|e| format_err!("my try block returned an error - {}", e));
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! try_block {
|
|
||||||
{ $($token:tt)* } => {{ (|| -> Result<_,_> { $($token)* })() }}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// The `BufferedRead` trait provides a single function
|
/// The `BufferedRead` trait provides a single function
|
||||||
/// `buffered_read`. It returns a reference to an internal buffer. The
|
/// `buffered_read`. It returns a reference to an internal buffer. The
|
||||||
/// purpose of this traid is to avoid unnecessary data copies.
|
/// purpose of this traid is to avoid unnecessary data copies.
|
||||||
|
@ -108,123 +81,6 @@ pub fn map_struct_mut<T>(buffer: &mut [u8]) -> Result<&mut T, Error> {
|
||||||
Ok(unsafe { &mut * (buffer.as_ptr() as *mut T) })
|
Ok(unsafe { &mut * (buffer.as_ptr() as *mut T) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_read_firstline<P: AsRef<Path>>(path: P) -> Result<String, Error> {
|
|
||||||
|
|
||||||
let path = path.as_ref();
|
|
||||||
|
|
||||||
try_block!({
|
|
||||||
let file = std::fs::File::open(path)?;
|
|
||||||
|
|
||||||
use std::io::{BufRead, BufReader};
|
|
||||||
|
|
||||||
let mut reader = BufReader::new(file);
|
|
||||||
|
|
||||||
let mut line = String::new();
|
|
||||||
|
|
||||||
let _ = reader.read_line(&mut line)?;
|
|
||||||
|
|
||||||
Ok(line)
|
|
||||||
}).map_err(|err: Error| format_err!("unable to read {:?} - {}", path, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn file_get_contents<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, Error> {
|
|
||||||
|
|
||||||
let path = path.as_ref();
|
|
||||||
|
|
||||||
try_block!({
|
|
||||||
std::fs::read(path)
|
|
||||||
}).map_err(|err| format_err!("unable to read {:?} - {}", path, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn file_get_json<P: AsRef<Path>>(path: P, default: Option<Value>) -> Result<Value, Error> {
|
|
||||||
|
|
||||||
let path = path.as_ref();
|
|
||||||
|
|
||||||
let raw = match std::fs::read(path) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(err) => {
|
|
||||||
if err.kind() == std::io::ErrorKind::NotFound {
|
|
||||||
if let Some(v) = default {
|
|
||||||
return Ok(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bail!("unable to read json {:?} - {}", path, err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try_block!({
|
|
||||||
let data = String::from_utf8(raw)?;
|
|
||||||
let json = serde_json::from_str(&data)?;
|
|
||||||
Ok(json)
|
|
||||||
}).map_err(|err: Error| format_err!("unable to parse json from {:?} - {}", path, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atomically write a file
|
|
||||||
///
|
|
||||||
/// We first create a temporary file, which is then renamed.
|
|
||||||
pub fn file_set_contents<P: AsRef<Path>>(
|
|
||||||
path: P,
|
|
||||||
data: &[u8],
|
|
||||||
perm: Option<stat::Mode>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
file_set_contents_full(path, data, perm, None, None)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atomically write a file with owner and group
|
|
||||||
pub fn file_set_contents_full<P: AsRef<Path>>(
|
|
||||||
path: P,
|
|
||||||
data: &[u8],
|
|
||||||
perm: Option<stat::Mode>,
|
|
||||||
owner: Option<unistd::Uid>,
|
|
||||||
group: Option<unistd::Gid>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
|
|
||||||
let path = path.as_ref();
|
|
||||||
|
|
||||||
// Note: we use mkstemp heŕe, because this worka with different
|
|
||||||
// processes, threads, and even tokio tasks.
|
|
||||||
let mut template = path.to_owned();
|
|
||||||
template.set_extension("tmp_XXXXXX");
|
|
||||||
let (fd, tmp_path) = match unistd::mkstemp(&template) {
|
|
||||||
Ok((fd, path)) => (fd, path),
|
|
||||||
Err(err) => bail!("mkstemp {:?} failed: {}", template, err),
|
|
||||||
};
|
|
||||||
|
|
||||||
let tmp_path = tmp_path.as_path();
|
|
||||||
|
|
||||||
let mode : stat::Mode = perm.unwrap_or(stat::Mode::from(
|
|
||||||
stat::Mode::S_IRUSR | stat::Mode::S_IWUSR |
|
|
||||||
stat::Mode::S_IRGRP | stat::Mode::S_IROTH
|
|
||||||
));
|
|
||||||
|
|
||||||
if perm != None {
|
|
||||||
if let Err(err) = stat::fchmod(fd, mode) {
|
|
||||||
let _ = unistd::unlink(tmp_path);
|
|
||||||
bail!("fchmod {:?} failed: {}", tmp_path, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if owner != None || group != None {
|
|
||||||
if let Err(err) = fchown(fd, owner, group) {
|
|
||||||
let _ = unistd::unlink(tmp_path);
|
|
||||||
bail!("fchown {:?} failed: {}", tmp_path, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut file = unsafe { File::from_raw_fd(fd) };
|
|
||||||
|
|
||||||
if let Err(err) = file.write_all(data) {
|
|
||||||
let _ = unistd::unlink(tmp_path);
|
|
||||||
bail!("write failed: {}", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(err) = std::fs::rename(tmp_path, path) {
|
|
||||||
let _ = unistd::unlink(tmp_path);
|
|
||||||
bail!("Atomic rename failed for file {:?} - {}", path, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a file lock using fntl. This function allows you to specify
|
/// Create a file lock using fntl. This function allows you to specify
|
||||||
/// a timeout if you want to avoid infinite blocking.
|
/// a timeout if you want to avoid infinite blocking.
|
||||||
|
@ -362,52 +218,6 @@ pub fn getpwnam_ugid(username: &str) -> Result<(libc::uid_t,libc::gid_t), Error>
|
||||||
Ok((info.pw_uid, info.pw_gid))
|
Ok((info.pw_uid, info.pw_gid))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates directory at the provided path with specified ownership
|
|
||||||
///
|
|
||||||
/// Simply returns if the directory already exists.
|
|
||||||
pub fn create_dir_chown<P: AsRef<Path>>(
|
|
||||||
path: P,
|
|
||||||
perm: Option<stat::Mode>,
|
|
||||||
owner: Option<unistd::Uid>,
|
|
||||||
group: Option<unistd::Gid>,
|
|
||||||
) -> Result<(), nix::Error>
|
|
||||||
{
|
|
||||||
let mode : stat::Mode = perm.unwrap_or(stat::Mode::from_bits_truncate(0o770));
|
|
||||||
|
|
||||||
let path = path.as_ref();
|
|
||||||
|
|
||||||
match nix::unistd::mkdir(path, mode) {
|
|
||||||
Ok(()) => {},
|
|
||||||
Err(nix::Error::Sys(nix::errno::Errno::EEXIST)) => {
|
|
||||||
return Ok(());
|
|
||||||
},
|
|
||||||
err => return err,
|
|
||||||
}
|
|
||||||
|
|
||||||
unistd::chown(path, owner, group)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change ownership of an open file handle
|
|
||||||
pub fn fchown(
|
|
||||||
fd: RawFd,
|
|
||||||
owner: Option<nix::unistd::Uid>,
|
|
||||||
group: Option<nix::unistd::Gid>
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
|
|
||||||
// According to the POSIX specification, -1 is used to indicate that owner and group
|
|
||||||
// are not to be changed. Since uid_t and gid_t are unsigned types, we have to wrap
|
|
||||||
// around to get -1 (copied fron nix crate).
|
|
||||||
let uid = owner.map(Into::into).unwrap_or((0 as libc::uid_t).wrapping_sub(1));
|
|
||||||
let gid = group.map(Into::into).unwrap_or((0 as libc::gid_t).wrapping_sub(1));
|
|
||||||
|
|
||||||
let res = unsafe { libc::fchown(fd, uid, gid) };
|
|
||||||
nix::errno::Errno::result(res)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the hosts node name (UTS node name)
|
// Returns the hosts node name (UTS node name)
|
||||||
pub fn nodename() -> &'static str {
|
pub fn nodename() -> &'static str {
|
||||||
|
|
||||||
|
@ -561,7 +371,7 @@ pub fn get_hardware_address() -> Result<String, Error> {
|
||||||
|
|
||||||
static FILENAME: &str = "/etc/ssh/ssh_host_rsa_key.pub";
|
static FILENAME: &str = "/etc/ssh/ssh_host_rsa_key.pub";
|
||||||
|
|
||||||
let contents = file_get_contents(FILENAME)?;
|
let contents = proxmox::tools::fs::file_get_contents(FILENAME)?;
|
||||||
let digest = md5::compute(contents);
|
let digest = md5::compute(contents);
|
||||||
|
|
||||||
Ok(format!("{:0x}", digest))
|
Ok(format!("{:0x}", digest))
|
||||||
|
@ -716,31 +526,3 @@ impl<T: Any> AsAny for T {
|
||||||
fn as_any(&self) -> &dyn Any { self }
|
fn as_any(&self) -> &dyn Any { self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// /usr/include/linux/fs.h: #define BLKGETSIZE64 _IOR(0x12,114,size_t)
|
|
||||||
// return device size in bytes (u64 *arg)
|
|
||||||
nix::ioctl_read!(blkgetsize64, 0x12, 114, u64);
|
|
||||||
|
|
||||||
/// Return file or block device size
|
|
||||||
pub fn image_size(path: &Path) -> Result<u64, Error> {
|
|
||||||
|
|
||||||
use std::os::unix::fs::FileTypeExt;
|
|
||||||
|
|
||||||
let file = std::fs::File::open(path)?;
|
|
||||||
let metadata = file.metadata()?;
|
|
||||||
let file_type = metadata.file_type();
|
|
||||||
|
|
||||||
if file_type.is_block_device() {
|
|
||||||
let mut size : u64 = 0;
|
|
||||||
let res = unsafe { blkgetsize64(file.as_raw_fd(), &mut size) };
|
|
||||||
|
|
||||||
if let Err(err) = res {
|
|
||||||
bail!("blkgetsize64 failed for {:?} - {}", path, err);
|
|
||||||
}
|
|
||||||
Ok(size)
|
|
||||||
} else if file_type.is_file() {
|
|
||||||
Ok(metadata.len())
|
|
||||||
} else {
|
|
||||||
bail!("image size failed - got unexpected file type {:?}", file_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -220,8 +220,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use nix::{convert_ioctl_res, request_code_read, request_code_write, ioc};
|
|
||||||
|
|
||||||
// /usr/include/linux/fs.h: #define FS_IOC_GETFLAGS _IOR('f', 1, long)
|
// /usr/include/linux/fs.h: #define FS_IOC_GETFLAGS _IOR('f', 1, long)
|
||||||
// read Linux file system attributes (see man chattr)
|
// read Linux file system attributes (see man chattr)
|
||||||
nix::ioctl_read!(read_attr_fd, b'f', 1, usize);
|
nix::ioctl_read!(read_attr_fd, b'f', 1, usize);
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::io::{BufRead, BufReader};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
use crate::tools;
|
use proxmox::tools::fs::file_read_firstline;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use libc;
|
use libc;
|
||||||
|
@ -32,7 +32,7 @@ pub struct ProcFsPidStat {
|
||||||
|
|
||||||
pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<ProcFsPidStat, Error> {
|
pub fn read_proc_pid_stat(pid: libc::pid_t) -> Result<ProcFsPidStat, Error> {
|
||||||
|
|
||||||
let statstr = tools::file_read_firstline(format!("/proc/{}/stat", pid))?;
|
let statstr = file_read_firstline(format!("/proc/{}/stat", pid))?;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref REGEX: Regex = Regex::new(concat!(
|
static ref REGEX: Regex = Regex::new(concat!(
|
||||||
|
@ -89,7 +89,7 @@ pub fn check_process_running_pstart(pid: libc::pid_t, pstart: u64) -> Option<Pro
|
||||||
|
|
||||||
pub fn read_proc_uptime() -> Result<(f64, f64), Error> {
|
pub fn read_proc_uptime() -> Result<(f64, f64), Error> {
|
||||||
let path = "/proc/uptime";
|
let path = "/proc/uptime";
|
||||||
let line = tools::file_read_firstline(&path)?;
|
let line = file_read_firstline(&path)?;
|
||||||
let mut values = line.split_whitespace().map(|v| v.parse::<f64>());
|
let mut values = line.split_whitespace().map(|v| v.parse::<f64>());
|
||||||
|
|
||||||
match (values.next(), values.next()) {
|
match (values.next(), values.next()) {
|
||||||
|
@ -152,7 +152,7 @@ pub fn read_meminfo() -> Result<ProcFsMemInfo, Error> {
|
||||||
|
|
||||||
meminfo.swapused = meminfo.swaptotal - meminfo.swapfree;
|
meminfo.swapused = meminfo.swaptotal - meminfo.swapfree;
|
||||||
|
|
||||||
let spages_line = tools::file_read_firstline("/sys/kernel/mm/ksm/pages_sharing")?;
|
let spages_line = file_read_firstline("/sys/kernel/mm/ksm/pages_sharing")?;
|
||||||
meminfo.memshared = spages_line.trim_end().parse::<u64>()? * 4096;
|
meminfo.memshared = spages_line.trim_end().parse::<u64>()? * 4096;
|
||||||
|
|
||||||
Ok(meminfo)
|
Ok(meminfo)
|
||||||
|
@ -221,7 +221,7 @@ pub struct ProcFsMemUsage {
|
||||||
|
|
||||||
pub fn read_memory_usage() -> Result<ProcFsMemUsage, Error> {
|
pub fn read_memory_usage() -> Result<ProcFsMemUsage, Error> {
|
||||||
let path = format!("/proc/{}/statm", process::id());
|
let path = format!("/proc/{}/statm", process::id());
|
||||||
let line = tools::file_read_firstline(&path)?;
|
let line = file_read_firstline(&path)?;
|
||||||
let mut values = line.split_whitespace().map(|v| v.parse::<u64>());
|
let mut values = line.split_whitespace().map(|v| v.parse::<u64>());
|
||||||
|
|
||||||
let ps = 4096;
|
let ps = 4096;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
use crate::try_block;
|
use proxmox::tools::try_block;
|
||||||
|
|
||||||
/// Returns whether the current stdin is a tty .
|
/// Returns whether the current stdin is a tty .
|
||||||
pub fn stdin_isatty() -> bool {
|
pub fn stdin_isatty() -> bool {
|
||||||
|
|
Loading…
Reference in New Issue