Add file removal, rm
This commit is contained in:
@@ -23,3 +23,4 @@ mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/ls ::bin/ls
|
|||||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cat ::bin/cat
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cat ::bin/cat
|
||||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cp ::bin/cp
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cp ::bin/cp
|
||||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/mkdir ::bin/mkdir
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/mkdir ::bin/mkdir
|
||||||
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/rm ::bin/rm
|
||||||
|
|||||||
+39
@@ -388,3 +388,42 @@ custom_target(
|
|||||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||||
build_by_default: true,
|
build_by_default: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rm_start = custom_target(
|
||||||
|
'rm_start',
|
||||||
|
input: 'src/user/start.asm',
|
||||||
|
output: 'rm_start.o',
|
||||||
|
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
rm_syscall = custom_target(
|
||||||
|
'rm_syscall',
|
||||||
|
input: 'src/user/syscall.asm',
|
||||||
|
output: 'rm_syscall.o',
|
||||||
|
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
rm_elf = executable(
|
||||||
|
'rm.elf',
|
||||||
|
sources: [rm_start, rm_syscall, lib_sources, 'src/user/app/rm/rm.c'],
|
||||||
|
c_args: [
|
||||||
|
'-ffreestanding',
|
||||||
|
'-nostdlib',
|
||||||
|
'-fno-stack-protector',
|
||||||
|
'-mcmodel=large',
|
||||||
|
'-DVERSION="' + meson.project_version() + '"',
|
||||||
|
],
|
||||||
|
link_args: [
|
||||||
|
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||||
|
'-nostdlib',
|
||||||
|
],
|
||||||
|
link_depends: 'src/user/linker.ld',
|
||||||
|
)
|
||||||
|
|
||||||
|
custom_target(
|
||||||
|
'rm',
|
||||||
|
input: rm_elf,
|
||||||
|
output: 'rm',
|
||||||
|
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||||
|
build_by_default: true,
|
||||||
|
)
|
||||||
|
|||||||
+76
-12
@@ -42,21 +42,20 @@ typedef struct {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint16_t dir_cluster;
|
uint16_t dir_cluster;
|
||||||
uint16_t dir_index;
|
uint16_t dir_index;
|
||||||
uint8_t valid;
|
uint8_t removed;
|
||||||
} fat16_inode_t;
|
} fat16_inode_t;
|
||||||
|
|
||||||
static fat16_inode_t inodes[MAX_INODES];
|
static fat16_inode_t inodes[MAX_INODES];
|
||||||
|
|
||||||
static fat16_inode_t *inode_create(uint16_t first_cluster, uint32_t size, uint16_t dir_cluster, uint16_t dir_index) {
|
static fat16_inode_t *inode_create(uint16_t first_cluster, uint32_t size, uint16_t dir_cluster, uint16_t dir_index) {
|
||||||
for (uint64_t i = 0; i < MAX_INODES; i++) {
|
for (uint64_t i = 0; i < MAX_INODES; i++) {
|
||||||
if (!inodes[i].valid) {
|
if (!inodes[i].refs) {
|
||||||
inodes[i] = (fat16_inode_t){
|
inodes[i] = (fat16_inode_t){
|
||||||
.refs = 1,
|
.refs = 1,
|
||||||
.first_cluster = first_cluster,
|
.first_cluster = first_cluster,
|
||||||
.size = size,
|
.size = size,
|
||||||
.dir_cluster = dir_cluster,
|
.dir_cluster = dir_cluster,
|
||||||
.dir_index = dir_index,
|
.dir_index = dir_index,
|
||||||
.valid = 1,
|
|
||||||
};
|
};
|
||||||
return &inodes[i];
|
return &inodes[i];
|
||||||
}
|
}
|
||||||
@@ -66,7 +65,7 @@ static fat16_inode_t *inode_create(uint16_t first_cluster, uint32_t size, uint16
|
|||||||
|
|
||||||
static fat16_inode_t *inode_get(uint32_t dir_cluster, uint16_t dir_index) {
|
static fat16_inode_t *inode_get(uint32_t dir_cluster, uint16_t dir_index) {
|
||||||
for (uint64_t i = 0; i < MAX_INODES; i++) {
|
for (uint64_t i = 0; i < MAX_INODES; i++) {
|
||||||
if (inodes[i].valid && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) {
|
if (inodes[i].refs && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) {
|
||||||
return &inodes[i];
|
return &inodes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,14 +83,8 @@ static fat16_inode_t *inode_use(uint16_t first_cluster, uint32_t size, uint16_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void inode_free(fat16_inode_t *inode) {
|
static void inode_free(fat16_inode_t *inode) {
|
||||||
inode->refs--;
|
if (inode->refs) {
|
||||||
if (!inode->refs) {
|
inode->refs--;
|
||||||
for (uint64_t i = 0; i < MAX_INODES; i++) {
|
|
||||||
if (&inodes[i] == inode) {
|
|
||||||
inodes[i].valid = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +256,10 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t
|
|||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((fat16_node_t *)directory)->inode->removed) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
|
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
|
||||||
|
|
||||||
char name_8_3[12];
|
char name_8_3[12];
|
||||||
@@ -350,6 +347,10 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t fl
|
|||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((fat16_node_t *)directory)->inode->removed) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
|
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
|
||||||
|
|
||||||
fat16_dir_entry_t *entries;
|
fat16_dir_entry_t *entries;
|
||||||
@@ -403,6 +404,10 @@ uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void
|
|||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fat_file->inode->removed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (offset >= fat_file->inode->size) {
|
if (offset >= fat_file->inode->size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -460,6 +465,10 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_
|
|||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fat_file->inode->removed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ensure_fat();
|
ensure_fat();
|
||||||
|
|
||||||
if (!fat_file->inode->first_cluster) {
|
if (!fat_file->inode->first_cluster) {
|
||||||
@@ -540,6 +549,10 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) {
|
|||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fat_file->inode->removed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (file->size == size) {
|
if (file->size == size) {
|
||||||
return size;
|
return size;
|
||||||
} else if (file->size < size) {
|
} else if (file->size < size) {
|
||||||
@@ -585,6 +598,57 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) {
|
|||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t fat16_remove(fs_node_t *file) {
|
||||||
|
fat16_node_t *fat_file = (fat16_node_t *)file;
|
||||||
|
|
||||||
|
if (fat_file->base.type != FAT16) {
|
||||||
|
return (uint64_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fat_file->inode->removed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->is_dir) {
|
||||||
|
fat16_dir_entry_t *subentries;
|
||||||
|
uint16_t subentries_count = read_directory(fat_file->inode->first_cluster, &subentries);
|
||||||
|
uint16_t ei = 0, vi = 0;
|
||||||
|
while (ei < subentries_count && subentries[ei].name[0]) {
|
||||||
|
if ((uint8_t)subentries[ei].name[0] != 0xE5 && (uint8_t)subentries[ei].attributes != 0x0F) {
|
||||||
|
vi++;
|
||||||
|
}
|
||||||
|
ei++;
|
||||||
|
}
|
||||||
|
memory_free(subentries);
|
||||||
|
if (vi > 2) {
|
||||||
|
return (uint64_t)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fat_file->inode->removed = 1;
|
||||||
|
|
||||||
|
if (fat_file->inode->first_cluster) {
|
||||||
|
ensure_fat();
|
||||||
|
uint64_t next_cluster = fat_file->inode->first_cluster;
|
||||||
|
do {
|
||||||
|
uint32_t swap = fat[next_cluster];
|
||||||
|
fat[next_cluster] = 0;
|
||||||
|
next_cluster = swap;
|
||||||
|
} while (next_cluster < 0xFFF8);
|
||||||
|
flush_fat();
|
||||||
|
}
|
||||||
|
|
||||||
|
fat16_dir_entry_t *entries;
|
||||||
|
uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries);
|
||||||
|
entries[fat_file->inode->dir_index].name[0] = 0xE5;
|
||||||
|
entries[fat_file->inode->dir_index].first_cluster = 0;
|
||||||
|
entries[fat_file->inode->dir_index].size = 0;
|
||||||
|
write_directory(fat_file->inode->dir_cluster, entries, entries_count);
|
||||||
|
memory_free(entries);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
stream_t stream;
|
stream_t stream;
|
||||||
fs_node_t *node;
|
fs_node_t *node;
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_
|
|||||||
|
|
||||||
uint64_t fat16_truncate(fs_node_t *file, uint32_t size);
|
uint64_t fat16_truncate(fs_node_t *file, uint32_t size);
|
||||||
|
|
||||||
|
uint64_t fat16_remove(fs_node_t *file);
|
||||||
|
|
||||||
void fat16_close(fs_node_t *node);
|
void fat16_close(fs_node_t *node);
|
||||||
|
|
||||||
void fat16_unmount(fs_node_t *fs);
|
void fat16_unmount(fs_node_t *fs);
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ void fs_truncate(fs_node_t *file, uint32_t size) {
|
|||||||
fat16_truncate(file, size);
|
fat16_truncate(file, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fs_remove(fs_node_t *file) {
|
||||||
|
fat16_remove(file);
|
||||||
|
}
|
||||||
|
|
||||||
void fs_close(fs_node_t *node) {
|
void fs_close(fs_node_t *node) {
|
||||||
fat16_close(node);
|
fat16_close(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ void fs_write(fs_node_t *file, uint32_t offset, const void *from, uint32_t bytes
|
|||||||
|
|
||||||
void fs_truncate(fs_node_t *file, uint32_t size);
|
void fs_truncate(fs_node_t *file, uint32_t size);
|
||||||
|
|
||||||
|
void fs_remove(fs_node_t *file);
|
||||||
|
|
||||||
void fs_close(fs_node_t *node);
|
void fs_close(fs_node_t *node);
|
||||||
|
|
||||||
void fs_unmount(fs_node_t *fs);
|
void fs_unmount(fs_node_t *fs);
|
||||||
|
|||||||
@@ -74,3 +74,12 @@ void path_close(path_t *path) {
|
|||||||
}
|
}
|
||||||
memory_free(path);
|
memory_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void path_remove(const fs_node_t *root, const path_t *source, const char *path) {
|
||||||
|
path_t *p = path_open(root, source, path, OPEN_FILE | OPEN_DIRECTORY);
|
||||||
|
if (!p || !p->depth) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs_remove(p->stack[p->depth - 1]);
|
||||||
|
path_close(p);
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,3 +17,5 @@ fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const cha
|
|||||||
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags);
|
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags);
|
||||||
|
|
||||||
void path_close(path_t *path);
|
void path_close(path_t *path);
|
||||||
|
|
||||||
|
void path_remove(const fs_node_t *root, const path_t *source, const char *path);
|
||||||
|
|||||||
@@ -185,6 +185,11 @@ static uint64_t truncate(uint64_t fd, uint64_t size) {
|
|||||||
return current_process->fds[fd]->truncate(current_process->fds[fd], size);
|
return current_process->fds[fd]->truncate(current_process->fds[fd], size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t remove(const char *path) {
|
||||||
|
path_remove(current_process->root, current_process->cwd, path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void exit(exit_code_t code) {
|
static void exit(exit_code_t code) {
|
||||||
current_process->state = PROCESS_ZOMBIE;
|
current_process->state = PROCESS_ZOMBIE;
|
||||||
current_process->code = code;
|
current_process->code = code;
|
||||||
@@ -219,6 +224,8 @@ uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t
|
|||||||
return close(arg1);
|
return close(arg1);
|
||||||
case SYSCALL_TRUNCATE:
|
case SYSCALL_TRUNCATE:
|
||||||
return truncate(arg1, arg2);
|
return truncate(arg1, arg2);
|
||||||
|
case SYSCALL_REMOVE:
|
||||||
|
return remove((char *)arg1);
|
||||||
case SYSCALL_EXIT:
|
case SYSCALL_EXIT:
|
||||||
exit(arg1);
|
exit(arg1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#define SYSCALL_OPEN 6
|
#define SYSCALL_OPEN 6
|
||||||
#define SYSCALL_CLOSE 7
|
#define SYSCALL_CLOSE 7
|
||||||
#define SYSCALL_TRUNCATE 8
|
#define SYSCALL_TRUNCATE 8
|
||||||
|
#define SYSCALL_REMOVE 9
|
||||||
#define SYSCALL_EXIT 60
|
#define SYSCALL_EXIT 60
|
||||||
|
|
||||||
#define OPEN_CREATE 0b0001
|
#define OPEN_CREATE 0b0001
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#include "src/lib/syscall.h"
|
||||||
|
#include "src/lib/util.h"
|
||||||
|
#include "src/user/syscall.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 65536
|
||||||
|
|
||||||
|
#define PRINT_S(s) write(1, s, sizeof(s) - 1);
|
||||||
|
#define PRINT_D(s) write(1, s, string_length(s));
|
||||||
|
|
||||||
|
exit_code_t main(uint64_t argc, const char **argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
PRINT_S("rm: requires one or more arguments\n");
|
||||||
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t code = EXIT_CODE_OK;
|
||||||
|
for (uint64_t i = 1; i < argc; i++) {
|
||||||
|
exit_code_t c = remove(argv[i]);
|
||||||
|
if (c != EXIT_CODE_OK) {
|
||||||
|
PRINT_S("rm: coult not remove file\n");
|
||||||
|
code = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
@@ -54,6 +54,12 @@ truncate:
|
|||||||
syscall
|
syscall
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
global remove
|
||||||
|
remove:
|
||||||
|
mov rax, 9
|
||||||
|
syscall
|
||||||
|
ret
|
||||||
|
|
||||||
global exit
|
global exit
|
||||||
exit:
|
exit:
|
||||||
mov rax, 60
|
mov rax, 60
|
||||||
|
|||||||
@@ -20,4 +20,6 @@ uint64_t close(uint64_t fd);
|
|||||||
|
|
||||||
uint64_t truncate(uint64_t fd, uint64_t size);
|
uint64_t truncate(uint64_t fd, uint64_t size);
|
||||||
|
|
||||||
|
uint64_t remove(const char *path);
|
||||||
|
|
||||||
void exit(exit_code_t code);
|
void exit(exit_code_t code);
|
||||||
|
|||||||
Reference in New Issue
Block a user