Add support for "/proc/[pid]/comm" and fix "/proc/[pid]/cmdline"
This commit is contained in:
parent
63d2de1043
commit
17e4810d3e
@ -1,6 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::process::table::get_process;
|
use crate::process::table::get_process;
|
||||||
use crate::process::ProcessRef;
|
use crate::process::{ProcessRef, ProcessStatus};
|
||||||
|
|
||||||
pub struct LockedPidDirINode(RwLock<PidDirINode>);
|
pub struct LockedPidDirINode(RwLock<PidDirINode>);
|
||||||
|
|
||||||
@ -41,7 +41,9 @@ impl LockedPidDirINode {
|
|||||||
// root
|
// root
|
||||||
let root_inode = ProcRootSymINode::new(&file.process_ref);
|
let root_inode = ProcRootSymINode::new(&file.process_ref);
|
||||||
file.entries.insert(String::from("root"), root_inode);
|
file.entries.insert(String::from("root"), root_inode);
|
||||||
|
// comm
|
||||||
|
let comm_inode = ProcCommINode::new(&file.process_ref);
|
||||||
|
file.entries.insert(String::from("comm"), comm_inode);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,7 +138,15 @@ impl ProcCmdlineINode {
|
|||||||
|
|
||||||
impl ProcINode for ProcCmdlineINode {
|
impl ProcINode for ProcCmdlineINode {
|
||||||
fn generate_data_in_bytes(&self) -> vfs::Result<Vec<u8>> {
|
fn generate_data_in_bytes(&self) -> vfs::Result<Vec<u8>> {
|
||||||
Ok(self.0.exec_path().to_owned().into_bytes())
|
let cmdline = if let ProcessStatus::Zombie = self.0.status() {
|
||||||
|
Vec::new()
|
||||||
|
} else {
|
||||||
|
// Null-terminated bytes
|
||||||
|
std::ffi::CString::new(self.0.exec_path())
|
||||||
|
.expect("failed to new CString")
|
||||||
|
.into_bytes_with_nul()
|
||||||
|
};
|
||||||
|
Ok(cmdline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,6 +196,24 @@ impl ProcINode for ProcRootSymINode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ProcCommINode(ProcessRef);
|
||||||
|
|
||||||
|
impl ProcCommINode {
|
||||||
|
pub fn new(process_ref: &ProcessRef) -> Arc<dyn INode> {
|
||||||
|
Arc::new(File::new(Self(Arc::clone(process_ref))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcINode for ProcCommINode {
|
||||||
|
fn generate_data_in_bytes(&self) -> vfs::Result<Vec<u8>> {
|
||||||
|
let main_thread = self.0.main_thread().ok_or(FsError::EntryNotFound)?;
|
||||||
|
let mut comm = main_thread.name().as_c_str().to_bytes().to_vec();
|
||||||
|
// Add '\n' at the end to make the result same with Linux
|
||||||
|
comm.push(b'\n');
|
||||||
|
Ok(comm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FdSymINode(FileRef);
|
pub struct FdSymINode(FileRef);
|
||||||
|
|
||||||
impl FdSymINode {
|
impl FdSymINode {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -10,7 +11,8 @@
|
|||||||
// Helper variable and function
|
// Helper variable and function
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
const char **g_argv;
|
// Contains the name that was used to invoke the calling program
|
||||||
|
extern char *program_invocation_short_name;
|
||||||
|
|
||||||
static int test_readlink_from_procfs(const char *proc_inode, char *buf, int buf_size,
|
static int test_readlink_from_procfs(const char *proc_inode, char *buf, int buf_size,
|
||||||
const char *expected_target) {
|
const char *expected_target) {
|
||||||
@ -36,7 +38,8 @@ static int test_readlink_from_proc_self_exe() {
|
|||||||
char absolute_path[PATH_MAX] = { 0 };
|
char absolute_path[PATH_MAX] = { 0 };
|
||||||
const char *proc_exe = "/proc/self/exe";
|
const char *proc_exe = "/proc/self/exe";
|
||||||
|
|
||||||
int n = snprintf(absolute_path, sizeof(absolute_path), "/bin/%s", *g_argv);
|
int n = snprintf(absolute_path, sizeof(absolute_path), "/bin/%s",
|
||||||
|
program_invocation_short_name);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
THROW_ERROR("failed to call snprintf");
|
THROW_ERROR("failed to call snprintf");
|
||||||
}
|
}
|
||||||
@ -94,13 +97,41 @@ static int test_read_from_proc_self_cmdline() {
|
|||||||
char absolute_path[PATH_MAX] = { 0 };
|
char absolute_path[PATH_MAX] = { 0 };
|
||||||
const char *proc_cmdline = "/proc/self/cmdline";
|
const char *proc_cmdline = "/proc/self/cmdline";
|
||||||
|
|
||||||
int n = snprintf(absolute_path, sizeof(absolute_path), "/bin/%s", *g_argv);
|
int n = snprintf(absolute_path, sizeof(absolute_path), "/bin/%s",
|
||||||
|
program_invocation_short_name);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
THROW_ERROR("failed to call snprintf");
|
THROW_ERROR("failed to call snprintf");
|
||||||
}
|
}
|
||||||
if (fs_check_file_content(proc_cmdline, absolute_path) < 0) {
|
char read_buf[PATH_MAX] = { 0 };
|
||||||
|
int fd = open(proc_cmdline, O_RDONLY);
|
||||||
|
size_t len = read(fd, read_buf, sizeof(read_buf));
|
||||||
|
if (len != strlen(absolute_path) + 1) {
|
||||||
|
THROW_ERROR("failed check the return value of reading from %s", proc_cmdline);
|
||||||
|
}
|
||||||
|
if (read_buf[strlen(absolute_path)] != '\0') {
|
||||||
|
THROW_ERROR("failed check the buffer of reading from %s", proc_cmdline);
|
||||||
|
}
|
||||||
|
if (strcmp(absolute_path, read_buf) != 0) {
|
||||||
THROW_ERROR("failed to check result in %s", proc_cmdline);
|
THROW_ERROR("failed to check result in %s", proc_cmdline);
|
||||||
}
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_read_from_proc_self_comm() {
|
||||||
|
// The name can be up to 16 bytes long, including the terminating null byte.
|
||||||
|
char comm_name[16] = { 0 };
|
||||||
|
const char *proc_comm = "/proc/self/comm";
|
||||||
|
|
||||||
|
if (snprintf(comm_name, sizeof(comm_name), "%s", program_invocation_short_name) < 0) {
|
||||||
|
THROW_ERROR("failed to call snprintf");
|
||||||
|
}
|
||||||
|
// The last byte shoud be '\n'
|
||||||
|
int end_idx = strlen(comm_name);
|
||||||
|
comm_name[end_idx] = '\n';
|
||||||
|
if (fs_check_file_content(proc_comm, comm_name) < 0) {
|
||||||
|
THROW_ERROR("failed to check result in %s", proc_comm);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -169,12 +200,12 @@ static test_case_t test_cases[] = {
|
|||||||
TEST_CASE(test_readlink_from_proc_self_root),
|
TEST_CASE(test_readlink_from_proc_self_root),
|
||||||
TEST_CASE(test_create_and_unlink_file_from_proc_self_root),
|
TEST_CASE(test_create_and_unlink_file_from_proc_self_root),
|
||||||
TEST_CASE(test_read_from_proc_self_cmdline),
|
TEST_CASE(test_read_from_proc_self_cmdline),
|
||||||
|
TEST_CASE(test_read_from_proc_self_comm),
|
||||||
TEST_CASE(test_read_from_proc_meminfo),
|
TEST_CASE(test_read_from_proc_meminfo),
|
||||||
TEST_CASE(test_read_from_proc_cpuinfo),
|
TEST_CASE(test_read_from_proc_cpuinfo),
|
||||||
TEST_CASE(test_statfs),
|
TEST_CASE(test_statfs),
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
g_argv = argv;
|
|
||||||
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user