summaryrefslogtreecommitdiff
path: root/kernel/src/arch/x86_64/syscalls/file.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/arch/x86_64/syscalls/file.cpp')
-rw-r--r--kernel/src/arch/x86_64/syscalls/file.cpp244
1 files changed, 206 insertions, 38 deletions
diff --git a/kernel/src/arch/x86_64/syscalls/file.cpp b/kernel/src/arch/x86_64/syscalls/file.cpp
index 0c15f68..954ad9b 100644
--- a/kernel/src/arch/x86_64/syscalls/file.cpp
+++ b/kernel/src/arch/x86_64/syscalls/file.cpp
@@ -2,6 +2,8 @@
#include <arch/x86_64/syscalls/syscalls.hpp>
#include <generic/vfs/vfs.hpp>
+#include <generic/mm/vmm.hpp>
+
#include <arch/x86_64/cpu/data.hpp>
#include <arch/x86_64/scheduling.hpp>
@@ -43,6 +45,8 @@ syscall_ret_t sys_openat(int dirfd, const char* path, int flags, int_frame_t* ct
memset(result,0,2048);
vfs::resolve_path(kpath,first_path,result,1,0);
+ //DEBUG(proc->is_debug,"Trying to open %s from proc %d",result,proc->id);
+
if(result[0] == '\0') {
result[0] = '/';
result[1] = '\0';
@@ -84,11 +88,11 @@ syscall_ret_t sys_openat(int dirfd, const char* path, int flags, int_frame_t* ct
if(status != 0)
new_fd_s->state = USERSPACE_FD_STATE_UNUSED;
-
- new_fd_s->offset = 0;
if(status != 0)
- Log::SerialDisplay(LEVEL_MESSAGE_WARN,"failed to open %s\n",result);
+ DEBUG(proc->is_debug,"Failed to open %s from proc %d",result,proc->id);
+
+ new_fd_s->offset = 0;
return {1,status,status == 0 ? new_fd : -1};
}
@@ -102,37 +106,36 @@ syscall_ret_t sys_read(int fd, void *buf, size_t count) {
if(!fd_s)
return {1,EBADF,0};
- char* temp_buffer = (char*)memory::pmm::_virtual::alloc(count + 1);
- memory::paging::maprangeid(proc->original_cr3,Other::toPhys(temp_buffer),(std::uint64_t)temp_buffer,count,PTE_PRESENT | PTE_RW,proc->id);
+ vmm_obj_t* vmm_object = memory::vmm::getlen(proc,(std::uint64_t)buf);
+ uint64_t need_phys = vmm_object->phys + ((std::uint64_t)buf - vmm_object->base);
+
+ char* temp_buffer = (char*)Other::toVirt(need_phys);
+ memset(temp_buffer,0,count);
std::int64_t bytes_read;
if(fd_s->state == USERSPACE_FD_STATE_FILE)
bytes_read = vfs::vfs::read(fd_s,temp_buffer,count);
else if(fd_s->state == USERSPACE_FD_STATE_PIPE && fd_s->pipe) {
- SYSCALL_ENABLE_PREEMPT();
bytes_read = fd_s->pipe->read(temp_buffer,count);
- SYSCALL_DISABLE_PREEMPT();
} else if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
if(!fd_s->write_socket_pipe || !fd_s->read_socket_pipe)
return {1,EFAULT,0};
+ DEBUG(proc->is_debug,"reading socket %d, buf 0x%p, count %d (target_size: %d)",fd,buf,count,fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER ? fd_s->write_socket_pipe->size : fd_s->read_socket_pipe->size);
+
if(fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
- SYSCALL_ENABLE_PREEMPT();
bytes_read = fd_s->write_socket_pipe->read(temp_buffer,count);
- SYSCALL_DISABLE_PREEMPT();
} else {
- SYSCALL_ENABLE_PREEMPT();
bytes_read = fd_s->read_socket_pipe->read(temp_buffer,count);
- SYSCALL_DISABLE_PREEMPT();
}
+
+ if(bytes_read == 0)
+ return {1,EAGAIN,0};
+
} else
return {1,EBADF,0};
- copy_in_userspace(proc,buf,temp_buffer,bytes_read);
-
- memory::pmm::_virtual::free(temp_buffer);
-
return {1,bytes_read >= 0 ? 0 : (int)(+bytes_read), bytes_read};
}
@@ -144,9 +147,14 @@ syscall_ret_t sys_write(int fd, const void *buf, size_t count) {
if(!fd_s)
return {1,EBADF,0};
- char* temp_buffer = (char*)memory::pmm::_virtual::alloc(count + 1);
- memory::paging::maprangeid(proc->original_cr3,Other::toPhys(temp_buffer),(std::uint64_t)temp_buffer,count,PTE_PRESENT | PTE_RW,proc->id);
- copy_in_userspace(proc,temp_buffer,(void*)buf,count);
+ vmm_obj_t* vmm_object = memory::vmm::getlen(proc,(std::uint64_t)buf);
+ uint64_t need_phys = vmm_object->phys + ((std::uint64_t)buf - vmm_object->base);
+
+ char* temp_buffer = (char*)Other::toVirt(need_phys);
+
+ const char* _0 = "Content view is disabled in files";
+
+ //DEBUG(proc->is_debug,"Writing to %s (fd %d) from proc %d with content \"%s\"",fd_s->path,fd,proc->id,temp_buffer,fd_s->state != USERSPACE_FD_STATE_FILE ? temp_buffer : _0);
std::int64_t bytes_written;
if(fd_s->state == USERSPACE_FD_STATE_FILE)
@@ -160,6 +168,10 @@ syscall_ret_t sys_write(int fd, const void *buf, size_t count) {
if(!fd_s->write_socket_pipe || !fd_s->read_socket_pipe)
return {1,EFAULT,0};
+ DEBUG(proc->is_debug,"Writing to socket %d from proc %d other_state: %d, buf: 0x%p, count: %d",fd,proc->id,fd_s->other_state,buf,count);
+
+
+
if(fd_s->other_state == USERSPACE_FD_OTHERSTATE_MASTER) {
SYSCALL_ENABLE_PREEMPT();
bytes_written = fd_s->read_socket_pipe->write(temp_buffer,count);
@@ -169,11 +181,13 @@ syscall_ret_t sys_write(int fd, const void *buf, size_t count) {
bytes_written = fd_s->write_socket_pipe->write(temp_buffer,count);
SYSCALL_DISABLE_PREEMPT();
}
+
+ if(bytes_written == 0)
+ return {1,EAGAIN,0};
+
} else
return {1,EBADF,0};
- memory::pmm::_virtual::free(temp_buffer);
-
return {1,bytes_written >= 0 ? 0 : (int)(+bytes_written), bytes_written};
}
@@ -192,12 +206,6 @@ syscall_ret_t sys_seek(int fd, long offset, int whence) {
if(fd_s->state == USERSPACE_FD_STATE_PIPE || fd_s->is_a_tty)
return {1,0,0};
- vfs::stat_t stat;
- int res = vfs::vfs::stat(fd_s,&stat);
-
- if(res != 0)
- return {1,res,0};
-
switch (whence)
{
case SEEK_SET:
@@ -208,9 +216,16 @@ syscall_ret_t sys_seek(int fd, long offset, int whence) {
fd_s->offset += offset;
break;
- case SEEK_END:
+ case SEEK_END: {
+ vfs::stat_t stat;
+ int res = vfs::vfs::stat(fd_s,&stat);
+
+ if(res != 0)
+ return {1,res,0};
+
fd_s->offset = stat.st_size + offset;
break;
+ }
default:
return {1,EINVAL,0};
@@ -253,6 +268,8 @@ syscall_ret_t sys_stat(int fd, void* out, int flags) {
if(!fd_s)
return {0,EBADF,0};
+ //DEBUG(proc->is_debug,"Trying to stat %s (fd %d) from proc %d",fd_s->path,fd,proc->id);
+
if(fd_s->state == USERSPACE_FD_STATE_FILE) {
vfs::stat_t stat;
int status;
@@ -286,7 +303,6 @@ syscall_ret_t sys_pipe(int flags) {
userspace_fd_t* fd1 = vfs::fdmanager::search(proc,read_fd);
userspace_fd_t* fd2 = vfs::fdmanager::search(proc,write_fd);
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"sys_pipe flags 0x%p\n",flags);
vfs::pipe* new_pipe = new vfs::pipe(flags);
fd1->pipe_side = PIPE_SIDE_READ;
fd2->pipe_side = PIPE_SIDE_WRITE;
@@ -321,6 +337,8 @@ syscall_ret_t sys_dup(int fd, int flags) {
nfd_s->read_counter = fd_s->read_counter;
nfd_s->write_counter = fd_s->write_counter;
nfd_s->can_be_closed = fd_s->can_be_closed;
+ nfd_s->write_socket_pipe = fd_s->write_socket_pipe;
+ nfd_s->read_socket_pipe = fd_s->read_socket_pipe;
memcpy(nfd_s->path,fd_s->path,sizeof(fd_s->path));
@@ -335,8 +353,6 @@ syscall_ret_t sys_dup2(int fd, int flags, int newfd) {
userspace_fd_t* fd_s = vfs::fdmanager::search(proc,fd);
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"dup2 from %d to %d in proc %d with flags 0x%p\n",fd,newfd,proc->id,flags);
-
if(!fd_s)
return {0,EBADF,0};
@@ -361,6 +377,8 @@ syscall_ret_t sys_dup2(int fd, int flags, int newfd) {
nfd_s->write_counter = fd_s->write_counter;
nfd_s->read_counter = fd_s->read_counter;
nfd_s->can_be_closed = fd_s->can_be_closed;
+ nfd_s->read_socket_pipe = fd_s->read_socket_pipe;
+ nfd_s->write_socket_pipe = fd_s->write_socket_pipe;
if(nfd_s->state == USERSPACE_FD_STATE_PIPE)
nfd_s->pipe->create(nfd_s->pipe_side);
@@ -458,8 +476,6 @@ syscall_ret_t sys_isatty(int fd) {
if(!fd_s)
return {0,EBADF,0};
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"isatty fd %d with state %d\n",fd,fd_s->state);
-
if(fd_s->state == USERSPACE_FD_STATE_PIPE || fd_s->state == USERSPACE_FD_STATE_SOCKET)
return {0,ENOTTY,0};
@@ -553,7 +569,7 @@ syscall_ret_t sys_read_dir(int fd, void* buffer) {
}
syscall_ret_t sys_fcntl(int fd, int request, std::uint64_t arg) {
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"fcntl %d\n",request);
+
switch(request) {
case F_DUPFD: {
return sys_dup(fd,arg);
@@ -577,9 +593,22 @@ syscall_ret_t sys_fcntl(int fd, int request, std::uint64_t arg) {
fd_s->flags &= ~(O_APPEND | O_ASYNC | O_NONBLOCK);
fd_s->flags |= (arg & (O_APPEND | O_ASYNC | O_NONBLOCK));
+ DEBUG(proc->is_debug,"Fcntl fd %d O_NONBLOCK %d from proc %d",fd,(fd_s->flags & O_NONBLOCK) ? 1 : 0,proc->id);
+
if(fd_s->state == USERSPACE_FD_STATE_PIPE) {
fd_s->pipe->flags & ~(O_NONBLOCK);
fd_s->pipe->flags |= (arg & O_NONBLOCK);
+ } else if(fd_s->state == USERSPACE_FD_STATE_SOCKET) {
+ if(fd_s->read_socket_pipe) {
+ fd_s->read_socket_pipe->flags & ~(O_NONBLOCK);
+ fd_s->read_socket_pipe->flags |= (arg & O_NONBLOCK);
+ }
+
+ if(fd_s->write_socket_pipe) {
+ fd_s->write_socket_pipe->flags & ~(O_NONBLOCK);
+ fd_s->write_socket_pipe->flags |= (arg & O_NONBLOCK);
+ }
+
}
return {1,0,0};
@@ -635,6 +664,7 @@ syscall_ret_t sys_mkfifoat(int dirfd, const char *path, int mode) {
vfs::resolve_path(kpath,first_path,result,1,0);
userspace_fd_t new_fd_s;
+ new_fd_s.is_cached_path = 0;
memset(new_fd_s.path,0,2048);
memcpy(new_fd_s.path,result,strlen(result));
@@ -645,7 +675,6 @@ syscall_ret_t sys_mkfifoat(int dirfd, const char *path, int mode) {
int status = vfs::vfs::create_fifo(result);
- Log::SerialDisplay(LEVEL_MESSAGE_INFO,"new fifo %s status %d\n",result,status);
return {0,status,0};
}
@@ -673,12 +702,19 @@ syscall_ret_t sys_poll(struct pollfd *fds, int count, int timeout) {
if(!fd0)
return {1,EINVAL,0};
+ DEBUG(proc->is_debug,"Trying to poll %s operation %d (fd %d with state %d, read_socket: 0x%p, write_socket: 0x%p) with timeout %d in proc %d",fd0->path,fd[i].events,fd[i].fd,fd0->state,fd0->read_socket_pipe,fd0->write_socket_pipe,timeout,proc->id);
+
if(fd[i].events & POLLIN)
total_events++;
if(fd[i].events & POLLOUT)
total_events++;
+ if(fd0->state == USERSPACE_FD_STATE_SOCKET && fd0->is_listen && fd0->read_counter == -1) {
+ fd0->read_counter = 0;
+ fd0->write_counter = 0;
+ }
+
if(fd0->write_counter == -1) {
std::int64_t ret = vfs::vfs::poll(fd0,POLLOUT);
fd0->write_counter = ret < 0 ? 0 : ret;
@@ -693,9 +729,46 @@ syscall_ret_t sys_poll(struct pollfd *fds, int count, int timeout) {
int num_events = 0;
- SYSCALL_ENABLE_PREEMPT();
-
int success = true;
+ int something_bad = 0;
+
+ if(timeout == -1) {
+ for(int i = 0;i < count; i++) {
+ userspace_fd_t* fd0 = vfs::fdmanager::search(proc,fd[i].fd);
+ if(fd[i].events & POLLIN) {
+ std::int64_t ret = vfs::vfs::poll(fd0,POLLIN);
+ if(fd0->is_listen)
+ DEBUG(proc->is_debug,"ret %d readcounter %d",ret,fd0->read_counter);
+ if(ret > fd0->read_counter) {
+ fd0->read_counter = ret;
+ num_events++;
+ fd[i].revents |= POLLIN;
+ }
+ }
+
+ if(fd[i].events & POLLOUT) {
+ std::int64_t ret = vfs::vfs::poll(fd0,POLLOUT);
+ if(ret > fd0->write_counter || ret == 0) {
+ fd0->write_counter = ret;
+ num_events++;
+ fd[i].revents |= POLLOUT;
+ }
+
+ }
+
+ if(num_events)
+ success = false;
+ }
+ }
+
+ if(success == false) {
+ copy_in_userspace(proc,fds,fd,count * sizeof(struct pollfd));
+
+ return {1,0,num_events};
+ }
+
+ success = true;
+ num_events = 0;
if(timeout == -1) {
while(success) {
@@ -705,22 +778,26 @@ syscall_ret_t sys_poll(struct pollfd *fds, int count, int timeout) {
SYSCALL_DISABLE_PREEMPT();
std::int64_t ret = vfs::vfs::poll(fd0,POLLIN);
SYSCALL_ENABLE_PREEMPT();
+ if(fd0->is_listen)
+ DEBUG(proc->is_debug,"ret %d readcounter %d",ret,fd0->read_counter);
if(ret > fd0->read_counter) {
fd0->read_counter = ret;
num_events++;
fd[i].revents |= POLLIN;
}
+
}
if(fd[i].events & POLLOUT) {
SYSCALL_DISABLE_PREEMPT();
std::int64_t ret = vfs::vfs::poll(fd0,POLLOUT);
SYSCALL_ENABLE_PREEMPT();
- if(ret > fd0->write_counter) {
+ if(ret > fd0->write_counter || ret == 0) {
fd0->write_counter = ret;
num_events++;
fd[i].revents |= POLLOUT;
}
+
}
if(num_events)
@@ -740,6 +817,7 @@ syscall_ret_t sys_poll(struct pollfd *fds, int count, int timeout) {
num_events++;
fd[i].revents |= POLLIN;
}
+
}
if(fd[i].events & POLLOUT) {
@@ -751,6 +829,7 @@ syscall_ret_t sys_poll(struct pollfd *fds, int count, int timeout) {
num_events++;
fd[i].revents |= POLLOUT;
}
+
}
if(num_events)
@@ -795,11 +874,100 @@ syscall_ret_t sys_readlinkat(int dirfd, const char* path, void* buffer, int_fram
int ret = vfs::vfs::readlink(result,readlink_buf,2048);
vfs::vfs::unlock();
- if(ret != 0)
+ if(ret != 0) {
+
return {1,ret,0};
+ }
copy_in_userspace(proc,buffer,readlink_buf, strlen(readlink_buf) > max_size ? max_size : strlen(readlink_buf));
return {1,0,(int64_t)(strlen(readlink_buf) > max_size ? max_size : strlen(readlink_buf))};
+}
+
+syscall_ret_t sys_link(char* old_path, char* new_path) {
+ char old_path0[2048];
+ char new_path0[2048];
+ memset(old_path0,0,2048);
+ memset(new_path0,0,2048);
+
+ SYSCALL_IS_SAFEA((void*)old_path,2048);
+ SYSCALL_IS_SAFEA((void*)new_path,2048);
+
+ arch::x86_64::process_t* proc = CURRENT_PROC;
+
+ copy_in_userspace_string(proc,old_path0,old_path,2048);
+ copy_in_userspace_string(proc,new_path0,new_path,2048);
+
+ int ret = vfs::vfs::create(new_path0,VFS_TYPE_SYMLINK);
+
+ if(ret != 0)
+ return {0,ret,0};
+
+ userspace_fd_t fd;
+ fd.is_cached_path = 0;
+ fd.offset = 0;
+ memset(fd.path,0,2048);
+ memcpy(fd.path,new_path0,strlen(new_path0));
+
+ ret = vfs::vfs::write(&fd,old_path0,2047);
+
+ return {0,0,0};
+
+}
+
+syscall_ret_t sys_mkdirat(int dirfd, char* path, int mode) {
+ SYSCALL_IS_SAFEA((void*)path,0);
+
+ arch::x86_64::process_t* proc = CURRENT_PROC;
+
+ char first_path[2048];
+ memset(first_path,0,2048);
+ if(dirfd >= 0)
+ memcpy(first_path,vfs::fdmanager::search(proc,dirfd)->path,strlen(vfs::fdmanager::search(proc,dirfd)->path));
+ else if(dirfd == AT_FDCWD)
+ memcpy(first_path,proc->cwd,strlen(proc->cwd));
+
+ char kpath[2048];
+ memset(kpath,0,2048);
+ copy_in_userspace_string(proc,kpath,(void*)path,2048);
+
+ char result[2048];
+ memset(result,0,2048);
+ vfs::resolve_path(kpath,first_path,result,1,0);
+
+ int ret = vfs::vfs::create(result,VFS_TYPE_DIRECTORY);
+
+ userspace_fd_t fd;
+ fd.is_cached_path = 0;
+ memcpy(fd.path,result,2048);
+
+ vfs::vfs::var(&fd,mode,TMPFS_VAR_CHMOD | (1 << 7));
+ return {0,ret,0};
+}
+
+syscall_ret_t sys_chmod(char* path, int mode) {
+ SYSCALL_IS_SAFEA((void*)path,0);
+
+ arch::x86_64::process_t* proc = CURRENT_PROC;
+
+ char result[2048];
+ memset(result,0,2048);
+
+ copy_in_userspace_string(proc,result,path,2048);
+
+ userspace_fd_t fd;
+ fd.is_cached_path = 0;
+ memset(&fd,0,sizeof(fd));
+ memcpy(fd.path,result,2048);
+
+ uint64_t value;
+ int ret = vfs::vfs::var(&fd,(uint64_t)&value,TMPFS_VAR_CHMOD);
+
+ if(ret != 0)
+ return {0,ret,0};
+
+ ret = vfs::vfs::var(&fd,value | mode, TMPFS_VAR_CHMOD | (1 << 7));
+
+ return {0,ret,0};
} \ No newline at end of file