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