Clean up and improve procfs, specifically, the procr folders
This commit is contained in:
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user