diff options
Diffstat (limited to 'kernel/src/generic/vfs.hpp')
| -rw-r--r-- | kernel/src/generic/vfs.hpp | 423 |
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; |
