//!
//! This is a collection of small and useful tools.
use std::any::Any;
-use std::collections::HashMap;
-use std::hash::BuildHasher;
-use std::fs::File;
-use std::io::{self, BufRead};
use std::os::unix::io::RawFd;
-use std::path::Path;
use anyhow::{bail, format_err, Error};
-use serde_json::Value;
use openssl::hash::{hash, DigestBytes, MessageDigest};
-use percent_encoding::{utf8_percent_encode, AsciiSet};
pub use proxmox::tools::fd::Fd;
use proxmox::tools::fs::{create_path, CreateOptions};
ProcessLocker, ProcessLockExclusiveGuard, ProcessLockSharedGuard
};
-pub mod acl;
pub mod apt;
pub mod async_io;
-pub mod cert;
pub mod compression;
pub mod config;
pub mod cpio;
pub mod daemon;
pub mod disks;
-pub mod fuse_loop;
mod memcom;
pub use memcom::Memcom;
pub mod logrotate;
-pub mod loopdev;
-pub mod lru_cache;
-pub mod async_lru_cache;
pub mod serde_filter;
pub mod statistics;
pub mod subscription;
pub mod systemd;
pub mod ticket;
-pub mod xattr;
-pub mod zip;
pub mod sgutils2;
-pub mod paperkey;
pub mod parallel_handler;
pub use parallel_handler::ParallelHandler;
-mod wrapped_reader_stream;
-pub use wrapped_reader_stream::{AsyncReaderStream, StdChannelStream, WrappedReaderStream};
-
-mod async_channel_writer;
-pub use async_channel_writer::AsyncChannelWriter;
-
-mod std_channel_writer;
-pub use std_channel_writer::StdChannelWriter;
-
-mod tokio_writer_adapter;
-pub use tokio_writer_adapter::TokioWriterAdapter;
-
mod file_logger;
pub use file_logger::{FileLogger, FileLogOptions};
-mod broadcast_future;
-pub use broadcast_future::{BroadcastData, BroadcastFuture};
-
-/// The `BufferedRead` trait provides a single function
-/// `buffered_read`. It returns a reference to an internal buffer. The
-/// purpose of this traid is to avoid unnecessary data copies.
-pub trait BufferedRead {
- /// This functions tries to fill the internal buffers, then
- /// returns a reference to the available data. It returns an empty
- /// buffer if `offset` points to the end of the file.
- fn buffered_read(&mut self, offset: u64) -> Result<&[u8], Error>;
-}
-
-pub fn required_string_param<'a>(param: &'a Value, name: &str) -> Result<&'a str, Error> {
- match param[name].as_str() {
- Some(s) => Ok(s),
- None => bail!("missing parameter '{}'", name),
- }
-}
-
-pub fn required_string_property<'a>(param: &'a Value, name: &str) -> Result<&'a str, Error> {
- match param[name].as_str() {
- Some(s) => Ok(s),
- None => bail!("missing property '{}'", name),
- }
-}
-
-pub fn required_integer_param(param: &Value, name: &str) -> Result<i64, Error> {
- match param[name].as_i64() {
- Some(s) => Ok(s),
- None => bail!("missing parameter '{}'", name),
- }
-}
-
-pub fn required_integer_property(param: &Value, name: &str) -> Result<i64, Error> {
- match param[name].as_i64() {
- Some(s) => Ok(s),
- None => bail!("missing property '{}'", name),
- }
-}
-
-pub fn required_array_param<'a>(param: &'a Value, name: &str) -> Result<&'a [Value], Error> {
- match param[name].as_array() {
- Some(s) => Ok(&s),
- None => bail!("missing parameter '{}'", name),
- }
-}
-
-pub fn required_array_property<'a>(param: &'a Value, name: &str) -> Result<&'a [Value], Error> {
- match param[name].as_array() {
- Some(s) => Ok(&s),
- None => bail!("missing property '{}'", name),
- }
-}
-
-pub fn complete_file_name<S>(arg: &str, _param: &HashMap<String, String, S>) -> Vec<String>
-where
- S: BuildHasher,
-{
- let mut result = vec![];
-
- use nix::fcntl::AtFlags;
- use nix::fcntl::OFlag;
- use nix::sys::stat::Mode;
-
- let mut dirname = std::path::PathBuf::from(if arg.is_empty() { "./" } else { arg });
-
- let is_dir = match nix::sys::stat::fstatat(libc::AT_FDCWD, &dirname, AtFlags::empty()) {
- Ok(stat) => (stat.st_mode & libc::S_IFMT) == libc::S_IFDIR,
- Err(_) => false,
- };
-
- if !is_dir {
- if let Some(parent) = dirname.parent() {
- dirname = parent.to_owned();
- }
- }
-
- let mut dir =
- match nix::dir::Dir::openat(libc::AT_FDCWD, &dirname, OFlag::O_DIRECTORY, Mode::empty()) {
- Ok(d) => d,
- Err(_) => return result,
- };
-
- for item in dir.iter() {
- if let Ok(entry) = item {
- if let Ok(name) = entry.file_name().to_str() {
- if name == "." || name == ".." {
- continue;
- }
- let mut newpath = dirname.clone();
- newpath.push(name);
-
- if let Ok(stat) =
- nix::sys::stat::fstatat(libc::AT_FDCWD, &newpath, AtFlags::empty())
- {
- if (stat.st_mode & libc::S_IFMT) == libc::S_IFDIR {
- newpath.push("");
- if let Some(newpath) = newpath.to_str() {
- result.push(newpath.to_owned());
- }
- continue;
- }
- }
- if let Some(newpath) = newpath.to_str() {
- result.push(newpath.to_owned());
- }
- }
- }
- }
-
- result
-}
+pub use pbs_tools::broadcast_future::{BroadcastData, BroadcastFuture};
+pub use pbs_tools::ops::ControlFlow;
/// Shortcut for md5 sums.
pub fn md5sum(data: &[u8]) -> Result<DigestBytes, Error> {
None
}
-/// percent encode a url component
-pub fn percent_encode_component(comp: &str) -> String {
- utf8_percent_encode(comp, percent_encoding::NON_ALPHANUMERIC).to_string()
-}
-
/// Detect modified configuration files
///
/// This function fails with a reasonable error message if checksums do not match.
Ok(())
}
-/// safe wrapper for `nix::unistd::pipe2` defaulting to `O_CLOEXEC` and guarding the file
-/// descriptors.
-pub fn pipe() -> Result<(Fd, Fd), Error> {
- let (pin, pout) = nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC)?;
- Ok((Fd(pin), Fd(pout)))
-}
-
/// safe wrapper for `nix::sys::socket::socketpair` defaulting to `O_CLOEXEC` and guarding the file
/// descriptors.
pub fn socketpair() -> Result<(Fd, Fd), Error> {
SimpleHttp::with_options(options)
}
-/// This used to be: `SIMPLE_ENCODE_SET` plus space, `"`, `#`, `<`, `>`, backtick, `?`, `{`, `}`
-pub const DEFAULT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS // 0..1f and 7e
- // The SIMPLE_ENCODE_SET adds space and anything >= 0x7e (7e itself is already included above)
- .add(0x20)
- .add(0x7f)
- // the DEFAULT_ENCODE_SET added:
- .add(b' ')
- .add(b'"')
- .add(b'#')
- .add(b'<')
- .add(b'>')
- .add(b'`')
- .add(b'?')
- .add(b'{')
- .add(b'}');
-
-/// Get an iterator over lines of a file, skipping empty lines and comments (lines starting with a
-/// `#`).
-pub fn file_get_non_comment_lines<P: AsRef<Path>>(
- path: P,
-) -> Result<impl Iterator<Item = io::Result<String>>, Error> {
- let path = path.as_ref();
-
- Ok(io::BufReader::new(
- File::open(path).map_err(|err| format_err!("error opening {:?}: {}", path, err))?,
- )
- .lines()
- .filter_map(|line| match line {
- Ok(line) => {
- let line = line.trim();
- if line.is_empty() || line.starts_with('#') {
- None
- } else {
- Some(Ok(line.to_string()))
- }
- }
- Err(err) => Some(Err(err)),
- }))
-}
-
pub fn setup_safe_path_env() {
std::env::set_var("PATH", "/sbin:/bin:/usr/sbin:/usr/bin");
// Make %ENV safer - as suggested by https://perldoc.perl.org/perlsec.html
}
}
-pub fn strip_ascii_whitespace(line: &[u8]) -> &[u8] {
- let line = match line.iter().position(|&b| !b.is_ascii_whitespace()) {
- Some(n) => &line[n..],
- None => return &[],
- };
- match line.iter().rev().position(|&b| !b.is_ascii_whitespace()) {
- Some(n) => &line[..(line.len() - n)],
- None => &[],
- }
-}
-
/// Create the base run-directory.
///
/// This exists to fixate the permissions for the run *base* directory while allowing intermediate
let _: bool = create_path(pbs_buildcfg::PROXMOX_BACKUP_RUN_DIR_M!(), None, Some(opts))?;
Ok(())
}
-
-/// Modeled after the nightly `std::ops::ControlFlow`.
-#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum ControlFlow<B, C = ()> {
- Continue(C),
- Break(B),
-}
-
-impl<B> ControlFlow<B> {
- pub const CONTINUE: ControlFlow<B, ()> = ControlFlow::Continue(());
-}