Upgraded stat

Negative fd safeguard (EBADF)
Stat time is now tracked
Catching unknown open() flags
This commit is contained in:
Marek Ledworowski 2025-11-05 22:34:43 +01:00
parent 7b9cc2d481
commit 552a43b767
14 changed files with 179 additions and 94 deletions

View File

@ -138,19 +138,18 @@ s32 HostIO_POSIX::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat*
// statbuf->st_ino = st.st_ino;
statbuf->st_mode = st.st_mode;
// statbuf->st_nlink = st.st_nlink;
// statbuf->st_uid = st.st_uid; // always 0
// statbuf->st_gid = st.st_gid; // always 0
statbuf->st_uid = 0; // st.st_uid; // always 0
statbuf->st_gid = 0; // st.st_gid; // always 0
// statbuf->st_rdev = st.st_rdev;
statbuf->st_atim.tv_sec = st.st_atim.tv_sec;
statbuf->st_atim.tv_nsec = st.st_atim.tv_nsec;
statbuf->st_mtim.tv_sec = st.st_mtim.tv_sec;
statbuf->st_mtim.tv_nsec = st.st_mtim.tv_nsec;
statbuf->st_ctim.tv_sec = st.st_ctim.tv_sec;
statbuf->st_ctim.tv_nsec = st.st_ctim.tv_nsec;
statbuf->st_atim.tv_sec = st.st_atim.tv_sec; //
statbuf->st_mtim.tv_sec = st.st_mtim.tv_sec; //
statbuf->st_ctim.tv_sec = st.st_ctim.tv_sec; //
statbuf->st_birthtim.tv_sec = st.st_ctim.tv_sec; // just assuming these are the same
statbuf->st_birthtim.tv_nsec = 0; // st.st_ctim.tv_nsec;
statbuf->st_size = st.st_size;
statbuf->st_blocks = st.st_blocks;
statbuf->st_blksize = st.st_blksize;
// statbuf->st_blocks = st.st_blocks;
// statbuf->st_blksize = st.st_blksize;
// statbuf->st_flags = st.st_;
// statbuf->st_gen = st.st_;
@ -170,19 +169,27 @@ s32 HostIO_POSIX::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbu
// handled by QFS
// statbuf->st_dev = st.st_dev;
// statbuf->st_ino = st.st_ino;
// statbuf->st_nlink = st.st_nlink;
// TODO: make working
statbuf->st_mode = st.st_mode;
// statbuf->st_nlink = st.st_nlink;
statbuf->st_uid = 0; // st.st_uid; // always 0
statbuf->st_gid = 0; // st.st_gid; // always 0
// statbuf->st_rdev = st.st_rdev;
statbuf->st_atim.tv_sec = st.st_atim.tv_sec; //
statbuf->st_atim.tv_nsec = 0; // st.st_atim.tv_nsec;
statbuf->st_mtim.tv_sec = st.st_mtim.tv_sec; //
statbuf->st_mtim.tv_nsec = 0; // st.st_mtim.tv_nsec;
statbuf->st_ctim.tv_sec = st.st_ctim.tv_sec; //
statbuf->st_ctim.tv_nsec = 0; // st.st_ctim.tv_nsec;
statbuf->st_birthtim.tv_sec = st.st_ctim.tv_sec; // just assuming these are the same
statbuf->st_birthtim.tv_nsec = 0; // st.st_ctim.tv_nsec;
statbuf->st_size = st.st_size;
statbuf->st_blksize = st.st_blksize;
statbuf->st_blocks = st.st_blocks;
statbuf->st_atim.tv_sec = st.st_atim.tv_sec;
statbuf->st_atim.tv_nsec = st.st_atim.tv_nsec;
statbuf->st_mtim.tv_sec = st.st_mtim.tv_sec;
statbuf->st_mtim.tv_nsec = st.st_mtim.tv_nsec;
statbuf->st_ctim.tv_sec = st.st_ctim.tv_sec;
statbuf->st_ctim.tv_nsec = st.st_ctim.tv_nsec;
// statbuf->st_blocks = st.st_blocks;
// statbuf->st_blksize = st.st_blksize;
// statbuf->st_flags = st.st_;
// statbuf->st_gen = st.st_;
// statbuf->st_lspare = st.st_;
return 0;
}

View File

@ -24,6 +24,9 @@ HostIO_Virtual::HostIO_Virtual() = default;
HostIO_Virtual::~HostIO_Virtual() = default;
s32 HostIO_Virtual::Open(const fs::path& path, s32 flags, u16 mode) {
if (int remainder = flags & ~__QUASI_O_ALLFLAGS_AT_ONCE; remainder != 0)
LOG_WARNING(Kernel_Fs, "open() received unknown flags: {:x}", remainder);
if (nullptr == this->res)
return -QUASI_EINVAL;

View File

@ -25,8 +25,6 @@ s32 HostIO_Win32::Creat(const fs::path& path, u16 mode) {
s32 HostIO_Win32::Close(const s32 fd) {
errno = 0;
if (fd < 0)
return -EBADF;
s32 status = _close(fd);
return 0 == status ? 0 : -errno;
}

View File

@ -15,4 +15,9 @@
#define QUASI_O_EXCL 0x0800
#define QUASI_O_DSYNC 0x1000
#define QUASI_O_DIRECT 0x00010000
#define QUASI_O_DIRECTORY 0x00020000
#define QUASI_O_DIRECTORY 0x00020000
#define __QUASI_O_ALLFLAGS_AT_ONCE \
(QUASI_O_RDONLY | QUASI_O_WRONLY | QUASI_O_RDWR | QUASI_O_NONBLOCK | QUASI_O_APPEND | \
QUASI_O_FSYNC | QUASI_O_SYNC | QUASI_O_CREAT | QUASI_O_TRUNC | QUASI_O_EXCL | QUASI_O_DSYNC | \
QUASI_O_DIRECT | QUASI_O_DIRECTORY)

View File

@ -2,7 +2,9 @@
#pragma once
#include <ctime>
#include <vector>
#include <assert.h>
#include "common/types.h"
#include "common/va_ctx.h"
@ -21,6 +23,17 @@ public:
st.st_nlink = 0;
st.st_uid = 0;
st.st_gid = 0;
static_assert(sizeof(time_t) == 8, "Time is not stored in 64 bits");
st.st_birthtim.tv_sec = time(0);
st.st_birthtim.tv_nsec = 0;
st.st_ctim.tv_sec = time(0);
st.st_ctim.tv_nsec = 0;
st.st_mtim.tv_sec = time(0);
st.st_mtim.tv_nsec = 0;
st.st_atim.tv_sec = time(0);
st.st_atim.tv_nsec = 0;
}
virtual ~Inode() = default;
@ -29,6 +42,8 @@ public:
return -QUASI_ENOTTY;
}
// these don't make sense with anything that's not a device
// kept here to verify
virtual s64 read(void* buf, u64 count) {
return -QUASI_EBADF;
}
@ -37,6 +52,7 @@ public:
return -QUASI_EBADF;
}
// these 4 make sense everywhere
virtual s64 pread(void* buf, u64 count, s64 offset) {
return -QUASI_EBADF;
}
@ -161,6 +177,7 @@ public:
int chmod(u16 mode) {
u16* st_mode = &this->st.st_mode;
*st_mode = ((*st_mode) & (~0x1FF)) | (mode & 0x1FF);
st.st_birthtim.tv_sec = time(0);
return 0;
}
};

View File

@ -79,6 +79,11 @@ public:
blkid_t GetBlkId(void) {
return this->block_id;
}
void AdjustStat(Libraries::Kernel::OrbisKernelStat* statbuf) {
auto& s = statbuf->st_size;
statbuf->st_blksize = this->block_size;
statbuf->st_blocks = (1 + (s / this->ioblock_size)) * this->ioblock_size / this->block_size;
}
inode_ptr GetInodeByFileno(fileno_t fileno);
int Resolve(fs::path& path, Resolved& res);

View File

@ -420,6 +420,7 @@ void QFS::SyncHostImpl(partition_ptr part) {
LOG_ERROR(Kernel_Fs, "Cannot stat file: {}", entry_path.string());
continue;
}
part->AdjustStat(&new_inode->st);
}
} catch (const std::exception& e) {
LOG_CRITICAL(Kernel_Fs, "An error occurred when syncing [{}]: {}", host_path.string(),

View File

@ -16,6 +16,7 @@ inode_ptr QuasiDirectory::lookup(const std::string& name) {
auto it = entries.find(name);
if (it == entries.end())
return nullptr;
st.st_atim.tv_sec = time(0);
return it->second;
}
@ -27,6 +28,7 @@ int QuasiDirectory::link(const std::string& name, inode_ptr child) {
entries[name] = child;
if (!child->is_link())
child->st.st_nlink++;
st.st_mtim.tv_sec = time(0);
return 0;
}
@ -54,10 +56,12 @@ int QuasiDirectory::unlink(const std::string& name) {
// not referenced in original location anymore
target->st.st_nlink--;
entries.erase(it);
st.st_mtim.tv_sec = time(0);
return 0;
}
std::vector<std::string> QuasiDirectory::list() {
st.st_atim.tv_sec = time(0);
std::vector<std::string> r;
for (auto& p : entries)
r.push_back(p.first);

View File

@ -11,15 +11,17 @@ s64 QuasiFile::pread(void* buf, size_t count, s64 offset) {
auto size = &this->st.st_size;
auto end_pos = offset + count;
st.st_atim.tv_sec = time(0);
return end_pos > *size ? *size - offset : count;
}
s64 QuasiFile::pwrite(const void* buf, size_t count, s64 offset) {
auto size = &this->st.st_size;
auto& size = this->st.st_size;
auto end_pos = offset + count;
*size = end_pos > *size ? end_pos : *size;
size = end_pos > size ? end_pos : size;
st.st_mtim.tv_sec = time(0);
return count;
}
@ -27,6 +29,7 @@ s32 QuasiFile::ftruncate(s64 length) {
if (length < 0)
return -QUASI_EINVAL;
this->st.st_size = length;
st.st_mtim.tv_sec = time(0);
return 0;
}

View File

@ -12,6 +12,7 @@ Symlink::Symlink(fs::path target) : target(target) {
}
fs::path Symlink::follow(void) {
st.st_atim.tv_sec = time(0);
return target;
}
} // namespace QuasiFS

View File

@ -20,6 +20,7 @@ s64 VirtualFile::pread(void* buf, size_t count, s64 offset) {
static_cast<char*>(buf)[idx] = c;
}
st.st_atim.tv_sec = time(0);
return read_amt;
}
@ -34,6 +35,7 @@ s64 VirtualFile::pwrite(const void* buf, size_t count, s64 offset) {
for (u64 idx = offset; idx < *size; idx++)
this->data[idx] = static_cast<const char*>(buf)[idx];
st.st_mtim.tv_sec = time(0);
return count;
}
@ -42,6 +44,7 @@ s32 VirtualFile::ftruncate(s64 length) {
return -QUASI_EINVAL;
this->data.resize(length, 0);
this->st.st_size = length;
st.st_mtim.tv_sec = time(0);
return 0;
}

View File

@ -119,13 +119,18 @@ s32 QFS::OperationImpl::Creat(const fs::path& path, u16 mode) {
};
s32 QFS::OperationImpl::Close(s32 fd) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
if (fd <= 2)
LOG_ERROR(Kernel_Fs, "Closing std stream, this will have consequences fd={}", fd);
// if it fails, it fails
if (int hio_status = qfs.hio_driver.Close(handle->host_fd); hio_status < 0)
return hio_status;
int hio_status = qfs.hio_driver.Close(handle->host_fd);
// no further action is required, this is pro-forma
qfs.vio_driver.Close(fd);
@ -135,11 +140,10 @@ s32 QFS::OperationImpl::Close(s32 fd) {
if (fd < (qfs.open_fd.size() - 1)) {
qfs.open_fd.at(fd) = nullptr;
return 0;
}
} else
qfs.open_fd.pop_back();
qfs.open_fd.pop_back();
return 0;
return hio_status;
}
s32 QFS::OperationImpl::LinkSymbolic(const fs::path& src, const fs::path& dst) {
@ -323,6 +327,9 @@ s32 QFS::OperationImpl::Unlink(const fs::path& path) {
}
s32 QFS::OperationImpl::Flush(const s32 fd) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -354,6 +361,9 @@ s32 QFS::OperationImpl::Flush(const s32 fd) {
}
s32 QFS::OperationImpl::FSync(const s32 fd) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -422,6 +432,9 @@ s32 QFS::OperationImpl::Truncate(const fs::path& path, u64 length) {
}
s32 QFS::OperationImpl::FTruncate(const s32 fd, u64 length) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -455,6 +468,9 @@ s32 QFS::OperationImpl::FTruncate(const s32 fd, u64 length) {
}
s64 QFS::OperationImpl::LSeek(const s32 fd, u64 offset, SeekOrigin origin) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -497,6 +513,9 @@ void UpdateStatFromHost(Libraries::Kernel::OrbisKernelStat* vfs,
}
s64 QFS::OperationImpl::Write(const s32 fd, const void* buf, u64 count) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -528,6 +547,9 @@ s64 QFS::OperationImpl::Write(const s32 fd, const void* buf, u64 count) {
}
s64 QFS::OperationImpl::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -559,6 +581,9 @@ s64 QFS::OperationImpl::PWrite(const s32 fd, const void* buf, u64 count, u64 off
};
s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -590,6 +615,9 @@ s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) {
}
s64 QFS::OperationImpl::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
@ -710,93 +738,98 @@ s32 QFS::OperationImpl::Stat(const fs::path& path, Libraries::Kernel::OrbisKerne
}
partition_ptr part = res.mountpoint;
bool host_used = false;
int hio_status = 0;
// bool host_used = false;
// int hio_status = 0;
int vio_status = 0;
Libraries::Kernel::OrbisKernelStat hio_stat;
// Libraries::Kernel::OrbisKernelStat hio_stat;
Libraries::Kernel::OrbisKernelStat vio_stat;
if (part->IsHostMounted()) {
fs::path host_path_target{};
if (int hostpath_status = part->GetHostPath(host_path_target, res.local_path);
hostpath_status != 0)
return hostpath_status;
// if (part->IsHostMounted()) {
// fs::path host_path_target{};
// if (int hostpath_status = part->GetHostPath(host_path_target, res.local_path);
// hostpath_status != 0)
// return hostpath_status;
if (hio_status = qfs.hio_driver.Stat(host_path_target, &hio_stat); 0 != hio_status) {
// hosts operation must succeed in order to continue
return hio_status;
}
// if (hio_status = qfs.hio_driver.Stat(host_path_target, &hio_stat); 0 != hio_status) {
// // hosts operation must succeed in order to continue
// return hio_status;
// }
host_used = true;
}
// host_used = true;
// }
qfs.vio_driver.SetCtx(&res, host_used, nullptr);
// qfs.vio_driver.SetCtx(&res, host_used, nullptr);
qfs.vio_driver.SetCtx(&res, false, nullptr);
vio_status = qfs.vio_driver.Stat(res.local_path, &vio_stat);
qfs.vio_driver.ClearCtx();
if (host_used) {
vio_stat.st_mode = hio_stat.st_mode;
vio_stat.st_size = hio_stat.st_size;
vio_stat.st_blksize = hio_stat.st_blksize;
vio_stat.st_blocks = hio_stat.st_blocks;
vio_stat.st_atim.tv_sec = hio_stat.st_atim.tv_sec;
vio_stat.st_atim.tv_nsec = hio_stat.st_atim.tv_nsec;
vio_stat.st_mtim.tv_sec = hio_stat.st_mtim.tv_sec;
vio_stat.st_mtim.tv_nsec = hio_stat.st_mtim.tv_nsec;
vio_stat.st_ctim.tv_sec = hio_stat.st_ctim.tv_sec;
vio_stat.st_ctim.tv_nsec = hio_stat.st_ctim.tv_nsec;
}
// if (host_used) {
// vio_stat.st_mode = hio_stat.st_mode;
// vio_stat.st_size = hio_stat.st_size;
// vio_stat.st_blksize = hio_stat.st_blksize;
// vio_stat.st_blocks = hio_stat.st_blocks;
// vio_stat.st_atim.tv_sec = hio_stat.st_atim.tv_sec;
// vio_stat.st_atim.tv_nsec = hio_stat.st_atim.tv_nsec;
// vio_stat.st_mtim.tv_sec = hio_stat.st_mtim.tv_sec;
// vio_stat.st_mtim.tv_nsec = hio_stat.st_mtim.tv_nsec;
// vio_stat.st_ctim.tv_sec = hio_stat.st_ctim.tv_sec;
// vio_stat.st_ctim.tv_nsec = hio_stat.st_ctim.tv_nsec;
// }
memcpy(statbuf, &vio_stat, sizeof(Libraries::Kernel::OrbisKernelStat));
if (host_used && (hio_status != vio_status))
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
vio_status);
// if (host_used && (hio_status != vio_status))
// LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
// vio_status);
return vio_status;
}
s32 QFS::OperationImpl::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
bool host_used = false;
int hio_status = 0;
// bool host_used = false;
// int hio_status = 0;
int vio_status = 0;
Libraries::Kernel::OrbisKernelStat hio_stat;
// Libraries::Kernel::OrbisKernelStat hio_stat;
Libraries::Kernel::OrbisKernelStat vio_stat;
if (handle->IsHostBound()) {
int host_fd = handle->host_fd;
hio_status = qfs.hio_driver.FStat(host_fd, &hio_stat);
host_used = true;
}
// if (handle->IsHostBound()) {
// int host_fd = handle->host_fd;
// hio_status = qfs.hio_driver.FStat(host_fd, &hio_stat);
// host_used = true;
// }
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
qfs.vio_driver.SetCtx(nullptr, false, handle);
// qfs.vio_driver.SetCtx(nullptr, host_used, handle);
vio_status = qfs.vio_driver.FStat(fd, &vio_stat);
qfs.vio_driver.ClearCtx();
if (host_used) {
vio_stat.st_mode = hio_stat.st_mode;
vio_stat.st_size = hio_stat.st_size;
vio_stat.st_blksize = hio_stat.st_blksize;
vio_stat.st_blocks = hio_stat.st_blocks;
vio_stat.st_atim.tv_sec = hio_stat.st_atim.tv_sec;
vio_stat.st_atim.tv_nsec = hio_stat.st_atim.tv_nsec;
vio_stat.st_mtim.tv_sec = hio_stat.st_mtim.tv_sec;
vio_stat.st_mtim.tv_nsec = hio_stat.st_mtim.tv_nsec;
vio_stat.st_ctim.tv_sec = hio_stat.st_ctim.tv_sec;
vio_stat.st_ctim.tv_nsec = hio_stat.st_ctim.tv_nsec;
}
// if (host_used) {
// vio_stat.st_mode = hio_stat.st_mode;
// vio_stat.st_size = hio_stat.st_size;
// vio_stat.st_blksize = hio_stat.st_blksize;
// vio_stat.st_blocks = hio_stat.st_blocks;
// vio_stat.st_atim.tv_sec = hio_stat.st_atim.tv_sec;
// vio_stat.st_atim.tv_nsec = hio_stat.st_atim.tv_nsec;
// vio_stat.st_mtim.tv_sec = hio_stat.st_mtim.tv_sec;
// vio_stat.st_mtim.tv_nsec = hio_stat.st_mtim.tv_nsec;
// vio_stat.st_ctim.tv_sec = hio_stat.st_ctim.tv_sec;
// vio_stat.st_ctim.tv_nsec = hio_stat.st_ctim.tv_nsec;
// }
memcpy(statbuf, &vio_stat, sizeof(Libraries::Kernel::OrbisKernelStat));
if (host_used && (hio_status != vio_status))
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
vio_status);
// if (host_used && (hio_status != vio_status))
// LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
// vio_status);
return vio_status;
}
@ -840,6 +873,9 @@ s32 QFS::OperationImpl::Chmod(const fs::path& path, u16 mode) {
}
s32 QFS::OperationImpl::FChmod(const s32 fd, u16 mode) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;

View File

@ -27,6 +27,8 @@ enum class SaveDataDialogMode : u32 {
};
// dirty hack
// *dows pollutes a lot of defines from winnt.h and wingdi.h
// I'm sick and tired of it, so here we are
#ifdef DELETE
#undef DELETE
#endif
@ -34,7 +36,6 @@ enum class SaveDataDialogMode : u32 {
#undef ERROR
#endif
enum class DialogType : u32 {
SAVE = 1,
LOAD = 2,

View File

@ -165,9 +165,9 @@ void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
qfs->SyncHost();
qfs::printTree(qfs->GetRoot(), "/");
qfs::printTree(qfs->GetRoot(), "/");
return;
return;
}
void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
@ -421,14 +421,14 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
g_window = window.get();
// const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
// const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
if (!std::filesystem::exists(mount_data_dir)) {
std::filesystem::create_directory(mount_data_dir);
}
mnt->Mount(mount_data_dir, "/data"); // should just exist, manually create with game serial
// Mounting temp folders
//const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
// const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
if (std::filesystem::exists(mount_temp_dir)) {
// Temp folder should be cleared on each boot.
std::filesystem::remove_all(mount_temp_dir);
@ -437,14 +437,15 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
mnt->Mount(mount_temp_dir, "/temp0");
mnt->Mount(mount_temp_dir, "/temp");
// const auto& mount_download_dir =
// Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
// const auto& mount_download_dir =
// Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
if (!std::filesystem::exists(mount_download_dir)) {
std::filesystem::create_directory(mount_download_dir);
}
mnt->Mount(mount_download_dir, "/download0");
// const auto& mount_captures_dir = Common::FS::GetUserPath(Common::FS::PathType::CapturesDir);
// const auto& mount_captures_dir =
// Common::FS::GetUserPath(Common::FS::PathType::CapturesDir);
if (!std::filesystem::exists(mount_captures_dir)) {
std::filesystem::create_directory(mount_captures_dir);
}