@@ -9,14 +9,19 @@
|
||||
|
||||
#include "xenia/kernel/objects/xfile.h"
|
||||
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/kernel/async_request.h"
|
||||
#include "xenia/kernel/objects/xevent.h"
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
XFile::XFile(KernelState* kernel_state, vfs::Mode mode)
|
||||
: mode_(mode), position_(0), XObject(kernel_state, kTypeFile) {
|
||||
XFile::XFile(KernelState* kernel_state, vfs::Mode mode, vfs::Entry* entry)
|
||||
: XObject(kernel_state, kTypeFile),
|
||||
entry_(entry),
|
||||
mode_(mode),
|
||||
position_(0),
|
||||
find_index_(0) {
|
||||
async_event_ = new XEvent(kernel_state);
|
||||
async_event_->Initialize(false, false);
|
||||
}
|
||||
@@ -29,6 +34,58 @@ XFile::~XFile() {
|
||||
|
||||
void* XFile::GetWaitHandle() { return async_event_->GetWaitHandle(); }
|
||||
|
||||
X_STATUS XFile::QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info,
|
||||
size_t length, const char* file_name,
|
||||
bool restart) {
|
||||
assert_not_null(out_info);
|
||||
|
||||
vfs::Entry* entry = nullptr;
|
||||
|
||||
if (file_name != nullptr) {
|
||||
// Only queries in the current directory are supported for now.
|
||||
assert_true(std::strchr(file_name, '\\') == nullptr);
|
||||
|
||||
find_engine_.SetRule(file_name);
|
||||
|
||||
// Always restart the search?
|
||||
find_index_ = 0;
|
||||
entry = entry_->IterateChildren(find_engine_, &find_index_);
|
||||
if (!entry) {
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
} else {
|
||||
if (restart) {
|
||||
find_index_ = 0;
|
||||
}
|
||||
|
||||
entry = entry_->IterateChildren(find_engine_, &find_index_);
|
||||
if (!entry) {
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
auto end = (uint8_t*)out_info + length;
|
||||
const auto& entry_name = entry->name();
|
||||
if (((uint8_t*)&out_info->file_name[0]) + entry_name.size() > end) {
|
||||
assert_always("Buffer overflow?");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
out_info->next_entry_offset = 0;
|
||||
out_info->file_index = static_cast<uint32_t>(find_index_);
|
||||
out_info->creation_time = entry->create_timestamp();
|
||||
out_info->last_access_time = entry->access_timestamp();
|
||||
out_info->last_write_time = entry->write_timestamp();
|
||||
out_info->change_time = entry->write_timestamp();
|
||||
out_info->end_of_file = entry->size();
|
||||
out_info->allocation_size = entry->allocation_size();
|
||||
out_info->attributes = entry->attributes();
|
||||
out_info->file_name_length = static_cast<uint32_t>(entry_name.size());
|
||||
std::memcpy(out_info->file_name, entry_name.data(), entry_name.size());
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
if (byte_offset == -1) {
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XFILE_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XFILE_H_
|
||||
|
||||
#include "xenia/base/filesystem.h"
|
||||
#include "xenia/kernel/xobject.h"
|
||||
#include "xenia/vfs/device.h"
|
||||
#include "xenia/vfs/entry.h"
|
||||
|
||||
#include "xenia/xbox.h"
|
||||
@@ -29,7 +31,7 @@ struct X_FILE_NETWORK_OPEN_INFORMATION {
|
||||
xe::be<uint64_t> change_time;
|
||||
xe::be<uint64_t> allocation_size;
|
||||
xe::be<uint64_t> end_of_file; // size in bytes
|
||||
xe::be<X_FILE_ATTRIBUTES> attributes;
|
||||
xe::be<uint32_t> attributes;
|
||||
xe::be<uint32_t> pad;
|
||||
};
|
||||
|
||||
@@ -45,7 +47,7 @@ class X_FILE_DIRECTORY_INFORMATION {
|
||||
uint64_t change_time;
|
||||
uint64_t end_of_file; // size in bytes
|
||||
uint64_t allocation_size;
|
||||
X_FILE_ATTRIBUTES attributes;
|
||||
uint32_t attributes; // X_FILE_ATTRIBUTES
|
||||
uint32_t file_name_length;
|
||||
char file_name[1];
|
||||
|
||||
@@ -75,20 +77,19 @@ static_assert_size(X_FILE_DIRECTORY_INFORMATION, 72);
|
||||
|
||||
class XFile : public XObject {
|
||||
public:
|
||||
virtual ~XFile();
|
||||
~XFile() override;
|
||||
|
||||
virtual const std::string& path() const = 0;
|
||||
virtual const std::string& name() const = 0;
|
||||
vfs::Device* device() const { return entry_->device(); }
|
||||
vfs::Entry* entry() const { return entry_; }
|
||||
|
||||
virtual vfs::Device* device() const = 0;
|
||||
const std::string& path() const { return entry_->path(); }
|
||||
const std::string& name() const { return entry_->name(); }
|
||||
|
||||
size_t position() const { return position_; }
|
||||
void set_position(size_t value) { position_ = value; }
|
||||
|
||||
virtual X_STATUS QueryInfo(X_FILE_NETWORK_OPEN_INFORMATION* out_info) = 0;
|
||||
virtual X_STATUS QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info,
|
||||
size_t length, const char* file_name,
|
||||
bool restart) = 0;
|
||||
X_STATUS QueryDirectory(X_FILE_DIRECTORY_INFORMATION* out_info, size_t length,
|
||||
const char* file_name, bool restart);
|
||||
|
||||
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read);
|
||||
@@ -101,7 +102,7 @@ class XFile : public XObject {
|
||||
virtual void* GetWaitHandle();
|
||||
|
||||
protected:
|
||||
XFile(KernelState* kernel_state, vfs::Mode mode);
|
||||
XFile(KernelState* kernel_state, vfs::Mode mode, vfs::Entry* entry);
|
||||
virtual X_STATUS ReadSync(void* buffer, size_t buffer_length,
|
||||
size_t byte_offset, size_t* out_bytes_read) = 0;
|
||||
virtual X_STATUS WriteSync(const void* buffer, size_t buffer_length,
|
||||
@@ -110,12 +111,16 @@ class XFile : public XObject {
|
||||
}
|
||||
|
||||
private:
|
||||
vfs::Entry* entry_;
|
||||
vfs::Mode mode_;
|
||||
XEvent* async_event_;
|
||||
|
||||
// TODO(benvanik): create flags, open state, etc.
|
||||
|
||||
size_t position_;
|
||||
|
||||
xe::filesystem::WildcardEngine find_engine_;
|
||||
size_t find_index_;
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
|
||||
@@ -59,18 +59,11 @@ X_STATUS XUserModule::LoadFromFile(std::string path) {
|
||||
// Load the module.
|
||||
result = LoadFromMemory(mmap->data(), mmap->size());
|
||||
} else {
|
||||
X_FILE_NETWORK_OPEN_INFORMATION file_info = {0};
|
||||
result = fs_entry->QueryInfo(&file_info);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buffer(file_info.end_of_file);
|
||||
std::vector<uint8_t> buffer(fs_entry->size());
|
||||
|
||||
// Open file for reading.
|
||||
XFile* file_ptr = nullptr;
|
||||
result = kernel_state()->file_system()->Open(
|
||||
std::move(fs_entry), kernel_state(), vfs::Mode::READ, false, &file_ptr);
|
||||
result = fs_entry->Open(kernel_state(), vfs::Mode::READ, false, &file_ptr);
|
||||
object_ref<XFile> file(file_ptr);
|
||||
if (result) {
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user