Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions kernel/include/kernel/fs/ramfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ int seek (inode* node, file* f, size_t offset, int whence);
int getdents (inode* node, file* f, void* buf, size_t count);
int istat (inode* node, stat* buf);
int fstat (inode* node, file* f, stat* buf);
int close (inode* node, file* f);
int unlink (inode* node);

typedef struct {
char* c_name;
Expand Down
3 changes: 3 additions & 0 deletions kernel/include/kernel/fs/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ typedef struct {
int (*create) (char*, inode**, inode*);
int (*mkdir) (char*, inode**, inode*);
int (*stat) (inode*, stat*);
int (*unlink) (inode*);
} inode_operations;

typedef struct {
Expand Down Expand Up @@ -93,6 +94,7 @@ int do_chdir (const char* path);
int do_getcwd (char* buf, size_t size);
int do_create (char* filename, inode** result, inode* parent);
int do_lookup (char* filename, inode** result, inode* root, inode* cwd);
int do_unlink (const char* path);

int do_read (struct file* f, void* buf, size_t size);
int do_seek (struct file* f, size_t offset, int whence);
Expand All @@ -116,6 +118,7 @@ uint64_t sys_getcwd (uint64_t buf, uint64_t size);
uint64_t sys_fstat (uint64_t fd, uint64_t buf);
uint64_t sys_stat (uint64_t path, uint64_t buf);
uint64_t sys_ioctl (uint64_t fd, uint64_t req, uint64_t arg);
uint64_t sys_unlink (uint64_t path);

inode* get_absolute_root (void);
void init_vfs (inode* absolute_root);
Expand Down
50 changes: 48 additions & 2 deletions kernel/src/kernel/fs/ramfs/ramfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ static inode_operations i_ops = {.lookup = lookup,
.lookup_by_ino = lookup_by_ino,
.mkdir = mkdir,
.create = create,
.stat = istat};
.stat = istat,
.unlink = unlink};
static file_operations f_ops = {.read = read,
.write = write,
.seek = seek,
.open = nullptr,
.close = nullptr,
.close = close,
.getdents = getdents,
.fstat = fstat};

Expand All @@ -48,6 +49,7 @@ int mkdir (char* dirname, inode** result, inode* root) {
new_dir->i_fops = &f_ops;
new_dir->i_no = next_inode++;
new_dir->i_parent = root;
new_dir->i_cnt = 1;

// manually add the '.' and '..' entries
((dir_content_t*)new_dir->i_pvt)->d_count = 2;
Expand Down Expand Up @@ -85,6 +87,7 @@ int create (char* filename, inode** result, inode* root) {
new_file->i_fops = &f_ops;
new_file->i_no = next_inode++;
new_file->i_parent = root;
new_file->i_cnt = 1;

// construct parent replacement structures
dir_content_t* parent_pvt = (dir_content_t*)root->i_pvt;
Expand Down Expand Up @@ -272,6 +275,48 @@ int fstat (inode* node, file* f, stat* buf) {
return istat (node, buf);
}

static void delete_node (inode* node) {
inode* parent_node = node->i_parent;
if (parent_node == node || !parent_node) goto parent_unlinked;

dir_content_t* dir_content = (dir_content_t*)parent_node->i_pvt;
for (uint64_t i = 0; i < dir_content->d_count; i++) {
child_t* d_child = &dir_content->d_children[i];
if (!d_child->c_inode || !d_child->c_name) continue;

if (d_child->c_inode == node) {
kfree (d_child->c_name);
dir_content->d_children[i] = dir_content->d_children[--dir_content->d_count];
void* tmp =
krealloc (dir_content->d_children, (dir_content->d_count) * sizeof (child_t));
if (tmp)
dir_content->d_children = tmp;
else
kmemset (&dir_content->d_children[dir_content->d_count], 0, sizeof (child_t));
break;
}
}

parent_unlinked:
if (node->i_pvt) kfree (node->i_pvt);
if (node->i_fsinfo) kfree (node->i_fsinfo);
if (node->i_info.ramfs_info) kfree (node->i_info.ramfs_info);

kfree (node);
}

int close (inode* node, file* f) {
(void)f;
if (node->i_cnt == 0 && node->i_type != DIRECTORY) delete_node (node);
return 0;
}

int unlink (inode* node) {
node->i_cnt--;
if (node->i_cnt == 0) delete_node (node);
return 0;
}

inode* init_ramfs_root (void) {
root_inode = kmalloc (sizeof (inode));
kmemset ((void*)root_inode, 0, sizeof (inode));
Expand All @@ -281,6 +326,7 @@ inode* init_ramfs_root (void) {
root_inode->i_fops = &f_ops;
root_inode->i_no = next_inode++;
root_inode->i_parent = root_inode;
root_inode->i_cnt = 1; // the single reference is us, COS

// manually add the '.' and '..' entries
((dir_content_t*)root_inode->i_pvt)->d_count = 2;
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/kernel/fs/vfs/close.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
int do_close (struct file* fd) {
if (!fd) return -EINVAL;
if (--fd->f_cnt == 0) {
if (fd->f_fops && fd->f_fops->close) fd->f_fops->close (fd->f_inode, fd);
fd->f_inode->i_cnt--;
if (fd->f_fops && fd->f_fops->close) fd->f_fops->close (fd->f_inode, fd);
kfree (fd);
}
return 0;
Expand Down
43 changes: 43 additions & 0 deletions kernel/src/kernel/fs/vfs/unlink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* unlink.c
* Copyright (C) 2026 Aditya Kumar
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, see <https://www.gnu.org/licenses/>.
*/

#include <kclib/string.h>
#include <kernel/error.h>
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
#include <liballoc/liballoc.h>
#include <stddef.h>

int do_unlink (const char* path) {
if (!path) return -EINVAL;

process* current = get_current_process ();
inode* node = nullptr;

int error = do_lookup ((char*)path, &node, current->p_root, current->p_wd);
if (error != 0) return error;

if (node->i_type == DIRECTORY) return -EISDIR;
if (!node->i_iops || !node->i_iops->unlink) return -ENOSYS;
return node->i_iops->unlink (node);
}

uint64_t sys_unlink (uint64_t path) {
const char* path_us = kstrdup ((const char*)path);
int error = do_unlink (path_us);
kfree ((void*)path_us);
return error;
}
1 change: 1 addition & 0 deletions kernel/src/kernel/fs/vfs/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ void init_vfs (inode* absolute_root) {
register_syscall (SYSCALL_SYS_CHDIR, SYS1 (sys_chdir));
register_syscall (SYSCALL_SYS_GETCWD, SYS2 (sys_getcwd));
register_syscall (SYSCALL_SYS_IOCTL, SYS3 (sys_ioctl));
register_syscall (SYSCALL_SYS_UNLINK, SYS1 (sys_unlink));
}
22 changes: 22 additions & 0 deletions lib/cos/src/unlink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* unlink.c
* Copyright (C) 2026 Aditya Kumar
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, see <https://www.gnu.org/licenses/>.
*/

#include <arch/x86_64-cos/syscalls.h>
#include <sys/unistd.h>

int unlink (const char* __path) {
return (int)syscall_ret ((long)syscall1 (SYSCALL_SYS_UNLINK, (uint64_t)__path));
}
1 change: 1 addition & 0 deletions user/cosh/include/builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ int builtin_source (int argc, char** argv);
int builtin_stat (int argc, char** argv);
int builtin_test (int argc, char** argv);
int builtin_touch (int argc, char** argv);
int builtin_unlink (int argc, char** argv);
2 changes: 2 additions & 0 deletions user/cosh/src/builtin/dispatch_builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ int dispatch_builtin (size_t argc, char** argv) {
return builtin_test (argc, argv);
else if (strcmp (argv[0], "clear") == 0)
return builtin_clear (argc, argv);
else if (strcmp (argv[0], "unlink") == 0)
return builtin_unlink (argc, argv);

return -1;
}
27 changes: 27 additions & 0 deletions user/cosh/src/builtin/unlink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* unlink.c
* Copyright (C) 2026 Aditya Kumar
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, see <https://www.gnu.org/licenses/>.
*/

#include <builtin.h>
#include <stdio.h>
#include <unistd.h>

int builtin_unlink (int argc, char** argv) {
if (argc == 1) {
printf ("usage: unlink file\n");
return 64;
}
return unlink (argv[1]);
}
2 changes: 1 addition & 1 deletion user/cosh/src/repl_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ int repl_loop (void) {
cmdbuf[strcspn (cmdbuf, "\n")] = '\0';
if (cmdbuf[0] == '\0') return 0;
last_exit = run_line (cmdbuf);
if (last_exit != 0) printf ("\033[31mexited with non-zero status: %i\n", last_exit);
if (last_exit != 0) printf ("\033[31m[%i] ", last_exit);

return 0;
}
Expand Down
Loading