Compare commits

..

No commits in common. '5a8d3f79313a8b0c60e6b6c6c1289fd2e2589967' and '75ea2d26b37340f6fe6348e6e055737726d7818f' have entirely different histories.

  1. 2
      build.sh
  2. 78
      meson.build
  3. 230
      src/kernel/fat16.c
  4. 6
      src/kernel/fat16.h
  5. 12
      src/kernel/fs.c
  6. 7
      src/kernel/fs.h
  7. 5
      src/kernel/kernel.c
  8. 56
      src/kernel/path.c
  9. 12
      src/kernel/path.h
  10. 23
      src/kernel/syscall.c
  11. 11
      src/kernel/syscall.h
  12. 2
      src/kernel/vga.c
  13. 16
      src/lib/syscall.h
  14. 3
      src/user/app/cat/cat.c
  15. 7
      src/user/app/cp/cp.c
  16. 3
      src/user/app/ls/ls.c
  17. 28
      src/user/app/mkdir/mkdir.c
  18. 26
      src/user/app/rm/rm.c
  19. 6
      src/user/syscall.asm
  20. 5
      src/user/syscall.h

@ -22,5 +22,3 @@ mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/echo ::bin/ec
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/ls ::bin/ls 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/rm ::bin/rm

@ -349,81 +349,3 @@ custom_target(
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'], command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
build_by_default: true, build_by_default: true,
) )
mkdir_start = custom_target(
'mkdir_start',
input: 'src/user/start.asm',
output: 'mkdir_start.o',
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
)
mkdir_syscall = custom_target(
'mkdir_syscall',
input: 'src/user/syscall.asm',
output: 'mkdir_syscall.o',
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
)
mkdir_elf = executable(
'mkdir.elf',
sources: [mkdir_start, mkdir_syscall, lib_sources, 'src/user/app/mkdir/mkdir.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(
'mkdir',
input: mkdir_elf,
output: 'mkdir',
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
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,
)

@ -5,7 +5,6 @@
#include "src/kernel/stream.h" #include "src/kernel/stream.h"
#include "src/lib/memory.h" #include "src/lib/memory.h"
#include "src/lib/string.h" #include "src/lib/string.h"
#include "src/lib/syscall.h"
#include "src/lib/util.h" #include "src/lib/util.h"
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
@ -42,20 +41,21 @@ 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 removed; uint8_t valid;
} 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].refs) { if (!inodes[i].valid) {
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];
} }
@ -65,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].refs && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) { if (inodes[i].valid && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) {
return &inodes[i]; return &inodes[i];
} }
} }
@ -83,8 +83,14 @@ 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) {
if (inode->refs) {
inode->refs--; inode->refs--;
if (!inode->refs) {
for (uint64_t i = 0; i < MAX_INODES; i++) {
if (&inodes[i] == inode) {
inodes[i].valid = 0;
break;
}
}
} }
} }
@ -173,34 +179,35 @@ static void flush_fat() {
ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat); ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat);
} }
static uint16_t read_directory(uint16_t dir_cluster, fat16_dir_entry_t **entries) { static fat16_dir_entry_t *read_directory(uint16_t dir_cluster) {
fat16_dir_entry_t *entries;
if (!dir_cluster) { if (!dir_cluster) {
uint8_t sectors = (uint8_t)((sizeof(fat16_dir_entry_t) * bpb.root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE); uint8_t sectors = (uint8_t)((sizeof(fat16_dir_entry_t) * bpb.root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE);
*entries = memory_allocate(sectors * SECTOR_SIZE); entries = memory_allocate(sectors * SECTOR_SIZE + sizeof(fat16_dir_entry_t)); // One extra as null terminator.
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, sectors, *entries); ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, sectors, entries);
return bpb.root_entry_count;
} else { } else {
ensure_fat(); ensure_fat();
uint16_t next_cluster = dir_cluster; uint16_t next_cluster = dir_cluster;
uint16_t cluster_count = 0; uint32_t cluster_count = 0;
while (next_cluster < 0xFFF8) { while (next_cluster < 0xFFF8) {
cluster_count++; cluster_count++;
next_cluster = fat[next_cluster]; next_cluster = fat[next_cluster];
} }
*entries = memory_allocate(cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE); entries =
memory_allocate(cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE + sizeof(fat16_dir_entry_t)); // One extra as null terminator.
uint8_t *chunk = (uint8_t *)*entries; uint8_t *chunk = (uint8_t *)entries;
next_cluster = dir_cluster; next_cluster = dir_cluster;
while (next_cluster < 0xFFF8) { while (next_cluster < 0xFFF8) {
ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk); ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk);
chunk += bpb.sectors_per_cluster * SECTOR_SIZE; chunk += bpb.sectors_per_cluster * SECTOR_SIZE;
next_cluster = fat[next_cluster]; next_cluster = fat[next_cluster];
} }
return cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t);
} }
return (uint64_t)-1; return entries;
} }
static fs_node_t *open_entry(uint16_t dir_cluster, const fat16_dir_entry_t *entries, uint16_t index) { static fs_node_t *open_entry(uint16_t dir_cluster, const fat16_dir_entry_t *entries, uint16_t index) {
@ -226,51 +233,37 @@ static fs_node_t *open_entry(uint16_t dir_cluster, const fat16_dir_entry_t *entr
return (fs_node_t *)result; return (fs_node_t *)result;
} }
static void write_directory(uint16_t dir_cluster, const fat16_dir_entry_t *entries, uint16_t count) { static void write_directory(uint16_t dir_cluster, const fat16_dir_entry_t *entries) {
ASSERT((count * sizeof(fat16_dir_entry_t)) % (bpb.sectors_per_cluster * SECTOR_SIZE) == 0,
"write_directory: entries must be aligned to clusters");
if (!dir_cluster) { if (!dir_cluster) {
ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat,
(uint8_t)((sizeof(fat16_dir_entry_t) * bpb.root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE), entries); (uint8_t)((sizeof(fat16_dir_entry_t) * bpb.root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE), entries);
} else { } else {
ensure_fat(); ensure_fat();
// Assuming no entries were added or removed.
uint8_t *chunk = (uint8_t *)entries; uint8_t *chunk = (uint8_t *)entries;
uint16_t next_cluster = dir_cluster; uint16_t next_cluster = dir_cluster;
while (count) { while (next_cluster < 0xFFF8) {
ata_write_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk); ata_write_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk);
chunk += bpb.sectors_per_cluster * SECTOR_SIZE; chunk += bpb.sectors_per_cluster * SECTOR_SIZE;
count -= bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t);
if (count && fat[next_cluster] >= 0xFFF8) {
fat[next_cluster] = allocate_cluster();
}
next_cluster = fat[next_cluster]; next_cluster = fat[next_cluster];
} }
flush_fat();
} }
} }
fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t flags) { fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name) {
if (directory->type != FAT16 || !directory->is_dir) { if (directory->type != FAT16 || !directory->is_dir) {
return NUL; return NUL;
} }
if (((fat16_node_t *)directory)->inode->removed) {
return NUL;
}
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
char name_8_3[12]; char name_8_3[12];
to_8_3(name, name_8_3); to_8_3(name, name_8_3);
fat16_dir_entry_t *entries; fat16_dir_entry_t *entries = read_directory(((fat16_node_t *)directory)->inode->first_cluster);
uint16_t entries_count = read_directory(dir_cluster, &entries);
fat16_dir_entry_t *entry = entries; fat16_dir_entry_t *entry = entries;
uint16_t index = 0; uint16_t index = 0;
while (index < entries_count && entry->name[0]) { while (entry->name[0]) {
if ((uint8_t)entry->name[0] != 0xE5 && (uint8_t)entry->attributes != 0x0F && bytes_equal(name_8_3, (char *)entry, 11)) { if ((uint8_t)entry->name[0] != 0xE5 && (uint8_t)entry->attributes != 0x0F && bytes_equal(name_8_3, (char *)entry, 11)) {
break; break;
} }
@ -278,86 +271,20 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t
index++; index++;
} }
fs_node_t *result = open_entry(dir_cluster, entries, index); fs_node_t *result = open_entry(((fat16_node_t *)directory)->inode->first_cluster, entries, index);
if (result && (flags & OPEN_EXCLUSIVE)) {
memory_free(entries);
return NUL;
}
if (!result && (flags & OPEN_CREATE)) {
index = 0;
while (index < entries_count && entries[index].name[0]) {
index++;
}
if (index >= entries_count) {
if (!dir_cluster) {
memory_free(entries);
return NUL;
} else {
uint16_t new_entries_count = entries_count + bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t);
fat16_dir_entry_t *new_entries = memory_allocate(new_entries_count * sizeof(fat16_dir_entry_t));
memory_copy(entries, entries_count * sizeof(fat16_dir_entry_t), new_entries);
memory_free(entries); memory_free(entries);
entries_count = new_entries_count;
entries = new_entries;
}
}
memory_copy(name_8_3, 11, &entries[index]);
if (flags & OPEN_DIRECTORY && !(flags & OPEN_FILE)) {
entries[index].attributes = ATTRIBUTE_SUBDIRECTORY;
entries[index].first_cluster = allocate_cluster();
fat16_dir_entry_t *inner_entries = memory_allocate(bpb.sectors_per_cluster * SECTOR_SIZE);
memory_copy(". ", 11, inner_entries[0].name);
inner_entries[0].attributes = ATTRIBUTE_SUBDIRECTORY;
inner_entries[0].first_cluster = entries[index].first_cluster;
memory_copy(".. ", 11, inner_entries[1].name);
inner_entries[1].attributes = ATTRIBUTE_SUBDIRECTORY;
inner_entries[1].first_cluster = dir_cluster;
write_directory(entries[index].first_cluster, inner_entries, bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t));
memory_free(inner_entries);
}
write_directory(dir_cluster, entries, entries_count);
result = open_entry(dir_cluster, entries, index);
}
memory_free(entries);
if (!result) {
return NUL;
}
if (result->is_dir && !(flags & OPEN_DIRECTORY)) {
return NUL;
}
if (!result->is_dir && !(flags & OPEN_FILE)) {
return NUL;
}
return result; return result;
} }
fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags) { fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index) {
if (directory->type != FAT16 || !directory->is_dir) { if (directory->type != FAT16 || !directory->is_dir) {
return NUL; return NUL;
} }
if (((fat16_node_t *)directory)->inode->removed) { fat16_dir_entry_t *entries = read_directory(((fat16_node_t *)directory)->inode->first_cluster);
return NUL;
}
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
fat16_dir_entry_t *entries;
uint16_t entries_count = read_directory(dir_cluster, &entries);
uint16_t ei = 0, vi = 0; uint16_t ei = 0, vi = 0;
while (ei < entries_count && entries[ei].name[0]) { while (entries[ei].name[0]) {
if ((uint8_t)entries[ei].name[0] != 0xE5 && (uint8_t)entries[ei].attributes != 0x0F) { if ((uint8_t)entries[ei].name[0] != 0xE5 && (uint8_t)entries[ei].attributes != 0x0F) {
if (vi == index) { if (vi == index) {
break; break;
@ -368,25 +295,7 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t fl
} }
fs_node_t *result = open_entry(((fat16_node_t *)directory)->inode->first_cluster, entries, ei); fs_node_t *result = open_entry(((fat16_node_t *)directory)->inode->first_cluster, entries, ei);
memory_free(entries); memory_free(entries);
if (result && (flags & OPEN_EXCLUSIVE)) {
return NUL;
}
if (!result) {
return NUL;
}
if (result->is_dir && !(flags & OPEN_DIRECTORY)) {
return NUL;
}
if (!result->is_dir && !(flags & OPEN_FILE)) {
return NUL;
}
return result; return result;
} }
@ -404,10 +313,6 @@ 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;
} }
@ -465,10 +370,6 @@ 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) {
@ -531,11 +432,10 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_
if (offset + written > fat_file->inode->size) { if (offset + written > fat_file->inode->size) {
fat_file->inode->size = offset + written; fat_file->inode->size = offset + written;
fat16_dir_entry_t *entries; fat16_dir_entry_t *entries = read_directory(fat_file->inode->dir_cluster);
uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries);
entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster; entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster;
entries[fat_file->inode->dir_index].size = fat_file->inode->size; entries[fat_file->inode->dir_index].size = fat_file->inode->size;
write_directory(fat_file->inode->dir_cluster, entries, entries_count); write_directory(fat_file->inode->dir_cluster, entries);
memory_free(entries); memory_free(entries);
} }
@ -549,10 +449,6 @@ 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) {
@ -586,11 +482,10 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) {
flush_fat(); flush_fat();
fat_file->inode->size = size; fat_file->inode->size = size;
fat16_dir_entry_t *entries; fat16_dir_entry_t *entries = read_directory(fat_file->inode->dir_cluster);
uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries);
entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster; entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster;
entries[fat_file->inode->dir_index].size = fat_file->inode->size; entries[fat_file->inode->dir_index].size = fat_file->inode->size;
write_directory(fat_file->inode->dir_cluster, entries, entries_count); write_directory(fat_file->inode->dir_cluster, entries);
memory_free(entries); memory_free(entries);
return size; return size;
@ -598,57 +493,6 @@ 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;
@ -691,7 +535,7 @@ static void file_stream_close(stream_t *self) {
typedef struct { typedef struct {
stream_t stream; stream_t stream;
fs_node_t *node; fs_node_t *node;
uint16_t index; uint32_t index;
} fat16_directory_stream_t; } fat16_directory_stream_t;
static uint64_t directory_stream_write(__attribute__((unused)) stream_t *self, __attribute__((unused)) const char *from, static uint64_t directory_stream_write(__attribute__((unused)) stream_t *self, __attribute__((unused)) const char *from,
@ -701,7 +545,7 @@ static uint64_t directory_stream_write(__attribute__((unused)) stream_t *self, _
static uint64_t directory_stream_read(stream_t *self, uint64_t max, char *to) { static uint64_t directory_stream_read(stream_t *self, uint64_t max, char *to) {
fat16_directory_stream_t *fds = (fat16_directory_stream_t *)self; fat16_directory_stream_t *fds = (fat16_directory_stream_t *)self;
fs_node_t *node = fat16_open_at(fds->node, fds->index++, OPEN_FILE | OPEN_DIRECTORY); fs_node_t *node = fat16_open_at(fds->node, fds->index++);
if (!node) { if (!node) {
return 0; return 0;
} }

@ -7,9 +7,9 @@
fs_node_t *fat16_mount(); fs_node_t *fat16_mount();
fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t flags); fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name);
fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags); fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index);
fs_node_t *fat16_open_again(const fs_node_t *source); fs_node_t *fat16_open_again(const fs_node_t *source);
@ -21,8 +21,6 @@ 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);

@ -5,12 +5,12 @@ fs_node_t *fs_mount() {
return fat16_mount(); return fat16_mount();
} }
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name, uint64_t flags) { fs_node_t *fs_open_by(const fs_node_t *directory, const char *name) {
return fat16_open_by(directory, name, flags); return fat16_open_by(directory, name);
} }
fs_node_t *fs_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags) { fs_node_t *fs_open_at(const fs_node_t *directory, uint64_t index) {
return fat16_open_at(directory, index, flags); return fat16_open_at(directory, index);
} }
fs_node_t *fs_open_again(const fs_node_t *source) { fs_node_t *fs_open_again(const fs_node_t *source) {
@ -33,10 +33,6 @@ 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);
} }

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "src/kernel/stream.h" #include "src/kernel/stream.h"
#include <stdint.h>
#define FILENAME_SIZE_LIMIT 255 #define FILENAME_SIZE_LIMIT 255
@ -13,9 +14,9 @@ typedef struct fs_node {
fs_node_t *fs_mount(); fs_node_t *fs_mount();
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name, uint64_t flags); fs_node_t *fs_open_by(const fs_node_t *directory, const char *name);
fs_node_t *fs_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags); fs_node_t *fs_open_at(const fs_node_t *directory, uint64_t index);
fs_node_t *fs_open_again(const fs_node_t *source); fs_node_t *fs_open_again(const fs_node_t *source);
@ -27,8 +28,6 @@ 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);

@ -14,7 +14,6 @@
#include "src/kernel/vga.h" #include "src/kernel/vga.h"
#include "src/lib/layout.h" #include "src/lib/layout.h"
#include "src/lib/memory.h" #include "src/lib/memory.h"
#include "src/lib/syscall.h"
__attribute__((interrupt)) void isr_divide_by_zero(__attribute__((unused)) struct interrupt_frame *frame) { __attribute__((interrupt)) void isr_divide_by_zero(__attribute__((unused)) struct interrupt_frame *frame) {
vga_set_string(VGA_HEIGHT - 1, 0, "EXCEPTION: divide by zero", 0x4F); vga_set_string(VGA_HEIGHT - 1, 0, "EXCEPTION: divide by zero", 0x4F);
@ -66,8 +65,8 @@ void kernel_main() {
current_process = kernel; current_process = kernel;
tss.rsp0 = (uint64_t)kernel->kernel_stack; tss.rsp0 = (uint64_t)kernel->kernel_stack;
fs_node_t *terminal_node = path_open_node(kernel->root, kernel->cwd, "bin/terminal", OPEN_FILE); fs_node_t *terminal_node = path_open_file(kernel->root, kernel->cwd, "bin/terminal");
fs_node_t *shell_node = path_open_node(kernel->root, kernel->cwd, "bin/shell", OPEN_FILE); fs_node_t *shell_node = path_open_file(kernel->root, kernel->cwd, "bin/shell");
ASSERT(terminal_node, "kernel: terminal not found"); ASSERT(terminal_node, "kernel: terminal not found");
ASSERT(shell_node, "kernel: shell not found"); ASSERT(shell_node, "kernel: shell not found");

@ -3,10 +3,9 @@
#include "src/kernel/stream.h" #include "src/kernel/stream.h"
#include "src/lib/memory.h" #include "src/lib/memory.h"
#include "src/lib/string.h" #include "src/lib/string.h"
#include "src/lib/syscall.h"
#include "src/lib/util.h" #include "src/lib/util.h"
path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) { path_t *path_open(const fs_node_t *root, const path_t *source, const char *path) {
uint64_t length = string_length(path); uint64_t length = string_length(path);
char *path_own = memory_allocate(length + 1); char *path_own = memory_allocate(length + 1);
memory_copy(path, length + 1, path_own); memory_copy(path, length + 1, path_own);
@ -30,9 +29,7 @@ path_t *path_open(const fs_node_t *root, const path_t *source, const char *path,
} }
} else { } else {
const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : root; const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : root;
fs_node_t *next = prev->is_dir ? fs_open_by(prev, path_components[i], fs_node_t *next = prev->is_dir ? fs_open_by(prev, path_components[i]) : NUL;
i < path_length - 1 ? (flags & ~(uint64_t)OPEN_EXCLUSIVE) | OPEN_DIRECTORY : flags)
: NUL;
if (!next || result->depth >= PATH_DEPTH) { if (!next || result->depth >= PATH_DEPTH) {
path_close(result); path_close(result);
memory_free(path_own); memory_free(path_own);
@ -48,8 +45,8 @@ path_t *path_open(const fs_node_t *root, const path_t *source, const char *path,
return result; return result;
} }
fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) { fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path) {
path_t *p = path_open(root, source, path, flags); path_t *p = path_open(root, source, path);
if (!p) { if (!p) {
return NUL; return NUL;
} }
@ -58,8 +55,40 @@ fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const cha
return n; return n;
} }
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) { fs_node_t *path_open_file(const fs_node_t *root, const path_t *source, const char *path) {
path_t *p = path_open(root, source, path, flags); path_t *p = path_open(root, source, path);
if (!p) {
return NUL;
}
if (!p->depth || p->stack[p->depth - 1]->is_dir) {
path_close(p);
return NUL;
}
fs_node_t *n = fs_open_again(p->stack[p->depth - 1]);
path_close(p);
return n;
}
fs_node_t *path_open_directory(const fs_node_t *root, const path_t *source, const char *path) {
path_t *p = path_open(root, source, path);
if (!p) {
return NUL;
}
if (!p->depth) {
path_close(p);
return fs_open_again(root);
}
if (!p->stack[p->depth - 1]->is_dir) {
path_close(p);
return NUL;
}
fs_node_t *n = fs_open_again(p->stack[p->depth - 1]);
path_close(p);
return n;
}
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path) {
path_t *p = path_open(root, source, path);
if (!p) { if (!p) {
return NUL; return NUL;
} }
@ -74,12 +103,3 @@ 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);
}

@ -10,12 +10,14 @@ typedef struct {
uint8_t depth; uint8_t depth;
} path_t; } path_t;
path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags); path_t *path_open(const fs_node_t *root, const path_t *source, const char *path);
fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags); fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path);
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags); fs_node_t *path_open_file(const fs_node_t *root, const path_t *source, const char *path);
void path_close(path_t *path); fs_node_t *path_open_directory(const fs_node_t *root, const path_t *source, const char *path);
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path);
void path_remove(const fs_node_t *root, const path_t *source, const char *path); void path_close(path_t *path);

@ -7,7 +7,6 @@
#include "src/lib/layout.h" #include "src/lib/layout.h"
#include "src/lib/memory.h" #include "src/lib/memory.h"
#include "src/lib/string.h" #include "src/lib/string.h"
#include "src/lib/syscall.h"
#include "src/lib/util.h" #include "src/lib/util.h"
#define MSR_EFER 0xC0000080 #define MSR_EFER 0xC0000080
@ -80,17 +79,22 @@ static uint64_t getcwd(uint64_t max, char *to) {
} }
static uint64_t chdir(const char *path) { static uint64_t chdir(const char *path) {
path_t *cwd = path_open(current_process->root, current_process->cwd, path, OPEN_DIRECTORY); path_t *cwd = path_open(current_process->root, current_process->cwd, path);
if (!cwd) { if (!cwd) {
return (uint64_t)-1; return (uint64_t)-1;
} }
if (!cwd->depth || !cwd->stack[cwd->depth - 1]->is_dir) {
path_close(cwd);
return (uint64_t)-1;
}
path_close((path_t *)current_process->cwd); path_close((path_t *)current_process->cwd);
current_process->cwd = cwd; current_process->cwd = cwd;
return current_process->cwd->depth; return current_process->cwd->depth;
} }
static uint64_t spawn(const char *path, uint64_t argc, const char **argv) { static uint64_t spawn(const char *path, uint64_t argc, const char **argv) {
fs_node_t *node = path_open_node(current_process->root, current_process->cwd, path, OPEN_FILE); fs_node_t *node = path_open_file(current_process->root, current_process->cwd, path);
if (!node) { if (!node) {
return EXIT_CODE_NOT_FOUND; return EXIT_CODE_NOT_FOUND;
} }
@ -157,11 +161,11 @@ static exit_code_t wait(uint64_t pid) {
return code; return code;
} }
static uint64_t open(const char *path, uint64_t flags) { static uint64_t open(const char *path) {
if (current_process->free_fd >= MAX_FDS) { if (current_process->free_fd >= MAX_FDS) {
return (uint64_t)-1; return (uint64_t)-1;
} }
stream_t *stream = path_open_stream(current_process->root, current_process->cwd, path, flags); stream_t *stream = path_open_stream(current_process->root, current_process->cwd, path);
if (!stream) { if (!stream) {
return (uint64_t)-1; return (uint64_t)-1;
} }
@ -185,11 +189,6 @@ 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,13 +218,11 @@ uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t
case SYSCALL_WAIT: case SYSCALL_WAIT:
return wait(arg1); return wait(arg1);
case SYSCALL_OPEN: case SYSCALL_OPEN:
return open((const char *)arg1, arg2); return open((const char *)arg1);
case SYSCALL_CLOSE: case SYSCALL_CLOSE:
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;

@ -2,6 +2,17 @@
#include <stdint.h> #include <stdint.h>
#define SYSCALL_READ 0
#define SYSCALL_WRITE 1
#define SYSCALL_GETCWD 2
#define SYSCALL_CHDIR 3
#define SYSCALL_SPAWN 4
#define SYSCALL_WAIT 5
#define SYSCALL_OPEN 6
#define SYSCALL_CLOSE 7
#define SYSCALL_TRUNCATE 8
#define SYSCALL_EXIT 60
void syscall_init(); void syscall_init();
uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);

@ -172,10 +172,8 @@ stream_t *vga_init() {
void vga_set_string(uint8_t row, uint8_t col, const char *str, uint8_t c) { void vga_set_string(uint8_t row, uint8_t col, const char *str, uint8_t c) {
ASSERT(row < VGA_HEIGHT && col < VGA_WIDTH, "vga_set_string: invalid coordinates") ASSERT(row < VGA_HEIGHT && col < VGA_WIDTH, "vga_set_string: invalid coordinates")
color = (uint16_t)((uint16_t)c << 8); color = (uint16_t)((uint16_t)c << 8);
uint16_t prev_offset = offset;
offset = row * VGA_WIDTH + col; offset = row * VGA_WIDTH + col;
while (*str) { while (*str) {
on_char_received(*str++); on_char_received(*str++);
} }
offset = prev_offset;
} }

@ -1,16 +0,0 @@
#define SYSCALL_READ 0
#define SYSCALL_WRITE 1
#define SYSCALL_GETCWD 2
#define SYSCALL_CHDIR 3
#define SYSCALL_SPAWN 4
#define SYSCALL_WAIT 5
#define SYSCALL_OPEN 6
#define SYSCALL_CLOSE 7
#define SYSCALL_TRUNCATE 8
#define SYSCALL_REMOVE 9
#define SYSCALL_EXIT 60
#define OPEN_CREATE 0b0001
#define OPEN_EXCLUSIVE 0b0010
#define OPEN_FILE 0b0100
#define OPEN_DIRECTORY 0b1000

@ -1,4 +1,3 @@
#include "src/lib/syscall.h"
#include "src/lib/util.h" #include "src/lib/util.h"
#include "src/user/syscall.h" #include "src/user/syscall.h"
@ -8,7 +7,7 @@
#define PRINT_D(s) write(1, s, string_length(s)); #define PRINT_D(s) write(1, s, string_length(s));
exit_code_t cat(const char *path) { exit_code_t cat(const char *path) {
uint64_t fd = open(path, OPEN_FILE); uint64_t fd = open(path);
if (fd == (uint64_t)-1) { if (fd == (uint64_t)-1) {
PRINT_S("cat: path does not exist\n"); PRINT_S("cat: path does not exist\n");

@ -1,4 +1,3 @@
#include "src/lib/syscall.h"
#include "src/lib/util.h" #include "src/lib/util.h"
#include "src/user/syscall.h" #include "src/user/syscall.h"
@ -13,15 +12,15 @@ exit_code_t main(uint64_t argc, const char **argv) {
return EXIT_CODE_GENERAL_FAILURE; return EXIT_CODE_GENERAL_FAILURE;
} }
uint64_t source = open(argv[1], OPEN_FILE); uint64_t source = open(argv[1]);
if (source == (uint64_t)-1) { if (source == (uint64_t)-1) {
PRINT_S("cp: source does not exist\n"); PRINT_S("cp: source does not exist\n");
return EXIT_CODE_GENERAL_FAILURE; return EXIT_CODE_GENERAL_FAILURE;
} }
uint64_t target = open(argv[2], OPEN_FILE | OPEN_CREATE); uint64_t target = open(argv[2]);
if (target == (uint64_t)-1) { if (target == (uint64_t)-1) {
PRINT_S("cp: target path does not exist\n"); PRINT_S("cp: target does not exist\n");
close(source); close(source);
return EXIT_CODE_GENERAL_FAILURE; return EXIT_CODE_GENERAL_FAILURE;
} }

@ -1,5 +1,4 @@
#include "src/lib/string.h" #include "src/lib/string.h"
#include "src/lib/syscall.h"
#include "src/lib/util.h" #include "src/lib/util.h"
#include "src/user/syscall.h" #include "src/user/syscall.h"
@ -7,7 +6,7 @@
#define PRINT_D(s) write(1, s, string_length(s)); #define PRINT_D(s) write(1, s, string_length(s));
exit_code_t ls(const char *path) { exit_code_t ls(const char *path) {
uint64_t fd = open(path, OPEN_DIRECTORY); uint64_t fd = open(path);
if (fd == (uint64_t)-1) { if (fd == (uint64_t)-1) {
PRINT_S("ls: path does not exist\n"); PRINT_S("ls: path does not exist\n");

@ -1,28 +0,0 @@
#include "src/lib/syscall.h"
#include "src/lib/util.h"
#include "src/user/syscall.h"
#include <stdint.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("mkdir: requires target(s)\n");
return EXIT_CODE_GENERAL_FAILURE;
}
for (uint64_t i = 1; i < argc; i++) {
uint64_t fd = open(argv[i], OPEN_DIRECTORY | OPEN_CREATE | OPEN_EXCLUSIVE);
if (fd == (uint64_t)-1) {
PRINT_S("mkdir: could not create directory\n");
return EXIT_CODE_GENERAL_FAILURE;
} else {
close(fd);
}
}
return EXIT_CODE_OK;
}

@ -1,26 +0,0 @@
#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,12 +54,6 @@ 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

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "src/lib/util.h" #include "src/lib/util.h"
#include <stdint.h>
uint64_t read(int64_t fd, uint64_t max, void *to); uint64_t read(int64_t fd, uint64_t max, void *to);
@ -14,12 +15,10 @@ uint64_t spawn(const char *path, uint64_t argc, const char **argv);
exit_code_t waitpid(uint64_t pid); exit_code_t waitpid(uint64_t pid);
uint64_t open(const char *path, uint64_t flags); uint64_t open(const char *path);
uint64_t close(uint64_t fd); 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);

Loading…
Cancel
Save