[Kernel] Add support for XFileEndOfFileInformation.

This commit is contained in:
gibbed 2018-05-23 04:24:37 -05:00
parent 19f93304c7
commit bc369e43cb
11 changed files with 45 additions and 2 deletions

View File

@ -88,6 +88,9 @@ class FileHandle {
virtual bool Write(size_t file_offset, const void* buffer, virtual bool Write(size_t file_offset, const void* buffer,
size_t buffer_length, size_t* out_bytes_written) = 0; size_t buffer_length, size_t* out_bytes_written) = 0;
// Set length of the file in bytes.
virtual bool SetLength(size_t length) = 0;
// Flushes any pending write buffers to the underlying filesystem. // Flushes any pending write buffers to the underlying filesystem.
virtual void Flush() = 0; virtual void Flush() = 0;

View File

@ -99,6 +99,9 @@ class PosixFileHandle : public FileHandle {
*out_bytes_written = out; *out_bytes_written = out;
return out >= 0 ? true : false; return out >= 0 ? true : false;
} }
bool SetLength(size_t length) override {
return ftruncate(handle_, length) >= 0 ? true : false;
}
void Flush() override { fsync(handle_); } void Flush() override { fsync(handle_); }
private: private:

View File

@ -115,6 +115,17 @@ class Win32FileHandle : public FileHandle {
return false; return false;
} }
} }
bool SetLength(size_t length) {
LARGE_INTEGER position;
position.QuadPart = length;
if (!SetFilePointerEx(handle_, position, nullptr, SEEK_SET)) {
return false;
}
if (!SetEndOfFile(handle_)) {
return false;
}
return true;
}
void Flush() override { FlushFileBuffers(handle_); } void Flush() override { FlushFileBuffers(handle_); }
private: private:

View File

@ -393,11 +393,16 @@ dword_result_t NtSetInformationFile(
file->set_position(xe::load_and_swap<uint64_t>(file_info)); file->set_position(xe::load_and_swap<uint64_t>(file_info));
break; break;
case XFileAllocationInformation: case XFileAllocationInformation:
case XFileEndOfFileInformation:
assert_true(length == 8); assert_true(length == 8);
info = 8; info = 8;
XELOGW("NtSetInformationFile ignoring alloc/eof"); XELOGW("NtSetInformationFile ignoring alloc");
break; break;
case XFileEndOfFileInformation: {
assert_true(length == 8);
auto eof = xe::load_and_swap<uint64_t>(file_info);
result = file->SetLength(eof);
break;
}
case XFileCompletionInformation: { case XFileCompletionInformation: {
// Info contains IO Completion handle and completion key // Info contains IO Completion handle and completion key
assert_true(length == 8); assert_true(length == 8);

View File

@ -147,6 +147,8 @@ X_STATUS XFile::Write(const void* buffer, size_t buffer_length,
return result; return result;
} }
X_STATUS XFile::SetLength(size_t length) { return file_->SetLength(length); }
void XFile::RegisterIOCompletionPort(uint32_t key, void XFile::RegisterIOCompletionPort(uint32_t key,
object_ref<XIOCompletion> port) { object_ref<XIOCompletion> port) {
std::lock_guard<std::mutex> lock(completion_port_lock_); std::lock_guard<std::mutex> lock(completion_port_lock_);

View File

@ -104,6 +104,8 @@ class XFile : public XObject {
X_STATUS Write(const void* buffer, size_t buffer_length, size_t byte_offset, X_STATUS Write(const void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_written, uint32_t apc_context); size_t* out_bytes_written, uint32_t apc_context);
X_STATUS SetLength(size_t length);
void RegisterIOCompletionPort(uint32_t key, object_ref<XIOCompletion> port); void RegisterIOCompletionPort(uint32_t key, object_ref<XIOCompletion> port);
void RemoveIOCompletionPort(uint32_t key); void RemoveIOCompletionPort(uint32_t key);

View File

@ -30,6 +30,7 @@ class DiscImageFile : public File {
size_t byte_offset, size_t* out_bytes_written) override { size_t byte_offset, size_t* out_bytes_written) override {
return X_STATUS_ACCESS_DENIED; return X_STATUS_ACCESS_DENIED;
} }
X_STATUS SetLength(size_t length) override { return X_STATUS_ACCESS_DENIED; }
private: private:
DiscImageEntry* entry_; DiscImageEntry* entry_;

View File

@ -52,5 +52,17 @@ X_STATUS HostPathFile::WriteSync(const void* buffer, size_t buffer_length,
} }
} }
X_STATUS HostPathFile::SetLength(size_t length) {
if (!(file_access_ & FileAccess::kFileWriteData)) {
return X_STATUS_ACCESS_DENIED;
}
if (file_handle_->SetLength(length)) {
return X_STATUS_SUCCESS;
} else {
return X_STATUS_END_OF_FILE;
}
}
} // namespace vfs } // namespace vfs
} // namespace xe } // namespace xe

View File

@ -32,6 +32,7 @@ class HostPathFile : public File {
size_t* out_bytes_read) override; size_t* out_bytes_read) override;
X_STATUS WriteSync(const void* buffer, size_t buffer_length, X_STATUS WriteSync(const void* buffer, size_t buffer_length,
size_t byte_offset, size_t* out_bytes_written) override; size_t byte_offset, size_t* out_bytes_written) override;
X_STATUS SetLength(size_t length) override;
private: private:
std::unique_ptr<xe::filesystem::FileHandle> file_handle_; std::unique_ptr<xe::filesystem::FileHandle> file_handle_;

View File

@ -32,6 +32,7 @@ class StfsContainerFile : public File {
size_t byte_offset, size_t* out_bytes_written) override { size_t byte_offset, size_t* out_bytes_written) override {
return X_STATUS_ACCESS_DENIED; return X_STATUS_ACCESS_DENIED;
} }
X_STATUS SetLength(size_t length) override { return X_STATUS_ACCESS_DENIED; }
private: private:
StfsContainerEntry* entry_; StfsContainerEntry* entry_;

View File

@ -44,6 +44,8 @@ class File {
return X_STATUS_NOT_IMPLEMENTED; return X_STATUS_NOT_IMPLEMENTED;
} }
virtual X_STATUS SetLength(size_t length) { return X_STATUS_NOT_IMPLEMENTED; }
// xe::filesystem::FileAccess // xe::filesystem::FileAccess
uint32_t file_access() const { return file_access_; } uint32_t file_access() const { return file_access_; }
const Entry* entry() const { return entry_; } const Entry* entry() const { return entry_; }