#include #include #include #include #include #include #include #include #include #include #include #include #include #include HelHandle __mlibc_getPassthrough(int fd) { auto handle = getHandleForFd(fd); __ensure(handle); return handle; } namespace mlibc { int sys_chdir(const char *path) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::CHDIR); req.set_path(frg::string(getSysdepsAllocator(), path)); auto [offer, send_req, recv_resp] = exchangeMsgsSync(getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_fchdir(int fd) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::FCHDIR); req.set_fd(fd); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } int sys_chroot(const char *path) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::CHROOT); req.set_path(frg::string(getSysdepsAllocator(), path)); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } int sys_mkdir(const char *path, mode_t mode) { return sys_mkdirat(AT_FDCWD, path, mode); } int sys_mkdirat(int dirfd, const char *path, mode_t mode) { (void)mode; SignalGuard sguard; managarm::posix::MkdirAtRequest req(getSysdepsAllocator()); req.set_fd(dirfd); req.set_path(frg::string(getSysdepsAllocator(), path)); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { return EEXIST; } else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { return ENOTDIR; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_symlink(const char *target_path, const char *link_path) { return sys_symlinkat(target_path, AT_FDCWD, link_path); } int sys_symlinkat(const char *target_path, int dirfd, const char *link_path) { SignalGuard sguard; managarm::posix::SymlinkAtRequest req(getSysdepsAllocator()); req.set_fd(dirfd); req.set_path(frg::string(getSysdepsAllocator(), link_path)); req.set_target_path(frg::string(getSysdepsAllocator(), target_path)); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { return ENOTDIR; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_link(const char *old_path, const char *new_path) { return sys_linkat(AT_FDCWD, old_path, AT_FDCWD, new_path, 0); } int sys_linkat(int olddirfd, const char *old_path, int newdirfd, const char *new_path, int flags) { SignalGuard sguard; managarm::posix::LinkAtRequest req(getSysdepsAllocator()); req.set_path(frg::string(getSysdepsAllocator(), old_path)); req.set_target_path(frg::string(getSysdepsAllocator(), new_path)); req.set_fd(olddirfd); req.set_newfd(newdirfd); req.set_flags(flags); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_rename(const char *path, const char *new_path) { return sys_renameat(AT_FDCWD, path, AT_FDCWD, new_path); } int sys_renameat(int olddirfd, const char *old_path, int newdirfd, const char *new_path) { SignalGuard sguard; managarm::posix::RenameAtRequest req(getSysdepsAllocator()); req.set_path(frg::string(getSysdepsAllocator(), old_path)); req.set_target_path(frg::string(getSysdepsAllocator(), new_path)); req.set_fd(olddirfd); req.set_newfd(newdirfd); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } } //namespace mlibc namespace mlibc { int sys_fcntl(int fd, int request, va_list args, int *result) { SignalGuard sguard; if(request == F_DUPFD) { int newfd; if(int e = sys_dup(fd, 0, &newfd); e) return e; *result = newfd; return 0; }else if(request == F_DUPFD_CLOEXEC) { int newfd; if(int e = sys_dup(fd, O_CLOEXEC, &newfd); e) return e; *result = newfd; return 0; }else if(request == F_GETFD) { managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::FD_GET_FLAGS); req.set_fd(fd); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) return EBADF; __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *result = resp.flags(); return 0; }else if(request == F_SETFD) { managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::FD_SET_FLAGS); req.set_fd(fd); req.set_flags(va_arg(args, int)); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) return EBADF; else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) return EINVAL; __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *result = static_cast(resp.error()); return 0; }else if(request == F_GETFL) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_GET_FILE_FLAGS); req.set_fd(fd); auto [offer, send_req, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_GETFL) unimplemented for this file\e[39m" << frg::endlog; return EINVAL; } __ensure(resp.error() == managarm::fs::Errors::SUCCESS); *result = resp.flags(); return 0; }else if(request == F_SETFL) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_SET_FILE_FLAGS); req.set_fd(fd); req.set_flags(va_arg(args, int)); auto [offer, send_req, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_SETFL) unimplemented for this file\e[39m" << frg::endlog; return EINVAL; } __ensure(resp.error() == managarm::fs::Errors::SUCCESS); *result = 0; return 0; }else if(request == F_SETLK) { mlibc::infoLogger() << "\e[31mmlibc: F_SETLK\e[39m" << frg::endlog; return 0; }else if(request == F_SETLKW) { mlibc::infoLogger() << "\e[31mmlibc: F_SETLKW\e[39m" << frg::endlog; return 0; }else if(request == F_GETLK) { struct flock *lock = va_arg(args, struct flock *); lock->l_type = F_UNLCK; mlibc::infoLogger() << "\e[31mmlibc: F_GETLK is stubbed!\e[39m" << frg::endlog; return 0; }else if(request == F_ADD_SEALS) { auto seals = va_arg(args, int); auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_ADD_SEALS); req.set_fd(fd); req.set_seals(seals); auto [offer, send_req, recv_resp] = exchangeMsgsSync(handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::RecvInline() )); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_ADD_SEALS) unimplemented for this file\e[39m" << frg::endlog; return EINVAL; } else if(resp.error() == managarm::fs::Errors::INSUFFICIENT_PERMISSIONS) { return EPERM; } __ensure(resp.error() == managarm::fs::Errors::SUCCESS); *result = resp.seals(); return 0; }else if(request == F_GET_SEALS) { auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_GET_SEALS); req.set_fd(fd); auto [offer, send_req, recv_resp] = exchangeMsgsSync(handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::RecvInline() )); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { mlibc::infoLogger() << "\e[31mmlibc: fcntl(F_GET_SEALS) unimplemented for this file\e[39m" << frg::endlog; return EINVAL; } __ensure(resp.error() == managarm::fs::Errors::SUCCESS); *result = resp.seals(); return 0; }else{ mlibc::infoLogger() << "\e[31mmlibc: Unexpected fcntl() request: " << request << "\e[39m" << frg::endlog; return EINVAL; } } int sys_open_dir(const char *path, int *handle) { return sys_open(path, 0, 0, handle); } int sys_read_entries(int fd, void *buffer, size_t max_size, size_t *bytes_read) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_READ_ENTRIES); auto [offer, send_req, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::END_OF_FILE) { *bytes_read = 0; return 0; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); __ensure(max_size > sizeof(struct dirent)); auto ent = new (buffer) struct dirent; memset(ent, 0, sizeof(struct dirent)); memcpy(ent->d_name, resp.path().data(), resp.path().size()); ent->d_reclen = sizeof(struct dirent); *bytes_read = sizeof(struct dirent); return 0; } } int sys_ttyname(int fd, char *buf, size_t size) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::TTY_NAME); req.set_fd(fd); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::NOT_A_TTY) { return ENOTTY; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); __ensure(size >= resp.path().size() + 1); memcpy(buf, resp.path().data(), size); buf[resp.path().size()] = '\0'; return 0; } } int sys_fdatasync(int) { mlibc::infoLogger() << "\e[35mmlibc: fdatasync() is a no-op\e[39m" << frg::endlog; return 0; } int sys_getcwd(char *buffer, size_t size) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::GETCWD); req.set_size(size); auto [offer, send_req, recv_resp, recv_path] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline(), helix_ng::recvBuffer(buffer, size)) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); HEL_CHECK(recv_path.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); if(static_cast(resp.size()) >= size) return ERANGE; return 0; } int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, void **window) { SignalGuard sguard; managarm::posix::VmMapRequest req(getSysdepsAllocator()); req.set_address_hint(reinterpret_cast(hint)); req.set_size(size); req.set_mode(prot); req.set_flags(flags); req.set_fd(fd); req.set_rel_offset(offset); auto [offer, sendReq, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendReq.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { return EEXIST; }else if(resp.error() == managarm::posix::Errors::NO_MEMORY) { return EFAULT; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *window = reinterpret_cast(resp.offset()); } return 0; } int sys_vm_remap(void *pointer, size_t size, size_t new_size, void **window) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::VM_REMAP); req.set_address(reinterpret_cast(pointer)); req.set_size(size); req.set_new_size(new_size); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *window = reinterpret_cast(resp.offset()); return 0; } int sys_vm_protect(void *pointer, size_t size, int prot) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::VM_PROTECT); req.set_address(reinterpret_cast(pointer)); req.set_size(size); req.set_mode(prot); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } int sys_vm_unmap(void *pointer, size_t size) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::VM_UNMAP); req.set_address(reinterpret_cast(pointer)); req.set_size(size); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } int sys_setsid(pid_t *sid) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::SETSID); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { *sid = -1; return EPERM; } __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *sid = resp.sid(); return 0; } int sys_tcgetattr(int fd, struct termios *attr) { int result; if(int e = sys_ioctl(fd, TCGETS, attr, &result); e) return e; return 0; } int sys_tcsetattr(int fd, int when, const struct termios *attr) { if(when < TCSANOW || when > TCSAFLUSH) return EINVAL; if(int e = sys_ioctl(fd, TCSETS, const_cast(attr), nullptr); e) return e; return 0; } int sys_tcdrain(int) { mlibc::infoLogger() << "\e[35mmlibc: tcdrain() is a stub\e[39m" << frg::endlog; return 0; } int sys_socket(int domain, int type_and_flags, int proto, int *fd) { constexpr int type_mask = int(0xF); constexpr int flags_mask = ~int(0xF); __ensure(!((type_and_flags & flags_mask) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))); SignalGuard sguard; managarm::posix::SocketRequest req(getSysdepsAllocator()); req.set_domain(domain); req.set_socktype(type_and_flags & type_mask); req.set_protocol(proto); req.set_flags(type_and_flags & flags_mask); auto [offer, sendReq, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendReq.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EAFNOSUPPORT; } else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); return 0; } } int sys_pipe(int *fds, int flags) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::PIPE_CREATE); req.set_flags(flags); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); __ensure(resp.fds_size() == 2); fds[0] = resp.fds(0); fds[1] = resp.fds(1); return 0; } int sys_socketpair(int domain, int type_and_flags, int proto, int *fds) { constexpr int type_mask = int(0xF); constexpr int flags_mask = ~int(0xF); __ensure(!((type_and_flags & flags_mask) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))); SignalGuard sguard; managarm::posix::SockpairRequest req(getSysdepsAllocator()); req.set_domain(domain); req.set_socktype(type_and_flags & type_mask); req.set_protocol(proto); req.set_flags(type_and_flags & flags_mask); auto [offer, sendReq, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendReq.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); if(resp.error() == managarm::posix::Errors::PROTOCOL_NOT_SUPPORTED) { return EPROTONOSUPPORT; } else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); } __ensure(resp.fds_size() == 2); fds[0] = resp.fds(0); fds[1] = resp.fds(1); return 0; } int sys_msg_send(int sockfd, const struct msghdr *hdr, int flags, ssize_t *length) { frg::vector sglist{getSysdepsAllocator()}; auto handle = getHandleForFd(sockfd); if (!handle) return EBADF; size_t overall_size = 0; for(int i = 0; i < hdr->msg_iovlen; i++) { HelSgItem item{ .buffer = hdr->msg_iov[i].iov_base, .length = hdr->msg_iov[i].iov_len, }; sglist.push_back(item); overall_size += hdr->msg_iov[i].iov_len; } SignalGuard sguard; managarm::fs::SendMsgRequest req(getSysdepsAllocator()); req.set_flags(flags); req.set_size(overall_size); for(auto cmsg = CMSG_FIRSTHDR(hdr); cmsg; cmsg = CMSG_NXTHDR(hdr, cmsg)) { __ensure(cmsg->cmsg_level == SOL_SOCKET); if(cmsg->cmsg_type == SCM_CREDENTIALS) { mlibc::infoLogger() << "mlibc: SCM_CREDENTIALS requested but we don't handle that yet!" << frg::endlog; return EINVAL; } __ensure(cmsg->cmsg_type == SCM_RIGHTS); __ensure(cmsg->cmsg_len >= sizeof(struct cmsghdr)); size_t size = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); __ensure(!(size % sizeof(int))); for(size_t off = 0; off < size; off += sizeof(int)) { int fd; memcpy(&fd, CMSG_DATA(cmsg) + off, sizeof(int)); req.add_fds(fd); } } auto [offer, send_head, send_tail, send_data, imbue_creds, send_addr, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::sendBufferSg(sglist.data(), hdr->msg_iovlen), helix_ng::imbueCredentials(), helix_ng::sendBuffer(hdr->msg_name, hdr->msg_namelen), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(send_data.error()); HEL_CHECK(imbue_creds.error()); HEL_CHECK(send_addr.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SendMsgReply resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::BROKEN_PIPE) { return EPIPE; }else if(resp.error() == managarm::fs::Errors::NOT_CONNECTED) { return ENOTCONN; }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { return EAGAIN; }else if(resp.error() == managarm::fs::Errors::HOST_UNREACHABLE) { return EHOSTUNREACH; }else if(resp.error() == managarm::fs::Errors::ACCESS_DENIED) { return EACCES; }else if(resp.error() == managarm::fs::Errors::NETWORK_UNREACHABLE) { return ENETUNREACH; }else if(resp.error() == managarm::fs::Errors::DESTINATION_ADDRESS_REQUIRED) { return EDESTADDRREQ; }else if(resp.error() == managarm::fs::Errors::ADDRESS_NOT_AVAILABLE) { return EADDRNOTAVAIL; }else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { return EINVAL; }else if(resp.error() == managarm::fs::Errors::AF_NOT_SUPPORTED) { return EAFNOSUPPORT; }else if(resp.error() == managarm::fs::Errors::MESSAGE_TOO_LARGE) { return EMSGSIZE; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); *length = resp.size(); return 0; } } int sys_msg_recv(int sockfd, struct msghdr *hdr, int flags, ssize_t *length) { if(!hdr->msg_iovlen) { return EMSGSIZE; } auto handle = getHandleForFd(sockfd); if (!handle) return EBADF; SignalGuard sguard; managarm::fs::RecvMsgRequest req(getSysdepsAllocator()); req.set_flags(flags); req.set_size(hdr->msg_iov[0].iov_len); req.set_addr_size(hdr->msg_namelen); req.set_ctrl_size(hdr->msg_controllen); auto [offer, send_req, imbue_creds, recv_resp, recv_addr, recv_data, recv_ctrl] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::imbueCredentials(), helix_ng::recvInline(), helix_ng::recvBuffer(hdr->msg_name, hdr->msg_namelen), helix_ng::recvBuffer(hdr->msg_iov[0].iov_base, hdr->msg_iov[0].iov_len), helix_ng::recvBuffer(hdr->msg_control, hdr->msg_controllen)) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(imbue_creds.error()); HEL_CHECK(recv_resp.error()); managarm::fs::RecvMsgReply resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { return EAGAIN; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); HEL_CHECK(recv_addr.error()); HEL_CHECK(recv_data.error()); HEL_CHECK(recv_ctrl.error()); hdr->msg_namelen = resp.addr_size(); hdr->msg_controllen = recv_ctrl.actualLength(); hdr->msg_flags = resp.flags(); *length = resp.ret_val(); return 0; } } int sys_pselect(int, fd_set *read_set, fd_set *write_set, fd_set *except_set, const struct timespec *timeout, const sigset_t *sigmask, int *num_events) { // TODO: Do not keep errors from epoll (?). int fd = epoll_create1(0); if(fd == -1) return -1; for(int k = 0; k < FD_SETSIZE; k++) { struct epoll_event ev; memset(&ev, 0, sizeof(struct epoll_event)); if(read_set && FD_ISSET(k, read_set)) ev.events |= EPOLLIN; // TODO: Additional events. if(write_set && FD_ISSET(k, write_set)) ev.events |= EPOLLOUT; // TODO: Additional events. if(except_set && FD_ISSET(k, except_set)) ev.events |= EPOLLPRI; if(!ev.events) continue; ev.data.u32 = k; if(epoll_ctl(fd, EPOLL_CTL_ADD, k, &ev)) return -1; } struct epoll_event evnts[16]; int n = epoll_pwait(fd, evnts, 16, timeout ? (timeout->tv_sec * 1000 + timeout->tv_nsec / 100) : -1, sigmask); if(n == -1) return -1; fd_set res_read_set; fd_set res_write_set; fd_set res_except_set; FD_ZERO(&res_read_set); FD_ZERO(&res_write_set); FD_ZERO(&res_except_set); int m = 0; for(int i = 0; i < n; i++) { int k = evnts[i].data.u32; if(read_set && FD_ISSET(k, read_set) && evnts[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) { FD_SET(k, &res_read_set); m++; } if(write_set && FD_ISSET(k, write_set) && evnts[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) { FD_SET(k, &res_write_set); m++; } if(except_set && FD_ISSET(k, except_set) && evnts[i].events & EPOLLPRI) { FD_SET(k, &res_except_set); m++; } } if(close(fd)) __ensure("close() failed on epoll file"); if(read_set) memcpy(read_set, &res_read_set, sizeof(fd_set)); if(write_set) memcpy(write_set, &res_write_set, sizeof(fd_set)); if(except_set) memcpy(except_set, &res_except_set, sizeof(fd_set)); *num_events = m; return 0; } int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events) { __ensure(timeout >= 0 || timeout == -1); // TODO: Report errors correctly. SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::EPOLL_CALL); req.set_timeout(timeout > 0 ? int64_t{timeout} * 1000000 : timeout); for(nfds_t i = 0; i < count; i++) { req.add_fds(fds[i].fd); req.add_events(fds[i].events); } auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; } else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); __ensure(resp.events_size() == count); int m = 0; for(nfds_t i = 0; i < count; i++) { if(resp.events(i)) m++; fds[i].revents = resp.events(i); } *num_events = m; return 0; } } int sys_epoll_create(int flags, int *fd) { // Some applications assume EPOLL_CLOEXEC and O_CLOEXEC to be the same. // They are on linux, but not yet on managarm. __ensure(!(flags & ~(EPOLL_CLOEXEC | O_CLOEXEC))); SignalGuard sguard; uint32_t proto_flags = 0; if(flags & EPOLL_CLOEXEC || flags & O_CLOEXEC) proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::EPOLL_CREATE); req.set_flags(proto_flags); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); return 0; } int sys_epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); if(mode == EPOLL_CTL_ADD) { __ensure(ev); req.set_request_type(managarm::posix::CntReqType::EPOLL_ADD); req.set_flags(ev->events); req.set_cookie(ev->data.u64); }else if(mode == EPOLL_CTL_MOD) { __ensure(ev); req.set_request_type(managarm::posix::CntReqType::EPOLL_MODIFY); req.set_flags(ev->events); req.set_cookie(ev->data.u64); }else if(mode == EPOLL_CTL_DEL) { req.set_request_type(managarm::posix::CntReqType::EPOLL_DELETE); }else{ mlibc::panicLogger() << "\e[31mmlibc: Illegal epoll_ctl() mode\e[39m" << frg::endlog; } req.set_fd(epfd); req.set_newfd(fd); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; } else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { return EEXIST; } else if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; } else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } return 0; } int sys_epoll_pwait(int epfd, struct epoll_event *ev, int n, int timeout, const sigset_t *sigmask, int *raised) { __ensure(timeout >= 0 || timeout == -1); // TODO: Report errors correctly. SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::EPOLL_WAIT); req.set_fd(epfd); req.set_size(n); req.set_timeout(timeout > 0 ? int64_t{timeout} * 1000000 : timeout); if(sigmask != NULL) { req.set_sigmask((long int)*sigmask); req.set_sigmask_needed(true); } else { req.set_sigmask_needed(false); } auto [offer, send_req, recv_resp, recv_data] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline(), helix_ng::recvBuffer(ev, n * sizeof(struct epoll_event))) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); HEL_CHECK(recv_data.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; } __ensure(resp.error() == managarm::posix::Errors::SUCCESS); __ensure(!(recv_data.actualLength() % sizeof(struct epoll_event))); *raised = recv_data.actualLength() / sizeof(struct epoll_event); return 0; } int sys_timerfd_create(int clockid, int flags, int *fd) { (void) clockid; SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::TIMERFD_CREATE); req.set_flags(flags); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); return 0; } int sys_timerfd_settime(int fd, int, const struct itimerspec *value, struct itimerspec *oldvalue) { __ensure(!oldvalue); SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::TIMERFD_SETTIME); req.set_fd(fd); req.set_time_secs(value->it_value.tv_sec); req.set_time_nanos(value->it_value.tv_nsec); req.set_interval_secs(value->it_interval.tv_sec); req.set_interval_nanos(value->it_interval.tv_nsec); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } int sys_signalfd_create(const sigset_t *masks, int flags, int *fd) { __ensure(!(flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))); uint32_t proto_flags = 0; if(flags & SFD_CLOEXEC) proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; if(flags & SFD_NONBLOCK) proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::SIGNALFD_CREATE); req.set_flags(proto_flags); req.set_sigset(*masks); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); return 0; } int sys_inotify_create(int flags, int *fd) { __ensure(!(flags & ~(IN_CLOEXEC | IN_NONBLOCK))); SignalGuard sguard; uint32_t proto_flags = 0; if(flags & IN_CLOEXEC) proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; if(flags & IN_NONBLOCK) proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; managarm::posix::InotifyCreateRequest req(getSysdepsAllocator()); req.set_flags(proto_flags); auto [offer, sendReq, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendReq.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); return 0; } int sys_inotify_add_watch(int ifd, const char *path, uint32_t mask, int *wd) { SignalGuard sguard; managarm::posix::InotifyAddRequest req(getSysdepsAllocator()); req.set_fd(ifd); req.set_path(frg::string(getSysdepsAllocator(), path)); req.set_flags(mask); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *wd = resp.wd(); return 0; } } int sys_eventfd_create(unsigned int initval, int flags, int *fd) { SignalGuard sguard; uint32_t proto_flags = 0; if (flags & EFD_NONBLOCK) proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; if (flags & EFD_CLOEXEC) proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; if (flags & EFD_SEMAPHORE) return ENOSYS; managarm::posix::EventfdCreateRequest req(getSysdepsAllocator()); req.set_flags(proto_flags); req.set_initval(initval); auto [offer, sendReq, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendReq.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); return 0; } int sys_open(const char *path, int flags, mode_t mode, int *fd) { return sys_openat(AT_FDCWD, path, flags, mode, fd); } int sys_openat(int dirfd, const char *path, int flags, mode_t mode, int *fd) { SignalGuard sguard; // We do not support O_TMPFILE. if(flags & O_TMPFILE) return EOPNOTSUPP; uint32_t proto_flags = 0; if(flags & O_APPEND) proto_flags |= managarm::posix::OpenFlags::OF_APPEND; if(flags & O_CREAT) proto_flags |= managarm::posix::OpenFlags::OF_CREATE; if(flags & O_EXCL) proto_flags |= managarm::posix::OpenFlags::OF_EXCLUSIVE; if(flags & O_NONBLOCK) proto_flags |= managarm::posix::OpenFlags::OF_NONBLOCK; if(flags & O_TRUNC) proto_flags |= managarm::posix::OpenFlags::OF_TRUNC; if(flags & O_CLOEXEC) proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; if(flags & O_NOCTTY) proto_flags |= managarm::posix::OpenFlags::OF_NOCTTY; if(flags & O_RDONLY) proto_flags |= managarm::posix::OpenFlags::OF_RDONLY; else if(flags & O_WRONLY) proto_flags |= managarm::posix::OpenFlags::OF_WRONLY; else if(flags & O_RDWR) proto_flags |= managarm::posix::OpenFlags::OF_RDWR; else if(flags & O_PATH) proto_flags |= managarm::posix::OpenFlags::OF_PATH; managarm::posix::OpenAtRequest req(getSysdepsAllocator()); req.set_fd(dirfd); req.set_path(frg::string(getSysdepsAllocator(), path)); req.set_flags(proto_flags); req.set_mode(mode); auto [offer, sendHead, sendTail, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendHead.error()); HEL_CHECK(sendTail.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { return EEXIST; }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { return ENOTDIR; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_OPERATION_TARGET) { mlibc::infoLogger() << "\e[31mmlibc: openat unimplemented for this file " << path << "\e[39m" << frg::endlog; return EINVAL; }else if(resp.error() == managarm::posix::Errors::NO_BACKING_DEVICE) { return ENXIO; }else if(resp.error() == managarm::posix::Errors::IS_DIRECTORY) { return EISDIR; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *fd = resp.fd(); return 0; } } int sys_mkfifoat(int dirfd, const char *path, mode_t mode) { SignalGuard sguard; managarm::posix::MkfifoAtRequest req(getSysdepsAllocator()); req.set_fd(dirfd); req.set_path(frg::string(getSysdepsAllocator(), path)); req.set_mode(mode); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { return EEXIST; }else if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else if(resp.error() == managarm::posix::Errors::INTERNAL_ERROR) { return EIEIO; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_mknodat(int dirfd, const char *path, int mode, int dev) { SignalGuard sguard; managarm::posix::MknodAtRequest req(getSysdepsAllocator()); req.set_dirfd(dirfd); req.set_path(frg::string(getSysdepsAllocator(), path)); req.set_mode(mode); req.set_device(dev); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::ALREADY_EXISTS) { return EEXIST; }else if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_read(int fd, void *data, size_t max_size, ssize_t *bytes_read) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::READ); req.set_fd(fd); req.set_size(max_size); frg::string ser(getSysdepsAllocator()); req.SerializeToString(&ser); auto [offer, send_req, imbue_creds, recv_resp, recv_data] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBuffer(ser.data(), ser.size()), helix_ng::imbueCredentials(), helix_ng::recvInline(), helix_ng::recvBuffer(data, max_size) ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(imbue_creds.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); /* if(resp.error() == managarm::fs::Errors::NO_SUCH_FD) { return EBADF; }else*/ if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { return EINVAL; }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { return EAGAIN; }else if(resp.error() == managarm::fs::Errors::END_OF_FILE) { *bytes_read = 0; return 0; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); HEL_CHECK(recv_data.error()); *bytes_read = recv_data.actualLength(); return 0; } } int sys_readv(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) { for(int i = 0; i < iovc; i++) { ssize_t intermed = 0; if(int e = sys_read(fd, iovs[i].iov_base, iovs[i].iov_len, &intermed); e) return e; else if(intermed == 0) break; *bytes_read += intermed; } return 0; } int sys_write(int fd, const void *data, size_t size, ssize_t *bytes_written) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::WRITE); req.set_fd(fd); req.set_size(size); auto [offer, send_req, imbue_creds, send_data, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::imbueCredentials(), helix_ng::sendBuffer(data, size), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(imbue_creds.error()); HEL_CHECK(send_data.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); // TODO: implement NO_SUCH_FD /* if(resp.error() == managarm::fs::Errors::NO_SUCH_FD) { return EBADF; }else*/ if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { return EINVAL; // FD does not support writes. }else if(resp.error() == managarm::fs::Errors::NO_SPACE_LEFT) { return ENOSPC; }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { return EAGAIN; }else if(resp.error() == managarm::fs::Errors::NOT_CONNECTED) { return ENOTCONN; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); if(bytes_written) { *bytes_written = resp.size(); } return 0; } } int sys_pread(int fd, void *buf, size_t n, off_t off, ssize_t *bytes_read) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_PREAD); req.set_fd(fd); req.set_size(n); req.set_offset(off); auto [offer, send_req, imbue_creds, recv_resp, recv_data] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::imbueCredentials(), helix_ng::recvInline(), helix_ng::recvBuffer(buf, n)) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(imbue_creds.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); /* if(resp.error() == managarm::fs::Errors::NO_SUCH_FD) { return EBADF; }else*/ if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { return EINVAL; }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { return EAGAIN; }else if(resp.error() == managarm::fs::Errors::END_OF_FILE) { *bytes_read = 0; return 0; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); HEL_CHECK(recv_data.error()); *bytes_read = recv_data.actualLength(); return 0; } } int sys_pwrite(int fd, const void *buf, size_t n, off_t off, ssize_t *bytes_written) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_PWRITE); req.set_fd(fd); req.set_size(n); req.set_offset(off); frg::string ser(getSysdepsAllocator()); req.SerializeToString(&ser); auto [offer, send_head, imbue_creds, to_write, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::imbueCredentials(), helix_ng::sendBuffer(buf, n), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(imbue_creds.error()); HEL_CHECK(to_write.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { return EINVAL; }else if(resp.error() == managarm::fs::Errors::WOULD_BLOCK) { return EAGAIN; }else if(resp.error() == managarm::fs::Errors::NO_SPACE_LEFT) { return ENOSPC; }else if(resp.error() == managarm::fs::Errors::SEEK_ON_PIPE) { return ESPIPE; }else if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { return EINVAL; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); *bytes_written = n; return 0; } } int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { SignalGuard sguard; auto handle = getHandleForFd(fd); if(!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_fd(fd); req.set_rel_offset(offset); if(whence == SEEK_SET) { req.set_req_type(managarm::fs::CntReqType::SEEK_ABS); }else if(whence == SEEK_CUR) { req.set_req_type(managarm::fs::CntReqType::SEEK_REL); }else if(whence == SEEK_END) { req.set_req_type(managarm::fs::CntReqType::SEEK_EOF); }else{ return EINVAL; } frg::string ser(getSysdepsAllocator()); req.SerializeToString(&ser); auto [offer, send_req, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBuffer(ser.data(), ser.size()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::SEEK_ON_PIPE) { return ESPIPE; } else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { return EINVAL; } else { __ensure(resp.error() == managarm::fs::Errors::SUCCESS); *new_offset = resp.offset(); return 0; } } int sys_close(int fd) { SignalGuard sguard; managarm::posix::CloseRequest req(getSysdepsAllocator()); req.set_fd(fd); auto [offer, sendReq, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendReq.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::SUCCESS) { return 0; }else{ __ensure(!"Unexpected error"); __builtin_unreachable(); } } int sys_dup(int fd, int flags, int *newfd) { SignalGuard sguard; __ensure(!(flags & ~(O_CLOEXEC))); uint32_t proto_flags = 0; if(flags & O_CLOEXEC) proto_flags |= managarm::posix::OpenFlags::OF_CLOEXEC; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::DUP); req.set_fd(fd); req.set_flags(proto_flags); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if (resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; } else if (resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; } else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); } *newfd = resp.fd(); return 0; } int sys_dup2(int fd, int flags, int newfd) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::DUP2); req.set_fd(fd); req.set_newfd(newfd); req.set_flags(flags); auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if (resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; } else if (resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; } else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); } return 0; } int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *result) { SignalGuard sguard; managarm::posix::FstatAtRequest req(getSysdepsAllocator()); if (fsfdt == fsfd_target::path) { req.set_fd(AT_FDCWD); req.set_path(frg::string(getSysdepsAllocator(), path)); } else if (fsfdt == fsfd_target::fd) { flags |= AT_EMPTY_PATH; req.set_fd(fd); } else { __ensure(fsfdt == fsfd_target::fd_path); req.set_fd(fd); req.set_path(frg::string(getSysdepsAllocator(), path)); } if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) { return EINVAL; } if (!(flags & AT_EMPTY_PATH) && (!path || !strlen(path))) { return ENOENT; } req.set_flags(flags); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::BAD_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::NOT_A_DIRECTORY) { return ENOTDIR; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); memset(result, 0, sizeof(struct stat)); switch(resp.file_type()) { case managarm::posix::FileType::FT_REGULAR: result->st_mode = S_IFREG; break; case managarm::posix::FileType::FT_DIRECTORY: result->st_mode = S_IFDIR; break; case managarm::posix::FileType::FT_SYMLINK: result->st_mode = S_IFLNK; break; case managarm::posix::FileType::FT_CHAR_DEVICE: result->st_mode = S_IFCHR; break; case managarm::posix::FileType::FT_BLOCK_DEVICE: result->st_mode = S_IFBLK; break; case managarm::posix::FileType::FT_SOCKET: result->st_mode = S_IFSOCK; break; case managarm::posix::FileType::FT_FIFO: result->st_mode = S_IFIFO; break; default: __ensure(!resp.file_type()); } result->st_dev = 1; result->st_ino = resp.fs_inode(); result->st_mode |= resp.mode(); result->st_nlink = resp.num_links(); result->st_uid = resp.uid(); result->st_gid = resp.gid(); result->st_rdev = resp.ref_devnum(); result->st_size = resp.file_size(); result->st_atim.tv_sec = resp.atime_secs(); result->st_atim.tv_nsec = resp.atime_nanos(); result->st_mtim.tv_sec = resp.mtime_secs(); result->st_mtim.tv_nsec = resp.mtime_nanos(); result->st_ctim.tv_sec = resp.ctime_secs(); result->st_ctim.tv_nsec = resp.ctime_nanos(); result->st_blksize = 4096; result->st_blocks = resp.file_size() / 512 + 1; return 0; } } int sys_readlink(const char *path, void *data, size_t max_size, ssize_t *length) { SignalGuard sguard; managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::READLINK); req.set_path(frg::string(getSysdepsAllocator(), path)); auto [offer, send_req, recv_resp, recv_data] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline(), helix_ng::recvBuffer(data, max_size)) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); *length = recv_data.actualLength(); return 0; } } int sys_rmdir(const char *path) { SignalGuard sguard; managarm::posix::RmdirRequest req(getSysdepsAllocator()); req.set_path(frg::string(getSysdepsAllocator(), path)); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_ftruncate(int fd, size_t size) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_TRUNCATE); req.set_size(size); auto [offer, send_req, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { return EINVAL; } else { __ensure(resp.error() == managarm::fs::Errors::SUCCESS); return 0; } } int sys_fallocate(int fd, off_t offset, size_t size) { SignalGuard sguard; auto handle = getHandleForFd(fd); if (!handle) return EBADF; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::PT_FALLOCATE); req.set_rel_offset(offset); req.set_size(size); auto [offer, send_req, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::fs::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::fs::Errors::ILLEGAL_OPERATION_TARGET) { return EINVAL; }else if(resp.error() == managarm::fs::Errors::INSUFFICIENT_PERMISSIONS) { return EPERM; }else if(resp.error() == managarm::fs::Errors::ILLEGAL_ARGUMENT) { return EINVAL; }else{ __ensure(resp.error() == managarm::fs::Errors::SUCCESS); return 0; } return 0; } int sys_unlinkat(int fd, const char *path, int flags) { SignalGuard sguard; managarm::posix::UnlinkAtRequest req(getSysdepsAllocator()); req.set_fd(fd); req.set_path(frg::string(getSysdepsAllocator(), path)); req.set_flags(flags); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::RESOURCE_IN_USE) { return EBUSY; }else if(resp.error() == managarm::posix::Errors::IS_DIRECTORY) { return EISDIR; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_access(const char *path, int mode) { return sys_faccessat(AT_FDCWD, path, mode, 0); } int sys_faccessat(int dirfd, const char *pathname, int, int flags) { SignalGuard sguard; managarm::posix::AccessAtRequest req(getSysdepsAllocator()); req.set_path(frg::string(getSysdepsAllocator(), pathname)); req.set_fd(dirfd); req.set_flags(flags); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_flock(int fd, int opts) { SignalGuard sguard; managarm::fs::CntRequest req(getSysdepsAllocator()); req.set_req_type(managarm::fs::CntReqType::FLOCK); req.set_fd(fd); req.set_flock_flags(opts); auto handle = getHandleForFd(fd); if(!handle) { return EBADF; } auto [offer, send_req, recv_resp] = exchangeMsgsSync( handle, helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline()) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::WOULD_BLOCK) { return EWOULDBLOCK; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; } else { __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_isatty(int fd) { SignalGuard sguard; managarm::posix::IsTtyRequest req(getSysdepsAllocator()); req.set_fd(fd); auto [offer, sendReq, recvResp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(sendReq.error()); HEL_CHECK(recvResp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recvResp.data(), recvResp.length()); if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { return EBADF; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); if(resp.mode()) return 0; return ENOTTY; } } int sys_chmod(const char *pathname, mode_t mode) { return sys_fchmodat(AT_FDCWD, pathname, mode, 0); } int sys_fchmod(int fd, mode_t mode) { return sys_fchmodat(fd, "", mode, AT_EMPTY_PATH); } int sys_fchmodat(int fd, const char *pathname, mode_t mode, int flags) { SignalGuard sguard; managarm::posix::FchmodAtRequest req(getSysdepsAllocator()); req.set_fd(fd); req.set_path(frg::string(getSysdepsAllocator(), pathname)); req.set_mode(mode); req.set_flags(flags); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else if(resp.error() == managarm::posix::Errors::NOT_SUPPORTED) { return ENOTSUP; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags) { (void)dirfd; (void)pathname; (void)owner; (void)group; (void)flags; mlibc::infoLogger() << "mlibc: sys_fchownat is a stub!" << frg::endlog; return 0; } int sys_umask(mode_t mode, mode_t *old) { (void)mode; mlibc::infoLogger() << "mlibc: sys_umask is a stub, hardcoding 022!" << frg::endlog; *old = 022; return 0; } int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { SignalGuard sguard; managarm::posix::UtimensAtRequest req(getSysdepsAllocator()); req.set_fd(dirfd); if(pathname != nullptr) req.set_path(frg::string(getSysdepsAllocator(), pathname)); if(times) { req.set_atimeSec(times[0].tv_sec); req.set_atimeNsec(times[0].tv_nsec); req.set_mtimeSec(times[1].tv_sec); req.set_mtimeNsec(times[1].tv_nsec); } else { req.set_atimeSec(UTIME_NOW); req.set_atimeNsec(UTIME_NOW); req.set_mtimeSec(UTIME_NOW); req.set_mtimeNsec(UTIME_NOW); } req.set_flags(flags); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::FILE_NOT_FOUND) { return ENOENT; }else if(resp.error() == managarm::posix::Errors::NO_SUCH_FD) { return EBADF; }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; }else if(resp.error() == managarm::posix::Errors::NOT_SUPPORTED) { return ENOTSUP; }else{ __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } } int sys_getentropy(void *buffer, size_t length) { SignalGuard sguard; auto p = reinterpret_cast(buffer); size_t n = 0; while(n < length) { size_t chunk; HEL_CHECK(helGetRandomBytes(p + n, length - n, &chunk)); n+= chunk; } return 0; } int sys_gethostname(char *buffer, size_t bufsize) { SignalGuard sguard; mlibc::infoLogger() << "mlibc: gethostname always returns managarm" << frg::endlog; char name[10] = "managarm\0"; if(bufsize < 10) return ENAMETOOLONG; strncpy(buffer, name, 10); return 0; } int sys_fsync(int) { mlibc::infoLogger() << "mlibc: fsync is a stub" << frg::endlog; return 0; } int sys_memfd_create(const char *name, int flags, int *fd) { SignalGuard sguard; managarm::posix::MemFdCreateRequest req(getSysdepsAllocator()); req.set_name(frg::string(getSysdepsAllocator(), name)); req.set_flags(flags); auto [offer, send_head, send_tail, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadTail(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_head.error()); HEL_CHECK(send_tail.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; } *fd = resp.fd(); __ensure(resp.error() == managarm::posix::Errors::SUCCESS); return 0; } int sys_uname(struct utsname *buf) { __ensure(buf); mlibc::infoLogger() << "\e[31mmlibc: uname() returns static information\e[39m" << frg::endlog; strcpy(buf->sysname, "Managarm"); strcpy(buf->nodename, "managarm"); strcpy(buf->release, "0.0.1-rolling"); strcpy(buf->version, "Managarm is not Managram"); #if defined(__x86_64__) strcpy(buf->machine, "x86_64"); #elif defined (__aarch64__) strcpy(buf->machine, "aarch64"); #else # error Unknown architecture #endif return 0; } int sys_madvise(void *, size_t, int) { mlibc::infoLogger() << "mlibc: sys_madvise is a stub!" << frg::endlog; return 0; } int sys_ptsname(int fd, char *buffer, size_t length) { int index; if(int e = sys_ioctl(fd, TIOCGPTN, &index, NULL); e) return e; if((size_t)snprintf(buffer, length, "/dev/pts/%d", index) >= length) { return ERANGE; } return 0; } int sys_unlockpt(int fd) { int unlock = 0; if(int e = sys_ioctl(fd, TIOCSPTLCK, &unlock, NULL); e) return e; return 0; } } //namespace mlibc