summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-06-27 19:03:31 -0400
committerIan Moffett <ian@osmora.org>2025-06-27 19:04:55 -0400
commitbbd861c0cd4c26e2699392fec3ae0ec7df8ab145 (patch)
treecbed69b27dbb16486f28d0995ab9524266c508a3 /sys
parent8877f9b8a8992388b4f64d425a48b02a3229cf61 (diff)
kernel: vfs: Add support for O_CREAT flag
Add support for the O_CREAT flag which allows file creation upon an open() call. Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/ctlfs.c3
-rw-r--r--sys/fs/devfs.c3
-rw-r--r--sys/fs/initramfs.c3
-rw-r--r--sys/include/sys/fcntl.h1
-rw-r--r--sys/include/sys/vnode.h8
-rw-r--r--sys/kern/kern_descrip.c36
6 files changed, 48 insertions, 6 deletions
diff --git a/sys/fs/ctlfs.c b/sys/fs/ctlfs.c
index 64d3a1a..9225114 100644
--- a/sys/fs/ctlfs.c
+++ b/sys/fs/ctlfs.c
@@ -380,7 +380,8 @@ static const struct vops ctlfs_vops = {
.read = ctlfs_read,
.getattr = NULL,
.write = NULL,
- .reclaim = ctlfs_reclaim
+ .reclaim = ctlfs_reclaim,
+ .create = NULL
};
const struct vfsops g_ctlfs_vfsops = {
diff --git a/sys/fs/devfs.c b/sys/fs/devfs.c
index 0c087f0..293ee0a 100644
--- a/sys/fs/devfs.c
+++ b/sys/fs/devfs.c
@@ -273,7 +273,8 @@ const struct vops g_devfs_vops = {
.reclaim = devfs_reclaim,
.read = devfs_read,
.write = devfs_write,
- .getattr = devfs_getattr
+ .getattr = devfs_getattr,
+ .create = NULL
};
const struct vfsops g_devfs_vfsops = {
diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c
index c3f9b14..c41deb4 100644
--- a/sys/fs/initramfs.c
+++ b/sys/fs/initramfs.c
@@ -279,7 +279,8 @@ const struct vops g_initramfs_vops = {
.read = initramfs_read,
.write = NULL,
.reclaim = initramfs_reclaim,
- .getattr = initramfs_getattr
+ .getattr = initramfs_getattr,
+ .create = NULL,
};
const struct vfsops g_initramfs_vfsops = {
diff --git a/sys/include/sys/fcntl.h b/sys/include/sys/fcntl.h
index 122a378..83d38af 100644
--- a/sys/include/sys/fcntl.h
+++ b/sys/include/sys/fcntl.h
@@ -33,6 +33,7 @@
#define O_RDONLY 0x0000
#define O_WRONLY 0x0001
#define O_RDWR 0x0002
+#define O_CREAT 0x0004
/* Makes seal checking easier */
#if defined(_KERNEL)
diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h
index cd71817..1a6b2aa 100644
--- a/sys/include/sys/vnode.h
+++ b/sys/include/sys/vnode.h
@@ -86,6 +86,13 @@ struct vop_lookup_args {
struct vnode **vpp; /* Result vnode */
};
+struct vop_create_args {
+ const char *path; /* Full path */
+ const char *ppath; /* Parent path */
+ struct vnode *dirvp; /* Directory vnode */
+ struct vnode **vpp; /* Result vnode */
+};
+
/*
* A field in this structure is unavailable
* if it has a value of VNOVAL.
@@ -106,6 +113,7 @@ struct vops {
int(*read)(struct vnode *vp, struct sio_txn *sio);
int(*write)(struct vnode *vp, struct sio_txn *sio);
int(*reclaim)(struct vnode *vp);
+ int(*create)(struct vop_create_args *args);
};
extern struct vnode *g_root_vnode;
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index a2dd667..da67530 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -229,6 +229,29 @@ done:
return retval;
}
+static int
+fd_do_create(const char *path, struct nameidata *ndp)
+{
+ struct vop_create_args cargs;
+ struct vnode *dirvp = ndp->vp;
+ const struct vops *vops = dirvp->vops;
+ int error;
+
+ if (vops->create == NULL) {
+ return -EINVAL;
+ }
+
+ cargs.path = path;
+ cargs.ppath = ndp->path;
+ cargs.dirvp = dirvp;
+ cargs.vpp = &ndp->vp;
+ if ((error = vops->create(&cargs)) < 0) {
+ return error;
+ }
+
+ return 0;
+}
+
int
fd_read(unsigned int fd, void *buf, size_t count)
{
@@ -247,18 +270,17 @@ fd_write(unsigned int fd, void *buf, size_t count)
*
* @pathname: Path of file to open.
* @flags: Flags to use.
- *
- * TODO: Use of flags.
*/
int
fd_open(const char *pathname, int flags)
{
int error;
+ const struct vops *vops;
struct filedesc *filedes;
struct nameidata nd;
nd.path = pathname;
- nd.flags = 0;
+ nd.flags = ISSET(flags, O_CREAT) ? NAMEI_WANTPARENT : 0;
if ((error = namei(&nd)) < 0) {
return error;
@@ -269,6 +291,14 @@ fd_open(const char *pathname, int flags)
return error;
}
+ vops = nd.vp->vops;
+ if (ISSET(flags, O_CREAT) && vops->create != NULL) {
+ error = fd_do_create(pathname, &nd);
+ }
+ if (error < 0) {
+ return error;
+ }
+
filedes->vp = nd.vp;
filedes->flags = flags;
return filedes->fdno;