Skip to content

Commit f000c70

Browse files
committed
chore: Update vendored sources to duckdb/duckdb@9bc963f
Merge pull request duckdb/duckdb#11297 from Mytherin/tryopenfile2
1 parent 69396e1 commit f000c70

33 files changed

+331
-174
lines changed

src/duckdb/src/common/enum_util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
#include "duckdb/common/exception_format_value.hpp"
5757
#include "duckdb/common/extra_type_info.hpp"
5858
#include "duckdb/common/file_buffer.hpp"
59-
#include "duckdb/common/file_system.hpp"
59+
#include "duckdb/common/file_open_flags.hpp"
6060
#include "duckdb/common/printer.hpp"
6161
#include "duckdb/common/sort/partition_state.hpp"
6262
#include "duckdb/common/types.hpp"

src/duckdb/src/common/file_system.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,40 @@ extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG)
4545

4646
namespace duckdb {
4747

48+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_READ;
49+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_WRITE;
50+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_DIRECT_IO;
51+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_FILE_CREATE;
52+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_FILE_CREATE_NEW;
53+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_APPEND;
54+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_PRIVATE;
55+
constexpr FileOpenFlags FileFlags::FILE_FLAGS_NULL_IF_NOT_EXISTS;
56+
57+
void FileOpenFlags::Verify() {
58+
#ifdef DEBUG
59+
bool is_read = flags & FileOpenFlags::FILE_FLAGS_READ;
60+
bool is_write = flags & FileOpenFlags::FILE_FLAGS_WRITE;
61+
bool is_create =
62+
(flags & FileOpenFlags::FILE_FLAGS_FILE_CREATE) || (flags & FileOpenFlags::FILE_FLAGS_FILE_CREATE_NEW);
63+
bool is_private = (flags & FileOpenFlags::FILE_FLAGS_PRIVATE);
64+
bool null_if_not_exists = flags & FileOpenFlags::FILE_FLAGS_NULL_IF_NOT_EXISTS;
65+
66+
// require either READ or WRITE (or both)
67+
D_ASSERT(is_read || is_write);
68+
// CREATE/Append flags require writing
69+
D_ASSERT(is_write || !(flags & FileOpenFlags::FILE_FLAGS_APPEND));
70+
D_ASSERT(is_write || !(flags & FileOpenFlags::FILE_FLAGS_FILE_CREATE));
71+
D_ASSERT(is_write || !(flags & FileOpenFlags::FILE_FLAGS_FILE_CREATE_NEW));
72+
// cannot combine CREATE and CREATE_NEW flags
73+
D_ASSERT(!(flags & FileOpenFlags::FILE_FLAGS_FILE_CREATE && flags & FileOpenFlags::FILE_FLAGS_FILE_CREATE_NEW));
74+
75+
// For is_private can only be set along with a create flag
76+
D_ASSERT(!is_private || is_create);
77+
// FILE_FLAGS_NULL_IF_NOT_EXISTS cannot be combined with CREATE/CREATE_NEW
78+
D_ASSERT(!(null_if_not_exists && is_create));
79+
#endif
80+
}
81+
4882
FileSystem::~FileSystem() {
4983
}
5084

@@ -286,8 +320,7 @@ string FileSystem::ExpandPath(const string &path) {
286320
}
287321

288322
// LCOV_EXCL_START
289-
unique_ptr<FileHandle> FileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock,
290-
FileCompressionType compression, FileOpener *opener) {
323+
unique_ptr<FileHandle> FileSystem::OpenFile(const string &path, FileOpenFlags flags, optional_ptr<FileOpener> opener) {
291324
throw NotImplementedException("%s: OpenFile is not implemented!", GetName());
292325
}
293326

src/duckdb/src/common/http_state.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ shared_ptr<HTTPState> HTTPState::TryGetState(ClientContext &context, bool create
7474
return http_state;
7575
}
7676

77-
shared_ptr<HTTPState> HTTPState::TryGetState(FileOpener *opener, bool create_on_missing) {
77+
shared_ptr<HTTPState> HTTPState::TryGetState(optional_ptr<FileOpener> opener, bool create_on_missing) {
7878
auto client_context = FileOpener::TryGetClientContext(opener);
7979
if (client_context) {
8080
return TryGetState(*client_context, create_on_missing);

src/duckdb/src/common/local_file_system.cpp

Lines changed: 37 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,16 @@ extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG)
4444
// See e.g.:
4545
// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
4646
#elif defined(__APPLE__)
47-
#include <TargetConditionals.h> // NOLINT
48-
#if not(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) // NOLINT
49-
#include <libproc.h> // NOLINT
50-
#endif // NOLINT
47+
#include <TargetConditionals.h>
48+
#if not(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
49+
#include <libproc.h>
50+
#endif
5151
#elif defined(_WIN32)
5252
#include <restartmanager.h>
5353
#endif
5454

5555
namespace duckdb {
5656

57-
static void AssertValidFileFlags(uint8_t flags) {
58-
#ifdef DEBUG
59-
bool is_read = flags & FileFlags::FILE_FLAGS_READ;
60-
bool is_write = flags & FileFlags::FILE_FLAGS_WRITE;
61-
bool is_create = (flags & FileFlags::FILE_FLAGS_FILE_CREATE) || (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW);
62-
bool is_private = (flags & FileFlags::FILE_FLAGS_PRIVATE);
63-
64-
// require either READ or WRITE (or both)
65-
D_ASSERT(is_read || is_write);
66-
// CREATE/Append flags require writing
67-
D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_APPEND));
68-
D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE));
69-
D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW));
70-
// cannot combine CREATE and CREATE_NEW flags
71-
D_ASSERT(!(flags & FileFlags::FILE_FLAGS_FILE_CREATE && flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW));
72-
73-
// For is_private can only be set along with a create flag
74-
D_ASSERT(!is_private || is_create);
75-
#endif
76-
}
77-
7857
#ifndef _WIN32
7958
bool LocalFileSystem::FileExists(const string &filename) {
8059
if (!filename.empty()) {
@@ -292,19 +271,19 @@ bool LocalFileSystem::IsPrivateFile(const string &path_p, FileOpener *opener) {
292271
return true;
293272
}
294273

295-
unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t flags, FileLockType lock_type,
296-
FileCompressionType compression, FileOpener *opener) {
274+
unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, FileOpenFlags flags,
275+
optional_ptr<FileOpener> opener) {
297276
auto path = FileSystem::ExpandPath(path_p, opener);
298-
if (compression != FileCompressionType::UNCOMPRESSED) {
277+
if (flags.Compression() != FileCompressionType::UNCOMPRESSED) {
299278
throw NotImplementedException("Unsupported compression type for default file system");
300279
}
301280

302-
AssertValidFileFlags(flags);
281+
flags.Verify();
303282

304283
int open_flags = 0;
305284
int rc;
306-
bool open_read = flags & FileFlags::FILE_FLAGS_READ;
307-
bool open_write = flags & FileFlags::FILE_FLAGS_WRITE;
285+
bool open_read = flags.OpenForReading();
286+
bool open_write = flags.OpenForWriting();
308287
if (open_read && open_write) {
309288
open_flags = O_RDWR;
310289
} else if (open_read) {
@@ -316,18 +295,18 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t f
316295
}
317296
if (open_write) {
318297
// need Read or Write
319-
D_ASSERT(flags & FileFlags::FILE_FLAGS_WRITE);
298+
D_ASSERT(flags.OpenForWriting());
320299
open_flags |= O_CLOEXEC;
321-
if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) {
300+
if (flags.CreateFileIfNotExists()) {
322301
open_flags |= O_CREAT;
323-
} else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) {
302+
} else if (flags.OverwriteExistingFile()) {
324303
open_flags |= O_CREAT | O_TRUNC;
325304
}
326-
if (flags & FileFlags::FILE_FLAGS_APPEND) {
305+
if (flags.OpenForAppending()) {
327306
open_flags |= O_APPEND;
328307
}
329308
}
330-
if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) {
309+
if (flags.DirectIO()) {
331310
#if defined(__sun) && defined(__SVR4)
332311
throw InvalidInputException("DIRECT_IO not supported on Solaris");
333312
#endif
@@ -341,7 +320,7 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t f
341320

342321
// Determine permissions
343322
mode_t filesec;
344-
if (flags & FileFlags::FILE_FLAGS_PRIVATE) {
323+
if (flags.CreatePrivateFile()) {
345324
open_flags |= O_EXCL; // Ensure we error on existing files or the permissions may not set
346325
filesec = 0600;
347326
} else {
@@ -352,6 +331,9 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t f
352331
int fd = open(path.c_str(), open_flags, filesec);
353332

354333
if (fd == -1) {
334+
if (flags.ReturnNullIfNotExists() && errno == ENOENT) {
335+
return nullptr;
336+
}
355337
throw IOException("Cannot open file \"%s\": %s", {{"errno", std::to_string(errno)}}, path, strerror(errno));
356338
}
357339
// #if defined(__DARWIN__) || defined(__APPLE__)
@@ -363,14 +345,14 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t f
363345
// }
364346
// }
365347
// #endif
366-
if (lock_type != FileLockType::NO_LOCK) {
348+
if (flags.Lock() != FileLockType::NO_LOCK) {
367349
// set lock on file
368350
// but only if it is not an input/output stream
369351
auto file_type = GetFileTypeInternal(fd);
370352
if (file_type != FileType::FILE_TYPE_FIFO && file_type != FileType::FILE_TYPE_SOCKET) {
371353
struct flock fl;
372354
memset(&fl, 0, sizeof fl);
373-
fl.l_type = lock_type == FileLockType::READ_LOCK ? F_RDLCK : F_WRLCK;
355+
fl.l_type = flags.Lock() == FileLockType::READ_LOCK ? F_RDLCK : F_WRLCK;
374356
fl.l_whence = SEEK_SET;
375357
fl.l_start = 0;
376358
fl.l_len = 0;
@@ -387,7 +369,7 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t f
387369
message = AdditionalProcessInfo(*this, fl.l_pid);
388370
}
389371

390-
if (lock_type == FileLockType::WRITE_LOCK) {
372+
if (flags.Lock() == FileLockType::WRITE_LOCK) {
391373
// maybe we can get a read lock instead and tell this to the user.
392374
fl.l_type = F_RDLCK;
393375
rc = fcntl(fd, F_SETLK, &fl);
@@ -776,20 +758,20 @@ bool LocalFileSystem::IsPrivateFile(const string &path_p, FileOpener *opener) {
776758
return true;
777759
}
778760

779-
unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t flags, FileLockType lock_type,
780-
FileCompressionType compression, FileOpener *opener) {
761+
unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, FileOpenFlags flags,
762+
optional_ptr<FileOpener> opener) {
781763
auto path = FileSystem::ExpandPath(path_p, opener);
782-
if (compression != FileCompressionType::UNCOMPRESSED) {
764+
if (flags.Compression() != FileCompressionType::UNCOMPRESSED) {
783765
throw NotImplementedException("Unsupported compression type for default file system");
784766
}
785-
AssertValidFileFlags(flags);
767+
flags.Verify();
786768

787769
DWORD desired_access;
788770
DWORD share_mode;
789771
DWORD creation_disposition = OPEN_EXISTING;
790772
DWORD flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
791-
bool open_read = flags & FileFlags::FILE_FLAGS_READ;
792-
bool open_write = flags & FileFlags::FILE_FLAGS_WRITE;
773+
bool open_read = flags.OpenForReading();
774+
bool open_write = flags.OpenForWriting();
793775
if (open_read && open_write) {
794776
desired_access = GENERIC_READ | GENERIC_WRITE;
795777
share_mode = 0;
@@ -803,30 +785,33 @@ unique_ptr<FileHandle> LocalFileSystem::OpenFile(const string &path_p, uint8_t f
803785
throw InternalException("READ, WRITE or both should be specified when opening a file");
804786
}
805787
if (open_write) {
806-
if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) {
788+
if (flags.CreateFileIfNotExists()) {
807789
creation_disposition = OPEN_ALWAYS;
808-
} else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) {
790+
} else if (flags.OverwriteExistingFile()) {
809791
creation_disposition = CREATE_ALWAYS;
810792
}
811793
}
812-
if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) {
794+
if (flags.DirectIO()) {
813795
flags_and_attributes |= FILE_FLAG_NO_BUFFERING;
814796
}
815797
auto unicode_path = WindowsUtil::UTF8ToUnicode(path.c_str());
816798
HANDLE hFile = CreateFileW(unicode_path.c_str(), desired_access, share_mode, NULL, creation_disposition,
817799
flags_and_attributes, NULL);
818800
if (hFile == INVALID_HANDLE_VALUE) {
801+
if (flags.ReturnNullIfNotExists() && GetLastError() == ERROR_FILE_NOT_FOUND) {
802+
return nullptr;
803+
}
819804
auto error = LocalFileSystem::GetLastErrorAsString();
820805

821806
auto better_error = AdditionalLockInfo(unicode_path);
822807
if (!better_error.empty()) {
823808
throw IOException(better_error);
809+
} else {
810+
throw IOException("Cannot open file \"%s\": %s", path.c_str(), error);
824811
}
825-
826-
throw IOException("Cannot open file \"%s\": %s", path.c_str(), error);
827812
}
828813
auto handle = make_uniq<WindowsFileHandle>(*this, path.c_str(), hFile);
829-
if (flags & FileFlags::FILE_FLAGS_APPEND) {
814+
if (flags.OpenForAppending()) {
830815
auto file_size = GetFileSize(*handle);
831816
SetFilePointer(*handle, file_size);
832817
}

src/duckdb/src/common/serializer/buffered_file_reader.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ namespace duckdb {
1010
BufferedFileReader::BufferedFileReader(FileSystem &fs, const char *path, FileLockType lock_type,
1111
optional_ptr<FileOpener> opener)
1212
: fs(fs), data(make_unsafe_uniq_array<data_t>(FILE_BUFFER_SIZE)), offset(0), read_data(0), total_read(0) {
13-
handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ, lock_type, FileSystem::DEFAULT_COMPRESSION, opener.get());
13+
handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ | lock_type, opener.get());
14+
file_size = fs.GetFileSize(*handle);
15+
}
16+
17+
BufferedFileReader::BufferedFileReader(FileSystem &fs, unique_ptr<FileHandle> handle_p)
18+
: fs(fs), data(make_unsafe_uniq_array<data_t>(FILE_BUFFER_SIZE)), offset(0), read_data(0),
19+
handle(std::move(handle_p)), total_read(0) {
1420
file_size = fs.GetFileSize(*handle);
1521
}
1622

@@ -51,6 +57,12 @@ void BufferedFileReader::Seek(uint64_t location) {
5157
read_data = offset = 0;
5258
}
5359

60+
void BufferedFileReader::Reset() {
61+
handle->Reset();
62+
total_read = 0;
63+
read_data = offset = 0;
64+
}
65+
5466
uint64_t BufferedFileReader::CurrentOffset() {
5567
return total_read + offset;
5668
}

src/duckdb/src/common/serializer/buffered_file_writer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
namespace duckdb {
88

99
// Remove this when we switch C++17: https://stackoverflow.com/a/53350948
10-
constexpr uint8_t BufferedFileWriter::DEFAULT_OPEN_FLAGS;
10+
constexpr FileOpenFlags BufferedFileWriter::DEFAULT_OPEN_FLAGS;
1111

12-
BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path_p, uint8_t open_flags)
12+
BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path_p, FileOpenFlags open_flags)
1313
: fs(fs), path(path_p), data(make_unsafe_uniq_array<data_t>(FILE_BUFFER_SIZE)), offset(0), total_written(0) {
14-
handle = fs.OpenFile(path, open_flags, FileLockType::WRITE_LOCK);
14+
handle = fs.OpenFile(path, open_flags | FileLockType::WRITE_LOCK);
1515
}
1616

1717
int64_t BufferedFileWriter::GetFileSize() {

src/duckdb/src/common/virtual_file_system.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ VirtualFileSystem::VirtualFileSystem() : default_fs(FileSystem::CreateLocal()) {
99
VirtualFileSystem::RegisterSubSystem(FileCompressionType::GZIP, make_uniq<GZipFileSystem>());
1010
}
1111

12-
unique_ptr<FileHandle> VirtualFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock,
13-
FileCompressionType compression, FileOpener *opener) {
12+
unique_ptr<FileHandle> VirtualFileSystem::OpenFile(const string &path, FileOpenFlags flags,
13+
optional_ptr<FileOpener> opener) {
14+
auto compression = flags.Compression();
1415
if (compression == FileCompressionType::AUTO_DETECT) {
1516
// auto detect compression settings based on file name
1617
auto lower_path = StringUtil::Lower(path);
@@ -26,8 +27,12 @@ unique_ptr<FileHandle> VirtualFileSystem::OpenFile(const string &path, uint8_t f
2627
compression = FileCompressionType::UNCOMPRESSED;
2728
}
2829
}
29-
// open the base file handle
30-
auto file_handle = FindFileSystem(path).OpenFile(path, flags, lock, FileCompressionType::UNCOMPRESSED, opener);
30+
// open the base file handle in UNCOMPRESSED mode
31+
flags.SetCompression(FileCompressionType::UNCOMPRESSED);
32+
auto file_handle = FindFileSystem(path).OpenFile(path, flags, opener);
33+
if (!file_handle) {
34+
return nullptr;
35+
}
3136
if (file_handle->GetType() == FileType::FILE_TYPE_FIFO) {
3237
file_handle = PipeFileSystem::OpenPipe(std::move(file_handle));
3338
} else if (compression != FileCompressionType::UNCOMPRESSED) {
@@ -36,7 +41,7 @@ unique_ptr<FileHandle> VirtualFileSystem::OpenFile(const string &path, uint8_t f
3641
throw NotImplementedException(
3742
"Attempting to open a compressed file, but the compression type is not supported");
3843
}
39-
file_handle = entry->second->OpenCompressedFile(std::move(file_handle), flags & FileFlags::FILE_FLAGS_WRITE);
44+
file_handle = entry->second->OpenCompressedFile(std::move(file_handle), flags.OpenForWriting());
4045
}
4146
return file_handle;
4247
}
@@ -103,6 +108,7 @@ bool VirtualFileSystem::FileExists(const string &filename) {
103108
bool VirtualFileSystem::IsPipe(const string &filename) {
104109
return FindFileSystem(filename).IsPipe(filename);
105110
}
111+
106112
void VirtualFileSystem::RemoveFile(const string &filename) {
107113
FindFileSystem(filename).RemoveFile(filename);
108114
}

src/duckdb/src/execution/operator/csv_scanner/buffer_manager/csv_file_handle.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ CSVFileHandle::CSVFileHandle(FileSystem &fs, Allocator &allocator, unique_ptr<Fi
1414

1515
unique_ptr<FileHandle> CSVFileHandle::OpenFileHandle(FileSystem &fs, Allocator &allocator, const string &path,
1616
FileCompressionType compression) {
17-
auto file_handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ, FileLockType::NO_LOCK, compression);
17+
auto file_handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ | compression);
1818
if (file_handle->CanSeek()) {
1919
file_handle->Reset();
2020
}

src/duckdb/src/execution/operator/persistent/physical_export.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ static void WriteCatalogEntries(stringstream &ss, vector<reference<CatalogEntry>
2929

3030
static void WriteStringStreamToFile(FileSystem &fs, stringstream &ss, const string &path) {
3131
auto ss_string = ss.str();
32-
auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE_NEW,
33-
FileLockType::WRITE_LOCK);
32+
auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE_NEW |
33+
FileLockType::WRITE_LOCK);
3434
fs.Write(*handle, (void *)ss_string.c_str(), ss_string.size());
3535
handle.reset();
3636
}

src/duckdb/src/function/pragma/pragma_queries.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ string PragmaImportDatabase(ClientContext &context, const FunctionParameters &pa
139139
vector<string> files = {"schema.sql", "load.sql"};
140140
for (auto &file : files) {
141141
auto file_path = fs.JoinPath(parameters.values[0].ToString(), file);
142-
auto handle = fs.OpenFile(file_path, FileFlags::FILE_FLAGS_READ, FileSystem::DEFAULT_LOCK,
143-
FileSystem::DEFAULT_COMPRESSION);
142+
auto handle = fs.OpenFile(file_path, FileFlags::FILE_FLAGS_READ);
144143
auto fsize = fs.GetFileSize(*handle);
145144
auto buffer = make_unsafe_uniq_array<char>(fsize);
146145
fs.Read(*handle, buffer.get(), fsize);

0 commit comments

Comments
 (0)