Fix wrong argument of write. Fix return type of getdents. Fix procfs_getdents. Finish implementing the base version of the ps command.

This commit is contained in:
Enrico Fraccaroli (Galfurian)
2023-01-27 11:38:40 -05:00
parent e926850ce3
commit 59d9bcb596
15 changed files with 133 additions and 93 deletions
+4 -3
View File
@@ -377,7 +377,7 @@ static ssize_t ext2_write(vfs_file_t *file, const void *buffer, off_t offset, si
static off_t ext2_lseek(vfs_file_t *file, off_t offset, int whence);
static int ext2_fstat(vfs_file_t *file, stat_t *stat);
static int ext2_ioctl(vfs_file_t *file, int request, void *data);
static int ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count);
static ssize_t ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count);
static int ext2_mkdir(const char *path, mode_t mode);
static int ext2_rmdir(const char *path);
@@ -2640,7 +2640,7 @@ static int ext2_ioctl(vfs_file_t *file, int request, void *data)
/// @param doff The offset inside the buffer where the data should be written.
/// @param count The maximum length of the buffer.
/// @return The number of written bytes in the buffer.
static int ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count)
static ssize_t ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count)
{
pr_debug("ext2_getdents(%s, %p, %d, %d)\n", file->name, dirp, doff, count);
// Get the filesystem.
@@ -2655,7 +2655,8 @@ static int ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t co
pr_err("Failed to read the inode (%d).\n", file->ino);
return -ENOENT;
}
uint32_t current = 0, written = 0;
uint32_t current = 0;
ssize_t written = 0;
// Allocate the cache.
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
// Clean the cache.
+52 -44
View File
@@ -90,7 +90,7 @@ static ssize_t procfs_write(vfs_file_t *file, const void *buffer, off_t offset,
static off_t procfs_lseek(vfs_file_t *file, off_t offset, int whence);
static int procfs_fstat(vfs_file_t *file, stat_t *stat);
static int procfs_ioctl(vfs_file_t *file, int request, void *data);
static int procfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count);
static ssize_t procfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count);
// ============================================================================
// Virtual FileSystem (VFS) Operaions
@@ -691,63 +691,71 @@ static int procfs_ioctl(vfs_file_t *file, int request, void *data)
/// @param doff The offset inside the buffer where the data should be written.
/// @param count The maximum length of the buffer.
/// @return The number of written bytes in the buffer.
static inline int procfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count)
static inline ssize_t procfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count)
{
if (!file || !dirp)
return -1;
// Check if the size of the buffer is big enough to hold the data about the
// directory entry.
if (count < sizeof(dirent_t))
return -1;
// If there are no file, stop right here.
if (list_head_empty(&fs.files))
return 0;
// Find the directory entry.
procfs_file_t *direntry = procfs_find_entry_inode(file->ino);
if (direntry == NULL) {
return -ENOENT;
}
// Check if it is a directory.
if ((direntry->flags & DT_DIR) == 0)
return -ENOTDIR;
// Clear the buffer.
memset(dirp, 0, count);
// Initialize, the length of the directory name.
int len = strlen(direntry->name);
size_t written = 0;
off_t current = 0;
ssize_t written_size = 0;
off_t iterated_size = 0;
char *parent = NULL;
procfs_file_t *entry;
if (!list_head_empty(&fs.files)) {
list_for_each_decl(it, &fs.files)
{
// Get the file structure.
entry = procfs_get_file(it);
// Check if it a valid procfs file.
if (!entry)
continue;
// If the entry is the directory itself, skip.
if (strcmp(direntry->name, entry->name) == 0) {
continue;
}
// Get the parent directory.
parent = dirname(entry->name);
// Check if the entry is inside the directory.
if (strcmp(direntry->name, parent) != 0) {
continue;
}
// Skip if already provided.
if (current++ < doff) {
continue;
}
if (*(entry->name + len) == '/')
++len;
// Write on current dirp.
dirp->d_ino = entry->inode;
dirp->d_type = entry->flags;
strcpy(dirp->d_name, entry->name + len);
dirp->d_off = sizeof(dirent_t);
dirp->d_reclen = sizeof(dirent_t);
// Increment the written counter.
written += sizeof(dirent_t);
// Move to next writing position.
dirp += 1;
if (written >= count)
break;
// Iterate the filesystem files.
list_for_each_decl(it, &fs.files)
{
// Get the file structure.
procfs_file_t *entry = procfs_get_file(it);
// Check if it a valid procfs file.
if (!entry)
continue;
// If the entry is the directory itself, skip.
if (!strcmp(direntry->name, entry->name))
continue;
// Get the parent directory.
parent = dirname(entry->name);
// Check if the parent of the entry is the directory we are iterating.
if (strcmp(direntry->name, parent))
continue;
// Advance the size we just iterated.
iterated_size += sizeof(dirent_t);
// Check if the iterated size is still below the offset.
if (iterated_size < doff) {
continue;
}
// Check if the last character of the entry is a slash.
if (*(entry->name + len) == '/')
++len;
// Write on current dirp.
dirp->d_ino = entry->inode;
dirp->d_type = entry->flags;
strcpy(dirp->d_name, entry->name + len);
dirp->d_off = sizeof(dirent_t);
dirp->d_reclen = sizeof(dirent_t);
// Increment the written counter.
written_size += sizeof(dirent_t);
// Move to next writing position.
++dirp;
if (written_size >= count)
break;
}
return written;
return written_size;
}
/// @brief Mounts the block device as an EXT2 filesystem.
+1 -1
View File
@@ -46,7 +46,7 @@ ssize_t sys_read(int fd, void *buf, size_t nbytes)
return read;
}
ssize_t sys_write(int fd, void *buf, size_t nbytes)
ssize_t sys_write(int fd, const void *buf, size_t nbytes)
{
// Get the current task.
task_struct *task = scheduler_get_current_process();
+16 -21
View File
@@ -11,45 +11,40 @@
#include "stdio.h"
#include "fs/vfs.h"
#include "string.h"
#include "assert.h"
int sys_getdents(int fd, dirent_t *dirp, unsigned int count)
ssize_t sys_getdents(int fd, dirent_t *dirp, unsigned int count)
{
if (dirp == NULL) {
printf("getdents: cannot read directory :"
"Directory pointer is not valid\n");
return 0;
}
// Get the current task.
task_struct *task = scheduler_get_current_process();
// Get the current process.
task_struct *current_process = scheduler_get_current_process();
// Check the current task.
assert(current_process && "There is no current process!");
// Check the current FD.
if (fd < 0 || fd >= task->max_fd) {
if ((fd < 0) || (fd >= current_process->max_fd)) {
return -EMFILE;
}
// Get the file descriptor.
vfs_file_descriptor_t *vfd = &task->fd_list[fd];
// Check the permissions.
// Get the process-specific file descriptor.
vfs_file_descriptor_t *process_fd = &current_process->fd_list[fd];
#if 0
if (!(task->fd_list[fd].flags_mask & O_RDONLY)) {
// Check the permissions.
if (!(current_process->fd_list[fd].flags_mask & O_RDONLY)) {
return -EROFS;
}
#endif
// Get the file.
vfs_file_t *file = vfd->file_struct;
// Get the associated file.
vfs_file_t *file = process_fd->file_struct;
if (file == NULL) {
return -ENOSYS;
}
// Clean the buffer.
memset(dirp, 0, count);
// Perform the read.
int actual_read = vfs_getdents(file, dirp, vfd->file_struct->f_pos, count);
// Update the offset.
ssize_t actual_read = vfs_getdents(file, dirp, process_fd->file_struct->f_pos, count);
// Update the offset, only if the value the function returns is positive.
if (actual_read > 0)
vfd->file_struct->f_pos += actual_read;
process_fd->file_struct->f_pos += actual_read;
return actual_read;
}
+2 -2
View File
@@ -172,7 +172,7 @@ ssize_t vfs_read(vfs_file_t *file, void *buf, size_t offset, size_t nbytes)
return file->fs_operations->read_f(file, buf, offset, nbytes);
}
ssize_t vfs_write(vfs_file_t *file, void *buf, size_t offset, size_t nbytes)
ssize_t vfs_write(vfs_file_t *file, const void *buf, size_t offset, size_t nbytes)
{
if (file->fs_operations->write_f == NULL) {
pr_err("No WRITE function found for the current filesystem.\n");
@@ -190,7 +190,7 @@ off_t vfs_lseek(vfs_file_t *file, off_t offset, int whence)
return file->fs_operations->lseek_f(file, offset, whence);
}
int vfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t off, size_t count)
ssize_t vfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t off, size_t count)
{
if (file->fs_operations->getdents_f == NULL) {
pr_err("No GETDENTS function found for the current filesystem.\n");