Skip to content

Commit d68f58d

Browse files
authored
Add access, rmdir, chroot and stubs for chmod, chown and fsync (#72)
* Implement access syscall * Implement empty() function in ramfs * Route rmdir * Add rmdir inode operation * Fixes in do_rmdir implementation * Rmdir in libcos + cosh * Format * Ditch empty() op + fixes * Unlink should reject trailing slashes * Trailing slash should always check for directory * Format * Remove unnecessary print statement * Wire up (in libcos) chmod, chown, fsync and chroot * Make chroot visible always in the patch * Implement chroot (chdir but changes root?) * Contain processes to their new root (only if they start within it) * Add chmod + i_perms field * Format * Add chown + i_uid and i_gid fields * Add fsync (stubbed out) * Sort vfs declarations and syscall regs
1 parent 2f6edeb commit d68f58d

26 files changed

Lines changed: 598 additions & 56 deletions

File tree

kernel/include/kernel/fs/ramfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ int symlink (char* target, char* linkname, inode** result, inode* parent);
3737
int readlink (inode* node, char* buf, size_t bufsz);
3838
int rename (inode* old_node, inode* old_parent, const char* old_name, inode* new_parent,
3939
const char* new_name);
40+
int rmdir (inode* parent, inode* node);
41+
int fsync (file* f);
4042

4143
typedef struct {
4244
char* c_name;

kernel/include/kernel/fs/stat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ typedef struct {
5757
#define S_IXUSR 0000100 /* execute/search permission, owner */
5858
#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
5959
#define S_IRGRP 0000040 /* read permission, group */
60-
#define S_IWGRP 0000020 /* write permission, grougroup */
60+
#define S_IWGRP 0000020 /* write permission, group */
6161
#define S_IXGRP 0000010 /* execute/search permission, group */
6262
#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
6363
#define S_IROTH 0000004 /* read permission, other */

kernel/include/kernel/fs/vfs.h

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
#define L_DCHK 0x0004
4545
#define L_NDCHK 0x0008
4646

47+
#define F_OK 0x0000
48+
#define R_OK 0x0004
49+
#define W_OK 0x0002
50+
#define X_OK 0x0001
51+
4752
#define ALIGN_UP(value, alignment) (((value) + (alignment) - 1) & ~((alignment) - 1))
4853

4954
typedef enum { UNDEF, EFILE, DIRECTORY, LINK, CHAR_DEV, PIPE } file_type_t;
@@ -66,6 +71,7 @@ typedef struct {
6671
int (*readlink) (inode*, char*, size_t);
6772
int (*link) (inode*, char*, inode*);
6873
int (*rename) (inode*, inode*, const char*, inode*, const char*);
74+
int (*rmdir) (inode*, inode*);
6975
} inode_operations;
7076

7177
typedef struct {
@@ -77,16 +83,18 @@ typedef struct {
7783
int (*getdents) (inode*, file*, void*, size_t);
7884
int (*fstat) (inode*, file*, stat*);
7985
int (*ioctl) (inode*, file*, uint64_t, uint64_t);
86+
int (*fsync) (file*);
8087
} file_operations;
8188

8289
struct inode {
83-
uint64_t i_no, i_sz, i_cnt;
90+
uint64_t i_no, i_sz, i_cnt, i_uid, i_gid;
8491
void* i_pvt;
8592
void* i_fsinfo;
8693
inode_operations* i_iops;
8794
file_operations* i_fops;
8895
file_type_t i_type;
8996
inode* i_parent;
97+
uint16_t i_perms;
9098
union {
9199
chardev_info_t* chardev_info;
92100
ramfs_info_t* ramfs_info;
@@ -107,47 +115,58 @@ int lookup_inode_by_path (const char* path, inode* proc_root, inode* proc_cwd,
107115
int resolve_parent_and_childname (char* path, inode* proc_root, inode* proc_cwd,
108116
inode** result_parent, char** result_childname);
109117

110-
int do_mkdir (char* dirname, inode** result, inode* parent);
118+
int do_access (const char* path, uint8_t flags);
111119
int do_chdir (const char* path);
112-
int do_getcwd (char* buf, size_t size);
113-
int do_create (char* filename, inode** result, inode* parent);
114-
int do_unlink (const char* path);
115-
int do_rename (const char* old, const char* new);
116-
117-
int do_read (struct file* f, void* buf, size_t size);
118-
int do_seek (struct file* f, size_t offset, int whence);
119-
int do_write (struct file* f, void* buf, size_t size);
120-
int do_open (inode* file, struct file* dest_fd);
120+
int do_chmod (const char* path, uint16_t mode);
121+
int do_chown (const char* path, uint64_t uid, uint64_t gid);
122+
int do_chroot (const char* path);
121123
int do_close (struct file* fd);
122-
int do_getdents (struct file* f, void* buf, size_t count);
124+
int do_create (char* filename, inode** result, inode* parent);
123125
int do_fstat (struct file* fd, stat* buf);
124-
int do_lstat (const char* restrict path, stat* restrict buf);
125-
int do_stat (const char* restrict path, stat* restrict buf);
126+
int do_fsync (struct file* fd);
127+
int do_getcwd (char* buf, size_t size);
128+
int do_getdents (struct file* f, void* buf, size_t count);
126129
int do_ioctl (struct file* fd, uint64_t req, uint64_t arg);
127130
int do_link (const char* oldpath, const char* newpath);
128-
int do_symlink (const char* restrict target, const char* restrict linkpath);
131+
int do_lstat (const char* restrict path, stat* restrict buf);
132+
int do_mkdir (char* dirname, inode** result, inode* parent);
133+
int do_open (inode* file, struct file* dest_fd);
134+
int do_read (struct file* f, void* buf, size_t size);
129135
int do_readlink (const char* path, char* buf, size_t bufsz);
136+
int do_rename (const char* old, const char* new);
137+
int do_rmdir (const char* path);
138+
int do_seek (struct file* f, size_t offset, int whence);
139+
int do_stat (const char* restrict path, stat* restrict buf);
140+
int do_symlink (const char* restrict target, const char* restrict linkpath);
141+
int do_unlink (const char* path);
142+
int do_write (struct file* f, void* buf, size_t size);
130143

131-
uint64_t sys_read (uint64_t fd, uint64_t buf, uint64_t size);
132-
uint64_t sys_write (uint64_t fd, uint64_t buf, uint64_t size);
133-
uint64_t sys_seek (uint64_t fd, uint64_t offset, uint64_t whence);
134-
uint64_t sys_open (uint64_t filename_ptr, uint64_t flags, uint64_t mode);
135-
uint64_t sys_close (uint64_t fd);
136-
uint64_t sys_mkdir (uint64_t path, uint64_t mode);
144+
uint64_t sys_access (uint64_t path, uint64_t mode);
137145
uint64_t sys_chdir (uint64_t path);
138-
uint64_t sys_getdents (uint64_t fd, uint64_t buf, uint64_t count);
139-
uint64_t sys_getcwd (uint64_t buf, uint64_t size);
146+
uint64_t sys_chmod (uint64_t path, uint64_t mode);
147+
uint64_t sys_chown (uint64_t path, uint64_t uid, uint64_t gid);
148+
uint64_t sys_chroot (uint64_t path);
149+
uint64_t sys_close (uint64_t fd);
150+
uint64_t sys_dup (uint64_t fd);
151+
uint64_t sys_dup2 (uint64_t oldfd, uint64_t newfd);
140152
uint64_t sys_fstat (uint64_t fd, uint64_t buf);
141-
uint64_t sys_lstat (uint64_t path, uint64_t buf);
142-
uint64_t sys_stat (uint64_t path, uint64_t buf);
153+
uint64_t sys_fsync (uint64_t fd);
154+
uint64_t sys_getcwd (uint64_t buf, uint64_t size);
155+
uint64_t sys_getdents (uint64_t fd, uint64_t buf, uint64_t count);
143156
uint64_t sys_ioctl (uint64_t fd, uint64_t req, uint64_t arg);
144157
uint64_t sys_link (uint64_t oldpath, uint64_t newpath);
145-
uint64_t sys_unlink (uint64_t path);
146-
uint64_t sys_symlink (uint64_t target, uint64_t linkpath);
158+
uint64_t sys_lstat (uint64_t path, uint64_t buf);
159+
uint64_t sys_mkdir (uint64_t path, uint64_t mode);
160+
uint64_t sys_open (uint64_t filename_ptr, uint64_t flags, uint64_t mode);
161+
uint64_t sys_read (uint64_t fd, uint64_t buf, uint64_t size);
147162
uint64_t sys_readlink (uint64_t path, uint64_t buf, uint64_t bufsz);
148-
uint64_t sys_dup (uint64_t fd);
149-
uint64_t sys_dup2 (uint64_t oldfd, uint64_t newfd);
150163
uint64_t sys_rename (uint64_t old, uint64_t new);
164+
uint64_t sys_rmdir (uint64_t path);
165+
uint64_t sys_seek (uint64_t fd, uint64_t offset, uint64_t whence);
166+
uint64_t sys_stat (uint64_t path, uint64_t buf);
167+
uint64_t sys_symlink (uint64_t target, uint64_t linkpath);
168+
uint64_t sys_unlink (uint64_t path);
169+
uint64_t sys_write (uint64_t fd, uint64_t buf, uint64_t size);
151170

152171
inode* get_absolute_root (void);
153172
void init_vfs (inode* absolute_root);

kernel/include/kernel/syscall.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
#define SYSCALL_SYS_DUP2 21
4747
#define SYSCALL_SYS_PIPE 22
4848
#define SYSCALL_SYS_RENAME 23
49+
#define SYSCALL_SYS_ACCESS 24
50+
#define SYSCALL_SYS_RMDIR 25
51+
#define SYSCALL_SYS_CHMOD 26
52+
#define SYSCALL_SYS_CHOWN 27
53+
#define SYSCALL_SYS_FSYNC 28
54+
#define SYSCALL_SYS_CHROOT 29
4955

5056
/* Memory syscalls */
5157

@@ -64,6 +70,12 @@
6470
#define SYSCALL_SYS_TIMES 49
6571
#define SYSCALL_SYS_WAITPID 50
6672

73+
/* User syscalls */
74+
75+
#define SYSCALL_SYS_GETLOGIN 71
76+
#define SYSCALL_SYS_SETLOGIN 72
77+
#define SYSCALL_SYS_GETUID 73
78+
6779
/* Utility syscalls */
6880

6981
#define SYSCALL_SYS_GETTIMEOFDAY 81

kernel/src/kernel/fs/ramfs/ramfs.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,16 @@ static inode_operations i_ops = {.lookup = lookup,
3333
.unlink = unlink,
3434
.symlink = symlink,
3535
.readlink = readlink,
36-
.rename = rename};
36+
.rename = rename,
37+
.rmdir = rmdir};
3738
static file_operations f_ops = {.read = read,
3839
.write = write,
3940
.seek = seek,
4041
.open = nullptr,
4142
.close = close,
4243
.getdents = getdents,
43-
.fstat = fstat};
44+
.fstat = fstat,
45+
.fsync = fsync};
4446

4547
int mkdir (char* dirname, inode** result, inode* root) {
4648
// requires: guarantee that vfs input is valid
@@ -294,6 +296,22 @@ static void remove_dirent (inode* parent, char* name) {
294296
}
295297
}
296298

299+
static void remove_dirent_by_node (inode* parent, inode* node) {
300+
dir_content_t* dir = (dir_content_t*)parent->i_pvt;
301+
for (uint64_t i = 0; i < dir->d_count; i++) {
302+
if (dir->d_children[i].c_inode == node) {
303+
kfree (dir->d_children[i].c_name);
304+
dir->d_children[i] = dir->d_children[--dir->d_count];
305+
void* tmp = krealloc (dir->d_children, dir->d_count * sizeof (child_t));
306+
if (tmp)
307+
dir->d_children = tmp;
308+
else
309+
kmemset (&dir->d_children[dir->d_count], 0, sizeof (child_t));
310+
return;
311+
}
312+
}
313+
}
314+
297315
static void free_inode (inode* node) {
298316
if (node->i_pvt) kfree (node->i_pvt);
299317
if (node->i_fsinfo) kfree (node->i_fsinfo);
@@ -359,6 +377,20 @@ int rename (inode* old_node, inode* old_parent, const char* old_name, inode* new
359377
return 0;
360378
}
361379

380+
int rmdir (inode* parent, inode* node) {
381+
if (node->i_type != DIRECTORY) return -ENOTDIR;
382+
if (((dir_content_t*)node->i_pvt)->d_count > 2) return -ENOTEMPTY;
383+
384+
remove_dirent_by_node (parent, node);
385+
if (--node->i_cnt == 0) free_inode (node);
386+
return 0;
387+
}
388+
389+
int fsync (file* f) {
390+
(void)f;
391+
return 0;
392+
}
393+
362394
inode* init_ramfs_root (void) {
363395
root_inode = kmalloc (sizeof (inode));
364396
kmemset ((void*)root_inode, 0, sizeof (inode));

kernel/src/kernel/fs/vfs/access.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* access.c
3+
* Copyright (C) 2026 Aditya Kumar
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the
6+
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+
* General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License along with this program; if
14+
* not, see <https://www.gnu.org/licenses/>.
15+
*/
16+
17+
#include <kclib/string.h>
18+
#include <kernel/error.h>
19+
#include <kernel/fs/vfs.h>
20+
#include <kernel/process.h>
21+
#include <liballoc/liballoc.h>
22+
23+
int do_access (const char* path, uint8_t flags) {
24+
(void)flags;
25+
26+
process* current = get_current_process ();
27+
inode* result = nullptr;
28+
29+
int error = lookup_inode_by_path (path, current->p_root, current->p_wd, &result, L_FLNK);
30+
if (error) return error;
31+
32+
bool access_ok = true;
33+
34+
// TODO: check for permissions, when implemented
35+
36+
return access_ok;
37+
}
38+
39+
uint64_t sys_access (uint64_t path, uint64_t flags) {
40+
char* path_norm = nullptr;
41+
42+
int error = path_normalise_from_user ((char*)path, &path_norm);
43+
if (error < 0) return error;
44+
45+
error = do_access (path_norm, (uint8_t)(flags & 0xF));
46+
47+
kfree ((void*)path_norm);
48+
return error;
49+
}

kernel/src/kernel/fs/vfs/chmod.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* chmod.c
3+
* Copyright (C) 2026 Aditya Kumar
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the
6+
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+
* General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License along with this program; if
14+
* not, see <https://www.gnu.org/licenses/>.
15+
*/
16+
17+
#include <kernel/error.h>
18+
#include <kernel/fs/vfs.h>
19+
#include <kernel/process.h>
20+
#include <liballoc/liballoc.h>
21+
22+
int do_chmod (const char* path, uint16_t mode) {
23+
if (!path) return -EINVAL;
24+
inode* node = nullptr;
25+
process* current = get_current_process ();
26+
27+
char* norm_path = nullptr;
28+
int error = path_normalise_from_user (path, &norm_path);
29+
if (error < 0) return error;
30+
error = lookup_inode_by_path ((char*)norm_path, current->p_root, current->p_wd, &node, L_FLNK);
31+
kfree (norm_path);
32+
if (error != 0) return error;
33+
34+
node->i_perms = (node->i_perms & ~07777) | (uint16_t)(mode & 07777);
35+
36+
return 0;
37+
}
38+
39+
uint64_t sys_chmod (uint64_t path, uint64_t mode) {
40+
return (uint64_t)do_chmod ((const char*)path, mode);
41+
}

kernel/src/kernel/fs/vfs/chown.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* chown.c
3+
* Copyright (C) 2026 Aditya Kumar
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the
6+
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+
* General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License along with this program; if
14+
* not, see <https://www.gnu.org/licenses/>.
15+
*/
16+
17+
#include <kernel/error.h>
18+
#include <kernel/fs/vfs.h>
19+
#include <kernel/process.h>
20+
#include <liballoc/liballoc.h>
21+
22+
int do_chown (const char* path, uint64_t uid, uint64_t gid) {
23+
if (!path) return -EINVAL;
24+
inode* node = nullptr;
25+
process* current = get_current_process ();
26+
27+
char* norm_path = nullptr;
28+
int error = path_normalise_from_user (path, &norm_path);
29+
if (error < 0) return error;
30+
error = lookup_inode_by_path ((char*)norm_path, current->p_root, current->p_wd, &node, L_FLNK);
31+
kfree (norm_path);
32+
if (error != 0) return error;
33+
34+
node->i_uid = uid;
35+
node->i_gid = gid;
36+
37+
return 0;
38+
}
39+
40+
uint64_t sys_chown (uint64_t path, uint64_t uid, uint64_t gid) {
41+
return (uint64_t)do_chown ((const char*)path, uid, gid);
42+
}

0 commit comments

Comments
 (0)