mirror of
https://github.com/thunderbrewhq/bc.git
synced 2025-12-12 01:52:30 +00:00
refactor(file): overhaul filesystem for better accuracy, add some new features too
This commit is contained in:
parent
e674242b47
commit
5d96890167
111 changed files with 3708 additions and 3420 deletions
29
bc/File.hpp
Normal file
29
bc/File.hpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef BC_FILE_HPP
|
||||
#define BC_FILE_HPP
|
||||
|
||||
#include "bc/file/Defines.hpp"
|
||||
#include "bc/file/Error.hpp"
|
||||
|
||||
#include "bc/file/SimpleGlob.hpp"
|
||||
|
||||
#include "bc/file/Close.hpp"
|
||||
#include "bc/file/Copy.hpp"
|
||||
#include "bc/file/CreateDirectory.hpp"
|
||||
#include "bc/file/Delete.hpp"
|
||||
#include "bc/file/Exists.hpp"
|
||||
#include "bc/file/GetFileInfo.hpp"
|
||||
#include "bc/file/GetPos.hpp"
|
||||
#include "bc/file/GetWorkingDirectory.hpp"
|
||||
#include "bc/file/IsAbsolutePath.hpp"
|
||||
#include "bc/file/MakeAbsolutePath.hpp"
|
||||
#include "bc/file/Move.hpp"
|
||||
#include "bc/file/Open.hpp"
|
||||
#include "bc/file/ProcessDirFast.hpp"
|
||||
#include "bc/file/Read.hpp"
|
||||
#include "bc/file/RemoveDirectory.hpp"
|
||||
#include "bc/file/SetAttributes.hpp"
|
||||
#include "bc/file/SetPos.hpp"
|
||||
#include "bc/file/SetWorkingDirectory.hpp"
|
||||
#include "bc/file/Write.hpp"
|
||||
|
||||
#endif
|
||||
19
bc/file/Close.cpp
Normal file
19
bc/file/Close.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "bc/file/Close.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Close(StreamRecord* file) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, close);
|
||||
parms.file = file;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->close(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
16
bc/file/Close.hpp
Normal file
16
bc/file/Close.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef BC_FILE_CLOSE_HPP
|
||||
#define BC_FILE_CLOSE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// close
|
||||
bool Close(StreamRecord* file);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
20
bc/file/Copy.cpp
Normal file
20
bc/file/Copy.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include "bc/file/Copy.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Copy(const char* src, const char* dst, bool overwrite) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, copy);
|
||||
parms.name = src;
|
||||
parms.newname = dst;
|
||||
parms.overwrite = overwrite;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->copy(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
13
bc/file/Copy.hpp
Normal file
13
bc/file/Copy.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BC_FILE_COPY_HPP
|
||||
#define BC_FILE_COPY_HPP
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// copy
|
||||
bool Copy(const char* src, const char* dst, bool overwrite);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
19
bc/file/CreateDirectory.cpp
Normal file
19
bc/file/CreateDirectory.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "bc/file/CreateDirectory.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool CreateDirectory(const char* name, bool recurse) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, mkdir);
|
||||
parms.name = name;
|
||||
parms.recurse = recurse;
|
||||
parms.set_acl = 0;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->mkdir(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
15
bc/file/CreateDirectory.hpp
Normal file
15
bc/file/CreateDirectory.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef BC_FILE_CREATE_DIRECTORY_HPP
|
||||
#define BC_FILE_CREATE_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// mkdir
|
||||
bool CreateDirectory(const char* name, bool recurse);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
|
|
@ -1,22 +1,9 @@
|
|||
#ifndef BC_FILE_DEFINES_HPP
|
||||
#define BC_FILE_DEFINES_HPP
|
||||
|
||||
// How many bytes to when translating stacked filesystem names to large, native file paths
|
||||
#define BC_FILE_MAX_PATH 1024
|
||||
|
||||
// File open/creation flags.
|
||||
// See Blizzard::File::Open() for more info
|
||||
#define BC_FILE_OPEN_READ 0x0001
|
||||
#define BC_FILE_OPEN_WRITE 0x0002
|
||||
#define BC_FILE_OPEN_SHARE_READ 0x0004
|
||||
#define BC_FILE_OPEN_SHARE_WRITE 0x0008
|
||||
#define BC_FILE_OPEN_TRUNCATE 0x0100
|
||||
#define BC_FILE_OPEN_ALWAYS 0x0200
|
||||
#define BC_FILE_OPEN_CREATE 0x0400
|
||||
#define BC_FILE_OPEN_MUST_NOT_EXIST 0x0800
|
||||
#define BC_FILE_OPEN_MUST_EXIST 0x1000
|
||||
|
||||
// File attribute flags
|
||||
// file attribute flags
|
||||
#define BC_FILE_ATTRIBUTE_READONLY 0x01
|
||||
#define BC_FILE_ATTRIBUTE_HIDDEN 0x02
|
||||
#define BC_FILE_ATTRIBUTE_SYSTEM 0x04
|
||||
|
|
@ -25,28 +12,28 @@
|
|||
#define BC_FILE_ATTRIBUTE_NORMAL 0x20
|
||||
#define BC_FILE_ATTRIBUTE_DIRECTORY 0x40
|
||||
|
||||
// File error codes
|
||||
// file error codes
|
||||
#define BC_FILE_ERROR_GENERIC_FAILURE 0
|
||||
#define BC_FILE_ERROR_ACCESS_DENIED 1
|
||||
#define BC_FILE_ERROR_FILE_NOT_FOUND 2
|
||||
#define BC_FILE_ERROR_BAD_FILE 3
|
||||
#define BC_FILE_ERROR_BUSY 4
|
||||
#define BC_FILE_ERROR_OOM 5
|
||||
#define BC_FILE_ERROR_INVALID_HANDLE 6
|
||||
#define BC_FILE_ERROR_READ 5
|
||||
#define BC_FILE_ERROR_WRITE 6
|
||||
#define BC_FILE_ERROR_END_OF_FILE 7
|
||||
#define BC_FILE_ERROR_INVALID_ARGUMENT 8
|
||||
#define BC_FILE_ERROR_UNIMPLEMENTED 9
|
||||
#define BC_FILE_ERROR_NO_SPACE_ON_DEVICE 11
|
||||
|
||||
// File SetPos whence
|
||||
// file SetPos whence
|
||||
#define BC_FILE_SEEK_START 0
|
||||
#define BC_FILE_SEEK_CURRENT 1
|
||||
#define BC_FILE_SEEK_END 2
|
||||
|
||||
// Error handling utilities
|
||||
// error handling utilities
|
||||
#define BC_FILE_SET_ERROR(errorcode) ::Blizzard::File::SetLastError(static_cast<int32_t>(errorcode))
|
||||
#define BC_FILE_SET_ERROR_MSG(errorcode, pfmt, ...) \
|
||||
::Blizzard::File::SetLastError(errorcode); \
|
||||
::Blizzard::File::AddToLastErrorStack(errorcode, ::Blizzard::String::QuickFormat<1024>(pfmt, ##__VA_ARGS__).Str(), 1)
|
||||
::Blizzard::File::AddToLastErrorStack(errorcode, ::Blizzard::String::QuickFormat<1024>(pfmt, ##__VA_ARGS__).ToString(), 1)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
19
bc/file/Delete.cpp
Normal file
19
bc/file/Delete.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "bc/file/Delete.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Delete(const char* name) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, unlink);
|
||||
parms.name = name;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->unlink(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
13
bc/file/Delete.hpp
Normal file
13
bc/file/Delete.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BC_FILE_DELETE_HPP
|
||||
#define BC_FILE_DELETE_HPP
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// unlink
|
||||
bool Delete(const char* name);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
28
bc/file/Error.cpp
Normal file
28
bc/file/Error.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "bc/file/Error.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// Functions
|
||||
|
||||
void SetLastError(int32_t errorcode) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void AddToLastErrorStack(int32_t errorcode, const char* msg, int32_t a3) {
|
||||
// TODO: use proper logging
|
||||
|
||||
char empty[] = "";
|
||||
|
||||
if (!msg) {
|
||||
msg = empty;
|
||||
}
|
||||
|
||||
fprintf(stderr, "[bc/file] %" PRIi32 ": '%s'\n", errorcode, msg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
17
bc/file/Error.hpp
Normal file
17
bc/file/Error.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef BC_FILE_ERROR_HPP
|
||||
#define BC_FILE_ERROR_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// Functions
|
||||
void SetLastError(int32_t errorcode);
|
||||
|
||||
void AddToLastErrorStack(int32_t errorcode, const char* msg, int32_t param_3);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
34
bc/file/Exists.cpp
Normal file
34
bc/file/Exists.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include "bc/file/Exists.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
uint32_t Exists(const char* name) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
|
||||
parms.op = offsetof(Filesystem, exists);
|
||||
parms.name = name;
|
||||
parms.info = &parms.noinfo;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
|
||||
if (name && fs && fs->exists(fs, &parms)) {
|
||||
return parms.info->filetype;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFile(const char* name) {
|
||||
return Exists(name) == 1;
|
||||
}
|
||||
|
||||
bool IsDirectory(const char* name) {
|
||||
return Exists(name) == 2;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
|
||||
21
bc/file/Exists.hpp
Normal file
21
bc/file/Exists.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef BC_FILE_EXISTS_HPP
|
||||
#define BC_FILE_EXISTS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// exists
|
||||
uint32_t Exists(const char* name);
|
||||
|
||||
// exists
|
||||
bool IsFile(const char* name);
|
||||
|
||||
// exists
|
||||
bool IsDirectory(const char* name);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
371
bc/file/File.cpp
371
bc/file/File.cpp
|
|
@ -1,371 +0,0 @@
|
|||
#include "bc/file/File.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// Functions
|
||||
|
||||
void SetLastError(int32_t errorcode) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void AddToLastErrorStack(int32_t errorcode, const char* msg, int32_t a3) {
|
||||
// TODO: use proper logging
|
||||
|
||||
char empty[] = "";
|
||||
|
||||
if (!msg) {
|
||||
msg = empty;
|
||||
}
|
||||
|
||||
fprintf(stderr, "[bc/file] %" PRIi32 ": '%s'\n", errorcode, msg);
|
||||
}
|
||||
|
||||
// In BlizzardCore parlance, a file only exists if its path points to a regular file. (not a directory)
|
||||
// i.e. directories are not considered to be file objects.
|
||||
bool Exists(const char* path) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileInfo info = {};
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = path;
|
||||
parms.info = &info;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Exists, &parms);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Flush(StreamRecord* stream) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.stream = stream;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Flush, &parms);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Alias of Exists.
|
||||
bool IsFile(const char* path) {
|
||||
return Exists(path);
|
||||
}
|
||||
|
||||
// Calls Exists internally, only checking whether it has the directory attribute instead of normal attribute
|
||||
bool IsDirectory(const char* path) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileInfo info = {};
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = path;
|
||||
parms.info = &info;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Exists, &parms);
|
||||
|
||||
return info.attributes & BC_FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
|
||||
// Delete a file.
|
||||
bool Delete(const char* path) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = path;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Delete, &parms);
|
||||
return status;
|
||||
}
|
||||
|
||||
bool IsAbsolutePath(const char* path) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = path;
|
||||
return manager->Do(Filesystem::Call::IsAbsolutePath, &parms);
|
||||
}
|
||||
|
||||
// Get file information about path, writing information to the passed info pointer.
|
||||
bool GetFileInfo(const char* path, FileInfo* info) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = path;
|
||||
parms.info = info;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::GetFileInfo, &parms);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Get file information from a StreamRecord, writing information to the passed info pointer.
|
||||
bool GetFileInfo(StreamRecord* stream, FileInfo* info) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.stream = stream;
|
||||
parms.info = info;
|
||||
|
||||
return manager->Do(Filesystem::Call::GetFileInfo, &parms);
|
||||
}
|
||||
|
||||
bool GetWorkingDirectory(char* path, size_t capacity) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.directory = path;
|
||||
parms.directorySize = capacity;
|
||||
|
||||
return manager->Do(Filesystem::Call::GetWorkingDirectory, &parms);
|
||||
}
|
||||
|
||||
bool SetWorkingDirectory(const char* path) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = path;
|
||||
|
||||
return manager->Do(Filesystem::Call::SetWorkingDirectory, &parms);
|
||||
}
|
||||
|
||||
// Get file information from a stream record, returning a file info pointer owned by StreamRecord
|
||||
// The FileInfo ptr returned is invalidated after a call to File::Close(stream)
|
||||
FileInfo* GetFileInfo(StreamRecord* stream) {
|
||||
static FileInfo s_noinfo = {};
|
||||
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return &s_noinfo;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.stream = stream;
|
||||
parms.info = nullptr;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::GetFileInfo, &parms);
|
||||
|
||||
if (status) {
|
||||
return parms.info;
|
||||
}
|
||||
|
||||
return &s_noinfo;
|
||||
}
|
||||
|
||||
bool MakeAbsolutePath(const char* rel, char* result, int32_t capacity, bool unkflag) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
|
||||
parms.filename = rel;
|
||||
parms.flag = unkflag;
|
||||
parms.directory = result;
|
||||
parms.directorySize = capacity;
|
||||
|
||||
return manager->Do(Filesystem::Call::MakeAbsolutePath, &parms);
|
||||
}
|
||||
|
||||
// Open a filename according to flags (see Defines.hpp)
|
||||
// if successful, will return true and referenced file object will be set
|
||||
bool Open(const char* filename, uint32_t flags, StreamRecord*& file) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
|
||||
parms.filename = filename;
|
||||
parms.flag = flags;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Open, &parms);
|
||||
|
||||
if (status) {
|
||||
file = parms.stream;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool SetAttributes(const char* filename, uint32_t attributes) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = filename;
|
||||
parms.flag = static_cast<uint32_t>(attributes);
|
||||
parms.mode = File::Mode::setperms;
|
||||
|
||||
return manager->Do(Filesystem::Call::SetAttributes, &parms);
|
||||
}
|
||||
|
||||
bool Close(StreamRecord* stream) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.stream = stream;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Close, &parms);
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Copy(const char* source, const char* destination, bool overwrite) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = source;
|
||||
parms.destination = destination;
|
||||
|
||||
return manager->Do(Filesystem::Call::Copy, &parms);
|
||||
}
|
||||
|
||||
bool CreateDirectory(const char* path, bool recursive) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
parms.filename = path;
|
||||
parms.flag = recursive;
|
||||
|
||||
return manager->Do(Filesystem::Call::CreateDirectory, &parms);
|
||||
}
|
||||
|
||||
bool ProcessDirFast(const char* path, void* param, ProcessDirCallback callback, bool unkflag) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
|
||||
parms.filename = path;
|
||||
parms.param = param;
|
||||
parms.flag = unkflag;
|
||||
parms.callback = callback;
|
||||
|
||||
return manager->Do(Filesystem::Call::ProcessDirFast, &parms);
|
||||
}
|
||||
|
||||
bool Read(StreamRecord* file, void* buffer, size_t bytesToRead, size_t* bytesRead) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
|
||||
parms.stream = file;
|
||||
parms.param = buffer;
|
||||
parms.size = bytesToRead;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Read, &parms);
|
||||
|
||||
if (bytesRead) {
|
||||
*bytesRead = static_cast<size_t>(parms.size);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Write(StreamRecord* file, void* buffer, size_t bytesToWrite, size_t* bytesWritten) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
|
||||
parms.stream = file;
|
||||
parms.param = buffer;
|
||||
parms.size = bytesToWrite;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::Write, &parms);
|
||||
|
||||
if (bytesWritten) {
|
||||
*bytesWritten = static_cast<size_t>(parms.size);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool SetPos(StreamRecord* file, int64_t pos, int32_t whence) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
|
||||
parms.stream = file;
|
||||
parms.position = pos;
|
||||
parms.whence = whence;
|
||||
|
||||
return manager->Do(Filesystem::Call::SetPos, &parms);
|
||||
}
|
||||
|
||||
bool GetPos(StreamRecord* file, int64_t& pos) {
|
||||
auto manager = System_File::Stacked::Manager();
|
||||
if (!manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
System_File::Stacked::FileParms parms = {};
|
||||
|
||||
parms.stream = file;
|
||||
parms.position = pos;
|
||||
|
||||
auto status = manager->Do(Filesystem::Call::GetPos, &parms);
|
||||
if (status) {
|
||||
pos = parms.position;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
#ifndef BC_FILE_FILE_HPP
|
||||
#define BC_FILE_FILE_HPP
|
||||
|
||||
#include "bc/Time.hpp"
|
||||
#include "bc/file/Defines.hpp"
|
||||
#include "bc/file/Types.hpp"
|
||||
#include "bc/system/file/System_File.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// Functions
|
||||
void SetLastError(int32_t errorcode);
|
||||
|
||||
void AddToLastErrorStack(int32_t errorcode, const char* msg, int32_t param_3);
|
||||
|
||||
bool Copy(const char* source, const char* destination, bool overwrite);
|
||||
|
||||
bool CreateDirectory(const char* path, bool recursive);
|
||||
|
||||
bool Delete(const char* path);
|
||||
|
||||
bool Exists(const char* path);
|
||||
|
||||
bool Flush(StreamRecord* stream);
|
||||
|
||||
bool IsFile(const char* path);
|
||||
|
||||
bool IsDirectory(const char* path);
|
||||
|
||||
bool IsAbsolutePath(const char* path);
|
||||
|
||||
bool GetFileInfo(const char* path, FileInfo* info);
|
||||
bool GetFileInfo(StreamRecord* stream, FileInfo* info);
|
||||
FileInfo* GetFileInfo(StreamRecord* stream);
|
||||
|
||||
bool GetWorkingDirectory(char* path, size_t capacity);
|
||||
|
||||
bool SetWorkingDirectory(const char* path);
|
||||
|
||||
bool MakeAbsolutePath(const char* rel, char* result, int32_t capacity, bool unkflag);
|
||||
|
||||
bool Open(const char* filename, uint32_t flags, StreamRecord*& stream);
|
||||
|
||||
bool Close(StreamRecord* stream);
|
||||
|
||||
bool SetAttributes(const char* filename, uint32_t attributes);
|
||||
|
||||
bool Read(StreamRecord* stream, void* buffer, size_t bytesToRead, size_t* bytesRead);
|
||||
|
||||
bool Write(StreamRecord* stream, void* buffer, size_t bytesToWrite, size_t* bytesWritten);
|
||||
|
||||
bool SetPos(StreamRecord* stream, int64_t pos, int32_t whence);
|
||||
|
||||
bool GetPos(StreamRecord* stream, int64_t& pos);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#include "bc/file/Filesystem.hpp"
|
||||
#include <cstddef>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Filesystem::Do(Filesystem::Call fscall, System_File::Stacked::FileParms* parms) {
|
||||
uint32_t callindex = static_cast<uint32_t>(fscall);
|
||||
// Mark byte offset of Call function.
|
||||
// Allows the filesystem stack to resume normal activity in case of a fallback
|
||||
parms->offset = offsetof(Filesystem, funcs) + (callindex * sizeof(uintptr_t));
|
||||
// Get filesystem call from array
|
||||
|
||||
auto func = reinterpret_cast<Filesystem::CallFunc>(this->funcs[callindex]);
|
||||
// Do call
|
||||
return func(this, parms);
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
|
|
@ -7,57 +7,49 @@
|
|||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
class Filesystem;
|
||||
|
||||
typedef bool (*Operation)(Filesystem* fs, System_File::Stacked::FileParms* parms);
|
||||
|
||||
// Filesystem describes the layout of a virtual filesystem.
|
||||
// It is linked to other Filesystems in a list structure.
|
||||
class Filesystem {
|
||||
public:
|
||||
enum class Call : uint32_t {
|
||||
SetWorkingDirectory,
|
||||
Close,
|
||||
Create,
|
||||
GetWorkingDirectory,
|
||||
ProcessDirFast,
|
||||
Exists,
|
||||
Flush,
|
||||
GetFileInfo,
|
||||
GetFreeSpace,
|
||||
GetPos,
|
||||
GetRootChars,
|
||||
IsAbsolutePath,
|
||||
IsReadOnly,
|
||||
MakeAbsolutePath,
|
||||
CreateDirectory,
|
||||
Move,
|
||||
Copy,
|
||||
Open,
|
||||
Read,
|
||||
ReadP,
|
||||
RemoveDirectory,
|
||||
SetCacheMode,
|
||||
SetEOF,
|
||||
SetAttributes,
|
||||
SetPos,
|
||||
Delete,
|
||||
Write,
|
||||
WriteP,
|
||||
Shutdown,
|
||||
EndOfCalls
|
||||
};
|
||||
|
||||
// I hate C++ enums
|
||||
static constexpr size_t s_numCalls = static_cast<size_t>(Call::EndOfCalls);
|
||||
|
||||
// One signature for all filesystem calls
|
||||
typedef bool (*CallFunc)(Filesystem*, System_File::Stacked::FileParms*);
|
||||
|
||||
// The source filesystem (where it was copied from)
|
||||
// You can tell if base == this, that it is the original stack and not part of the filesystem manager
|
||||
Filesystem* base;
|
||||
// The next filesystem (towards lower filesystems)
|
||||
Filesystem* next;
|
||||
CallFunc funcs[s_numCalls];
|
||||
|
||||
bool Do(Call call, System_File::Stacked::FileParms* parms);
|
||||
Operation cd;
|
||||
Operation close;
|
||||
Operation create;
|
||||
Operation cwd;
|
||||
Operation dirwalk;
|
||||
Operation exists;
|
||||
Operation flush;
|
||||
Operation getfileinfo;
|
||||
Operation getfreespace;
|
||||
Operation getpos;
|
||||
Operation getrootchars;
|
||||
Operation isabspath;
|
||||
Operation isreadonly;
|
||||
Operation makeabspath;
|
||||
Operation mkdir;
|
||||
Operation move;
|
||||
Operation copy;
|
||||
Operation open;
|
||||
Operation read;
|
||||
Operation readp;
|
||||
Operation rmdir;
|
||||
Operation setcachemode;
|
||||
Operation seteof;
|
||||
Operation setfileinfo;
|
||||
Operation setpos;
|
||||
Operation unlink;
|
||||
Operation write;
|
||||
Operation writep;
|
||||
Operation shutdown;
|
||||
};
|
||||
|
||||
} // namespace File
|
||||
|
|
|
|||
61
bc/file/GetFileInfo.cpp
Normal file
61
bc/file/GetFileInfo.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#include "bc/file/GetFileInfo.hpp"
|
||||
#include "bc/file/Types.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool GetFileInfo(const char* name, FileInfo* info) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, getfileinfo);
|
||||
parms.name = name;
|
||||
parms.file = nullptr;
|
||||
parms.setinfo = 0;
|
||||
parms.getinfo = 0xFFFFFFFF;
|
||||
parms.info = &parms.noinfo;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (fs && fs->getfileinfo(fs, &parms)) {
|
||||
*info = *parms.info;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FileInfo* GetFileInfo(StreamRecord* file) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, getfileinfo);
|
||||
parms.name = nullptr;
|
||||
parms.file = file;
|
||||
parms.setinfo = 0;
|
||||
parms.getinfo = 0xFFFFFFFF;
|
||||
parms.info = nullptr;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (fs && fs->getfileinfo(fs, &parms)) {
|
||||
return parms.info;
|
||||
}
|
||||
|
||||
static FileInfo s_noinfo = {};
|
||||
return &s_noinfo;
|
||||
}
|
||||
|
||||
bool GetFileInfo(StreamRecord* file, FileInfo* info) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, getfileinfo);
|
||||
parms.name = nullptr;
|
||||
parms.file = file;
|
||||
parms.info = nullptr;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (fs && fs->getfileinfo(fs, &parms)) {
|
||||
*info = *parms.info;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
22
bc/file/GetFileInfo.hpp
Normal file
22
bc/file/GetFileInfo.hpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef BC_FILE_GET_FILE_INFO_HPP
|
||||
#define BC_FILE_GET_FILE_INFO_HPP
|
||||
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// getfileinfo
|
||||
bool GetFileInfo(const char* name, FileInfo* info);
|
||||
|
||||
// getfileinfo
|
||||
FileInfo* GetFileInfo(StreamRecord* file);
|
||||
|
||||
// getfileinfo
|
||||
bool GetFileInfo(StreamRecord* file, FileInfo* info);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
|
||||
#endif
|
||||
25
bc/file/GetPos.cpp
Normal file
25
bc/file/GetPos.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include "bc/file/GetPos.hpp"
|
||||
#include "bc/file/Defines.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool GetPos(StreamRecord* file, int64_t& offset) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, getpos);
|
||||
parms.file = file;
|
||||
parms.offset = offset;
|
||||
parms.whence = BC_FILE_SEEK_CURRENT;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (!fs || !fs->setpos(fs, &parms)) {
|
||||
return false;
|
||||
}
|
||||
offset = parms.offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
17
bc/file/GetPos.hpp
Normal file
17
bc/file/GetPos.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef BC_FILE_GET_POS_HPP
|
||||
#define BC_FILE_GET_POS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// getpos
|
||||
bool GetPos(StreamRecord* file, int64_t& offset);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
|
||||
#endif
|
||||
21
bc/file/GetWorkingDirectory.cpp
Normal file
21
bc/file/GetWorkingDirectory.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include "bc/file/GetWorkingDirectory.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool GetWorkingDirectory(char* buffer, int32_t buffersize) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, cwd);
|
||||
parms.buffer = buffer;
|
||||
parms.buffersize = buffersize;
|
||||
|
||||
*buffer = '\0';
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->cwd(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
15
bc/file/GetWorkingDirectory.hpp
Normal file
15
bc/file/GetWorkingDirectory.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef BC_FILE_GET_WORKING_DIRECTORY_HPP
|
||||
#define BC_FILE_GET_WORKING_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// cwd
|
||||
bool GetWorkingDirectory(char* buffer, int32_t buffersize);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
19
bc/file/IsAbsolutePath.cpp
Normal file
19
bc/file/IsAbsolutePath.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "bc/file/IsAbsolutePath.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool IsAbsolutePath(const char* name) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, isabspath);
|
||||
parms.name = name;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->isabspath(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
12
bc/file/IsAbsolutePath.hpp
Normal file
12
bc/file/IsAbsolutePath.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef BC_FILE_IS_ABSOLUTE_PATH_HPP
|
||||
#define BC_FILE_IS_ABSOLUTE_PATH_HPP
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool IsAbsolutePath(const char* name);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
22
bc/file/MakeAbsolutePath.cpp
Normal file
22
bc/file/MakeAbsolutePath.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "bc/file/MakeAbsolutePath.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool MakeAbsolutePath(const char* name, char* buffer, int32_t buffersize, bool canonicalize) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, makeabspath);
|
||||
parms.name = name;
|
||||
parms.buffer = buffer;
|
||||
parms.buffersize = buffersize;
|
||||
parms.canonicalize = canonicalize;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->makeabspath(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
15
bc/file/MakeAbsolutePath.hpp
Normal file
15
bc/file/MakeAbsolutePath.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef BC_FILE_MAKE_ABSOLUTE_PATH_HPP
|
||||
#define BC_FILE_MAKE_ABSOLUTE_PATH_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// makeabspath
|
||||
bool MakeAbsolutePath(const char* name, char* buffer, int32_t buffersize, bool canonicalize);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
19
bc/file/Move.cpp
Normal file
19
bc/file/Move.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "bc/file/Move.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Move(const char* src, const char* dst) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, move);
|
||||
parms.name = src;
|
||||
parms.newname = dst;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->move(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
13
bc/file/Move.hpp
Normal file
13
bc/file/Move.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BC_FILE_MOVE_HPP
|
||||
#define BC_FILE_MOVE_HPP
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// move
|
||||
bool Move(const char* src, const char* dst);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
25
bc/file/Open.cpp
Normal file
25
bc/file/Open.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include "bc/file/Open.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Open(const char* name, int32_t mode, StreamRecord*& file) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, open);
|
||||
parms.name = name;
|
||||
parms.mode = mode;
|
||||
parms.file = nullptr;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (!fs || !fs->open(fs, &parms)) {
|
||||
return false;
|
||||
}
|
||||
file = parms.file;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
16
bc/file/Open.hpp
Normal file
16
bc/file/Open.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef BC_FILE_OPEN_HPP
|
||||
#define BC_FILE_OPEN_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// open
|
||||
bool Open(const char* name, int32_t mode, StreamRecord*& file);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
|
|
@ -1 +0,0 @@
|
|||
#include "bc/file/path/Path.hpp"
|
||||
22
bc/file/ProcessDirFast.cpp
Normal file
22
bc/file/ProcessDirFast.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "bc/file/ProcessDirFast.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool ProcessDirFast(const char* name, void* param, ProcessDirCallback callback, bool nofollow) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, dirwalk);
|
||||
parms.name = name;
|
||||
parms.dirwalkparam = param;
|
||||
parms.dirwalkcallback = callback;
|
||||
// parms.unk88 = false;
|
||||
parms.mode = nofollow;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->dirwalk(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
15
bc/file/ProcessDirFast.hpp
Normal file
15
bc/file/ProcessDirFast.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef BC_FILE_PROCESS_DIR_FAST_HPP
|
||||
#define BC_FILE_PROCESS_DIR_FAST_HPP
|
||||
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// dirwalk
|
||||
bool ProcessDirFast(const char* name, void* param, ProcessDirCallback callback, bool flag);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
41
bc/file/Read.cpp
Normal file
41
bc/file/Read.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include "bc/file/Read.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Read(StreamRecord* file, void* buffer, int32_t* count) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, read);
|
||||
parms.file = file;
|
||||
parms.data = buffer;
|
||||
parms.count = *count;
|
||||
*count = 0;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (!fs || !fs->read(fs, &parms)) {
|
||||
return false;
|
||||
}
|
||||
*count = parms.count;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Read(StreamRecord* file, void* buffer, int64_t offset, int32_t* count) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, readp);
|
||||
parms.file = file;
|
||||
parms.data = buffer;
|
||||
parms.offset = offset;
|
||||
parms.count = *count;
|
||||
*count = 0;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (!fs || !fs->readp(fs, &parms)) {
|
||||
return false;
|
||||
}
|
||||
*count = parms.count;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
19
bc/file/Read.hpp
Normal file
19
bc/file/Read.hpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef BC_FILE_READ_HPP
|
||||
#define BC_FILE_READ_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// read
|
||||
bool Read(StreamRecord* file, void* buffer, int32_t* count);
|
||||
|
||||
// readp
|
||||
bool Read(StreamRecord* file, void* buffer, int64_t offset, int32_t* count);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
90
bc/file/RemoveDirectory.cpp
Normal file
90
bc/file/RemoveDirectory.cpp
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#include "bc/file/RemoveDirectory.hpp"
|
||||
#include "bc/file/ProcessDirFast.hpp"
|
||||
#include "bc/file/Defines.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/file/SetAttributes.hpp"
|
||||
#include "bc/file/Exists.hpp"
|
||||
#include "bc/file/Delete.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/String.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool RemoveDirectory(const char* name) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, rmdir);
|
||||
parms.name = name;
|
||||
parms.recurse = false;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->rmdir(fs, &parms) : false;
|
||||
}
|
||||
|
||||
bool RemoveDirectoryAndContents(const char* name, bool noreadonly) {
|
||||
class Internal {
|
||||
public:
|
||||
struct RemoveDirectoryRecurseData {
|
||||
bool unk00;
|
||||
bool noreadonly;
|
||||
};
|
||||
|
||||
static bool RemoveDirectoryRecurse(RemoveDirectoryRecurseData* data, const char* name, bool noreadonly) {
|
||||
data->unk00 = true;
|
||||
data->noreadonly = noreadonly;
|
||||
|
||||
return File::ProcessDirFast(name, static_cast<void*>(data), Callback, false) && data->unk00;
|
||||
}
|
||||
|
||||
static bool Callback(const ProcessDirParms& dirwalkparms) {
|
||||
char name[BC_FILE_MAX_PATH];
|
||||
|
||||
auto rmdirdata = reinterpret_cast<RemoveDirectoryRecurseData*>(dirwalkparms.param);
|
||||
|
||||
bool removeditem = false;
|
||||
|
||||
if (dirwalkparms.isdir) {
|
||||
String::Format(name, BC_FILE_MAX_PATH, "%s%s/", dirwalkparms.dir, dirwalkparms.item);
|
||||
removeditem = File::RemoveDirectoryAndContents(name, true);
|
||||
} else {
|
||||
String::Format(name, BC_FILE_MAX_PATH, "%s%s", dirwalkparms.dir, dirwalkparms.item);
|
||||
|
||||
if (rmdirdata->noreadonly) {
|
||||
File::SetAttributes(name, BC_FILE_ATTRIBUTE_NORMAL);
|
||||
}
|
||||
|
||||
// TODO: ???
|
||||
// if (sub_44EFB0(name)) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
removeditem = File::Delete(name);
|
||||
}
|
||||
|
||||
if (!removeditem) {
|
||||
rmdirdata->unk00 = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (File::Exists(name) != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char path[BC_FILE_MAX_PATH];
|
||||
String::Copy(path, name, BC_FILE_MAX_PATH);
|
||||
String::ForceTrailingSeparator(path, BC_FILE_MAX_PATH, '\0');
|
||||
|
||||
Internal::RemoveDirectoryRecurseData rmdirdata;
|
||||
if (!Internal::RemoveDirectoryRecurse(&rmdirdata, path, noreadonly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return File::RemoveDirectory(name);
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
18
bc/file/RemoveDirectory.hpp
Normal file
18
bc/file/RemoveDirectory.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef BC_FILE_REMOVE_DIRECTORY_HPP
|
||||
#define BC_FILE_REMOVE_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// rmdir
|
||||
bool RemoveDirectory(const char* name);
|
||||
|
||||
// rmdir (-r)
|
||||
bool RemoveDirectoryAndContents(const char* name, bool a2);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
23
bc/file/SetAttributes.cpp
Normal file
23
bc/file/SetAttributes.cpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#include "bc/file/SetAttributes.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/file/Defines.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include <cstddef>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool SetAttributes(const char* name, int32_t attributes) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, setfileinfo);
|
||||
parms.name = name;
|
||||
parms.setinfo = BC_SYSTEM_FILE_INFO_ATTRIBUTES;
|
||||
parms.noinfo.attributes = attributes;
|
||||
parms.info = &parms.noinfo;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->setfileinfo(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
16
bc/file/SetAttributes.hpp
Normal file
16
bc/file/SetAttributes.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef BC_FILE_SET_ATTRIBUTES_HPP
|
||||
#define BC_FILE_SET_ATTRIBUTES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// setfileinfo
|
||||
bool SetAttributes(const char* name, int32_t attributes);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
|
||||
#endif
|
||||
20
bc/file/SetPos.cpp
Normal file
20
bc/file/SetPos.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include "bc/file/SetPos.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool SetPos(StreamRecord* file, int64_t offset, int32_t whence) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, setpos);
|
||||
parms.file = file;
|
||||
parms.offset = offset;
|
||||
parms.whence = whence;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->setpos(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
17
bc/file/SetPos.hpp
Normal file
17
bc/file/SetPos.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef BC_FILE_SET_POS_HPP
|
||||
#define BC_FILE_SET_POS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// setpos
|
||||
bool SetPos(StreamRecord* file, int64_t offset, int32_t whence);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
|
||||
#endif
|
||||
19
bc/file/SetWorkingDirectory.cpp
Normal file
19
bc/file/SetWorkingDirectory.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "bc/file/SetWorkingDirectory.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool SetWorkingDirectory(const char* name) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, cd);
|
||||
parms.name = name;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->cd(fs, &parms) : false;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
13
bc/file/SetWorkingDirectory.hpp
Normal file
13
bc/file/SetWorkingDirectory.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BC_FILE_SET_WORKING_DIRECTORY_HPP
|
||||
#define BC_FILE_SET_WORKING_DIRECTORY_HPP
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// cd
|
||||
bool SetWorkingDirectory(const char* name);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
72
bc/file/SimpleGlob.cpp
Normal file
72
bc/file/SimpleGlob.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#include "bc/file/SimpleGlob.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool SimpleGlob(const char* name, const char* pattern) {
|
||||
auto p = pattern;
|
||||
auto n = name;
|
||||
|
||||
while (true) {
|
||||
if (*p == '\0') {
|
||||
return !*n;
|
||||
}
|
||||
if (!*n && *p != '*') {
|
||||
return false;
|
||||
}
|
||||
if (*p == '*') {
|
||||
break;
|
||||
}
|
||||
if (*p == '?') {
|
||||
if (!*n) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (*p == '\\' && p[1]) {
|
||||
p++;
|
||||
}
|
||||
if (*p != *n) {
|
||||
if (tolower(static_cast<uint8_t>(*n)) != tolower(static_cast<uint8_t>(*p))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
p++;
|
||||
}
|
||||
|
||||
while (*p == '*') {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p) {
|
||||
if (*p != '?' && *p != '\\') {
|
||||
if (!*n) {
|
||||
return false;
|
||||
}
|
||||
while (*p != *n) {
|
||||
if (!*++n) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!*n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!SimpleGlob(n, p)) {
|
||||
n++;
|
||||
if (*n == '\0') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
12
bc/file/SimpleGlob.hpp
Normal file
12
bc/file/SimpleGlob.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef BC_FILE_SIMPLE_GLOB_HPP
|
||||
#define BC_FILE_SIMPLE_GLOB_HPP
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool SimpleGlob(const char* name, const char* pattern);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
#include "bc/time/Time.hpp"
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include <windows.h>
|
||||
typedef void* HANDLE;
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
|
@ -15,59 +15,57 @@ namespace File {
|
|||
|
||||
// Types
|
||||
|
||||
// Used by SetCacheMode
|
||||
enum Mode {
|
||||
setperms = 4,
|
||||
settimes = 16,
|
||||
nocache = 64
|
||||
read = 0x0001,
|
||||
write = 0x0002,
|
||||
shareread = 0x0004,
|
||||
sharewrite = 0x0008,
|
||||
nocache = 0x0040,
|
||||
temporary = 0x0080,
|
||||
truncate = 0x0100,
|
||||
append = 0x0200,
|
||||
create = 0x0400,
|
||||
mustnotexist = 0x0800,
|
||||
mustexist = 0x1000
|
||||
};
|
||||
|
||||
class FileInfo {
|
||||
public:
|
||||
Time::TimeRec* time;
|
||||
// The device ID storing this file.
|
||||
uint32_t device;
|
||||
// Tell if a file is a directory
|
||||
// read-only, hidden
|
||||
// See file/Defines.hpp for more
|
||||
uint32_t attributes;
|
||||
// Size in bytes
|
||||
const char* name;
|
||||
int32_t unk04;
|
||||
uint64_t size;
|
||||
// Note that these are Y2K time, not Unix
|
||||
Time::Timestamp accessTime;
|
||||
Time::Timestamp modificationTime;
|
||||
Time::Timestamp attributeModificationTime;
|
||||
int32_t attributes;
|
||||
Time::Timestamp createtime;
|
||||
Time::Timestamp writetime;
|
||||
Time::Timestamp accesstime;
|
||||
int32_t filetype;
|
||||
int32_t normal;
|
||||
};
|
||||
|
||||
class ProcessDirParms {
|
||||
public:
|
||||
const char* root = nullptr;
|
||||
const char* item = nullptr;
|
||||
bool itemIsDirectory = false;
|
||||
void* param = nullptr;
|
||||
const char* dir;
|
||||
const char* item;
|
||||
void* param;
|
||||
bool isdir;
|
||||
};
|
||||
|
||||
typedef bool (*ProcessDirCallback)(const ProcessDirParms&);
|
||||
|
||||
class StreamRecord {
|
||||
public:
|
||||
static constexpr size_t s_padPath = 80;
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
HANDLE filehandle;
|
||||
#endif
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
// File descriptor
|
||||
int32_t filefd;
|
||||
int filefd;
|
||||
#endif
|
||||
// Open flags
|
||||
uint32_t flags;
|
||||
// Determines whether info object is initialized
|
||||
bool hasInfo;
|
||||
FileInfo info;
|
||||
// The path of the opened file.
|
||||
char path[s_padPath];
|
||||
|
||||
int32_t mode;
|
||||
bool haveinfo;
|
||||
uint32_t unk0C;
|
||||
Blizzard::File::FileInfo info;
|
||||
int32_t* unk48;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
} // namespace File
|
||||
|
|
|
|||
57
bc/file/Write.cpp
Normal file
57
bc/file/Write.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "bc/file/Write.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/file/Types.hpp"
|
||||
#include "bc/system/file/Stacked.hpp"
|
||||
#include "bc/system/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
bool Write(StreamRecord* file, const void* data, int32_t count) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, write);
|
||||
parms.file = file;
|
||||
parms.data = const_cast<void*>(data);
|
||||
parms.offset = -1LL;
|
||||
parms.count = count;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
return fs ? fs->write(fs, &parms) : false;
|
||||
}
|
||||
|
||||
bool Write(StreamRecord* file, const void* data, int32_t* count) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, write);
|
||||
parms.file = file;
|
||||
parms.data = const_cast<void*>(data);
|
||||
parms.offset = -1LL;
|
||||
parms.count = *count;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (!fs || fs->write(fs, &parms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*count = parms.count;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Write(StreamRecord* file, const void* data, int64_t offset, int32_t* count) {
|
||||
System_File::Stacked::FileParms parms;
|
||||
parms.op = offsetof(Filesystem, writep);
|
||||
parms.file = file;
|
||||
parms.data = const_cast<void*>(data);
|
||||
parms.offset = offset;
|
||||
parms.count = *count;
|
||||
|
||||
auto fs = System_File::Stacked::s_manager;
|
||||
if (!fs || fs->writep(fs, &parms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*count = parms.count;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
22
bc/file/Write.hpp
Normal file
22
bc/file/Write.hpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef BC_FILE_WRITE_HPP
|
||||
#define BC_FILE_WRITE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
|
||||
// write
|
||||
bool Write(StreamRecord* file, const void* data, int32_t count);
|
||||
|
||||
// write
|
||||
bool Write(StreamRecord* file, const void* data, int32_t* count);
|
||||
|
||||
// writep
|
||||
bool Write(StreamRecord* file, const void* data, int64_t offset, int32_t* count);
|
||||
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
#include "bc/file/path/Path.hpp"
|
||||
#include "bc/file/path/Posix.hpp"
|
||||
#include "bc/String.hpp"
|
||||
#include "bc/Memory.hpp"
|
||||
#include "bc/Debug.hpp"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
namespace Path {
|
||||
|
||||
// Classes
|
||||
|
||||
QuickNative::QuickNative(const char* path) {
|
||||
this->size = 0;
|
||||
this->slowpath = nullptr;
|
||||
this->fastpath[0] = '\0';
|
||||
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Null byte
|
||||
constexpr size_t reserved = 1;
|
||||
|
||||
this->size = String::Length(path) + reserved;
|
||||
|
||||
char* nativePath = nullptr;
|
||||
|
||||
if (this->size < BC_FILE_MAX_PATH) {
|
||||
// (fast)
|
||||
nativePath = this->fastpath;
|
||||
MakeNativePath(path, this->fastpath, BC_FILE_MAX_PATH);
|
||||
} else {
|
||||
// (slow)
|
||||
this->slowpath = reinterpret_cast<char*>(Memory::Allocate(this->size));
|
||||
nativePath = this->slowpath;
|
||||
MakeNativePath(path, this->slowpath, this->size);
|
||||
}
|
||||
|
||||
#if defined(WHOA_SYSTEM_LINUX)
|
||||
// Linux typically does not involve a case-sensitive filesystem
|
||||
// For compatibility, try to find if this path exists in another case
|
||||
// This is much slower
|
||||
|
||||
// The size of the resolved path. Maybe be larger due to "./"
|
||||
size_t resolvedSize = this->size + 2;
|
||||
|
||||
auto resolvedPath = static_cast<char*>(Memory::Allocate(resolvedSize));
|
||||
resolvedPath[resolvedSize-1] = '\0';
|
||||
|
||||
bool wasResolved = ResolvePosixCasePath(nativePath, resolvedPath);
|
||||
if (!wasResolved) {
|
||||
Memory::Free(resolvedPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->slowpath != nullptr) {
|
||||
Memory::Free(this->slowpath);
|
||||
}
|
||||
|
||||
this->slowpath = resolvedPath;
|
||||
#endif
|
||||
}
|
||||
|
||||
QuickNative::~QuickNative() {
|
||||
if (this->slowpath != nullptr) {
|
||||
Memory::Free(this->slowpath);
|
||||
}
|
||||
}
|
||||
|
||||
const char* QuickNative::Str() {
|
||||
if (this->slowpath != nullptr) {
|
||||
return this->slowpath;
|
||||
}
|
||||
|
||||
return this->fastpath;
|
||||
}
|
||||
|
||||
size_t QuickNative::Size() {
|
||||
return this->size;
|
||||
}
|
||||
|
||||
// Functions
|
||||
|
||||
void ForceTrailingSeparator(char* buf, size_t bufMax, char sep) {
|
||||
if (buf == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If no separator character is provided, infer correct separator based on runes
|
||||
if (sep == '\0') {
|
||||
auto ptr = buf;
|
||||
|
||||
char ch;
|
||||
|
||||
while (true) {
|
||||
ch = *ptr++;
|
||||
// Make inference based on what data we have.
|
||||
if (ch == '/' || ch == '\\') {
|
||||
sep = ch;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '\0') {
|
||||
// Fail safe to the system's path separator.
|
||||
sep = BC_FILE_SYSTEM_PATH_SEPARATOR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Buffer needs at least two characters.
|
||||
if (bufMax < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Slice off the end of the path buffer, so that any existing* trailing separator is discarded.
|
||||
auto len = String::Length(buf);
|
||||
char ch = '\0';
|
||||
if (len > 0) {
|
||||
ch = buf[len - 1];
|
||||
}
|
||||
switch (ch) {
|
||||
case '/':
|
||||
case '\\':
|
||||
len--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Add (back*) trailing separator
|
||||
BLIZZARD_ASSERT(len <= bufMax - 2);
|
||||
buf[len] = sep;
|
||||
buf[len + 1] = '\0'; // pad null
|
||||
}
|
||||
|
||||
// Convert path to DOS-style.
|
||||
// the function will iterate through the path string, converting all occurrences of forward slashes (/) to backslashes (\)
|
||||
bool MakeBackslashPath(const char* path, char* result, size_t capacity) {
|
||||
size_t i = 0;
|
||||
size_t c = capacity - 1;
|
||||
|
||||
while (i <= c) {
|
||||
if (path[i] == '\0') {
|
||||
result[i] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
result[i] = path[i] == '/' ? '\\' : path[i];
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
result[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make a path string consistent before the last path separator.
|
||||
bool MakeConsistentPath(const char* path, char* result, size_t capacity) {
|
||||
if (!result || (capacity < 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!path || (capacity == 1)) {
|
||||
*result = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto i = capacity - 1; i != -1; i--) {
|
||||
auto ch = path[i];
|
||||
|
||||
switch (ch) {
|
||||
case '\\':
|
||||
return MakeBackslashPath(path, result, capacity);
|
||||
case '/':
|
||||
return MakeUnivPath(path, result, capacity);
|
||||
case '\0':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String::Copy(result, path, capacity);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert any path string into something that can be used on the current OS.
|
||||
bool MakeNativePath(const char* path, char* result, size_t capacity) {
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
return MakeWindowsPath(path, result, capacity);
|
||||
#else
|
||||
return MakeUnivPath(path, result, capacity);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Convert a path string into something UNIX-friendly.
|
||||
bool MakeUnivPath(const char* path, char* result, size_t capacity) {
|
||||
size_t i = 0; // path and result index
|
||||
size_t c = capacity - 1; // ceiling
|
||||
|
||||
while (i <= c) {
|
||||
if (path[i] == '\0') {
|
||||
result[i] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
result[i] = path[i] == '\\' ? '/' : path[i];
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
result[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MakeWindowsPath(const char* path, char* result, size_t capacity) {
|
||||
return MakeBackslashPath(path, result, capacity);
|
||||
}
|
||||
|
||||
} // namespace Path
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef BC_FILE_PATH_PATH_HPP
|
||||
#define BC_FILE_PATH_PATH_HPP
|
||||
|
||||
#include "bc/file/Defines.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace File {
|
||||
namespace Path {
|
||||
|
||||
// Classes
|
||||
|
||||
// Quick native path translation on the stack.
|
||||
// Can be slow in some instances, as it resorts to heap allocation if path size >= BC_FILE_MAX_PATH
|
||||
// Note: this name is an invention, however its behavior is repeated in all System_File implementations.
|
||||
// So it probably did exist as an inlined class.
|
||||
class QuickNative {
|
||||
private:
|
||||
size_t size;
|
||||
// stack allocation
|
||||
char fastpath[BC_FILE_MAX_PATH];
|
||||
// heap
|
||||
char* slowpath;
|
||||
|
||||
public:
|
||||
QuickNative(const char* path);
|
||||
~QuickNative();
|
||||
const char* Str();
|
||||
size_t Size();
|
||||
};
|
||||
|
||||
// Functions
|
||||
|
||||
void ForceTrailingSeparator(char* buf, size_t bufMax, char sep);
|
||||
|
||||
bool MakeBackslashPath(const char* path, char* result, size_t capacity);
|
||||
|
||||
bool MakeConsistentPath(const char* path, char* result, size_t capacity);
|
||||
|
||||
bool MakeNativePath(const char* path, char* result, size_t capacity);
|
||||
|
||||
bool MakeUnivPath(const char* path, char* result, size_t capacity);
|
||||
|
||||
bool MakeWindowsPath(const char* path, char* result, size_t capacity);
|
||||
|
||||
} // namespace Path
|
||||
} // namespace File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
#include "bc/file/path/Posix.hpp"
|
||||
|
||||
#if defined(WHOA_SYSTEM_LINUX)
|
||||
#include <cstring>
|
||||
#include <dirent.h>
|
||||
#include <alloca.h>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
// adapted from https://github.com/OneSadCookie/fcaseopen/blob/master/fcaseopen.c
|
||||
bool ResolvePosixCasePath(const char* path, char* r) {
|
||||
auto l = strlen(path);
|
||||
auto p = static_cast<char*>(alloca(l + 1));
|
||||
strcpy(p, path);
|
||||
size_t rl = 0;
|
||||
|
||||
DIR* d;
|
||||
if (p[0] == '/') {
|
||||
d = opendir("/");
|
||||
p = p + 1;
|
||||
} else {
|
||||
d = opendir(".");
|
||||
r[0] = '.';
|
||||
r[1] = 0;
|
||||
rl = 1;
|
||||
}
|
||||
|
||||
int32_t last = 0;
|
||||
auto c = strsep(&p, "/");
|
||||
while (c) {
|
||||
if (!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
closedir(d);
|
||||
return false;
|
||||
}
|
||||
|
||||
r[rl] = '/';
|
||||
rl += 1;
|
||||
r[rl] = 0;
|
||||
|
||||
struct dirent* e = readdir(d);
|
||||
while (e) {
|
||||
if (strcasecmp(c, e->d_name) == 0) {
|
||||
strcpy(r + rl, e->d_name);
|
||||
rl += strlen(e->d_name);
|
||||
|
||||
closedir(d);
|
||||
d = opendir(r);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
e = readdir(d);
|
||||
}
|
||||
|
||||
if (!e) {
|
||||
strcpy(r + rl, c);
|
||||
rl += strlen(c);
|
||||
last = 1;
|
||||
}
|
||||
|
||||
c = strsep(&p, "/");
|
||||
}
|
||||
|
||||
if (d) {
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef BC_FILE_PATH_POSIX_HPP
|
||||
#define BC_FILE_PATH_POSIX_HPP
|
||||
|
||||
bool ResolvePosixCasePath(const char* path, char* r);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,75 +1,25 @@
|
|||
#ifndef BC_OS_FILE_HPP
|
||||
#define BC_OS_FILE_HPP
|
||||
|
||||
#include "bc/file/Types.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum EOSFileDisposition {
|
||||
OS_CREATE_NEW = 1,
|
||||
OS_CREATE_ALWAYS = 2,
|
||||
OS_OPEN_EXISTING = 3,
|
||||
OS_OPEN_ALWAYS = 4,
|
||||
OS_TRUNCATE_EXISTING = 5
|
||||
};
|
||||
|
||||
enum EOSFileAccess {
|
||||
OS_GENERIC_ALL = 0x10000000,
|
||||
OS_GENERIC_EXECUTE = 0x20000000,
|
||||
OS_GENERIC_WRITE = 0x40000000,
|
||||
OS_GENERIC_READ = 0x80000000
|
||||
};
|
||||
|
||||
enum EOSFileShare {
|
||||
OS_FILE_SHARE_READ = 0x00000001,
|
||||
OS_FILE_SHARE_WRITE = 0x00000002
|
||||
};
|
||||
|
||||
enum EOSFileFlagsAndAttributes {
|
||||
OS_FILE_ATTRIBUTE_READONLY = 0x1,
|
||||
OS_FILE_ATTRIBUTE_HIDDEN = 0x2,
|
||||
OS_FILE_ATTRIBUTE_SYSTEM = 0x4,
|
||||
OS_FILE_ATTRIBUTE_DIRECTORY = 0x10,
|
||||
OS_FILE_ATTRIBUTE_ARCHIVE = 0x20,
|
||||
OS_FILE_ATTRIBUTE_NORMAL = 0x80,
|
||||
OS_FILE_ATTRIBUTE_TEMPORARY = 0x100,
|
||||
OS_FILE_ATTRIBUTE_OFFLINE = 0x1000,
|
||||
OS_FILE_ATTRIBUTE_ENCRYPTED = 0x4000,
|
||||
|
||||
OS_FILE_FLAG_OPEN_NO_RECALL = 0x00100000,
|
||||
OS_FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000,
|
||||
OS_FILE_FLAG_POSIX_SEMANTICS = 0x01000000,
|
||||
OS_FILE_FLAG_BACKUP_SEMANTICS = 0x02000000,
|
||||
OS_FILE_FLAG_DELETE_ON_CLOSE = 0x04000000,
|
||||
OS_FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000,
|
||||
OS_FILE_FLAG_RANDOM_ACCESS = 0x10000000,
|
||||
OS_FILE_FLAG_NO_BUFFERING = 0x20000000,
|
||||
OS_FILE_FLAG_OVERLAPPED = 0x40000000,
|
||||
OS_FILE_FLAG_WRITE_THROUGH = 0x80000000
|
||||
};
|
||||
|
||||
typedef Blizzard::File::StreamRecord* HOSFILE;
|
||||
|
||||
constexpr HOSFILE HOSFILE_INVALID = nullptr;
|
||||
|
||||
HOSFILE OsCreateFile(const char* fileName, uint32_t desiredAccess, uint32_t shareMode, uint32_t createDisposition, uint32_t flagsAndAttributes, uint32_t extendedFileType);
|
||||
|
||||
int32_t OsSetFileAttributes(const char* fileName, uint32_t attributes);
|
||||
|
||||
uint64_t OsGetFileSize(HOSFILE fileHandle);
|
||||
|
||||
int32_t OsWriteFile(HOSFILE fileHandle, void* buffer, size_t bytesToWrite, size_t* bytesWritten);
|
||||
|
||||
int32_t OsReadFile(HOSFILE fileHandle, void* buffer, size_t bytesToRead, size_t* bytesRead);
|
||||
|
||||
void OsCloseFile(HOSFILE fileHandle);
|
||||
|
||||
int64_t OsSetFilePointer(HOSFILE fileHandle, int64_t distanceToMove, uint32_t moveMethod);
|
||||
|
||||
int32_t OsSetCurrentDirectory(const char* pathName);
|
||||
|
||||
int32_t OsGetCurrentDirectory(size_t pathLen, char* pathName);
|
||||
|
||||
int32_t OsCreateDirectory(const char* pathName, int32_t recursive);
|
||||
#include "bc/os/file/CloseFile.hpp"
|
||||
#include "bc/os/file/CopyFile.hpp"
|
||||
#include "bc/os/file/CreateDirectory.hpp"
|
||||
#include "bc/os/file/CreateFile.hpp"
|
||||
#include "bc/os/file/DeleteFile.hpp"
|
||||
#include "bc/os/file/DirectoryExists.hpp"
|
||||
#include "bc/os/file/FileExists.hpp"
|
||||
#include "bc/os/file/FileList.hpp"
|
||||
#include "bc/os/file/GetCurrentDirectory.hpp"
|
||||
#include "bc/os/file/GetDownloadFolder.hpp"
|
||||
#include "bc/os/file/GetFileAttributes.hpp"
|
||||
#include "bc/os/file/GetFileSize.hpp"
|
||||
#include "bc/os/file/MoveFile.hpp"
|
||||
#include "bc/os/file/ReadFile.hpp"
|
||||
#include "bc/os/file/RemoveDirectory.hpp"
|
||||
#include "bc/os/file/RemoveDirectoryRecurse.hpp"
|
||||
#include "bc/os/file/SetCurrentDirectory.hpp"
|
||||
#include "bc/os/file/SetFileAttributes.hpp"
|
||||
#include "bc/os/file/SetFilePointer.hpp"
|
||||
#include "bc/os/file/WriteFile.hpp"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
6
bc/os/file/CloseFile.cpp
Normal file
6
bc/os/file/CloseFile.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "bc/os/file/CloseFile.hpp"
|
||||
#include "bc/file/Close.hpp"
|
||||
|
||||
void OsCloseFile(HOSFILE fileHandle) {
|
||||
Blizzard::File::Close(reinterpret_cast<Blizzard::File::StreamRecord*>(fileHandle));
|
||||
}
|
||||
8
bc/os/file/CloseFile.hpp
Normal file
8
bc/os/file/CloseFile.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_CLOSE_FILE_HPP
|
||||
#define BC_OS_FILE_CLOSE_FILE_HPP
|
||||
|
||||
#include "bc/os/file/Types.hpp"
|
||||
|
||||
void OsCloseFile(HOSFILE fileHandle);
|
||||
|
||||
#endif
|
||||
12
bc/os/file/CopyFile.cpp
Normal file
12
bc/os/file/CopyFile.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "bc/os/file/CopyFile.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
#include "bc/file/Copy.hpp"
|
||||
|
||||
int32_t OsCopyFile(const char* existingFileName, const char* newFileName, int32_t failIfExists) {
|
||||
if (!existingFileName || !newFileName) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::Copy(existingFileName, newFileName, failIfExists == 0);
|
||||
}
|
||||
8
bc/os/file/CopyFile.hpp
Normal file
8
bc/os/file/CopyFile.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_COPY_FILE_HPP
|
||||
#define BC_OS_FILE_COPY_FILE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsCopyFile(const char* existingFileName, const char* newFileName, int32_t failIfExists);
|
||||
|
||||
#endif
|
||||
12
bc/os/file/CreateDirectory.cpp
Normal file
12
bc/os/file/CreateDirectory.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "bc/os/file/CreateDirectory.hpp"
|
||||
#include "bc/file/CreateDirectory.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
|
||||
int32_t OsCreateDirectory(const char* pathName, int32_t recursive) {
|
||||
if (pathName == nullptr) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::CreateDirectory(pathName, recursive != 0);
|
||||
}
|
||||
8
bc/os/file/CreateDirectory.hpp
Normal file
8
bc/os/file/CreateDirectory.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_CREATE_DIRECTORY_HPP
|
||||
#define BC_OS_FILE_CREATE_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsCreateDirectory(const char* pathName, int32_t recursive);
|
||||
|
||||
#endif
|
||||
67
bc/os/file/CreateFile.cpp
Normal file
67
bc/os/file/CreateFile.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#include "bc/os/file/CreateFile.hpp"
|
||||
#include "bc/os/file/SetFileAttributes.hpp"
|
||||
#include "bc/Debug.hpp"
|
||||
#include "bc/file/Open.hpp"
|
||||
#include "bc/os/file/Types.hpp"
|
||||
|
||||
int32_t OsCreateFileMode(uint32_t desiredAccess, uint32_t shareMode, uint32_t createDisposition) {
|
||||
using Mode = Blizzard::File::Mode;
|
||||
|
||||
int32_t mode;
|
||||
|
||||
if (desiredAccess & OS_GENERIC_READ) {
|
||||
mode |= Mode::read;
|
||||
}
|
||||
if (desiredAccess & OS_GENERIC_WRITE) {
|
||||
mode |= Mode::write;
|
||||
}
|
||||
|
||||
if (shareMode & OS_FILE_SHARE_READ) {
|
||||
mode |= Mode::shareread;
|
||||
}
|
||||
if (shareMode & OS_FILE_SHARE_WRITE) {
|
||||
mode |= Mode::sharewrite;
|
||||
}
|
||||
|
||||
switch (createDisposition) {
|
||||
case OS_CREATE_NEW:
|
||||
// mode |= 0xC00;
|
||||
mode |= (Mode::create|Mode::mustnotexist);
|
||||
break;
|
||||
case OS_CREATE_ALWAYS:
|
||||
// mode |= 0x400;
|
||||
mode |= Mode::create;
|
||||
break;
|
||||
case OS_OPEN_EXISTING:
|
||||
// mode |= 0x1000
|
||||
mode |= Mode::mustexist;
|
||||
break;
|
||||
case OS_OPEN_ALWAYS:
|
||||
// mode |= 0x200;
|
||||
mode |= Mode::append;
|
||||
break;
|
||||
case OS_TRUNCATE_EXISTING:
|
||||
// mode |= 0x100;
|
||||
mode |= Mode::truncate;
|
||||
break;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
HOSFILE OsCreateFile(const char* fileName, uint32_t desiredAccess, uint32_t shareMode, uint32_t createDisposition, uint32_t flagsAndAttributes, uint32_t extendedFileType) {
|
||||
BLIZZARD_VALIDATE(fileName, "invalid filename", HOSFILE_INVALID);
|
||||
BLIZZARD_VALIDATE(desiredAccess != 0, "invalid desired access", HOSFILE_INVALID);
|
||||
BLIZZARD_VALIDATE(createDisposition <= OS_TRUNCATE_EXISTING, "invalid create disposition", HOSFILE_INVALID);
|
||||
|
||||
Blizzard::File::StreamRecord* file;
|
||||
if (!Blizzard::File::Open(fileName, OsCreateFileMode(desiredAccess, shareMode, createDisposition), file)) {
|
||||
return HOSFILE_INVALID;
|
||||
}
|
||||
|
||||
if ((flagsAndAttributes & OS_FILE_ATTRIBUTE_NORMAL) == 0) {
|
||||
OsSetFileAttributes(fileName, flagsAndAttributes);
|
||||
}
|
||||
|
||||
return reinterpret_cast<HOSFILE>(file);
|
||||
}
|
||||
10
bc/os/file/CreateFile.hpp
Normal file
10
bc/os/file/CreateFile.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef BC_OS_FILE_CREATE_FILE_HPP
|
||||
#define BC_OS_FILE_CREATE_FILE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "bc/os/file/Types.hpp"
|
||||
|
||||
HOSFILE OsCreateFile(const char* fileName, uint32_t desiredAccess, uint32_t shareMode, uint32_t createDisposition, uint32_t flagsAndAttributes, uint32_t extendedFileType);
|
||||
|
||||
#endif
|
||||
10
bc/os/file/Defines.hpp
Normal file
10
bc/os/file/Defines.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef BC_OS_FILE_DEFINES_HPP
|
||||
#define BC_OS_FILE_DEFINES_HPP
|
||||
|
||||
#define OS_FILE_ERROR_INVALID_PARAMETER 0x57
|
||||
|
||||
#include "bc/file/Error.hpp"
|
||||
|
||||
#define OS_FILE_SET_LAST_ERROR(err) ::Blizzard::File::SetLastError(err)
|
||||
|
||||
#endif
|
||||
12
bc/os/file/DeleteFile.cpp
Normal file
12
bc/os/file/DeleteFile.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "bc/os/file/DeleteFile.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
#include "bc/file/Delete.hpp"
|
||||
|
||||
int32_t OsDeleteFile(const char* fileName) {
|
||||
if (!fileName) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::Delete(fileName);
|
||||
}
|
||||
8
bc/os/file/DeleteFile.hpp
Normal file
8
bc/os/file/DeleteFile.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_DELETE_FILE_HPP
|
||||
#define BC_OS_FILE_DELETE_FILE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsDeleteFile(const char* fileName);
|
||||
|
||||
#endif
|
||||
6
bc/os/file/DirectoryExists.cpp
Normal file
6
bc/os/file/DirectoryExists.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "bc/os/file/DirectoryExists.hpp"
|
||||
#include "bc/file/Exists.hpp"
|
||||
|
||||
int32_t OsDirectoryExists(const char* dirName) {
|
||||
return Blizzard::File::IsDirectory(dirName);
|
||||
}
|
||||
8
bc/os/file/DirectoryExists.hpp
Normal file
8
bc/os/file/DirectoryExists.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_DIRECTORY_EXISTS_HPP
|
||||
#define BC_OS_FILE_DIRECTORY_EXISTS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsDirectoryExists(const char* dirName);
|
||||
|
||||
#endif
|
||||
6
bc/os/file/FileExists.cpp
Normal file
6
bc/os/file/FileExists.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "bc/os/file/FileExists.hpp"
|
||||
#include "bc/file/Exists.hpp"
|
||||
|
||||
int32_t OsFileExists(const char* path) {
|
||||
return Blizzard::File::IsFile(path);
|
||||
}
|
||||
8
bc/os/file/FileExists.hpp
Normal file
8
bc/os/file/FileExists.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_FILE_EXISTS_HPP
|
||||
#define BC_OS_FILE_FILE_EXISTS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsFileExists(const char* path);
|
||||
|
||||
#endif
|
||||
73
bc/os/file/FileList.cpp
Normal file
73
bc/os/file/FileList.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include "bc/os/file/FileList.hpp"
|
||||
#include "bc/file/Defines.hpp"
|
||||
#include "bc/file/GetFileInfo.hpp"
|
||||
#include "bc/file/MakeAbsolutePath.hpp"
|
||||
#include "bc/file/ProcessDirFast.hpp"
|
||||
#include "bc/file/SimpleGlob.hpp"
|
||||
#include "bc/file/Types.hpp"
|
||||
#include "bc/string/Copy.hpp"
|
||||
#include "bc/string/Path.hpp"
|
||||
|
||||
int32_t OsFileList(const char* dir, const char* pattern, OsFileListCallback callback, void* param, int32_t flags) {
|
||||
class Internal {
|
||||
public:
|
||||
struct FileListParms {
|
||||
OsFileListCallback callback;
|
||||
void* param;
|
||||
uint32_t flags;
|
||||
const char* pattern;
|
||||
};
|
||||
|
||||
static bool Callback(const Blizzard::File::ProcessDirParms& parms) {
|
||||
char path[260];
|
||||
OS_FILE_DATA data;
|
||||
Blizzard::String::Copy(data.fileName, parms.item, sizeof(data.fileName));
|
||||
Blizzard::String::JoinPath(path, sizeof(path), parms.dir, parms.item);
|
||||
|
||||
auto list = static_cast<FileListParms*>(parms.param);
|
||||
|
||||
if (Blizzard::File::SimpleGlob(parms.item, list->pattern)) {
|
||||
Blizzard::File::FileInfo info;
|
||||
if (Blizzard::File::GetFileInfo(path, &info)) {
|
||||
// TODO: consider making this 64 bits
|
||||
data.size = static_cast<uint32_t>(info.size);
|
||||
data.flags = 0;
|
||||
|
||||
if (info.attributes & BC_FILE_ATTRIBUTE_DIRECTORY) {
|
||||
data.flags |= 0x10;
|
||||
}
|
||||
if (info.attributes & BC_FILE_ATTRIBUTE_READONLY) {
|
||||
data.flags |= 0x01;
|
||||
}
|
||||
if (info.attributes & BC_FILE_ATTRIBUTE_HIDDEN) {
|
||||
data.flags |= 0x02;
|
||||
}
|
||||
|
||||
if (list->flags && ((info.attributes & BC_FILE_ATTRIBUTE_HIDDEN) == 0)) {
|
||||
if (list->callback(data, list->param)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
char finddir[260];
|
||||
char findpath[260];
|
||||
Blizzard::String::Copy(finddir, dir, 260);
|
||||
|
||||
if (!Blizzard::File::MakeAbsolutePath(finddir, findpath, 260, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Internal::FileListParms parms;
|
||||
parms.param = param;
|
||||
parms.flags = flags;
|
||||
parms.callback = callback;
|
||||
parms.pattern = pattern;
|
||||
|
||||
return Blizzard::File::ProcessDirFast(findpath, static_cast<void*>(&parms), Internal::Callback, false);
|
||||
}
|
||||
17
bc/os/file/FileList.hpp
Normal file
17
bc/os/file/FileList.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef BC_OS_FILE_FILE_LIST_HPP
|
||||
#define BC_OS_FILE_FILE_LIST_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class OS_FILE_DATA {
|
||||
public:
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
char fileName[260];
|
||||
};
|
||||
|
||||
typedef int32_t (*OsFileListCallback)(const OS_FILE_DATA& data, void* param);
|
||||
|
||||
int32_t OsFileList(const char* dir, const char* pattern, OsFileListCallback callback, void* param, int32_t flags);
|
||||
|
||||
#endif
|
||||
12
bc/os/file/GetCurrentDirectory.cpp
Normal file
12
bc/os/file/GetCurrentDirectory.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "bc/os/file/GetCurrentDirectory.hpp"
|
||||
#include "bc/file/GetWorkingDirectory.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
|
||||
int32_t OsGetCurrentDirectory(uint32_t buffersize, char* buffer) {
|
||||
if (!buffer) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::GetWorkingDirectory(buffer, buffersize);
|
||||
}
|
||||
8
bc/os/file/GetCurrentDirectory.hpp
Normal file
8
bc/os/file/GetCurrentDirectory.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_GET_CURRENT_DIRECTORY_HPP
|
||||
#define BC_OS_FILE_GET_CURRENT_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsGetCurrentDirectory(uint32_t buffersize, char* buffer);
|
||||
|
||||
#endif
|
||||
10
bc/os/file/GetDownloadFolder.cpp
Normal file
10
bc/os/file/GetDownloadFolder.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#include "bc/os/file/GetDownloadFolder.hpp"
|
||||
#include "bc/file/GetWorkingDirectory.hpp"
|
||||
|
||||
const char* OsFileGetDownloadFolder() {
|
||||
static char s_downloadfolder[260] = { 0 };
|
||||
if (s_downloadfolder[0] == '\0') {
|
||||
Blizzard::File::GetWorkingDirectory(s_downloadfolder, 260);
|
||||
}
|
||||
return s_downloadfolder;
|
||||
}
|
||||
6
bc/os/file/GetDownloadFolder.hpp
Normal file
6
bc/os/file/GetDownloadFolder.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef BC_OS_FILE_GET_DOWNLOAD_FOLDER_HPP
|
||||
#define BC_OS_FILE_GET_DOWNLOAD_FOLDER_HPP
|
||||
|
||||
const char* OsFileGetDownloadFolder();
|
||||
|
||||
#endif
|
||||
17
bc/os/file/GetFileAttributes.cpp
Normal file
17
bc/os/file/GetFileAttributes.cpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include "bc/os/file/GetFileAttributes.hpp"
|
||||
#include "bc/file/GetFileInfo.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
|
||||
int32_t OsGetFileAttributes(const char* fileName) {
|
||||
if (!fileName) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Blizzard::File::FileInfo info;
|
||||
if (!Blizzard::File::GetFileInfo(fileName, &info)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return info.attributes;
|
||||
}
|
||||
8
bc/os/file/GetFileAttributes.hpp
Normal file
8
bc/os/file/GetFileAttributes.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_GET_FILE_ATTRIBUTES_HPP
|
||||
#define BC_OS_FILE_GET_FILE_ATTRIBUTES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsGetFileAttributes(const char* fileName);
|
||||
|
||||
#endif
|
||||
8
bc/os/file/GetFileSize.cpp
Normal file
8
bc/os/file/GetFileSize.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include "bc/os/file/GetFileSize.hpp"
|
||||
#include "bc/file/GetFileInfo.hpp"
|
||||
#include <limits>
|
||||
|
||||
uint64_t OsGetFileSize(HOSFILE fileHandle) {
|
||||
auto info = Blizzard::File::GetFileInfo(reinterpret_cast<Blizzard::File::StreamRecord*>(fileHandle));
|
||||
return info ? info->size : std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
8
bc/os/file/GetFileSize.hpp
Normal file
8
bc/os/file/GetFileSize.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_GET_FILE_SIZE_HPP
|
||||
#define BC_OS_FILE_GET_FILE_SIZE_HPP
|
||||
|
||||
#include "bc/os/file/Types.hpp"
|
||||
|
||||
uint64_t OsGetFileSize(HOSFILE fileHandle);
|
||||
|
||||
#endif
|
||||
12
bc/os/file/MoveFile.cpp
Normal file
12
bc/os/file/MoveFile.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "bc/os/file/MoveFile.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
#include "bc/file/Move.hpp"
|
||||
|
||||
int32_t OsMoveFile(const char* existingFileName, const char* newFileName) {
|
||||
if (!existingFileName || !newFileName) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::Move(existingFileName, newFileName);
|
||||
}
|
||||
8
bc/os/file/MoveFile.hpp
Normal file
8
bc/os/file/MoveFile.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_MOVE_FILE_HPP
|
||||
#define BC_OS_FILE_MOVE_FILE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsMoveFile(const char* existingFileName, const char* newFileName);
|
||||
|
||||
#endif
|
||||
13
bc/os/file/ReadFile.cpp
Normal file
13
bc/os/file/ReadFile.cpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include "bc/os/file/ReadFile.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
#include "bc/file/Read.hpp"
|
||||
|
||||
int32_t OsReadFile(HOSFILE fileHandle, void* buffer, uint32_t bytesToRead, uint32_t* bytesRead) {
|
||||
if (!buffer || !bytesRead) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*bytesRead = bytesToRead;
|
||||
return Blizzard::File::Read(reinterpret_cast<Blizzard::File::StreamRecord*>(fileHandle), buffer, reinterpret_cast<int32_t*>(bytesRead));
|
||||
}
|
||||
9
bc/os/file/ReadFile.hpp
Normal file
9
bc/os/file/ReadFile.hpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef BC_OS_FILE_READ_FILE_HPP
|
||||
#define BC_OS_FILE_READ_FILE_HPP
|
||||
|
||||
#include "bc/os/file/Types.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsReadFile(HOSFILE fileHandle, void* buffer, uint32_t bytesToRead, uint32_t* bytesRead);
|
||||
|
||||
#endif
|
||||
12
bc/os/file/RemoveDirectory.cpp
Normal file
12
bc/os/file/RemoveDirectory.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "bc/os/file/RemoveDirectory.hpp"
|
||||
#include "bc/file/RemoveDirectory.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
|
||||
int32_t OsRemoveDirectory(const char* pathName) {
|
||||
if (!pathName) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::RemoveDirectory(pathName);
|
||||
}
|
||||
8
bc/os/file/RemoveDirectory.hpp
Normal file
8
bc/os/file/RemoveDirectory.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_REMOVE_DIRECTORY_HPP
|
||||
#define BC_OS_FILE_REMOVE_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsRemoveDirectory(const char* pathName);
|
||||
|
||||
#endif
|
||||
12
bc/os/file/RemoveDirectoryRecurse.cpp
Normal file
12
bc/os/file/RemoveDirectoryRecurse.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "bc/os/file/RemoveDirectoryRecurse.hpp"
|
||||
#include "bc/file/RemoveDirectory.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
|
||||
int32_t OsRemoveDirectoryRecurse(const char* pathName, uint32_t flags) {
|
||||
if (!pathName) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::RemoveDirectoryAndContents(pathName, (flags & 0x1) != 0);
|
||||
}
|
||||
8
bc/os/file/RemoveDirectoryRecurse.hpp
Normal file
8
bc/os/file/RemoveDirectoryRecurse.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_REMOVE_DIRECTORY_HPP
|
||||
#define BC_OS_FILE_REMOVE_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsRemoveDirectoryRecurse(const char* pathName, uint32_t flags);
|
||||
|
||||
#endif
|
||||
13
bc/os/file/SetCurrentDirectory.cpp
Normal file
13
bc/os/file/SetCurrentDirectory.cpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include "bc/os/file/SetCurrentDirectory.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
#include "bc/file/SetWorkingDirectory.hpp"
|
||||
|
||||
int32_t OsSetCurrentDirectory(const char* pathName) {
|
||||
if (pathName == nullptr) {
|
||||
// SetLastError(0x57);
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::SetWorkingDirectory(pathName);
|
||||
}
|
||||
8
bc/os/file/SetCurrentDirectory.hpp
Normal file
8
bc/os/file/SetCurrentDirectory.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_SET_CURRENT_DIRECTORY_HPP
|
||||
#define BC_OS_FILE_SET_CURRENT_DIRECTORY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsSetCurrentDirectory(const char* pathName);
|
||||
|
||||
#endif
|
||||
13
bc/os/file/SetFileAttributes.cpp
Normal file
13
bc/os/file/SetFileAttributes.cpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include "bc/os/file/SetFileAttributes.hpp"
|
||||
#include "bc/file/SetAttributes.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
|
||||
int32_t OsSetFileAttributes(const char* fileName, uint32_t attributes) {
|
||||
if (!fileName) {
|
||||
// SetLastError(0x57);
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Blizzard::File::SetAttributes(fileName, attributes);
|
||||
}
|
||||
8
bc/os/file/SetFileAttributes.hpp
Normal file
8
bc/os/file/SetFileAttributes.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef BC_OS_FILE_SET_FILE_ATTRIBUTES_HPP
|
||||
#define BC_OS_FILE_SET_FILE_ATTRIBUTES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsSetFileAttributes(const char* fileName, uint32_t attributes);
|
||||
|
||||
#endif
|
||||
28
bc/os/file/SetFilePointer.cpp
Normal file
28
bc/os/file/SetFilePointer.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "bc/os/file/SetFilePointer.hpp"
|
||||
#include "bc/Debug.hpp"
|
||||
#include "bc/file/GetPos.hpp"
|
||||
#include "bc/file/SetPos.hpp"
|
||||
#include "bc/file/Defines.hpp"
|
||||
|
||||
int64_t OsSetFilePointer(HOSFILE fileHandle, int64_t distanceToMove, uint32_t moveMethod) {
|
||||
BLIZZARD_ASSERT(moveMethod <= 2);
|
||||
|
||||
auto file = reinterpret_cast<Blizzard::File::StreamRecord*>(fileHandle);
|
||||
|
||||
int64_t offset;
|
||||
if (moveMethod != 0 && !Blizzard::File::GetPos(file, offset)) {
|
||||
return -1LL;
|
||||
}
|
||||
|
||||
uint32_t whence[] = {
|
||||
BC_FILE_SEEK_START,
|
||||
BC_FILE_SEEK_CURRENT,
|
||||
BC_FILE_SEEK_END
|
||||
};
|
||||
|
||||
if (!Blizzard::File::SetPos(file, offset, whence[moveMethod])) {
|
||||
return -1LL;
|
||||
}
|
||||
|
||||
return offset + distanceToMove;
|
||||
}
|
||||
9
bc/os/file/SetFilePointer.hpp
Normal file
9
bc/os/file/SetFilePointer.hpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef BC_OS_FILE_SET_FILE_POINTER_HPP
|
||||
#define BC_OS_FILE_SET_FILE_POINTER_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include "bc/os/file/Types.hpp"
|
||||
|
||||
int64_t OsSetFilePointer(HOSFILE fileHandle, int64_t distanceToMove, uint32_t moveMethod);
|
||||
|
||||
#endif
|
||||
40
bc/os/file/Types.hpp
Normal file
40
bc/os/file/Types.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef BC_OS_FILE_TYPES_HPP
|
||||
#define BC_OS_FILE_TYPES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define OS_FILE_ATTRIBUTE_NORMAL 0x80
|
||||
|
||||
// this is passed into last argument of OsCreateFile
|
||||
#define OS_FILE_TYPE_DEFAULT 0x3F3F3F3F
|
||||
|
||||
enum EOSFileDisposition {
|
||||
OS_CREATE_NEW = 1,
|
||||
OS_CREATE_ALWAYS = 2,
|
||||
OS_OPEN_EXISTING = 3,
|
||||
OS_OPEN_ALWAYS = 4,
|
||||
OS_TRUNCATE_EXISTING = 5
|
||||
};
|
||||
|
||||
enum EOSFileAccess {
|
||||
OS_GENERIC_ALL = 0x10000000,
|
||||
OS_GENERIC_EXECUTE = 0x20000000,
|
||||
OS_GENERIC_WRITE = 0x40000000,
|
||||
OS_GENERIC_READ = 0x80000000
|
||||
};
|
||||
|
||||
enum EOSFileShare {
|
||||
OS_FILE_SHARE_READ = 0x00000001,
|
||||
OS_FILE_SHARE_WRITE = 0x00000002
|
||||
};
|
||||
|
||||
// TODO: generate a proper handle here
|
||||
struct HOSFILE__ {
|
||||
int32_t unused;
|
||||
};
|
||||
|
||||
typedef HOSFILE__* HOSFILE;
|
||||
|
||||
constexpr HOSFILE HOSFILE_INVALID = nullptr;
|
||||
|
||||
#endif
|
||||
13
bc/os/file/WriteFile.cpp
Normal file
13
bc/os/file/WriteFile.cpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include "bc/os/file/WriteFile.hpp"
|
||||
#include "bc/file/Write.hpp"
|
||||
#include "bc/os/file/Defines.hpp"
|
||||
|
||||
int32_t OsWriteFile(HOSFILE fileHandle, void* buffer, uint32_t bytesToWrite, uint32_t* bytesWritten) {
|
||||
if (!buffer || !bytesWritten) {
|
||||
OS_FILE_SET_LAST_ERROR(OS_FILE_ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*bytesWritten = bytesToWrite;
|
||||
return Blizzard::File::Write(reinterpret_cast<Blizzard::File::StreamRecord*>(fileHandle), buffer, reinterpret_cast<int32_t*>(bytesWritten));
|
||||
}
|
||||
9
bc/os/file/WriteFile.hpp
Normal file
9
bc/os/file/WriteFile.hpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef BC_OS_FILE_WRITE_FILE_HPP
|
||||
#define BC_OS_FILE_WRITE_FILE_HPP
|
||||
|
||||
#include "bc/os/file/Types.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
int32_t OsWriteFile(HOSFILE fileHandle, void* buffer, uint32_t bytesToWrite, uint32_t* bytesWritten);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
#ifndef BC_FILE_SYSTEM_DEFINES_HPP
|
||||
#define BC_FILE_SYSTEM_DEFINES_HPP
|
||||
#ifndef BC_SYSTEM_FILE_DEFINES_HPP
|
||||
#define BC_SYSTEM_FILE_DEFINES_HPP
|
||||
|
||||
// Constants
|
||||
// how much data to buffer when copying with File::Copy
|
||||
#define BC_SYSTEM_FILE_COPYBUFFER_SIZE 0xA00000LL
|
||||
|
||||
// How much data to buffer when copying with File::Copy
|
||||
#define BC_FILE_SYSTEM_COPYBUFFER_SIZE 0xA00000UL
|
||||
|
||||
// Utility macros
|
||||
|
||||
#define BC_FILE_PATH(localname) char localname[BC_FILE_MAX_PATH] = {0}
|
||||
// this bit field controls which file information is set by SetFileInfo
|
||||
#define BC_SYSTEM_FILE_INFO_UNK_0 0x01
|
||||
#define BC_SYSTEM_FILE_INFO_UNK_1 0x02
|
||||
#define BC_SYSTEM_FILE_INFO_ATTRIBUTES 0x04
|
||||
#define BC_SYSTEM_FILE_INFO_UNK_3 0x08
|
||||
#define BC_SYSTEM_FILE_INFO_TIMES 0x10
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,105 +5,104 @@
|
|||
#include "bc/String.hpp"
|
||||
#include "bc/Memory.hpp"
|
||||
|
||||
namespace Blizzard {
|
||||
namespace System_File {
|
||||
namespace Stacked {
|
||||
|
||||
bool null_cd(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_cd(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_close(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_close(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_create(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_create(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_cwd(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_cwd(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_dirwalk(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_dirwalk(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_exists(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_exists(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_flush(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_flush(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_getfileinfo(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_getfileinfo(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_getfreespace(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_getfreespace(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_getpos(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_getpos(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_getrootchars(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_getrootchars(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_isabspath(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_isabspath(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_isreadonly(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_isreadonly(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_makeabspath(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_makeabspath(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_mkdir(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_mkdir(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_move(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_move(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_copy(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_copy(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_open(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_open(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_read(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_read(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_readp(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_readp(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_rmdir(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_rmdir(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_setcachemode(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_setcachemode(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_seteof(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_seteof(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_setfileinfo(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_setfileinfo(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_setpos(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_setpos(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_unlink(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_unlink(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_write(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_write(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_writep(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_writep(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
bool null_shutdown(File::Filesystem* fs, FileParms* parms) {
|
||||
bool null_shutdown(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Null stack: this stack does absolutely nothing. Its only purpose is to store fallback functions.
|
||||
static File::Filesystem s_nullstack = {
|
||||
// null stack: does absolutely nothing
|
||||
// only purpose is to store fallback functions
|
||||
static Blizzard::File::Filesystem s_nullstack = {
|
||||
&s_nullstack,
|
||||
|
||||
nullptr,
|
||||
|
||||
{
|
||||
null_cd,
|
||||
null_close,
|
||||
null_create,
|
||||
|
|
@ -133,16 +132,14 @@ static File::Filesystem s_nullstack = {
|
|||
null_write,
|
||||
null_writep,
|
||||
null_shutdown
|
||||
}
|
||||
};
|
||||
|
||||
// Base stack: this stack contains the base System_File functions.
|
||||
static File::Filesystem s_basestack = {
|
||||
// base stack: contains the base System_File functions.
|
||||
static Blizzard::File::Filesystem s_basestack = {
|
||||
&s_basestack,
|
||||
|
||||
nullptr,
|
||||
|
||||
{
|
||||
System_File::SetWorkingDirectory,
|
||||
System_File::Close,
|
||||
System_File::Create,
|
||||
|
|
@ -172,16 +169,14 @@ static File::Filesystem s_basestack = {
|
|||
System_File::Write,
|
||||
System_File::WriteP,
|
||||
System_File::Shutdown
|
||||
}
|
||||
};
|
||||
|
||||
// File initialization stack: this is the default
|
||||
static File::Filesystem s_fileinit = {
|
||||
static Blizzard::File::Filesystem s_fileinit = {
|
||||
&s_fileinit,
|
||||
|
||||
nullptr,
|
||||
|
||||
{
|
||||
file_init,
|
||||
file_init,
|
||||
file_init,
|
||||
|
|
@ -211,81 +206,90 @@ static File::Filesystem s_fileinit = {
|
|||
file_init,
|
||||
file_init,
|
||||
file_init
|
||||
}
|
||||
};
|
||||
|
||||
// Manager will be initialized upon first use
|
||||
static File::Filesystem* s_manager = &s_fileinit;
|
||||
// manager will be initialized upon first use
|
||||
Blizzard::File::Filesystem* s_manager = &s_fileinit;
|
||||
|
||||
// Manager getter
|
||||
File::Filesystem* Manager() {
|
||||
return s_manager;
|
||||
}
|
||||
// push a Filesystem onto the stack
|
||||
void Push(Blizzard::File::Filesystem* fs) {
|
||||
auto head = reinterpret_cast<Blizzard::File::Filesystem*>(Blizzard::Memory::Allocate(sizeof(Blizzard::File::Filesystem)));
|
||||
Blizzard::String::MemFill(head, sizeof(Blizzard::File::Filesystem), 0);
|
||||
Blizzard::String::MemCopy(head, fs, sizeof(Blizzard::File::Filesystem));
|
||||
|
||||
// Push a filesystem stack to manager linked list
|
||||
void Push(File::Filesystem* fs) {
|
||||
auto stack = reinterpret_cast<File::Filesystem*>(Memory::Allocate(sizeof(File::Filesystem)));
|
||||
String::MemFill(stack, sizeof(File::Filesystem), 0);
|
||||
|
||||
// Add stack
|
||||
String::MemCopy(stack, fs, sizeof(File::Filesystem));
|
||||
stack->next = s_manager;
|
||||
|
||||
s_manager = stack;
|
||||
head->next = s_manager;
|
||||
s_manager = head;
|
||||
|
||||
HoistAll();
|
||||
}
|
||||
|
||||
// file_init is part of the default filesystem stack
|
||||
// The first use of s_manager will call this function only once; it is a fallback function in case s_basestack's funcs are not yet hoisted.
|
||||
bool file_init(File::Filesystem* fs, FileParms* parms) {
|
||||
// Allocate a null stack, replacing what was previously a pointer to s_fileinit
|
||||
s_manager = reinterpret_cast<File::Filesystem*>(Memory::Allocate(sizeof(File::Filesystem)));
|
||||
// the first use of s_manager will call this function only once; it is a fallback function in case s_basestack's funcs are not yet hoisted.
|
||||
bool file_init(Blizzard::File::Filesystem* fs, FileParms* parms) {
|
||||
// allocate a null stack, replacing what was previously a pointer to s_fileinit
|
||||
s_manager = reinterpret_cast<Blizzard::File::Filesystem*>(Blizzard::Memory::Allocate(sizeof(Blizzard::File::Filesystem)));
|
||||
if (s_manager == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add null fs calls to stack
|
||||
// After Push/HoistAll, if a filesystem call is unimplemented, the func from s_nullstack gets called instead.
|
||||
String::MemCopy(s_manager, &s_nullstack, sizeof(File::Filesystem));
|
||||
// add null fs calls to stack
|
||||
// after Push/HoistAll, if a filesystem call is unimplemented, the func from s_nullstack gets called instead.
|
||||
Blizzard::String::MemCopy(s_manager, &s_nullstack, sizeof(Blizzard::File::Filesystem));
|
||||
|
||||
// Hoist basic file functions
|
||||
// add basic file functions
|
||||
Push(&s_basestack);
|
||||
|
||||
// fs manager is now ready to use!
|
||||
// Execute the original call.
|
||||
if (s_manager != nullptr) {
|
||||
auto func = *reinterpret_cast<File::Filesystem::CallFunc*>(reinterpret_cast<uintptr_t>(s_manager) + parms->offset);
|
||||
return func(fs, parms);
|
||||
}
|
||||
|
||||
if (s_manager == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensures that the filesystem manager will always have a corresponding function address for enum Call call.
|
||||
void Hoist(uint32_t call) {
|
||||
if (s_manager->funcs[call] == nullptr) {
|
||||
auto topStack = s_manager;
|
||||
auto prev = s_manager;
|
||||
auto next = s_manager->next;
|
||||
while (next && topStack->funcs[call] == nullptr) {
|
||||
topStack->funcs[call] = next->funcs[call];
|
||||
prev = next;
|
||||
next = next->next;
|
||||
}
|
||||
|
||||
// Remove call from lower stack
|
||||
prev->funcs[call] = nullptr;
|
||||
}
|
||||
// do the original operation
|
||||
auto op = *reinterpret_cast<Blizzard::File::Operation*>(reinterpret_cast<uintptr_t>(s_manager) + parms->op);
|
||||
return op(fs, parms);
|
||||
}
|
||||
|
||||
// Hoist all functions in the filesystem stack to the top, i.e. the manager
|
||||
void HoistAll() {
|
||||
for (uint32_t call = 0; call < File::Filesystem::s_numCalls; call++) {
|
||||
Hoist(call);
|
||||
#define HOIST_OP(op) if (s_manager->op == nullptr) { \
|
||||
auto cur = s_manager; \
|
||||
while (cur->next) { \
|
||||
cur->op = cur->next->op; \
|
||||
cur = cur->next; \
|
||||
} \
|
||||
}
|
||||
|
||||
HOIST_OP(cd);
|
||||
HOIST_OP(close);
|
||||
HOIST_OP(create);
|
||||
HOIST_OP(cwd);
|
||||
HOIST_OP(dirwalk);
|
||||
HOIST_OP(exists);
|
||||
HOIST_OP(flush);
|
||||
HOIST_OP(getfileinfo);
|
||||
HOIST_OP(getfreespace);
|
||||
HOIST_OP(getpos);
|
||||
HOIST_OP(getrootchars);
|
||||
HOIST_OP(isabspath);
|
||||
HOIST_OP(isreadonly);
|
||||
HOIST_OP(makeabspath);
|
||||
HOIST_OP(mkdir);
|
||||
HOIST_OP(move);
|
||||
HOIST_OP(copy);
|
||||
HOIST_OP(open);
|
||||
HOIST_OP(read);
|
||||
HOIST_OP(readp);
|
||||
HOIST_OP(rmdir);
|
||||
HOIST_OP(setcachemode);
|
||||
HOIST_OP(seteof);
|
||||
HOIST_OP(setfileinfo);
|
||||
HOIST_OP(setpos);
|
||||
HOIST_OP(unlink);
|
||||
HOIST_OP(write);
|
||||
HOIST_OP(writep);
|
||||
HOIST_OP(shutdown);
|
||||
|
||||
#undef HOIST_OP
|
||||
}
|
||||
|
||||
} // namespace Stacked
|
||||
} // namespace System_File
|
||||
} // namespace Blizzard
|
||||
|
|
|
|||
|
|
@ -3,83 +3,54 @@
|
|||
|
||||
#include "bc/file/Types.hpp"
|
||||
#include "bc/file/Filesystem.hpp"
|
||||
#include "bc/file/File.hpp"
|
||||
#include "bc/system/file/System_File.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Blizzard {
|
||||
namespace System_File {
|
||||
namespace Stacked {
|
||||
|
||||
extern Blizzard::File::Filesystem* s_manager;
|
||||
|
||||
// Functions
|
||||
bool Open(FileParms* parms);
|
||||
|
||||
bool file_init(File::Filesystem* fs, FileParms* parms);
|
||||
|
||||
File::Filesystem* Manager();
|
||||
bool file_init(Blizzard::File::Filesystem* fs, FileParms* parms);
|
||||
|
||||
void HoistAll();
|
||||
|
||||
void Push(File::Filesystem* fs);
|
||||
void Push(Blizzard::File::Filesystem* fs);
|
||||
|
||||
// Stacked file functions
|
||||
bool SetWorkingDirectory(FileParms* parms);
|
||||
|
||||
bool Close(FileParms* parms);
|
||||
|
||||
bool GetWorkingDirectory(FileParms* parms);
|
||||
|
||||
bool ProcessDirFast(FileParms* parms);
|
||||
|
||||
bool Exists(FileParms* parms);
|
||||
|
||||
bool Flush(FileParms* parms);
|
||||
|
||||
bool GetFileInfo(FileParms* parms);
|
||||
|
||||
bool GetFreeSpace(FileParms* parms);
|
||||
|
||||
bool GetPos(FileParms* parms);
|
||||
|
||||
bool GetRootChars(FileParms* parms);
|
||||
|
||||
bool IsAbsolutePath(FileParms* parms);
|
||||
|
||||
bool IsReadOnly(FileParms* parms);
|
||||
|
||||
bool MakeAbsolutePath(FileParms* parms);
|
||||
|
||||
bool CreateDirectory(FileParms* parms);
|
||||
|
||||
bool Move(FileParms* parms);
|
||||
|
||||
bool Copy(FileParms* parms);
|
||||
|
||||
bool Open(FileParms* parms);
|
||||
|
||||
bool Read(FileParms* parms);
|
||||
|
||||
bool ReadP(FileParms* parms);
|
||||
|
||||
bool RemoveDirectory(FileParms* parms);
|
||||
|
||||
bool SetCacheMode(FileParms* parms);
|
||||
|
||||
bool SetEOF(FileParms* parms);
|
||||
|
||||
bool SetAttributes(FileParms* parms);
|
||||
|
||||
bool SetPos(FileParms* parms);
|
||||
|
||||
bool Delete(FileParms* parms);
|
||||
|
||||
bool Write(FileParms* parms);
|
||||
|
||||
bool WriteP(FileParms* parms);
|
||||
bool (SetWorkingDirectory)(FileParms* parms);
|
||||
bool (Close)(FileParms* parms);
|
||||
bool (Create)(FileParms* parms);
|
||||
bool (GetWorkingDirectory)(FileParms* parms);
|
||||
bool (ProcessDirFast)(FileParms* parms);
|
||||
bool (Exists)(FileParms* parms);
|
||||
bool (Flush)(FileParms* parms);
|
||||
bool (GetFileInfo)(FileParms* parms);
|
||||
bool (GetFreeSpace)(FileParms* parms);
|
||||
bool (GetPos)(FileParms* parms);
|
||||
bool (GetRootChars)(FileParms* parms);
|
||||
bool (IsAbsolutePath)(FileParms* parms);
|
||||
bool (IsReadOnly)(FileParms* parms);
|
||||
bool (MakeAbsolutePath)(FileParms* parms);
|
||||
bool (CreateDirectory)(FileParms* parms);
|
||||
bool (Move)(FileParms* parms);
|
||||
bool (Copy)(FileParms* parms);
|
||||
bool (Open)(FileParms* parms);
|
||||
bool (Read)(FileParms* parms);
|
||||
bool (ReadP)(FileParms* parms);
|
||||
bool (RemoveDirectory)(FileParms* parms);
|
||||
bool (SetCacheMode)(FileParms* parms);
|
||||
bool (SetEOF)(FileParms* parms);
|
||||
bool (SetAttributes)(FileParms* parms);
|
||||
bool (SetPos)(FileParms* parms);
|
||||
bool (Delete)(FileParms* parms);
|
||||
bool (Write)(FileParms* parms);
|
||||
bool (WriteP)(FileParms* parms);
|
||||
bool (Shutdown)(FileParms* parms);
|
||||
|
||||
} // namespace Stacked
|
||||
} // namespace System_File
|
||||
} // namespace Blizzard
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue