mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
Kernel: Use AK::Stream
to write packed binary data
This commit is contained in:
parent
23e10a30ad
commit
81863eaf57
|
@ -483,6 +483,8 @@ endif()
|
||||||
set(AK_SOURCES
|
set(AK_SOURCES
|
||||||
../AK/GenericLexer.cpp
|
../AK/GenericLexer.cpp
|
||||||
../AK/Hex.cpp
|
../AK/Hex.cpp
|
||||||
|
../AK/MemoryStream.cpp
|
||||||
|
../AK/Stream.cpp
|
||||||
../AK/StringBuilder.cpp
|
../AK/StringBuilder.cpp
|
||||||
../AK/StringUtils.cpp
|
../AK/StringUtils.cpp
|
||||||
../AK/StringView.cpp
|
../AK/StringView.cpp
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/DeprecatedMemoryStream.h>
|
#include <AK/MemoryStream.h>
|
||||||
#include <Kernel/API/POSIX/errno.h>
|
#include <Kernel/API/POSIX/errno.h>
|
||||||
#include <Kernel/Debug.h>
|
#include <Kernel/Debug.h>
|
||||||
#include <Kernel/FileSystem/Ext2FS/Inode.h>
|
#include <Kernel/FileSystem/Ext2FS/Inode.h>
|
||||||
|
@ -40,16 +40,15 @@ ErrorOr<void> Ext2FSInode::write_indirect_block(BlockBasedFileSystem::BlockIndex
|
||||||
auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block());
|
auto const entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block());
|
||||||
VERIFY(blocks_indices.size() <= entries_per_block);
|
VERIFY(blocks_indices.size() <= entries_per_block);
|
||||||
|
|
||||||
auto block_contents = TRY(ByteBuffer::create_uninitialized(fs().block_size()));
|
auto block_contents = TRY(ByteBuffer::create_zeroed(fs().block_size()));
|
||||||
DeprecatedOutputMemoryStream stream { block_contents };
|
FixedMemoryStream stream { block_contents.bytes() };
|
||||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
|
auto buffer = UserOrKernelBuffer::for_kernel_buffer(block_contents.data());
|
||||||
|
|
||||||
VERIFY(blocks_indices.size() <= EXT2_ADDR_PER_BLOCK(&fs().super_block()));
|
VERIFY(blocks_indices.size() <= EXT2_ADDR_PER_BLOCK(&fs().super_block()));
|
||||||
for (unsigned i = 0; i < blocks_indices.size(); ++i)
|
for (unsigned i = 0; i < blocks_indices.size(); ++i)
|
||||||
stream << static_cast<u32>(blocks_indices[i].value());
|
MUST(stream.write_value<u32>(blocks_indices[i].value()));
|
||||||
stream.fill_to_end(0);
|
|
||||||
|
|
||||||
return fs().write_block(block, buffer, stream.size());
|
return fs().write_block(block, buffer, block_contents.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Ext2FSInode::grow_doubly_indirect_block(BlockBasedFileSystem::BlockIndex block, size_t old_blocks_length, Span<BlockBasedFileSystem::BlockIndex> blocks_indices, Vector<Ext2FS::BlockIndex>& new_meta_blocks, unsigned& meta_blocks)
|
ErrorOr<void> Ext2FSInode::grow_doubly_indirect_block(BlockBasedFileSystem::BlockIndex block, size_t old_blocks_length, Span<BlockBasedFileSystem::BlockIndex> blocks_indices, Vector<Ext2FS::BlockIndex>& new_meta_blocks, unsigned& meta_blocks)
|
||||||
|
@ -62,10 +61,10 @@ ErrorOr<void> Ext2FSInode::grow_doubly_indirect_block(BlockBasedFileSystem::Bloc
|
||||||
VERIFY(blocks_indices.size() > old_blocks_length);
|
VERIFY(blocks_indices.size() > old_blocks_length);
|
||||||
VERIFY(blocks_indices.size() <= entries_per_doubly_indirect_block);
|
VERIFY(blocks_indices.size() <= entries_per_doubly_indirect_block);
|
||||||
|
|
||||||
auto block_contents = TRY(ByteBuffer::create_uninitialized(fs().block_size()));
|
auto block_contents = TRY(ByteBuffer::create_zeroed(fs().block_size()));
|
||||||
auto* block_as_pointers = (unsigned*)block_contents.data();
|
auto* block_as_pointers = (unsigned*)block_contents.data();
|
||||||
DeprecatedOutputMemoryStream stream { block_contents };
|
FixedMemoryStream stream { block_contents.bytes() };
|
||||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
|
auto buffer = UserOrKernelBuffer::for_kernel_buffer(block_contents.data());
|
||||||
|
|
||||||
if (old_blocks_length > 0) {
|
if (old_blocks_length > 0) {
|
||||||
TRY(fs().read_block(block, &buffer, fs().block_size()));
|
TRY(fs().read_block(block, &buffer, fs().block_size()));
|
||||||
|
@ -73,14 +72,13 @@ ErrorOr<void> Ext2FSInode::grow_doubly_indirect_block(BlockBasedFileSystem::Bloc
|
||||||
|
|
||||||
// Grow the doubly indirect block.
|
// Grow the doubly indirect block.
|
||||||
for (unsigned i = 0; i < old_indirect_blocks_length; i++)
|
for (unsigned i = 0; i < old_indirect_blocks_length; i++)
|
||||||
stream << static_cast<u32>(block_as_pointers[i]);
|
MUST(stream.write_value<u32>(block_as_pointers[i]));
|
||||||
for (unsigned i = old_indirect_blocks_length; i < new_indirect_blocks_length; i++) {
|
for (unsigned i = old_indirect_blocks_length; i < new_indirect_blocks_length; i++) {
|
||||||
auto new_block = new_meta_blocks.take_last().value();
|
auto new_block = new_meta_blocks.take_last().value();
|
||||||
dbgln_if(EXT2_BLOCKLIST_DEBUG, "Ext2FSInode[{}]::grow_doubly_indirect_block(): Allocating indirect block {} at index {}", identifier(), new_block, i);
|
dbgln_if(EXT2_BLOCKLIST_DEBUG, "Ext2FSInode[{}]::grow_doubly_indirect_block(): Allocating indirect block {} at index {}", identifier(), new_block, i);
|
||||||
stream << static_cast<u32>(new_block);
|
MUST(stream.write_value<u32>(new_block));
|
||||||
meta_blocks++;
|
meta_blocks++;
|
||||||
}
|
}
|
||||||
stream.fill_to_end(0);
|
|
||||||
|
|
||||||
// Write out the indirect blocks.
|
// Write out the indirect blocks.
|
||||||
for (unsigned i = old_blocks_length / entries_per_block; i < new_indirect_blocks_length; i++) {
|
for (unsigned i = old_blocks_length / entries_per_block; i < new_indirect_blocks_length; i++) {
|
||||||
|
@ -89,7 +87,7 @@ ErrorOr<void> Ext2FSInode::grow_doubly_indirect_block(BlockBasedFileSystem::Bloc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out the doubly indirect block.
|
// Write out the doubly indirect block.
|
||||||
return fs().write_block(block, buffer, stream.size());
|
return fs().write_block(block, buffer, block_contents.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Ext2FSInode::shrink_doubly_indirect_block(BlockBasedFileSystem::BlockIndex block, size_t old_blocks_length, size_t new_blocks_length, unsigned& meta_blocks)
|
ErrorOr<void> Ext2FSInode::shrink_doubly_indirect_block(BlockBasedFileSystem::BlockIndex block, size_t old_blocks_length, size_t new_blocks_length, unsigned& meta_blocks)
|
||||||
|
@ -135,10 +133,10 @@ ErrorOr<void> Ext2FSInode::grow_triply_indirect_block(BlockBasedFileSystem::Bloc
|
||||||
VERIFY(blocks_indices.size() > old_blocks_length);
|
VERIFY(blocks_indices.size() > old_blocks_length);
|
||||||
VERIFY(blocks_indices.size() <= entries_per_triply_indirect_block);
|
VERIFY(blocks_indices.size() <= entries_per_triply_indirect_block);
|
||||||
|
|
||||||
auto block_contents = TRY(ByteBuffer::create_uninitialized(fs().block_size()));
|
auto block_contents = TRY(ByteBuffer::create_zeroed(fs().block_size()));
|
||||||
auto* block_as_pointers = (unsigned*)block_contents.data();
|
auto* block_as_pointers = (unsigned*)block_contents.data();
|
||||||
DeprecatedOutputMemoryStream stream { block_contents };
|
FixedMemoryStream stream { block_contents.bytes() };
|
||||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
|
auto buffer = UserOrKernelBuffer::for_kernel_buffer(block_contents.data());
|
||||||
|
|
||||||
if (old_blocks_length > 0) {
|
if (old_blocks_length > 0) {
|
||||||
TRY(fs().read_block(block, &buffer, fs().block_size()));
|
TRY(fs().read_block(block, &buffer, fs().block_size()));
|
||||||
|
@ -146,14 +144,13 @@ ErrorOr<void> Ext2FSInode::grow_triply_indirect_block(BlockBasedFileSystem::Bloc
|
||||||
|
|
||||||
// Grow the triply indirect block.
|
// Grow the triply indirect block.
|
||||||
for (unsigned i = 0; i < old_doubly_indirect_blocks_length; i++)
|
for (unsigned i = 0; i < old_doubly_indirect_blocks_length; i++)
|
||||||
stream << static_cast<u32>(block_as_pointers[i]);
|
MUST(stream.write_value<u32>(block_as_pointers[i]));
|
||||||
for (unsigned i = old_doubly_indirect_blocks_length; i < new_doubly_indirect_blocks_length; i++) {
|
for (unsigned i = old_doubly_indirect_blocks_length; i < new_doubly_indirect_blocks_length; i++) {
|
||||||
auto new_block = new_meta_blocks.take_last().value();
|
auto new_block = new_meta_blocks.take_last().value();
|
||||||
dbgln_if(EXT2_BLOCKLIST_DEBUG, "Ext2FSInode[{}]::grow_triply_indirect_block(): Allocating doubly indirect block {} at index {}", identifier(), new_block, i);
|
dbgln_if(EXT2_BLOCKLIST_DEBUG, "Ext2FSInode[{}]::grow_triply_indirect_block(): Allocating doubly indirect block {} at index {}", identifier(), new_block, i);
|
||||||
stream << static_cast<u32>(new_block);
|
MUST(stream.write_value<u32>(new_block));
|
||||||
meta_blocks++;
|
meta_blocks++;
|
||||||
}
|
}
|
||||||
stream.fill_to_end(0);
|
|
||||||
|
|
||||||
// Write out the doubly indirect blocks.
|
// Write out the doubly indirect blocks.
|
||||||
for (unsigned i = old_blocks_length / entries_per_doubly_indirect_block; i < new_doubly_indirect_blocks_length; i++) {
|
for (unsigned i = old_blocks_length / entries_per_doubly_indirect_block; i < new_doubly_indirect_blocks_length; i++) {
|
||||||
|
@ -164,7 +161,7 @@ ErrorOr<void> Ext2FSInode::grow_triply_indirect_block(BlockBasedFileSystem::Bloc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out the triply indirect block.
|
// Write out the triply indirect block.
|
||||||
return fs().write_block(block, buffer, stream.size());
|
return fs().write_block(block, buffer, block_contents.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Ext2FSInode::shrink_triply_indirect_block(BlockBasedFileSystem::BlockIndex block, size_t old_blocks_length, size_t new_blocks_length, unsigned& meta_blocks)
|
ErrorOr<void> Ext2FSInode::shrink_triply_indirect_block(BlockBasedFileSystem::BlockIndex block, size_t old_blocks_length, size_t new_blocks_length, unsigned& meta_blocks)
|
||||||
|
@ -790,27 +787,28 @@ ErrorOr<void> Ext2FSInode::write_directory(Vector<Ext2FSDirectoryEntry>& entries
|
||||||
dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::write_directory(): New directory contents to write (size {}):", identifier(), directory_size);
|
dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::write_directory(): New directory contents to write (size {}):", identifier(), directory_size);
|
||||||
|
|
||||||
auto directory_data = TRY(ByteBuffer::create_uninitialized(directory_size));
|
auto directory_data = TRY(ByteBuffer::create_uninitialized(directory_size));
|
||||||
DeprecatedOutputMemoryStream stream { directory_data };
|
FixedMemoryStream stream { directory_data.bytes() };
|
||||||
|
|
||||||
for (auto& entry : entries) {
|
for (auto& entry : entries) {
|
||||||
dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::write_directory(): Writing inode: {}, name_len: {}, rec_len: {}, file_type: {}, name: {}", identifier(), entry.inode_index, u16(entry.name->length()), u16(entry.record_length), u8(entry.file_type), entry.name);
|
dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::write_directory(): Writing inode: {}, name_len: {}, rec_len: {}, file_type: {}, name: {}", identifier(), entry.inode_index, u16(entry.name->length()), u16(entry.record_length), u8(entry.file_type), entry.name);
|
||||||
|
|
||||||
stream << u32(entry.inode_index.value());
|
MUST(stream.write_value<u32>(entry.inode_index.value()));
|
||||||
stream << u16(entry.record_length);
|
MUST(stream.write_value<u16>(entry.record_length));
|
||||||
stream << u8(entry.name->length());
|
MUST(stream.write_value<u8>(entry.name->length()));
|
||||||
stream << u8(entry.file_type);
|
MUST(stream.write_value<u8>(entry.file_type));
|
||||||
stream << entry.name->bytes();
|
MUST(stream.write_entire_buffer(entry.name->bytes()));
|
||||||
int padding = entry.record_length - entry.name->length() - 8;
|
int padding = entry.record_length - entry.name->length() - 8;
|
||||||
for (int j = 0; j < padding; ++j)
|
for (int j = 0; j < padding; ++j)
|
||||||
stream << u8(0);
|
MUST(stream.write_value<u8>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY(stream.is_end());
|
auto serialized_bytes_count = TRY(stream.tell());
|
||||||
|
VERIFY(serialized_bytes_count == directory_size);
|
||||||
|
|
||||||
TRY(resize(stream.size()));
|
TRY(resize(serialized_bytes_count));
|
||||||
|
|
||||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
|
auto buffer = UserOrKernelBuffer::for_kernel_buffer(directory_data.data());
|
||||||
auto nwritten = TRY(write_bytes(0, stream.size(), buffer, nullptr));
|
auto nwritten = TRY(write_bytes(0, serialized_bytes_count, buffer, nullptr));
|
||||||
set_metadata_dirty(true);
|
set_metadata_dirty(true);
|
||||||
if (nwritten != directory_data.size())
|
if (nwritten != directory_data.size())
|
||||||
return EIO;
|
return EIO;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/DeprecatedMemoryStream.h>
|
#include <AK/MemoryStream.h>
|
||||||
#include <Kernel/API/POSIX/errno.h>
|
#include <Kernel/API/POSIX/errno.h>
|
||||||
#include <Kernel/Devices/BlockDevice.h>
|
#include <Kernel/Devices/BlockDevice.h>
|
||||||
#include <Kernel/FileSystem/Custody.h>
|
#include <Kernel/FileSystem/Custody.h>
|
||||||
|
@ -222,31 +222,34 @@ ErrorOr<size_t> OpenFileDescription::get_dir_entries(UserOrKernelBuffer& output_
|
||||||
size_t remaining = size;
|
size_t remaining = size;
|
||||||
u8 stack_buffer[PAGE_SIZE];
|
u8 stack_buffer[PAGE_SIZE];
|
||||||
Bytes temp_buffer(stack_buffer, sizeof(stack_buffer));
|
Bytes temp_buffer(stack_buffer, sizeof(stack_buffer));
|
||||||
DeprecatedOutputMemoryStream stream { temp_buffer };
|
FixedMemoryStream stream { temp_buffer };
|
||||||
|
|
||||||
auto flush_stream_to_output_buffer = [&stream, &remaining, &output_buffer]() -> ErrorOr<void> {
|
auto flush_stream_to_output_buffer = [&stream, &remaining, &temp_buffer, &output_buffer]() -> ErrorOr<void> {
|
||||||
if (stream.size() == 0)
|
auto buffered_size = TRY(stream.tell());
|
||||||
|
|
||||||
|
if (buffered_size == 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (remaining < stream.size())
|
if (remaining < buffered_size)
|
||||||
return Error::from_errno(EINVAL);
|
return Error::from_errno(EINVAL);
|
||||||
|
|
||||||
TRY(output_buffer.write(stream.bytes()));
|
TRY(output_buffer.write(temp_buffer.trim(buffered_size)));
|
||||||
output_buffer = output_buffer.offset(stream.size());
|
output_buffer = output_buffer.offset(buffered_size);
|
||||||
remaining -= stream.size();
|
remaining -= buffered_size;
|
||||||
stream.reset();
|
TRY(stream.seek(0));
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorOr<void> result = VirtualFileSystem::the().traverse_directory_inode(*m_inode, [&flush_stream_to_output_buffer, &stream, this](auto& entry) -> ErrorOr<void> {
|
ErrorOr<void> result = VirtualFileSystem::the().traverse_directory_inode(*m_inode, [&flush_stream_to_output_buffer, &stream, this](auto& entry) -> ErrorOr<void> {
|
||||||
|
// FIXME: Double check the calculation, at least the type for the name length mismatches.
|
||||||
size_t serialized_size = sizeof(ino_t) + sizeof(u8) + sizeof(size_t) + sizeof(char) * entry.name.length();
|
size_t serialized_size = sizeof(ino_t) + sizeof(u8) + sizeof(size_t) + sizeof(char) * entry.name.length();
|
||||||
if (serialized_size > stream.remaining())
|
if (serialized_size > TRY(stream.size()) - TRY(stream.tell()))
|
||||||
TRY(flush_stream_to_output_buffer());
|
TRY(flush_stream_to_output_buffer());
|
||||||
|
|
||||||
stream << (u64)entry.inode.index().value();
|
MUST(stream.write_value<u64>(entry.inode.index().value()));
|
||||||
stream << m_inode->fs().internal_file_type_to_directory_entry_type(entry);
|
MUST(stream.write_value(m_inode->fs().internal_file_type_to_directory_entry_type(entry)));
|
||||||
stream << (u32)entry.name.length();
|
MUST(stream.write_value<u32>(entry.name.length()));
|
||||||
stream << entry.name.bytes();
|
MUST(stream.write_entire_buffer(entry.name.bytes()));
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue