Clean up and improve procfs, specifically, the procr folders

This commit is contained in:
Enrico Fraccaroli (Galfurian)
2022-07-26 16:05:47 -04:00
parent 453644d57e
commit e17b350248
3 changed files with 141 additions and 137 deletions
+2 -2
View File
@@ -60,9 +60,9 @@ int proc_destroy_entry(const char *name, proc_dir_entry_t *parent);
/// @brief Create the entire procfs entry tree for the give process.
/// @param entry Pointer to the task_struct of the process.
/// @return 0 if succeed, or -errno in case of error.
int proc_create_entry_pid(task_struct *entry);
int procr_create_entry_pid(task_struct *entry);
/// @brief Destroy the entire procfs entry tree for the give process.
/// @param entry Pointer to the task_struct of the process.
/// @return 0 if succeed, or -errno in case of error.
int proc_destroy_entry_pid(task_struct *entry);
int procr_destroy_entry_pid(task_struct *entry);
+3 -3
View File
@@ -507,7 +507,7 @@ int vfs_init_task(task_struct *task)
return 0;
}
// Create the proc entry.
if (proc_create_entry_pid(task)) {
if (procr_create_entry_pid(task)) {
pr_err("Error while trying to create proc entry for process `%d`: %s\n", task->pid, strerror(errno));
return 0;
}
@@ -531,7 +531,7 @@ int vfs_dup_task(task_struct *task, task_struct *old_task)
}
}
// Create the proc entry.
if (proc_create_entry_pid(task)) {
if (procr_create_entry_pid(task)) {
pr_err("Error while trying to create proc entry for '%d': %s\n", task->pid, strerror(errno));
return 0;
}
@@ -558,7 +558,7 @@ int vfs_destroy_task(task_struct *task)
// Free the memory of the list.
kfree(task->fd_list);
// Remove the proc entry.
if (proc_destroy_entry_pid(task)) {
if (procr_destroy_entry_pid(task)) {
pr_err("Error while trying to remove proc entry for '%d': %s\n", task->pid, strerror(errno));
return 0;
}
+136 -132
View File
@@ -22,7 +22,7 @@
/// T Stopped
/// t Tracing stop
/// X Dead
static inline char get_task_state_char(int state)
static inline char __procr_get_task_state_char(int state)
{
if (state == 0x00) // TASK_RUNNING
return 'R';
@@ -41,140 +41,23 @@ static inline char get_task_state_char(int state)
return '?';
}
static ssize_t procr_do_cmdline(char *buffer, size_t bufsize, task_struct *task);
static ssize_t procr_do_stat(char *buffer, size_t bufsize, task_struct *task);
static ssize_t procr_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte)
{
if (file == NULL)
return -EFAULT;
// Get the entry.
proc_dir_entry_t *entry = (proc_dir_entry_t *)file->device;
if (entry == NULL)
return -EFAULT;
// Get the task.
task_struct *task = (task_struct *)entry->data;
if (task == NULL)
return -EFAULT;
// Prepare a buffer.
char buffer[BUFSIZ];
memset(buffer, 0, BUFSIZ);
// Call the specific function.
int ret = 0;
if (strcmp(entry->name, "cmdline") == 0)
ret = procr_do_cmdline(buffer, BUFSIZ, task);
else if (strcmp(entry->name, "stat") == 0)
ret = procr_do_stat(buffer, BUFSIZ, task);
// Perform read.
ssize_t it = 0;
if (ret == 1) {
size_t name_len = strlen(buffer);
size_t read_pos = offset;
if (read_pos < name_len) {
while ((it < nbyte) && (read_pos < name_len)) {
*buf++ = buffer[read_pos];
++read_pos;
++it;
}
}
}
return it;
}
/// Filesystem general operations.
static vfs_sys_operations_t procv_sys_operations = {
.mkdir_f = NULL,
.rmdir_f = NULL,
.stat_f = NULL
};
/// Filesystem file operations.
static vfs_file_operations_t procv_fs_operations = {
.open_f = NULL,
.unlink_f = NULL,
.close_f = NULL,
.read_f = procr_read,
.write_f = NULL,
.lseek_f = NULL,
.stat_f = NULL,
.ioctl_f = NULL,
.getdents_f = NULL
};
int proc_create_entry_pid(task_struct *entry)
{
char path[PATH_MAX];
proc_dir_entry_t *proc_dir = NULL, *proc_entry = NULL;
{
// Create `/proc/[PID]`.
sprintf(path, "%d", entry->pid);
// Create the proc entry root directory.
if ((proc_dir = proc_mkdir(path, NULL)) == NULL) {
pr_err("[task: %d] Cannot create proc root directory `%s`.\n", entry->pid, path);
return -ENOENT;
}
proc_dir->data = entry;
}
{
// Create `/proc/[PID]/cmdline`.
if ((proc_entry = proc_create_entry("cmdline", proc_dir)) == NULL) {
pr_err("[task: %d] Cannot create proc entry `%s`.\n", entry->pid, path);
return -ENOENT;
}
proc_entry->sys_operations = &procv_sys_operations;
proc_entry->fs_operations = &procv_fs_operations;
proc_entry->data = entry;
}
{
// Create `/proc/[PID]/stat`.
if ((proc_entry = proc_create_entry("stat", proc_dir)) == NULL) {
pr_err("[task: %d] Cannot create proc entry `%s`.\n", entry->pid, path);
return -ENOENT;
}
proc_entry->sys_operations = &procv_sys_operations;
proc_entry->fs_operations = &procv_fs_operations;
proc_entry->data = entry;
}
return 0;
}
int proc_destroy_entry_pid(task_struct *entry)
{
// Turn the pid into string. The maximum pid is 32768, thus entry pid is at most 6 chars.
char pid_str[6];
sprintf(pid_str, "%d", entry->pid);
// Get the root directory.
proc_dir_entry_t *proc_dir = proc_dir_entry_get(pid_str, NULL);
if (proc_dir == NULL) {
pr_err("[task: %d] Cannot find proc root directory `%s`.\n", entry->pid, pid_str);
return -ENOENT;
}
// Destroy `/proc/[PID]/cmdline`.
if (proc_destroy_entry("cmdline", proc_dir)) {
pr_err("[task: %d] Cannot destroy proc cmdline.\n", entry->pid);
return -ENOENT;
}
// Destroy `/proc/[PID]/stat`.
if (proc_destroy_entry("stat", proc_dir)) {
pr_err("[task: %d] Cannot destroy proc stat.\n", entry->pid);
return -ENOENT;
}
// Destroy `/proc/[PID]`.
if (proc_rmdir(pid_str, NULL)) {
pr_err("[task: %d] Cannot remove proc root directory `%s`.\n", entry->pid, pid_str);
return -ENOENT;
}
return 0;
}
static ssize_t procr_do_cmdline(char *buffer, size_t bufsize, task_struct *task)
/// @brief Returns the data for the `/proc/<PID>/cmdline` file.
/// @param buffer the buffer where the data should be placed.
/// @param bufsize the size of the buffer.
/// @param task the task associated with the `/proc/<PID>` folder.
/// @return size of the written data in buffer.
static inline ssize_t __procr_do_cmdline(char *buffer, size_t bufsize, task_struct *task)
{
strcpy(buffer, task->name);
return 1;
}
static ssize_t procr_do_stat(char *buffer, size_t bufsize, task_struct *task)
/// @brief Returns the data for the `/proc/<PID>/stat` file.
/// @param buffer the buffer where the data should be placed.
/// @param bufsize the size of the buffer.
/// @param task the task associated with the `/proc/<PID>` folder.
/// @return size of the written data in buffer.
static inline ssize_t __procr_do_stat(char *buffer, size_t bufsize, task_struct *task)
{
//(1) pid %d
// The process ID.
@@ -197,7 +80,7 @@ static ssize_t procr_do_stat(char *buffer, size_t bufsize, task_struct *task)
// T Stopped
// t Tracing stop
// X Dead
sprintf(buffer, "%s %c", buffer, get_task_state_char(task->state));
sprintf(buffer, "%s %c", buffer, __procr_get_task_state_char(task->state));
//(4) ppid %d
// The PID of the parent of this process.
//
@@ -486,4 +369,125 @@ static ssize_t procr_do_stat(char *buffer, size_t bufsize, task_struct *task)
// waitpid(2).
sprintf(buffer, "%s %d\n", buffer, task->exit_code);
return 1;
}
}
/// @brief Performs a read of files inside the `/proc/<PID>/` folder.
/// @param file is the `/proc/<PID>/` folder, thus, it should be a `proc_dir_entry_t` data.
/// @param buffer buffer where the read content must be placed.
/// @param offset offset from which we start reading from the file.
/// @param nbyte the number of bytes to read.
/// @return The number of bytes we read.
static inline ssize_t __procr_read(vfs_file_t *file, char *buffer, off_t offset, size_t nbyte)
{
if (file == NULL)
return -EFAULT;
// Get the entry.
proc_dir_entry_t *entry = (proc_dir_entry_t *)file->device;
if (entry == NULL)
return -EFAULT;
// Get the task.
task_struct *task = (task_struct *)entry->data;
if (task == NULL)
return -EFAULT;
// Prepare a support buffer.
char support[BUFSIZ];
memset(support, 0, BUFSIZ);
// Call the specific function.
int ret = 0;
if (strcmp(entry->name, "cmdline") == 0)
ret = __procr_do_cmdline(support, BUFSIZ, task);
else if (strcmp(entry->name, "stat") == 0)
ret = __procr_do_stat(support, BUFSIZ, task);
// Copmute the amounts of bytes we want (and can) read.
ssize_t bytes_to_read = max(0, min(strlen(support) - offset, nbyte));
// Perform the read.
if (bytes_to_read > 0)
memcpy(buffer, support + offset, bytes_to_read);
return bytes_to_read;
}
/// Filesystem general operations.
static vfs_sys_operations_t procr_sys_operations = {
.mkdir_f = NULL,
.rmdir_f = NULL,
.stat_f = NULL
};
/// Filesystem file operations.
static vfs_file_operations_t procr_fs_operations = {
.open_f = NULL,
.unlink_f = NULL,
.close_f = NULL,
.read_f = __procr_read,
.write_f = NULL,
.lseek_f = NULL,
.stat_f = NULL,
.ioctl_f = NULL,
.getdents_f = NULL
};
int procr_create_entry_pid(task_struct *entry)
{
char path[PATH_MAX];
proc_dir_entry_t *proc_dir = NULL, *proc_entry = NULL;
{
// Create `/proc/[PID]`.
sprintf(path, "%d", entry->pid);
// Create the proc entry root directory.
if ((proc_dir = proc_mkdir(path, NULL)) == NULL) {
pr_err("[task: %d] Cannot create proc root directory `%s`.\n", entry->pid, path);
return -ENOENT;
}
proc_dir->data = entry;
}
{
// Create `/proc/[PID]/cmdline`.
if ((proc_entry = proc_create_entry("cmdline", proc_dir)) == NULL) {
pr_err("[task: %d] Cannot create proc entry `%s`.\n", entry->pid, path);
return -ENOENT;
}
proc_entry->sys_operations = &procr_sys_operations;
proc_entry->fs_operations = &procr_fs_operations;
proc_entry->data = entry;
}
{
// Create `/proc/[PID]/stat`.
if ((proc_entry = proc_create_entry("stat", proc_dir)) == NULL) {
pr_err("[task: %d] Cannot create proc entry `%s`.\n", entry->pid, path);
return -ENOENT;
}
proc_entry->sys_operations = &procr_sys_operations;
proc_entry->fs_operations = &procr_fs_operations;
proc_entry->data = entry;
}
return 0;
}
int procr_destroy_entry_pid(task_struct *entry)
{
// Turn the pid into string. The maximum pid is 32768, thus entry pid is at most 6 chars.
char pid_str[6];
sprintf(pid_str, "%d", entry->pid);
// Get the root directory.
proc_dir_entry_t *proc_dir = proc_dir_entry_get(pid_str, NULL);
if (proc_dir == NULL) {
pr_err("[task: %d] Cannot find proc root directory `%s`.\n", entry->pid, pid_str);
return -ENOENT;
}
// Destroy `/proc/[PID]/cmdline`.
if (proc_destroy_entry("cmdline", proc_dir)) {
pr_err("[task: %d] Cannot destroy proc cmdline.\n", entry->pid);
return -ENOENT;
}
// Destroy `/proc/[PID]/stat`.
if (proc_destroy_entry("stat", proc_dir)) {
pr_err("[task: %d] Cannot destroy proc stat.\n", entry->pid);
return -ENOENT;
}
// Destroy `/proc/[PID]`.
if (proc_rmdir(pid_str, NULL)) {
pr_err("[task: %d] Cannot remove proc root directory `%s`.\n", entry->pid, pid_str);
return -ENOENT;
}
return 0;
}