diff --git a/src/kernel/fileSystem.cpp b/src/kernel/fileSystem.cpp index c4d5e65..2c42025 100644 --- a/src/kernel/fileSystem.cpp +++ b/src/kernel/fileSystem.cpp @@ -64,6 +64,7 @@ struct File { std::filesystem::path real_name; std::atomic_bool opened; std::atomic_bool directory; + std::atomic_bool writable; std::atomic_bool append; std::atomic_bool sync_writes; SpecialFile special; @@ -129,6 +130,7 @@ int FileDescriptors::CreateDescriptor() { auto* file = new File {}; file->opened = false; file->directory = false; + file->writable = false; file->append = false; file->sync_writes = false; file->special = SpecialFile::None; @@ -408,6 +410,7 @@ int KYTY_SYSV_ABI KernelOpen(const char* path, int flags, uint16_t mode) { EXIT_IF(file == nullptr || file->opened || file->directory); file->name = path; + file->writable = rw_mode != Common::File::Mode::Read; file->append = append; file->sync_writes = fsync || sync || dsync; @@ -953,6 +956,47 @@ int KYTY_SYSV_ABI KernelFstat(int d, FileStat* sb) { return OK; } +int KYTY_SYSV_ABI KernelFtruncate(int d, int64_t length) { + PRINT_NAME(); + + if (d < DESCRIPTOR_MIN) { + return KERNEL_ERROR_EBADF; + } + + if (length < 0) { + return KERNEL_ERROR_EINVAL; + } + + if (::Libs::Network::Net::IsSocket(d)) { + return KERNEL_ERROR_EINVAL; + } + + auto* file = g_files->GetFile(d); + + if (file == nullptr || !file->opened) { + return KERNEL_ERROR_EBADF; + } + + if (!file->writable) { + return KERNEL_ERROR_EBADF; + } + + if (file->directory || file->special != SpecialFile::None) { + return KERNEL_ERROR_EINVAL; + } + + Common::LockGuard lock(file->mutex); + + if (file->f.IsInvalid() || !file->f.Truncate(static_cast(length))) { + return KERNEL_ERROR_EIO; + } + + LOGF("\tFtruncate (size = %" PRId64 ") file: %s\n", length, + Common::PathToString(file->real_name).c_str()); + + return OK; +} + int KYTY_SYSV_ABI KernelUnlink(const char* path) { PRINT_NAME(); diff --git a/src/kernel/fileSystem.h b/src/kernel/fileSystem.h index 0c5e553..bc73d18 100644 --- a/src/kernel/fileSystem.h +++ b/src/kernel/fileSystem.h @@ -48,6 +48,7 @@ int64_t KYTY_SYSV_ABI KernelPwrite(int d, const void* buf, size_t nbytes, int64_ int64_t KYTY_SYSV_ABI KernelLseek(int d, int64_t offset, int whence); int KYTY_SYSV_ABI KernelStat(const char* path, FileStat* sb); int KYTY_SYSV_ABI KernelFstat(int d, FileStat* sb); +int KYTY_SYSV_ABI KernelFtruncate(int d, int64_t length); int KYTY_SYSV_ABI KernelUnlink(const char* path); int KYTY_SYSV_ABI KernelRename(const char* from, const char* to); int KYTY_SYSV_ABI KernelGetdirentries(int fd, char* buf, int nbytes, int64_t* basep); diff --git a/src/libs/libKernel.cpp b/src/libs/libKernel.cpp index 4646fd2..0b5f717 100644 --- a/src/libs/libKernel.cpp +++ b/src/libs/libKernel.cpp @@ -2021,6 +2021,12 @@ int64_t KYTY_SYSV_ABI fstat(int d, LibKernel::FileSystem::FileStat* sb) { return POSIX_N_CALL(LibKernel::FileSystem::KernelFstat(d, sb)); } +int KYTY_SYSV_ABI ftruncate(int d, int64_t length) { + PRINT_NAME(); + + return POSIX_CALL(LibKernel::FileSystem::KernelFtruncate(d, length)); +} + int KYTY_SYSV_ABI socket(int family, int type, int protocol) { PRINT_NAME(); return Network::Net::Socket(family, type, protocol); @@ -2159,6 +2165,7 @@ LIB_DEFINE(InitLibKernel_1_Posix) { LIB_FUNC("yS8U2TGCe1A", nanosleep); LIB_FUNC("E6ao34wPw+U", stat); LIB_FUNC("JGMio+21L4c", mkdir); + LIB_FUNC("ih4CD9-gghM", Posix::ftruncate); LIB_FUNC("pDuPEf3m4fI", Posix::sem_init); LIB_FUNC("cDW233RAwWo", Posix::sem_destroy); LIB_FUNC("YCV5dGGBcCo", Posix::sem_wait);