/* * Copyright (c) 2021-2022, Andreas Kling * Copyright (c) 2021-2022, Kenneth Myhra * Copyright (c) 2021-2022, Sam Atkins * Copyright (c) 2022, Matthias Zimmerman * Copyright (c) 2023, Cameron Youell * Copyright (c) 2024, stasoid * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include namespace Core::System { ErrorOr open(StringView path, int options, mode_t mode) { ByteString string_path = path; auto sz_path = string_path.characters(); int rc = _open(sz_path, options, mode); if (rc < 0) { int error = errno; struct stat st = {}; if (::stat(sz_path, &st) == 0 && (st.st_mode & S_IFDIR)) { HANDLE dir_handle = CreateFile(sz_path, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (dir_handle == INVALID_HANDLE_VALUE) return Error::from_windows_error(GetLastError()); int dir_fd = _open_osfhandle((intptr_t)dir_handle, 0); if (dir_fd != -1) return dir_fd; } return Error::from_syscall("open"sv, -error); } return rc; } ErrorOr close(int fd) { if (_close(fd) < 0) return Error::from_syscall("close"sv, -errno); return {}; } ErrorOr read(int fd, Bytes buffer) { int rc = _read(fd, buffer.data(), buffer.size()); if (rc < 0) return Error::from_syscall("read"sv, -errno); return rc; } ErrorOr write(int fd, ReadonlyBytes buffer) { int rc = _write(fd, buffer.data(), buffer.size()); if (rc < 0) return Error::from_syscall("write"sv, -errno); return rc; } ErrorOr lseek(int fd, off_t offset, int whence) { long rc = _lseek(fd, offset, whence); if (rc < 0) return Error::from_syscall("lseek"sv, -errno); return rc; } ErrorOr ftruncate(int fd, off_t length) { long position = _tell(fd); if (position == -1) return Error::from_errno(errno); ScopeGuard restore_position { [&] { _lseek(fd, position, SEEK_SET); } }; auto result = lseek(fd, length, SEEK_SET); if (result.is_error()) return result.release_error(); if (SetEndOfFile((HANDLE)_get_osfhandle(fd)) == 0) return Error::from_windows_error(GetLastError()); return {}; } ErrorOr fstat(int fd) { struct stat st = {}; if (::fstat(fd, &st) < 0) return Error::from_syscall("fstat"sv, -errno); return st; } ErrorOr ioctl(int, unsigned, ...) { dbgln("Core::System::ioctl() is not implemented"); VERIFY_NOT_REACHED(); } ErrorOr getcwd() { auto* cwd = _getcwd(nullptr, 0); if (!cwd) return Error::from_syscall("getcwd"sv, -errno); ByteString string_cwd(cwd); free(cwd); return string_cwd; } ErrorOr stat(StringView path) { if (path.is_null()) return Error::from_syscall("stat"sv, -EFAULT); struct stat st = {}; ByteString path_string = path; if (::stat(path_string.characters(), &st) < 0) return Error::from_syscall("stat"sv, -errno); return st; } ErrorOr rmdir(StringView path) { if (path.is_null()) return Error::from_errno(EFAULT); ByteString path_string = path; if (_rmdir(path_string.characters()) < 0) return Error::from_syscall("rmdir"sv, -errno); return {}; } ErrorOr unlink(StringView path) { if (path.is_null()) return Error::from_errno(EFAULT); ByteString path_string = path; if (_unlink(path_string.characters()) < 0) return Error::from_syscall("unlink"sv, -errno); return {}; } ErrorOr mkdir(StringView path, mode_t) { ByteString str = path; if (_mkdir(str.characters()) < 0) return Error::from_syscall("mkdir"sv, -errno); return {}; } ErrorOr openat(int, StringView, int, mode_t) { dbgln("Core::System::openat() is not implemented"); VERIFY_NOT_REACHED(); } ErrorOr fstatat(int, StringView, int) { dbgln("Core::System::fstatat() is not implemented"); VERIFY_NOT_REACHED(); } ErrorOr mmap(void* address, size_t size, int protection, int flags, int fd, off_t offset, size_t alignment, StringView) { // custom alignment is not supported VERIFY(!alignment); void* ptr = ::mmap(address, size, protection, flags, fd, offset); if (ptr == MAP_FAILED) return Error::from_syscall("mmap"sv, -errno); return ptr; } ErrorOr munmap(void* address, size_t size) { if (::munmap(address, size) < 0) return Error::from_syscall("munmap"sv, -errno); return {}; } }