diff options
author | sotech117 <michael_foiani@brown.edu> | 2024-04-25 02:58:09 +0000 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2024-04-25 02:58:09 +0000 |
commit | a3e64ef2bf31dda9a94db011a96651de918ea968 (patch) | |
tree | 67c1d65ccc219c223d261dfd4cb024201220dcff | |
parent | d970aa2698d831645986effded059eb344a77486 (diff) |
old vfs fixes
-rw-r--r-- | Config.mk | 2 | ||||
-rw-r--r-- | kernel/fs/namev.c | 164 | ||||
-rw-r--r-- | kernel/fs/open.c | 101 | ||||
-rw-r--r-- | kernel/fs/vfs_syscall.c | 626 | ||||
-rw-r--r-- | kernel/fs/vnode_specials.c | 32 | ||||
-rw-r--r-- | kernel/main/kmain.c | 2 | ||||
-rw-r--r-- | kernel/proc/proc.c | 33 |
7 files changed, 917 insertions, 43 deletions
@@ -11,7 +11,7 @@ # are built. To enable something set it to 1, otherwise set it to 0. # DRIVERS=1 - VFS=0 + VFS=1 S5FS=0 VM=0 DYNAMIC=0 diff --git a/kernel/fs/namev.c b/kernel/fs/namev.c index e8b01e8..343f02c 100644 --- a/kernel/fs/namev.c +++ b/kernel/fs/namev.c @@ -76,8 +76,27 @@ long namev_is_descendant(vnode_t *a, vnode_t *b) long namev_lookup(vnode_t *dir, const char *name, size_t namelen, vnode_t **res_vnode) { - NOT_YET_IMPLEMENTED("VFS: namev_lookup"); - return 0; + // // NOT_YET_IMPLEMENTED("VFS: namev_lookup"); + + // KASSERT(NULL != dir); + // KASSERT(NULL != name); + // KASSERT(NULL != res_vnode); + + // if (namelen == 0) + // { + // return -EINVAL; + // } + + if ( + dir->vn_ops == NULL + || dir->vn_ops->lookup == NULL + || !S_ISDIR(dir->vn_mode) + ) + { + return -ENOTDIR; + } + + return dir->vn_ops->lookup(dir, name, namelen, res_vnode); } /* @@ -187,10 +206,85 @@ static const char *namev_tokenize(const char **search, size_t *len) long namev_dir(vnode_t *base, const char *path, vnode_t **res_vnode, const char **name, size_t *namelen) { - NOT_YET_IMPLEMENTED("VFS: namev_dir"); + // NOT_YET_IMPLEMENTED("VFS: namev_dir"); + + // Check if the pathname is nullish + if (path == NULL || *path == '\0') + { + return -EINVAL; + } + + // Get a vnode based on the pathname + vnode_t *dir = NULL; + if (*path == '/') + { + dir = vfs_root_fs.fs_root; + } + else if (base == NULL) + { + dir = curproc->p_cwd; + } + else + { + dir = base; + } + // Refcount it + vref(dir); + + // Tokenize the path + const char *token = NULL; + size_t len = 0; + while ((token = namev_tokenize(&path, &len)) && len > 0) + { + if (path == NULL || *path == '\0' || (*path == '/' && *(path + 1) == '\0')) + { + break; + } + + // Check if the name is too long + if (len > NAME_LEN) + { + vput(&dir); + return -ENAMETOOLONG; + } + + // Lookup the token + vnode_t *next = NULL; + vlock(dir); + long err = namev_lookup(dir, token, len, &next); + vunlock(dir); + if (err < 0) + { + vput(&dir); + return err; + } + + *res_vnode = dir; + *name = token; + *namelen = len; + + // Reduce refcount and move to the next token + if (next) + { + vput(&dir); + dir = next; + } + } + + // Check if it's a directory + if (!S_ISDIR(dir->vn_mode)) + { + vput(&dir); + return -ENOTDIR; + } + + // Assign the basename + *res_vnode = dir; + *name = token; + *namelen = len; + return 0; } - /* * Open the file specified by `base` and `path`, or create it, if necessary. * Return the file's vnode via `res_vnode`, which should be returned unlocked @@ -217,7 +311,67 @@ long namev_dir(vnode_t *base, const char *path, vnode_t **res_vnode, long namev_open(vnode_t *base, const char *path, int oflags, int mode, devid_t devid, struct vnode **res_vnode) { - NOT_YET_IMPLEMENTED("VFS: namev_open"); + // NOT_YET_IMPLEMENTED("VFS: namev_open"); + + // KASSERT(NULL != base); + KASSERT(NULL != path); + KASSERT(NULL != res_vnode); + + const char *name = NULL; + vnode_t *dir = NULL; + size_t namelen = 0; + + long err = namev_dir(base, path, &dir, &name, &namelen); + if (err < 0) + { + return err; + } + if (namelen > NAME_LEN) + { + vput(&dir); + return -ENAMETOOLONG; + } + + vnode_t *res = NULL; + vlock(dir); + err = namev_lookup(dir, name, namelen, &res); + vunlock(dir); + + if (err < 0) + { + if (!(oflags & O_CREAT)) + { + vput(&dir); + return err; + } + else + { + vlock(dir); + err = dir->vn_ops->mknod(dir, name, namelen, mode, devid, &res); + vunlock(dir); + + vput(&dir); + *res_vnode = res; + return err; + } + } + + if (path[strlen(path) - 1] == '/' && !S_ISDIR(res->vn_mode)) + { + vput(&dir); + vput(&res); + return -ENOTDIR; + } + + if (S_ISDIR(res->vn_mode) && (oflags & O_CREAT)) + { + vput(&dir); + vput(&res); + return -EISDIR; // TODO: check if this error + } + + vput(&dir); + *res_vnode = res; return 0; } diff --git a/kernel/fs/open.c b/kernel/fs/open.c index 8c9fee6..811a9c4 100644 --- a/kernel/fs/open.c +++ b/kernel/fs/open.c @@ -62,6 +62,103 @@ long get_empty_fd(int *fd) */ long do_open(const char *filename, int oflags) { - NOT_YET_IMPLEMENTED("VFS: do_open"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_open"); + + // Check if oflags is valid + if ((oflags & O_WRONLY) && (oflags & O_RDWR)) + { + return -EINVAL; + } + + // Get an empty file descriptor + int fd = -1; + long ret = get_empty_fd(&fd); + if (ret < 0) + { + return ret; + } + + // Check if the file is a directory + if (filename[strlen(filename) - 1] == '/' && (oflags & O_WRONLY)) + { + return -EISDIR; + } + + // Open the file + vnode_t *res_vnode = NULL; + vnode_t *base = curproc->p_cwd; + ret = namev_open(base, filename, oflags, S_IFREG, 0, &res_vnode); + if (ret < 0) + { + if (res_vnode != NULL) + { + vput(&res_vnode); + } + return ret; + } + + // Check if the vnode is a directory + if (S_ISDIR(res_vnode->vn_mode) && ((oflags & O_WRONLY) || (oflags & O_RDWR))) + { + return -EISDIR; + } + + // Check if the vnode is a blockdev or chardev + if (S_ISCHR(res_vnode->vn_mode) && res_vnode->vn_dev.chardev == NULL) + { + vput(&res_vnode); + return -ENXIO; + } + if (S_ISBLK(res_vnode->vn_mode) && res_vnode->vn_dev.blockdev == NULL) + { + vput(&res_vnode); + return -ENXIO; + } + + // Convert oflags to file access flags + int fmode = 0; + if (oflags & O_RDONLY) + { + fmode |= FMODE_READ; + } + + if (oflags & O_WRONLY) + { + fmode |= FMODE_WRITE; + } + else + { + fmode |= FMODE_READ; + } + + if (oflags & O_RDWR) + { + fmode |= FMODE_READ | FMODE_WRITE; + } + + if (oflags & O_APPEND) + { + fmode |= FMODE_APPEND; + } + // Truncate the file if O_TRUNC is specified + if (oflags & O_TRUNC && S_ISREG(res_vnode->vn_mode)) + { + vlock(res_vnode); + res_vnode->vn_ops->truncate_file(res_vnode); + vunlock(res_vnode); + } + + // Create the file descriptor + file_t *file = fcreate(fd, res_vnode, fmode); + if (file == NULL) + { + vput(&res_vnode); + return -ENOMEM; + } + + + // Set the file descriptor + // curproc->p_files[fd] = file; + vput(&res_vnode); + return fd; } diff --git a/kernel/fs/vfs_syscall.c b/kernel/fs/vfs_syscall.c index e05fe5f..ba4aa0c 100644 --- a/kernel/fs/vfs_syscall.c +++ b/kernel/fs/vfs_syscall.c @@ -26,8 +26,58 @@ */ ssize_t do_read(int fd, void *buf, size_t len) { - NOT_YET_IMPLEMENTED("VFS: do_read"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_read"); + + // Check if the file descriptor is valid + if (fd < 0 || fd >= NFILES) + { + return -EBADF; + } + + // fget the file + file_t *file = fget(fd); + if (file == NULL) + { + return -EBADF; + } + + // Check if the file is open for reading + if (!(file->f_mode & FMODE_READ)) + { + fput(&file); + return -EBADF; + } + + // Check if the file is a directory + if (S_ISDIR(file->f_vnode->vn_mode)) + { + fput(&file); + return -EISDIR; + } + + // Check is read is valid + if (file->f_vnode->vn_ops->read == NULL) + { + fput(&file); + return -EISDIR; + } + + // Read the file + vlock(file->f_vnode); + ssize_t bytes_read = file->f_vnode->vn_ops->read(file->f_vnode, file->f_pos, buf, len); + vunlock(file->f_vnode); + + // Check if the read was successful + if (bytes_read < 0) + { + fput(&file); + return bytes_read; + } + + // Update the file position + file->f_pos += bytes_read; + fput(&file); + return bytes_read; } /* @@ -46,8 +96,61 @@ ssize_t do_read(int fd, void *buf, size_t len) */ ssize_t do_write(int fd, const void *buf, size_t len) { - NOT_YET_IMPLEMENTED("VFS: do_write"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_write"); + + // Check if the file descriptor is valid + if (fd < 0 || fd >= NFILES) + { + return -EBADF; + } + + // dbg(DBG_PRINT, "VFS: do_write: fd = %d, len = %ld\n", fd, len); + + // fget the file + file_t *file = fget(fd); + if (file == NULL) + { + return -EBADF; + } + + // Check if the file is open for writing + if (!(file->f_mode & FMODE_WRITE)) + { + fput(&file); + return -EBADF; + } + + // Check is write is valid + if (file->f_vnode->vn_ops->write == NULL) + { + fput(&file); + return -EISDIR; + } + + // Move the file position to the end of the file if the file is open in append mode + if (file->f_mode & FMODE_APPEND) + { + vlock(file->f_vnode); + file->f_pos = file->f_vnode->vn_len; + vunlock(file->f_vnode); + } + + // Write the file + vlock(file->f_vnode); + ssize_t bytes_written = file->f_vnode->vn_ops->write(file->f_vnode, file->f_pos, buf, len); + vunlock(file->f_vnode); + + // Check if the write was successful + if (bytes_written < 0) + { + // fput(&file); + dbg(DBG_PRINT, "VFS: do_write: write failed\n"); + return bytes_written; + } + + file->f_pos += bytes_written; + fput(&file); + return bytes_written; } /* @@ -63,8 +166,26 @@ ssize_t do_write(int fd, const void *buf, size_t len) */ long do_close(int fd) { - NOT_YET_IMPLEMENTED("VFS: do_close"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_close"); + + // Check if the file descriptor is valid + if (fd < 0 || fd >= NFILES) + { + return -EBADF; + } + + // fget the file + file_t *file = fget(fd); + if (file == NULL) + { + return -EBADF; + } + + // Close the file + curproc->p_files[fd] = NULL; + fput(&file); + + return 0; } /* @@ -78,8 +199,32 @@ long do_close(int fd) */ long do_dup(int fd) { - NOT_YET_IMPLEMENTED("VFS: do_dup"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_dup"); + + // Check if the file descriptor is valid + if (fd < 0 || fd >= NFILES) + { + return -EBADF; + } + + // fget the file + file_t *file = fget(fd); + if (file == NULL) + { + return -EBADF; + } + + // Get an empty file descriptor + int new_fd = -1; + long ret = get_empty_fd(&new_fd); + if (ret < 0) + { + return ret; + } + + // Copy the file + curproc->p_files[new_fd] = file; + return new_fd; } /* @@ -94,8 +239,39 @@ long do_dup(int fd) */ long do_dup2(int ofd, int nfd) { - NOT_YET_IMPLEMENTED("VFS: do_dup2"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_dup2"); + + // Check if the file descriptors are valid + if (ofd < 0 || ofd >= NFILES || nfd < 0 || nfd >= NFILES) + { + return -EBADF; + } + // Check if the file descriptors are the same + if (!curproc->p_files[ofd]) + { + return -EBADF; + } + if (ofd == nfd) + { + return nfd; + } + + // fget the file + file_t *file = fget(ofd); + if (file == NULL) + { + return -EBADF; + } + // figet the new file + file_t *new_file = fget(nfd); + if (new_file != NULL) + { + do_close(nfd); + } + + // Copy the file + curproc->p_files[nfd] = file; + return nfd; } /* @@ -117,8 +293,19 @@ long do_dup2(int ofd, int nfd) */ long do_mknod(const char *path, int mode, devid_t devid) { - NOT_YET_IMPLEMENTED("VFS: do_mknod"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_mknod"); + + // Check if the mode is valid + if (mode != S_IFCHR && mode != S_IFBLK && mode != S_IFREG) + { + return -EINVAL; + } + + // get vnode + vnode_t *vnode = NULL; + vnode_t *base = curproc->p_cwd; + long ret = namev_open(base, path, O_CREAT, mode, devid, &vnode); + return ret; } /* @@ -143,8 +330,47 @@ long do_mknod(const char *path, int mode, devid_t devid) */ long do_mkdir(const char *path) { - NOT_YET_IMPLEMENTED("VFS: do_mkdir"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_mkdir"); + + // Call namev_dir() to find the parent of the directory to be created + size_t len = 0; + const char *name = NULL; + vnode_t *dir = NULL; + long ret = namev_dir(curproc->p_cwd, path, &dir, &name, &len); + dbg(DBG_TEST, "VFS: do_mkdir: namev_dir returned %ld\n", ret); + + if (ret < 0) + { + return ret; + } + if (!S_ISDIR(dir->vn_mode)) + { + vput(&dir); + return -ENOTDIR; + } + if (len > NAME_LEN) + { + vput(&dir); + return -ENAMETOOLONG; + } + + vnode_t *base = NULL; + vlock(dir); + ret = namev_lookup(dir, name, len, &base); + vunlock(dir); + // Check if the directory already exists + if (ret >= 0) + { + vput(&base); + vput(&dir); + return -EEXIST; + } + + // Create the directory + ret = dir->vn_ops->mkdir(dir, name, len, &base); + // vput(&base); + vput(&dir); + return ret; } /* @@ -165,8 +391,75 @@ long do_mkdir(const char *path) */ long do_rmdir(const char *path) { - NOT_YET_IMPLEMENTED("VFS: do_rmdir"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_rmdir"); + + // Call namev_dir() to find the parent of the directory to be removed + size_t len = 0; + const char *name = NULL; + vnode_t *dir = NULL; + long ret = namev_dir(curproc->p_cwd, path, &dir, &name, &len); + + // Check if the directory is valid + if (ret < 0) + { + return ret; + } + + // Check if the directory is a directory + if (!S_ISDIR(dir->vn_mode)) + { + vput(&dir); + return -ENOTDIR; + } + + // Check if name is too long + if (len > NAME_LEN) + { + vput(&dir); + return -ENAMETOOLONG; + } + + // Check if the directory is empty + if (len == 1 && name[0] == '.') + { + vput(&dir); + return -EINVAL; + } + if (len == 2 && name[0] == '.' && name[1] == '.') + { + vput(&dir); + return -ENOTEMPTY; + } + + // Remove the directory + vnode_t *base = NULL; + vlock(dir); + ret = namev_lookup(dir, name, len, &base); + vunlock(dir); + + // Check if the directory exists + if (ret < 0) + { + vput(&dir); + return ret; + } + + // Check if the directory is a directory + if (!S_ISDIR(base->vn_mode)) + { + vput(&base); + vput(&dir); + return -ENOTDIR; + } + + // Remove the directory + vlock(dir); + ret = dir->vn_ops->rmdir(dir, name, len); + vunlock(dir); + vput(&base); + vput(&dir); + + return ret; } /* @@ -183,8 +476,63 @@ long do_rmdir(const char *path) */ long do_unlink(const char *path) { - NOT_YET_IMPLEMENTED("VFS: do_unlink"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_unlink"); + + // Call namev_dir() to find the parent of the file to be unlinked + size_t len = 0; + const char *name = NULL; + vnode_t *dir = NULL; + long ret = namev_dir(curproc->p_cwd, path, &dir, &name, &len); + + // Check if the directory is valid + if (ret < 0) + { + return ret; + } + + // Check if the directory is a directory + if (!S_ISDIR(dir->vn_mode)) + { + vput(&dir); + return -ENOTDIR; + } + + // Check if name is too long + if (len > NAME_LEN) + { + vput(&dir); + return -ENAMETOOLONG; + } + + // Remove the link + vnode_t *base = NULL; + vlock(dir); + ret = namev_lookup(dir, name, len, &base); + vunlock(dir); + + // Check if the file exists + if (ret < 0) + { + vput(&dir); + return ret; + } + // Check if the file is a directory + if (S_ISDIR(base->vn_mode)) + { + vput(&base); + vput(&dir); + return -EPERM; + } + + // Call the unlink operation + vlock(dir); + ret = dir->vn_ops->unlink(dir, name, len); + vunlock(dir); + + vput(&base); + vput(&dir); + + return ret; } /* @@ -206,8 +554,58 @@ long do_unlink(const char *path) */ long do_link(const char *oldpath, const char *newpath) { - NOT_YET_IMPLEMENTED("VFS: do_link"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_link"); + + // Resolve the oldpath + vnode_t *old_vnode = NULL; + + long ret = namev_resolve(NULL, oldpath, &old_vnode); + // Check if the oldpath is valid + if (ret < 0) + { + return ret; + } + // Check if the oldpath is a directory + if (S_ISDIR(old_vnode->vn_mode)) + { + vput(&old_vnode); + return -EPERM; + } + + // Get the directory of the newpath + size_t len = 0; + const char *name = NULL; + vnode_t *dir = NULL; + ret = namev_dir(curproc->p_cwd, newpath, &dir, &name, &len); + // Check if the directory is valid + if (ret < 0) + { + vput(&old_vnode); + return ret; + } + // Check if the directory is a directory + if (!S_ISDIR(dir->vn_mode)) + { + vput(&old_vnode); + vput(&dir); + return -ENOTDIR; + } + // Check if name is too long + if (len > NAME_LEN) + { + vput(&old_vnode); + vput(&dir); + return -ENAMETOOLONG; + } + + // Lock the vnodes and call link + vlock_in_order(old_vnode, dir); + ret = dir->vn_ops->link(old_vnode, dir, name, len); + vunlock_in_order(old_vnode, dir); + + vput(&old_vnode); + vput(&dir); + return ret; } /* Rename a file or directory. @@ -231,7 +629,7 @@ long do_link(const char *oldpath, const char *newpath) * projects this is harder and you will get no extra credit (but you * will get our admiration). Please make sure the normal version works first. * Steps: - * 1. namev_dir oldpath --> olddir vnode + * 1. oldpath --> olddir vnode * 2. namev_dir newpath --> newdir vnode * 3. Lock the global filesystem `vnode_rename_mutex` * 4. Lock the olddir and newdir in ancestor-first order (see `vlock_in_order`) @@ -244,8 +642,60 @@ long do_link(const char *oldpath, const char *newpath) */ long do_rename(const char *oldpath, const char *newpath) { - NOT_YET_IMPLEMENTED("VFS: do_rename"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_rename"); + + // Get the old directory + size_t old_len = 0; + const char *old_name = NULL; + vnode_t *old_dir = NULL; + long ret = namev_dir(curproc->p_cwd, oldpath, &old_dir, &old_name, &old_len); + // Check if the old directory is valid + if (ret < 0) + { + return ret; + } + // Check if the old directory is a directory + if (!S_ISDIR(old_dir->vn_mode)) + { + vput(&old_dir); + return -ENOTDIR; + } + + // Get the new directory + size_t new_len = 0; + const char *new_name = NULL; + vnode_t *new_dir = NULL; + ret = namev_dir(curproc->p_cwd, newpath, &new_dir, &new_name, &new_len); + // Check if the new directory is valid + if (ret < 0) + { + vput(&old_dir); + return ret; + } + // Check if the new directory is a directory + if (!S_ISDIR(new_dir->vn_mode)) + { + vput(&old_dir); + vput(&new_dir); + return -ENOTDIR; + } + + // Check if the names are too long + if (old_len > NAME_LEN || new_len > NAME_LEN) + { + vput(&old_dir); + vput(&new_dir); + return -ENAMETOOLONG; + } + + // Lock the vnodes and call rename + vlock_in_order(old_dir, new_dir); + ret = old_dir->vn_ops->rename(old_dir, old_name, old_len, new_dir, new_name, new_len); + vunlock_in_order(old_dir, new_dir); + + vput(&old_dir); + vput(&new_dir); + return ret; } /* Set the current working directory to the directory represented by path. @@ -262,8 +712,27 @@ long do_rename(const char *oldpath, const char *newpath) */ long do_chdir(const char *path) { - NOT_YET_IMPLEMENTED("VFS: do_chdir"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_chdir"); + + // Resolve the path + vnode_t *vnode = NULL; + long ret = namev_resolve(NULL, path, &vnode); + // Check if the path is valid + if (ret < 0) + { + return ret; + } + // Check if the path is a directory + if (!S_ISDIR(vnode->vn_mode)) + { + vput(&vnode); + return -ENOTDIR; + } + + // Set the current working directory + vput(&curproc->p_cwd); + curproc->p_cwd = vnode; + return 0; } /* @@ -282,8 +751,43 @@ long do_chdir(const char *path) */ ssize_t do_getdent(int fd, struct dirent *dirp) { - NOT_YET_IMPLEMENTED("VFS: do_getdent"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_getdent"); + + // Check if the file descriptor is valid + if (fd < 0 || fd >= NFILES) + { + return -EBADF; + } + + // fget the file + file_t *file = fget(fd); + if (file == NULL) + { + return -EBADF; + } + + // Check if the file is a directory + if (!S_ISDIR(file->f_vnode->vn_mode)) + { + fput(&file); + return -ENOTDIR; + } + + // Read the directory entry + vlock(file->f_vnode); + ssize_t bytes_read = file->f_vnode->vn_ops->readdir(file->f_vnode, file->f_pos, dirp); + vunlock(file->f_vnode); + // Check if the read was successful + if (bytes_read <= 0) + { + fput(&file); + return bytes_read; + } + + // Update the file position + file->f_pos += bytes_read; + fput(&file); + return sizeof(dirent_t); } /* @@ -301,8 +805,51 @@ ssize_t do_getdent(int fd, struct dirent *dirp) */ off_t do_lseek(int fd, off_t offset, int whence) { - NOT_YET_IMPLEMENTED("VFS: do_lseek"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_lseek"); + + // Check if the file descriptor is valid + if (fd < 0 || fd >= NFILES) + { + return -EBADF; + } + + // fget the file + file_t *file = fget(fd); + if (file == NULL) + { + return -EBADF; + } + + // Check if the whence is valid + off_t new_pos = 0; + switch (whence) + { + case SEEK_SET: + new_pos = offset; + break; + case SEEK_CUR: + new_pos = file->f_pos + offset; + break; + case SEEK_END: + new_pos = file->f_vnode->vn_len + offset; + break; + default: + fput(&file); + return -EINVAL; + } + + // Check if the new position is negative + if (new_pos < 0) + { + fput(&file); + return -EINVAL; + } + + // Update the file position + file->f_pos = new_pos; + off_t pos = file->f_pos; + fput(&file); + return pos; } /* Use buf to return the status of the file represented by path. @@ -312,8 +859,25 @@ off_t do_lseek(int fd, off_t offset, int whence) */ long do_stat(const char *path, stat_t *buf) { - NOT_YET_IMPLEMENTED("VFS: do_stat"); - return -1; + // NOT_YET_IMPLEMENTED("VFS: do_stat"); + + // Resolve the path + vnode_t *vnode = NULL; + long ret = namev_resolve(NULL, path, &vnode); + + // Check if the path is valid + if (ret < 0) + { + return ret; + } + + // Get the status of the file + vlock(vnode); + ret = vnode->vn_ops->stat(vnode, buf); + vunlock(vnode); + vput(&vnode); + + return ret; } #ifdef __MOUNTING__ diff --git a/kernel/fs/vnode_specials.c b/kernel/fs/vnode_specials.c index cd21549..3e55830 100644 --- a/kernel/fs/vnode_specials.c +++ b/kernel/fs/vnode_specials.c @@ -110,7 +110,21 @@ static long special_file_stat(vnode_t *file, stat_t *ss) static ssize_t chardev_file_read(vnode_t *file, size_t pos, void *buf, size_t count) { - NOT_YET_IMPLEMENTED("VFS: chardev_file_read"); + // NOT_YET_IMPLEMENTED("VFS: chardev_file_read"); + + // check if the vnode represetns a chardev + if (file->vn_dev.chardev == NULL) + { + return -ENXIO; + } + + // Unlock the file and call read + vunlock(file); + ssize_t ret = file->vn_dev.chardev->cd_ops->read(file->vn_dev.chardev, pos, buf, count); + vlock(file); + + return ret; + return 0; } @@ -125,8 +139,20 @@ static ssize_t chardev_file_read(vnode_t *file, size_t pos, void *buf, static long chardev_file_write(vnode_t *file, size_t pos, const void *buf, size_t count) { - NOT_YET_IMPLEMENTED("VFS: chardev_file_write"); - return 0; + // NOT_YET_IMPLEMENTED("VFS: chardev_file_write"); + + // check if the vnode represents a chardev + if (file->vn_dev.chardev == NULL) + { + return -ENXIO; + } + + // Unlock the file and call write + vunlock(file); + long ret = file->vn_dev.chardev->cd_ops->write(file->vn_dev.chardev, pos, buf, count); + vlock(file); + + return ret; } /* diff --git a/kernel/main/kmain.c b/kernel/main/kmain.c index 4cec7bd..4c49b9a 100644 --- a/kernel/main/kmain.c +++ b/kernel/main/kmain.c @@ -171,7 +171,7 @@ static void *initproc_run(long arg1, void *arg2) // dbg(DBG_PROC, "%s", "In main thread!\n"); #ifdef __DRIVERS__ - driverstest_main(0, NULL); + // driverstest_main(0, NULL); char name[32] = {0}; for (long i = 0; i < __NTERMS__; i++) { diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 7ce42dc..1e38ca8 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -218,6 +218,23 @@ proc_t *proc_create(const char *name) list_insert_tail(&proc_list, &proc->p_list_link); dbg(DBG_PROC, "SUCESSFULLY created PROCESS name=%s & pid =%d\n", name, proc_pid); +#ifdef __VFS__ + // clone and ref the files from curproc + for (int fd = 0; fd < NFILES; fd++) + { + proc->p_files[fd] = NULL; + } + if (proc->p_pid != PID_INIT) + { + proc->p_cwd = proc->p_pproc->p_cwd; + vref(proc->p_cwd); + } + else + { + proc->p_cwd = NULL; + } +#endif + return proc; } @@ -272,6 +289,20 @@ void proc_cleanup(long status) // } else { curproc->p_status = status; // } + +#ifdef __VFS__ + for (int fd = 0; fd < NFILES; fd++) + { + if (curproc->p_files[fd]) + { + fput(curproc->p_files + fd); + } + } + if (curproc->p_cwd) + { + vput(&curproc->p_cwd); + } +#endif } /* @@ -365,7 +396,9 @@ void proc_destroy(proc_t *proc) for (int fd = 0; fd < NFILES; fd++) { if (proc->p_files[fd]) + { fput(proc->p_files + fd); + } } if (proc->p_cwd) { |