BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 2d05318728e0aa3fca502a2aeb1738773fffc98b / vfs / files.c

// Related

Nucleus

Barry Directory listing in VFS 2d05318 (3 years, 2 months ago)
diff --git a/vfs/files.c b/vfs/files.c
index b830e40..c285e51 100644
--- a/vfs/files.c
+++ b/vfs/files.c
@@ -86,6 +86,33 @@ install_fd(int fd, File *file)
 	current->files->fd[fd] = file;
 }
 
+/* Duplicate a file descriptor */
+int
+dup(int oldfd)
+{
+	int newfd = allocate_fd();
+	if (newfd == -1)
+		return -EMFILE;
+	return dup2(oldfd, newfd);
+}
+
+/* Duplicate a file descriptor to a new file descriptor */
+int
+dup2(int oldfd, int newfd)
+{
+	/* Check file descriptors */
+	File *oldfile = get_file_by_fd(oldfd);
+	File *newfile = get_file_by_fd(newfd);
+	if (!oldfile || newfd < 0 || newfd >= NFILES)
+		return -EBADF;
+	if (newfd != oldfd) {
+		if (newfile)
+			close(newfd);
+		install_fd(newfd, get(oldfile));
+	}
+	return newfd;
+}
+
 /* Close a file */
 int
 close(int fd)
@@ -113,10 +140,7 @@ read(int fd, void *buf, size_t count)
 	if (file->inode && S_ISDIR(file->inode->mode))
 		return -EISDIR;
 
-	lock(file);
-	int sz = file_read(file, buf, count);
-	unlock(file);
-	return sz;
+	return file_read(file, buf, count);
 }
 
 /* Write a file */
@@ -135,10 +159,7 @@ write(int fd, void *buf, size_t count)
 	if (file->inode && S_ISDIR(file->inode->mode))
 		return -EISDIR;
 
-	lock(file);
-	int sz = file_write(file, buf, count);
-	unlock(file);
-	return sz;
+	return file_write(file, buf, count);
 }
 
 /* Move a file's position */
@@ -181,8 +202,39 @@ ioctl(int fd, unsigned long request, ...)
 	uintptr_t argp = va_arg(args, uintptr_t);
 	va_end(args);
 
-	lock(file);
-	int ret = file_ioctl(file, request, argp);
-	unlock(file);
-	return ret;
+	return file_ioctl(file, request, argp);
+}
+
+/* Get directory entries */
+size_t
+getdents(int fd, void *buf, size_t count)
+{
+	if (!verify_access(buf, count, PROT_WRITE))
+		return -EFAULT;
+	if (count < sizeof(struct dirent))
+		return -EINVAL;
+
+	int err;
+	size_t i, size = 0;
+	struct dirent *dent = buf;
+	File *file = get_file_by_fd(fd);
+	if (!file)
+		return -EBADF;
+	if (!S_ISDIR(file->inode->mode))
+		return -ENOTDIR;
+
+	/* Read as many entries as possible */
+	for (i = 0; i < count / sizeof(struct dirent); i++) {
+		err = file_readdir(file, dent, i);
+		if (err < 0)
+			goto out;
+		size += sizeof(struct dirent) + dent->d_namelen;
+		*((char *) buf + size - 1) = '\0';
+		dent = (void *) ((char *) buf + size);
+	}
+
+out:
+	if (!i)
+		return err;
+	return size;
 }