mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 16:18:12 +00:00
unzip: Remove some magic numbers and create directories when needed
This commit also adds an assert about the compression method instead of just writing out the compressed data.
This commit is contained in:
parent
6a265f7c21
commit
3a7a689b87
1 changed files with 63 additions and 22 deletions
|
@ -64,49 +64,90 @@ bool find_next_central_directory(off_t file_size, const MappedFile& file, off_t
|
|||
|
||||
bool unpack_file_for_central_directory_index(off_t central_directory_index, const MappedFile& file)
|
||||
{
|
||||
enum CentralFileDirectoryHeaderOffsets {
|
||||
CFDHCompressionMethodOffset = 10,
|
||||
CFDHLocalFileHeaderIndexOffset = 42,
|
||||
};
|
||||
enum LocalFileHeaderOffsets {
|
||||
LFHCompressionMethodOffset = 10,
|
||||
LFHCompressedSizeOffset = 18,
|
||||
LFHFileNameLengthOffset = 26,
|
||||
LFHExtraFieldLengthOffset = 28,
|
||||
LFHFileNameBaseOffset = 30,
|
||||
};
|
||||
enum CompressionMethod {
|
||||
None = 0,
|
||||
Shrunk = 1,
|
||||
Factor1 = 2,
|
||||
Factor2 = 3,
|
||||
Factor3 = 4,
|
||||
Factor4 = 5,
|
||||
Implode = 6,
|
||||
Deflate = 8,
|
||||
EnhancedDeflate = 9,
|
||||
PKWareDCLImplode = 10,
|
||||
BZIP2 = 12,
|
||||
LZMA = 14,
|
||||
TERSE = 18,
|
||||
LZ77 = 19,
|
||||
};
|
||||
|
||||
u8 buffer[4];
|
||||
if (!seek_and_read(buffer, file, central_directory_index + 42, 4))
|
||||
if (!seek_and_read(buffer, file, central_directory_index + CFDHLocalFileHeaderIndexOffset, 4))
|
||||
return false;
|
||||
off_t local_file_header_index = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
|
||||
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + 18, 4))
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + LFHCompressionMethodOffset, 2))
|
||||
return false;
|
||||
auto compression_method = buffer[1] << 8 | buffer[0];
|
||||
// FIXME: Remove once any decompression is supported.
|
||||
ASSERT(compression_method == None);
|
||||
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + LFHCompressedSizeOffset, 4))
|
||||
return false;
|
||||
off_t compressed_file_size = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
|
||||
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + 26, 2))
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + LFHFileNameLengthOffset, 2))
|
||||
return false;
|
||||
off_t file_name_length = buffer[1] << 8 | buffer[0];
|
||||
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + 28, 2))
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + LFHExtraFieldLengthOffset, 2))
|
||||
return false;
|
||||
off_t extra_field_length = buffer[1] << 8 | buffer[0];
|
||||
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + 30, file_name_length))
|
||||
if (!seek_and_read(buffer, file, local_file_header_index + LFHFileNameBaseOffset, file_name_length))
|
||||
return false;
|
||||
char file_name[file_name_length + 1];
|
||||
memcpy(file_name, buffer, file_name_length);
|
||||
file_name[file_name_length] = '\0';
|
||||
|
||||
auto new_file = Core::File::construct(String { file_name });
|
||||
if (!new_file->open(Core::IODevice::WriteOnly)) {
|
||||
fprintf(stderr, "Can't write file %s: %s\n", file_name, new_file->error_string());
|
||||
return false;
|
||||
}
|
||||
if (file_name[file_name_length - 1] == '/') {
|
||||
if (mkdir(file_name, 0755) < 0) {
|
||||
perror("mkdir");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
auto new_file = Core::File::construct(String { file_name });
|
||||
if (!new_file->open(Core::IODevice::WriteOnly)) {
|
||||
fprintf(stderr, "Can't write file %s: %s\n", file_name, new_file->error_string());
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(" extracting: %s\n", file_name);
|
||||
u8 raw_file_contents[compressed_file_size];
|
||||
if (!seek_and_read(raw_file_contents, file, local_file_header_index + 30 + file_name_length + extra_field_length, compressed_file_size))
|
||||
return false;
|
||||
printf(" extracting: %s\n", file_name);
|
||||
u8 raw_file_contents[compressed_file_size];
|
||||
if (!seek_and_read(raw_file_contents, file, local_file_header_index + LFHFileNameBaseOffset + file_name_length + extra_field_length, compressed_file_size))
|
||||
return false;
|
||||
|
||||
// FIXME: Try to uncompress data here. We're just ignoring it as no decompression methods are implemented yet.
|
||||
if (!new_file->write(raw_file_contents, compressed_file_size)) {
|
||||
fprintf(stderr, "Can't write file contents in %s: %s\n", file_name, new_file->error_string());
|
||||
return false;
|
||||
}
|
||||
// FIXME: Try to uncompress data here. We're just ignoring it as no decompression methods are implemented yet.
|
||||
if (!new_file->write(raw_file_contents, compressed_file_size)) {
|
||||
fprintf(stderr, "Can't write file contents in %s: %s\n", file_name, new_file->error_string());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!new_file->close()) {
|
||||
fprintf(stderr, "Can't close file %s: %s\n", file_name, new_file->error_string());
|
||||
return false;
|
||||
if (!new_file->close()) {
|
||||
fprintf(stderr, "Can't close file %s: %s\n", file_name, new_file->error_string());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue