Skip to content

Commit

Permalink
implement serialization feature-flag
Browse files Browse the repository at this point in the history
  • Loading branch information
joppich committed Mar 12, 2019
1 parent 24a017c commit 912b9e1
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ maintenance = { status = "experimental" }
is-it-maintained-issue-resolution = { repository = "fubarnetes/rctl" }
is-it-maintained-open-issues = { repository = "fubarnetes/rctl" }

[features]
serialize = ["serde", "serde_json"]

[dependencies]
failure = "0.1"
libc = "0.2"
nix = "0.11"
number_prefix = "0.2"
sysctl = "0.2"
serde = { version="1.0", features = ["derive"], optional=true }
serde_json = { version="1.0", optional=true }
23 changes: 23 additions & 0 deletions examples/serialize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
extern crate libc;
extern crate rctl;

#[cfg(feature="serialize")]
extern crate serde_json;

#[cfg(feature="serialize")]
fn main() {

let uid = unsafe { libc::getuid() };

let subject = rctl::Subject::user_id(uid);

let serialized = serde_json::to_string(&subject)
.expect("Could not serialize RCTL subject.");

println!("{}", serialized);
}

#[cfg(not(feature="serialize"))]
fn main() {
println!("Run `cargo build --features=serialize` to enable this example");
}
46 changes: 46 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ extern crate nix;
extern crate number_prefix;
extern crate sysctl;

#[cfg(feature = "serialize")]
#[macro_use]
extern crate serde;

pub use nix::sys::signal::Signal;
use number_prefix::{binary_prefix, Prefix, Prefixed, Standalone};
use std::collections::HashMap;
Expand All @@ -54,6 +58,9 @@ use std::io;
use std::num;
use std::str;

#[cfg(feature = "serialize")]
use serde::Serializer;

// Set to the same value as found in rctl.c in FreeBSD 11.1
const RCTL_DEFAULT_BUFSIZE: usize = 128 * 1024;

Expand Down Expand Up @@ -125,6 +132,7 @@ mod subject {

/// Represents a user subject
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct User(pub libc::uid_t);

impl User {
Expand Down Expand Up @@ -207,6 +215,7 @@ mod subject {

/// Represents a process subject
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct Process(pub libc::pid_t);

impl fmt::Display for Process {
Expand All @@ -223,6 +232,7 @@ mod subject {

/// Represents a jail subject
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct Jail(pub String);

impl fmt::Display for Jail {
Expand All @@ -239,6 +249,7 @@ mod subject {

/// Represents a login class subject
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct LoginClass(pub String);

impl fmt::Display for LoginClass {
Expand Down Expand Up @@ -315,6 +326,7 @@ mod subject {
///
/// [`rctl(8)`]: https://www.freebsd.org/cgi/man.cgi?query=rctl&sektion=8&manpath=FreeBSD+11.2-stable
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub enum Subject {
Process(subject::Process),
Jail(subject::Jail),
Expand Down Expand Up @@ -487,6 +499,7 @@ impl str::FromStr for Subject {

/// The type of a [Subject].
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub enum SubjectType {
Process,
Jail,
Expand Down Expand Up @@ -551,6 +564,7 @@ impl fmt::Display for SubjectType {

/// An Enum representing a resource type
#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub enum Resource {
/// CPU time, in seconds
CpuTime,
Expand Down Expand Up @@ -755,6 +769,7 @@ impl fmt::Display for Resource {

/// Represents the action to be taken when a [Subject] offends against a Rule.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub enum Action {
/// Deny the resource allocation
///
Expand Down Expand Up @@ -792,6 +807,7 @@ pub enum Action {
/// ```
///
/// [signal]: Signal
#[cfg_attr(feature="serialize", serde(serialize_with = "signal_serialize"))]
Signal(Signal),

/// Slow down process execution
Expand Down Expand Up @@ -931,9 +947,19 @@ impl fmt::Display for Action {
}
}

#[cfg(feature="serialize")]
fn signal_serialize<S>(signal: &Signal, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let sig_str = format!("{:?}", signal);
s.serialize_str(&sig_str)
}

/// Defines how much of a [Resource] a process can use beofore the defined
/// [Action] triggers.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct Limit {
amount: usize,
per: Option<SubjectType>,
Expand Down Expand Up @@ -1093,6 +1119,7 @@ impl<'a> Into<String> for &'a Limit {
/// assert_eq!(rule.to_string(), "user:nobody:vmemoryuse:deny=1g".to_string());
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct Rule {
pub subject: Subject,
pub resource: Resource,
Expand Down Expand Up @@ -2182,4 +2209,23 @@ pub mod tests {

filter.remove_rules().expect("Could not remove rules");
}

#[cfg(feature="serialize")]
#[test]
fn serialize_rule() {
let rule = "process:23:vmemoryuse:sigterm=100m"
.parse::<Rule>()
.expect("Could not parse rule");

let serialized = serde_json::to_string(&rule)
.expect("Could not serialize rule");

let rule_map: serde_json::Value = serde_json::from_str(&serialized)
.expect("Could not load serialized rule");

assert_eq!(rule_map["subject"]["Process"], 23);
assert_eq!(rule_map["resource"], "VMemoryUse");
assert_eq!(rule_map["action"]["Signal"], "SIGTERM");
assert_eq!(rule_map["limit"]["amount"], 100 * 1024 * 1024)
}
}

0 comments on commit 912b9e1

Please sign in to comment.