kernel: rename VOP and syscall

This commit is contained in:
Matheus
2023-09-17 01:31:40 -03:00
parent 7173c11e59
commit ac0961c9a6
7 changed files with 167 additions and 7 deletions
+3 -1
View File
@@ -39,6 +39,7 @@ extern syscall_ftruncate
extern syscall_mount
extern syscall_fchownat
extern syscall_utimensat
extern syscall_renameat
syscalltab:
dq syscall_print
dq syscall_mmap
@@ -80,7 +81,8 @@ dq syscall_ftruncate
dq syscall_mount
dq syscall_fchownat
dq syscall_utimensat
syscallcount equ 40
dq syscall_renameat
syscallcount equ 41
section .text
global arch_syscall_entry
; on entry:
+4 -2
View File
@@ -4,7 +4,7 @@
#ifdef SYSCALL_LOGGING
#define SYSCALL_COUNT 40
#define SYSCALL_COUNT 41
#define LOGSTR(x) arch_e9_puts(x)
static char *name[] = {
@@ -48,6 +48,7 @@ static char *name[] = {
"mount",
"fchownat",
"utimensat",
"renameat"
};
static char *args[] = {
@@ -90,7 +91,8 @@ static char *args[] = {
"fd %d size %lu", // ftruncate
"backing %p mountpoint %s fs %s flags %d data %p", // mount
"fd %d path %s owner %d group %d flags %x", // fchownat
"dirfd %d path %p times %p flags %x" // utimensat
"dirfd %d path %p times %p flags %x", // utimensat
"olddirfd %d oldpath %s newdirfd %d newpath %s flags %d" // renameat
};
#endif
+2 -1
View File
@@ -334,7 +334,8 @@ static vops_t vnops = {
.isatty = devfs_isatty,
.ioctl = devfs_ioctl,
.maxseek = devfs_maxseek,
.resize = devfs_enodev
.resize = devfs_enodev,
.rename = devfs_enodev
};
static void ctor(scache_t *cache, void *obj) {
+2 -1
View File
@@ -235,7 +235,8 @@ static vops_t vnops = {
.mmap = pipefs_enodev,
.munmap = pipefs_enodev,
.getdents = pipefs_enodev,
.resize = pipefs_enodev
.resize = pipefs_enodev,
.rename = pipefs_enodev
};
static void ctor(scache_t *cache, void *obj) {
+65 -2
View File
@@ -343,6 +343,68 @@ static int tmpfs_link(vnode_t *node, vnode_t *dir, char *name, cred_t *cred) {
return 0;
}
static int tmpfs_rename(vnode_t *source, char *oldname, vnode_t *target, char *newname, int flags) {
if (source->vfs != target->vfs)
return EXDEV;
if (source->type != V_TYPE_DIR || target->type != V_TYPE_DIR)
return ENOTDIR;
tmpfsnode_t *sourcedir = (tmpfsnode_t *)source;
tmpfsnode_t *targetdir = (tmpfsnode_t *)target;
size_t oldlen = strlen(oldname);
size_t newlen = strlen(newname);
if (target != source) {
VOP_LOCK(source);
VOP_LOCK(target);
} else {
VOP_LOCK(target);
}
// get original node
void *v;
int error = hashtable_get(&sourcedir->children, &v, oldname, oldlen);
if (error)
goto cleanup;
vnode_t *node = v;
vnode_t *oldnode = NULL;
// get old node in target
error = hashtable_get(&targetdir->children, &v, newname, newlen);
if (error != ENOENT && error != 0)
goto cleanup;
else if (error == 0) // found
oldnode = v;
// same link, rename is a no-op
if (sourcedir == targetdir && strcmp(oldname, newname) == 0)
goto cleanup;
// link node to new name
error = hashtable_set(&targetdir->children, node, newname, newlen, true);
if (error)
goto cleanup;
// remove old link. should not fail
__assert(hashtable_remove(&sourcedir->children, oldname, oldlen) == 0);
if (oldnode)
VOP_RELEASE(oldnode);
cleanup:
if (target != source) {
VOP_UNLOCK(target);
VOP_UNLOCK(source);
} else {
VOP_UNLOCK(target);
}
return error;
}
static int tmpfs_symlink(vnode_t *node, char *name, vattr_t *attr, char *path, cred_t *cred) {
if (node->type != V_TYPE_DIR)
return ENOTDIR;
@@ -458,7 +520,7 @@ static int tmpfs_getdents(vnode_t *node, dent_t *buffer, size_t count, uintmax_t
ent->d_off = offset;
ent->d_reclen = sizeof(dent_t);
ent->d_type = vfs_getposixtype(itmpnode->vnode.type);
strcpy(ent->d_name, entry->key);
memcpy(ent->d_name, entry->key, entry->keysize);
*readcount += 1;
}
@@ -505,7 +567,8 @@ static vops_t vnops = {
.mmap = tmpfs_mmap,
.munmap = tmpfs_munmap,
.getdents = tmpfs_getdents,
.resize = tmpfs_resize
.resize = tmpfs_resize,
.rename = tmpfs_rename
};
static tmpfsnode_t *newnode(vfs_t *vfs, int type) {
+2
View File
@@ -98,6 +98,7 @@ typedef struct vops_t {
int (*ioctl)(vnode_t *node, unsigned long request, void *arg, int *result);
int (*maxseek)(vnode_t *node, size_t *max);
int (*resize)(vnode_t *node, size_t newsize, cred_t *cred);
int (*rename)(vnode_t *source, char *oldname, vnode_t *target, char *newname, int flags);
} vops_t;
#define VFS_INIT(v, o, f) \
@@ -145,6 +146,7 @@ typedef struct vops_t {
#define VOP_IOCTL(v, r, a, rp) ((v)->ops->ioctl ? (v)->ops->ioctl(v, r, a, rp) : ENOTTY)
#define VOP_MAXSEEK(v, rp) ((v)->ops->maxseek ? (v)->ops->maxseek(v, rp) : ENOTTY)
#define VOP_RESIZE(v, s, c) (v)->ops->resize(v, s, c)
#define VOP_RENAME(s, o, t, n, f) (s)->ops->rename(s, o, t, n, f)
#define VOP_HOLD(v) __atomic_add_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST)
#define VOP_RELEASE(v) {\
if (__atomic_sub_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) == 0) {\
+89
View File
@@ -0,0 +1,89 @@
#include <kernel/syscalls.h>
#include <kernel/alloc.h>
#include <string.h>
#include <logging.h>
syscallret_t syscall_renameat(context_t *context, int olddirfd, const char *uoldpath, int newdirfd, const char *unewpath, unsigned int flags) {
syscallret_t ret = {
.ret = -1
};
__assert(flags == 0);
char *oldcomponent = NULL;
char *newcomponent = NULL;
char *oldpath = alloc(strlen(uoldpath) + 1);
if (oldpath == NULL) {
ret.errno = ENOMEM;
return ret;
}
char *newpath = alloc(strlen(unewpath) + 1);
if (newpath == NULL) {
free(oldpath);
ret.errno = ENOMEM;
return ret;
}
// TODO safe strcopy
strcpy(oldpath, uoldpath);
strcpy(newpath, unewpath);
vnode_t *olddirnode = NULL;
file_t *oldfile = NULL;
vnode_t *newdirnode = NULL;
file_t *newfile = NULL;
vnode_t *targetdirnode = NULL;
vnode_t *sourcedirnode = NULL;
ret.errno = dirfd_enter(oldpath, olddirfd, &oldfile, &olddirnode);
if (ret.errno)
goto cleanup;
ret.errno = dirfd_enter(newpath, newdirfd, &newfile, &newdirnode);
if (ret.errno)
goto cleanup;
oldcomponent = alloc(strlen(oldpath));
newcomponent = alloc(strlen(newpath));
if (oldcomponent == NULL && newcomponent == NULL)
goto cleanup;
ret.errno = vfs_lookup(&sourcedirnode, olddirnode, oldpath, oldcomponent, VFS_LOOKUP_NOLINK | VFS_LOOKUP_PARENT);
if (ret.errno)
goto cleanup;
ret.errno = vfs_lookup(&targetdirnode, newdirnode, newpath, newcomponent, VFS_LOOKUP_NOLINK | VFS_LOOKUP_PARENT);
if (ret.errno)
goto cleanup;
ret.errno = VOP_RENAME(sourcedirnode, oldcomponent, targetdirnode, newcomponent, flags);
ret.ret = ret.errno ? -1 : 0;
cleanup:
if (targetdirnode)
VOP_RELEASE(targetdirnode);
if (sourcedirnode)
VOP_RELEASE(sourcedirnode);
if (oldcomponent)
free(oldcomponent);
if (newcomponent)
free(newcomponent);
if (olddirnode)
dirfd_leave(olddirnode, oldfile);
if (newdirnode)
dirfd_leave(newdirnode, newfile);
free(oldpath);
free(newpath);
return ret;
}