summaryrefslogtreecommitdiff
path: root/kernel/src/generic/vfs.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/generic/vfs.hpp')
-rw-r--r--kernel/src/generic/vfs.hpp423
1 files changed, 417 insertions, 6 deletions
diff --git a/kernel/src/generic/vfs.hpp b/kernel/src/generic/vfs.hpp
index d6fac32..ecfd25b 100644
--- a/kernel/src/generic/vfs.hpp
+++ b/kernel/src/generic/vfs.hpp
@@ -3,6 +3,144 @@
#include <drivers/disk.hpp>
#include <generic/lock/mutex.hpp>
#include <utils/linux.hpp>
+#include <utils/assert.hpp>
+#include <generic/scheduling.hpp>
+
+#define USERSPACE_PIPE_SIZE (64 * 1024)
+#define S_IFSOCK 0140000
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFBLK 0060000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+#define CS8 0000060
+#define ECHO 0000010 /* Enable echo. */
+#define IGNBRK 0000001 /* Ignore break condition. */
+#define BRKINT 0000002 /* Signal interrupt on break. */
+#define IGNPAR 0000004 /* Ignore characters with parity errors. */
+#define PARMRK 0000010 /* Mark parity and framing errors. */
+#define INPCK 0000020 /* Enable input parity check. */
+#define ISTRIP 0000040 /* Strip 8th bit off characters. */
+#define INLCR 0000100 /* Map NL to CR on input. */
+#define IGNCR 0000200 /* Ignore CR. */
+#define ICRNL 0000400 /* Map CR to NL on input. */
+#define OPOST 0000001 /* Post-process output. */
+
+#define ICANON 0000002
+#define VMIN 6
+
+#define S_IRWXU 0700
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define S_IXUSR 0100
+#define S_IRWXG 070
+#define S_IRGRP 040
+#define S_IWGRP 020
+#define S_IXGRP 010
+#define S_IRWXO 07
+#define S_IROTH 04
+#define S_IWOTH 02
+#define S_IXOTH 01
+#define S_ISUID 04000
+#define S_ISGID 02000
+#define S_ISVTX 01000
+
+/* open/fcntl. */
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#ifndef O_CREAT
+# define O_CREAT 0100 /* Not fcntl. */
+#endif
+#ifndef O_EXCL
+# define O_EXCL 0200 /* Not fcntl. */
+#endif
+#ifndef O_NOCTTY
+# define O_NOCTTY 0400 /* Not fcntl. */
+#endif
+#ifndef O_TRUNC
+# define O_TRUNC 01000 /* Not fcntl. */
+#endif
+#ifndef O_APPEND
+# define O_APPEND 02000
+#endif
+#ifndef O_NONBLOCK
+# define O_NONBLOCK 04000
+#endif
+#ifndef O_NDELAY
+# define O_NDELAY O_NONBLOCK
+#endif
+#ifndef O_SYNC
+# define O_SYNC 04010000
+#endif
+#define O_FSYNC O_SYNC
+#ifndef O_ASYNC
+# define O_ASYNC 020000
+#endif
+#ifndef __O_LARGEFILE
+# define __O_LARGEFILE 0100000
+#endif
+
+#ifndef __O_DIRECTORY
+# define __O_DIRECTORY 0200000
+#endif
+#ifndef __O_NOFOLLOW
+# define __O_NOFOLLOW 0400000
+#endif
+#ifndef __O_CLOEXEC
+# define __O_CLOEXEC 02000000
+#endif
+#ifndef __O_DIRECT
+# define __O_DIRECT 040000
+#endif
+#ifndef __O_NOATIME
+# define __O_NOATIME 01000000
+#endif
+#ifndef __O_PATH
+# define __O_PATH 010000000
+#endif
+#ifndef __O_DSYNC
+# define __O_DSYNC 010000
+#endif
+#ifndef __O_TMPFILE
+# define __O_TMPFILE (020000000 | __O_DIRECTORY)
+#endif
+
+inline static std::uint32_t s_to_dt_type(std::uint32_t s_type) {
+ switch (s_type)
+ {
+ case S_IFSOCK:
+ return DT_SOCK;
+ case S_IFREG:
+ return DT_REG;
+ case S_IFBLK:
+ return DT_BLK;
+ case S_IFIFO:
+ return DT_FIFO;
+ case S_IFDIR:
+ return DT_DIR;
+ case S_IFCHR:
+ return DT_CHR;
+ case S_IFLNK:
+ return DT_LNK;
+ default:
+ assert(0,"shitfuck");
+ return 0;
+ }
+ return 0;
+}
enum class file_descriptor_type : std::uint8_t {
unallocated = 0,
@@ -13,6 +151,15 @@ enum class file_descriptor_type : std::uint8_t {
memfd = 5
};
+struct dirent {
+ std::uint64_t d_ino;
+ std::int64_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[];
+};
+
+
struct stat {
dev_t st_dev;
ino_t st_ino;
@@ -34,6 +181,32 @@ struct stat {
#define st_ctime st_ctim.tv_sec
};
+enum class vfs_file_type : std::uint8_t {
+ file = 1,
+ directory = 2,
+ symlink = 3
+};
+
+enum class vfs_poll_type : std::uint8_t {
+ pollin = 1,
+ pollout = 2
+};
+
+inline static std::uint32_t vfs_to_dt_type(vfs_file_type type) {
+ switch(type) {
+ case vfs_file_type::directory:
+ return DT_DIR;
+ case vfs_file_type::file:
+ return DT_REG;
+ case vfs_file_type::symlink:
+ return DT_LNK;
+ default:
+ assert(0,"fsaifsi");
+ return 0; //
+ }
+ return 0;
+}
+
struct filesystem {
locks::mutex lock;
@@ -41,8 +214,11 @@ struct filesystem {
std::uint64_t partition;
} fs_specific;
- std::uint32_t (*open)(filesystem* fs, void* file_desc, char* path);
-
+ std::int32_t (*remove)(filesystem* fs, char* path);
+ std::int32_t (*open)(filesystem* fs, void* file_desc, char* path, bool is_directory);
+ std::int32_t (*readlink)(filesystem* fs, char* path, char* buffer);
+ std::int32_t (*create)(filesystem* fs, char* path, vfs_file_type type, std::uint32_t mode);
+
char path[2048];
};
@@ -59,27 +235,262 @@ struct file_descriptor {
} fs_specific;
struct {
+ int cycle;
+ int queue;
+ } other;
+
+ struct {
disk* target_disk;
filesystem* fs;
- signed long (*read)(file_descriptor* file, void* buffer, signed long count);
- signed long (*write)(file_descriptor* file, void* buffer, signed long count);
+ std::int32_t (*ioctl)(file_descriptor* file, std::uint64_t req, void* arg);
+ signed long (*read)(file_descriptor* file, void* buffer, std::size_t count);
+ signed long (*write)(file_descriptor* file, void* buffer, std::size_t count);
std::int32_t (*stat)(file_descriptor* file, stat* out);
void (*close)(file_descriptor* file);
+
+ signed long (*ls)(file_descriptor* file, char* out, std::size_t count);
+ bool (*poll)(file_descriptor* file, vfs_poll_type type);
+
} vnode;
};
namespace vfs {
+ struct node {
+ filesystem* fs;
+ char path[2048];
+ };
+
void init();
- std::int32_t open(file_descriptor* fd, char* path, bool follow_symlinks);
- std::int32_t create(char* path, std::uint32_t mode); // mode contains type too
+ std::int32_t open(file_descriptor* fd, char* path, bool follow_symlinks, bool is_directory);
+ std::int32_t create(char* path, vfs_file_type type, std::uint32_t mode);
std::int32_t readlink(char* path, char* out, std::uint32_t out_len);
+ std::int32_t remove(char* path);
}
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 19
+
+typedef struct {
+ tcflag_t c_iflag;
+ tcflag_t c_oflag;
+ tcflag_t c_cflag;
+ tcflag_t c_lflag;
+ cc_t c_line;
+ cc_t c_cc[NCCS];
+ speed_t ibaud;
+ speed_t obaud;
+} __attribute__((packed)) termios_t;
+
+typedef struct {
+ tcflag_t c_iflag;
+ tcflag_t c_oflag;
+ tcflag_t c_cflag;
+ tcflag_t c_lflag;
+ cc_t c_line;
+ cc_t c_cc[NCCS];
+} __attribute__((packed)) termiosold_t;
+
+#define PIPE_SIDE_WRITE 1
+#define PIPE_SIDE_READ 2
+
// took from old kernel
namespace vfs {
+
+ class pipe {
+ private:
+
+ std::uint64_t read_ptr = 0;
+
+ std::atomic_flag is_received = ATOMIC_FLAG_INIT;
+ std::atomic_flag is_n_closed = ATOMIC_FLAG_INIT;
+
+
+ int is_was_writed_ever = 0;
+
+ public:
+
+ char* buffer;
+
+ locks::preempt_spinlock lock;
+
+ std::atomic_flag is_closed = ATOMIC_FLAG_INIT;
+
+ std::uint64_t total_size = 0;
+ std::atomic<std::int64_t> size = 0;
+ std::int64_t write_counter = 0;
+ std::int64_t read_counter = 0;
+
+ std::uint32_t connected_to_pipe = 0;
+ std::uint32_t connected_to_pipe_write = 0;
+ std::uint64_t flags = 0;
+
+ std::uint32_t zero_message_count = 0;
+
+ int is_closed_socket = 0;
+
+ void* fd_pass = 0;
+ pipe(std::uint64_t flags) {
+ this->buffer = (char*)(pmm::buddy::alloc(USERSPACE_PIPE_SIZE).phys + etc::hhdm());
+ this->total_size = USERSPACE_PIPE_SIZE;
+ this->size = 0;
+ this->connected_to_pipe = 2; /* syscall which creates pipe should create 2 fds too */
+ this->connected_to_pipe_write = 1;
+ this->flags = flags;
+
+ this->is_closed.clear(std::memory_order_release);
+
+ }
+
+ void close(std::uint8_t side) {
+ bool state = this->lock.lock();
+ this->connected_to_pipe--;
+
+ if(side == PIPE_SIDE_WRITE) {
+ this->connected_to_pipe_write--;
+ if(this->connected_to_pipe_write == 0) {
+ this->is_received.clear();
+ this->is_closed.test_and_set(std::memory_order_acquire);
+ }
+ }
+
+ this->lock.unlock(state);
+
+ if(this->connected_to_pipe == 0) {
+ delete this;
+ }
+ }
+
+ void create(std::uint8_t side) {
+ bool state = this->lock.lock();
+ this->connected_to_pipe++;
+ if(side == PIPE_SIDE_WRITE)
+ this->connected_to_pipe_write++;
+ this->lock.unlock(state);
+ }
+
+ std::uint64_t force_write(const char* src_buffer, std::uint64_t count) {
+ if (this->size + count > this->total_size) {
+ count = this->total_size - this->size;
+ }
+ this->size += count;
+ klibc::memcpy(this->buffer + (this->size - count), src_buffer, count);
+ return count;
+ }
+
+ std::uint64_t write(const char* src_buffer, std::uint64_t count,int id) {
+
+ std::uint64_t written = 0;
+
+ while (written < count) {
+ bool state = this->lock.lock();
+
+ std::uint64_t space_left = this->total_size - this->size;
+ if (space_left == 0) {
+ this->lock.unlock(state);
+ process::yield();
+ continue;
+ }
+
+ uint64_t old_size = this->size;
+
+ std::uint64_t to_write = (count - written) < space_left ? (count - written) : space_left;
+ if(to_write < 0)
+ to_write = 0;
+
+
+ force_write(src_buffer + written, to_write);
+
+ written += to_write;
+
+ this->lock.unlock(state);
+ }
+ return written;
+ }
+
+ std::uint64_t nolock_write(const char* src_buffer, std::uint64_t count,int id) {
+
+ std::uint64_t written = 0;
+
+ if(count == 0) {
+ this->zero_message_count = 1;
+ return 0;
+ }
+
+ while (written < count) {
+
+ std::uint64_t space_left = this->total_size - this->size;
+
+ uint64_t old_size = this->size;
+
+ std::uint64_t to_write = (count - written) < space_left ? (count - written) : space_left;
+ if(to_write < 0)
+ to_write = 0;
+
+
+ force_write(src_buffer + written, to_write);
+
+ written += to_write;
+ this->read_counter++;
+
+ }
+ return written;
+ }
+
+ std::int64_t read(std::int64_t* read_count, char* dest_buffer, std::uint64_t count, int is_block) {
+
+ std::uint64_t read_bytes = 0;
+ int tries = 0;
+
+ while (true) {
+ bool state = this->lock.lock();
+
+ if (this->size == 0) {
+
+ if (this->is_closed.test(std::memory_order_acquire)) {
+ this->lock.unlock(state);
+ return 0;
+ }
+
+ if(this->is_closed_socket) {
+ this->lock.unlock(state);
+ return 0;
+ }
+
+ if (flags & O_NONBLOCK || is_block) {
+ this->lock.unlock(state);
+ return -11;
+ }
+ this->lock.unlock(state);
+ process::yield();
+ continue;
+ }
+
+ read_bytes = (count < (std::uint64_t)this->size) ? count : (std::uint64_t)this->size;
+ klibc::memcpy(dest_buffer, this->buffer, read_bytes);
+ klibc::memmove(this->buffer, this->buffer + read_bytes, this->size - read_bytes);
+ this->size -= read_bytes;
+
+ this->lock.unlock(state);
+ break;
+ }
+ return read_bytes;
+ }
+
+
+
+ ~pipe() {
+ pmm::buddy::free((std::uint64_t)this->buffer - etc::hhdm());
+ }
+
+ };
+
+
static inline std::uint64_t resolve_count(char* str,std::uint64_t sptr,char delim) {
char* current = str;
std::uint16_t att = 0;