Nucleus
Barry Inode mknod e440b5d (3 years, 2 months ago)
diff --git a/include/nucleus/vfs.h b/include/nucleus/vfs.h
index fa193fb..97ebf54 100644
--- a/include/nucleus/vfs.h
+++ b/include/nucleus/vfs.h
@@ -111,6 +111,7 @@ int inode_create(Inode *inode, DirEntry *entry, mode_t mode);
DirEntry *inode_lookup(Inode *inode, const char *name);
int inode_mkdir(Inode *inode, DirEntry *entry, mode_t mode);
int inode_rmdir(Inode *inode, DirEntry *entry);
+int inode_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev);
/* Directory Entry functions */
DirEntry *find_direntry(ObjectList *list, const char *name);
/* File functions */
diff --git a/vfs/inode.c b/vfs/inode.c
index e4414cf..e4ed8a8 100644
--- a/vfs/inode.c
+++ b/vfs/inode.c
@@ -186,3 +186,20 @@ inode_rmdir(Inode *inode, DirEntry *entry)
return err;
}
+/* Make a special node wrapper */
+int
+inode_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev)
+{
+ if (!inode->ops || !inode->ops->mknod)
+ return -EINVAL;
+ lock(inode);
+ int err = inode->ops->mknod(inode, entry, mode, dev);
+ if (!err) {
+ add(inode->dirEntries, entry);
+ entry->inode = super_alloc_inode(inode->super);
+ entry->inode->mode = mode;
+ entry->inode->dev = dev;
+ }
+ unlock(inode);
+ return err;
+}
diff --git a/vfs/open.c b/vfs/open.c
index 630b675..ff7fd01 100644
--- a/vfs/open.c
+++ b/vfs/open.c
@@ -225,3 +225,41 @@ end:
destroy_list(custody);
return err;
}
+
+/* Make a special node */
+int
+mknod(const char *pathname, mode_t mode, dev_t dev)
+{
+ if (!pathname)
+ return -EFAULT;
+ if (!verify_access(pathname, strnlen(pathname, PATH_MAX), PROT_READ))
+ return -EFAULT;
+ int err;
+ ObjectList *custody = create_list(&dirEntryType);
+ Inode *inode = lookup(pathname, custody);
+ if (inode) {
+ err = -EEXIST;
+ goto end;
+ }
+ if (!count(custody)) {
+ err = -ENOENT;
+ goto end;
+ }
+ /* Check write permission */
+ DirEntry *entry = get_nth_item(custody, count(custody) - 2);
+ if (entry)
+ inode = entry->inode;
+ else
+ inode = current->fs->root;
+ if (!permission(inode, PROT_WRITE)) {
+ err = -EACCES;
+ goto end;
+ }
+
+ /* Create node */
+ err = inode_mknod(inode, get_nth_item(custody, count(custody) - 1),
+ mode, dev);
+end:
+ destroy_list(custody);
+ return err;
+}