From 0ce57d934a20c2814d7a32ca84df8dc9e5e20bc6 Mon Sep 17 00:00:00 2001 From: Josh Abraham Date: Sat, 20 Oct 2018 20:44:26 -0400 Subject: [PATCH] Add acct(2) wrapper API This patch adds a wrapper for the acct(2) syscall, with two functions for enabling and disabling process accounting. --- CHANGELOG.md | 2 ++ src/unistd.rs | 25 +++++++++++++++++++++++++ test/test_unistd.rs | 27 ++++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f6cef9008..9d809501ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added support for `ptrace` on BSD operating systems ([#949](https://github.com/nix-rust/nix/pull/949)) - Added `ptrace` functions for reads and writes to tracee memory and ptrace kill ([#949](https://github.com/nix-rust/nix/pull/949)) +- Added a `acct` wrapper module for enabling and disabling process accounting + ([#952](https://github.com/nix-rust/nix/pull/952)) ### Changed - Increased required Rust version to 1.22.1/ diff --git a/src/unistd.rs b/src/unistd.rs index d5192977fd..c9c129c974 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1508,6 +1508,31 @@ pub fn sleep(seconds: c_uint) -> c_uint { unsafe { libc::sleep(seconds) } } +pub mod acct { + use libc; + use {Result, NixPath}; + use errno::Errno; + use std::ptr; + + /// Enable process accounting + /// + /// See also [acct(2)](https://linux.die.net/man/2/acct) + pub fn enable(filename: &P) -> Result<()> { + let res = try!(filename.with_nix_path(|cstr| { + unsafe { libc::acct(cstr.as_ptr()) } + })); + + Errno::result(res).map(drop) + } + + /// Disable process accounting + pub fn disable() -> Result<()> { + let res = unsafe { libc::acct(ptr::null()) }; + + Errno::result(res).map(drop) + } +} + /// Creates a regular file which persists even after process termination /// /// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX` diff --git a/test/test_unistd.rs b/test/test_unistd.rs index e5f9d448dd..52eb365c21 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -4,12 +4,13 @@ use nix::unistd::ForkResult::*; use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction}; use nix::sys::wait::*; use nix::sys::stat::{self, Mode, SFlag}; -use std::{env, iter}; +use std::{env, iter, thread, time}; use std::ffi::CString; -use std::fs::{self, File}; +use std::fs::{self, File, metadata}; use std::io::Write; use std::os::unix::prelude::*; -use tempfile::{self, tempfile}; +use std::process::Command; +use tempfile::{self, tempfile, NamedTempFile}; use libc::{self, _exit, off_t}; #[test] @@ -378,6 +379,26 @@ fn test_lseek64() { close(tmpfd).unwrap(); } +// Skip on FreeBSD because FreeBSD's CI environment is jailed, and jails +// aren't allowed to use acct(2) +#[cfg(not(target_os = "freebsd"))] +#[test] +fn test_acct() { + skip_if_not_root!("test_acct"); + let file = NamedTempFile::new().unwrap(); + let path = file.path().to_str().unwrap(); + + acct::enable(path).unwrap(); + Command::new("echo").arg("Hello world"); + acct::disable().unwrap(); + + loop { + let len = metadata(path).unwrap().len(); + if len > 0 { break; } + thread::sleep(time::Duration::from_millis(10)); + } +} + #[test] fn test_fpathconf_limited() { let f = tempfile().unwrap();