From e17b3502482dcd15b833583d6e3360339c5f5293 Mon Sep 17 00:00:00 2001 From: "Enrico Fraccaroli (Galfurian)" Date: Tue, 26 Jul 2022 16:05:47 -0400 Subject: [PATCH] Clean up and improve procfs, specifically, the procr folders --- mentos/inc/fs/procfs.h | 4 +- mentos/src/fs/vfs.c | 6 +- mentos/src/io/proc_running.c | 268 ++++++++++++++++++----------------- 3 files changed, 141 insertions(+), 137 deletions(-) diff --git a/mentos/inc/fs/procfs.h b/mentos/inc/fs/procfs.h index f7b175b..753ce26 100644 --- a/mentos/inc/fs/procfs.h +++ b/mentos/inc/fs/procfs.h @@ -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); \ No newline at end of file +int procr_destroy_entry_pid(task_struct *entry); \ No newline at end of file diff --git a/mentos/src/fs/vfs.c b/mentos/src/fs/vfs.c index 92a00c1..88b9d04 100644 --- a/mentos/src/fs/vfs.c +++ b/mentos/src/fs/vfs.c @@ -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; } diff --git a/mentos/src/io/proc_running.c b/mentos/src/io/proc_running.c index c75d812..4237604 100644 --- a/mentos/src/io/proc_running.c +++ b/mentos/src/io/proc_running.c @@ -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//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/` 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//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/` 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; -} \ No newline at end of file +} + +/// @brief Performs a read of files inside the `/proc//` folder. +/// @param file is the `/proc//` 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; +}