|
|
@@ -317,7 +317,7 @@ close() {
|
|
|
*/
|
|
|
std::string ZipArchive::
|
|
|
add_subfile(const std::string &subfile_name, const Filename &filename,
|
|
|
- int compression_level) {
|
|
|
+ int compression_level, size_t data_alignment) {
|
|
|
nassertr(is_write_valid(), std::string());
|
|
|
|
|
|
#ifndef HAVE_ZLIB
|
|
|
@@ -337,7 +337,7 @@ add_subfile(const std::string &subfile_name, const Filename &filename,
|
|
|
return std::string();
|
|
|
}
|
|
|
|
|
|
- std::string name = add_subfile(subfile_name, in, compression_level);
|
|
|
+ std::string name = add_subfile(subfile_name, in, compression_level, data_alignment);
|
|
|
vfs->close_read_file(in);
|
|
|
return name;
|
|
|
}
|
|
|
@@ -356,7 +356,7 @@ add_subfile(const std::string &subfile_name, const Filename &filename,
|
|
|
*/
|
|
|
std::string ZipArchive::
|
|
|
add_subfile(const std::string &subfile_name, std::istream *subfile_data,
|
|
|
- int compression_level) {
|
|
|
+ int compression_level, size_t data_alignment) {
|
|
|
nassertr(is_write_valid(), string());
|
|
|
|
|
|
#ifndef HAVE_ZLIB
|
|
|
@@ -367,14 +367,14 @@ add_subfile(const std::string &subfile_name, std::istream *subfile_data,
|
|
|
|
|
|
std::string name = standardize_subfile_name(subfile_name);
|
|
|
if (!name.empty()) {
|
|
|
- Subfile *subfile = new Subfile(subfile_name, compression_level);
|
|
|
+ Subfile *subfile = new Subfile(subfile_name, compression_level, data_alignment);
|
|
|
|
|
|
// Write it straight away, overwriting the index at the end of the file.
|
|
|
// This index will be rewritten at the next call to flush() or close().
|
|
|
std::streampos fpos = _index_start;
|
|
|
_write->seekp(fpos);
|
|
|
|
|
|
- if (!subfile->write_header(*_write, fpos)) {
|
|
|
+ if (!subfile->write_header(*_write, fpos, data_alignment)) {
|
|
|
delete subfile;
|
|
|
return "";
|
|
|
}
|
|
|
@@ -406,7 +406,7 @@ add_subfile(const std::string &subfile_name, std::istream *subfile_data,
|
|
|
*/
|
|
|
string ZipArchive::
|
|
|
update_subfile(const std::string &subfile_name, const Filename &filename,
|
|
|
- int compression_level) {
|
|
|
+ int compression_level, size_t data_alignment) {
|
|
|
nassertr(is_write_valid(), string());
|
|
|
|
|
|
#ifndef HAVE_ZLIB
|
|
|
@@ -431,7 +431,7 @@ update_subfile(const std::string &subfile_name, const Filename &filename,
|
|
|
|
|
|
// The subfile does not already exist or it is different from the source
|
|
|
// file. Add the new source file.
|
|
|
- Subfile *subfile = new Subfile(name, compression_level);
|
|
|
+ Subfile *subfile = new Subfile(name, compression_level, data_alignment);
|
|
|
add_new_subfile(subfile, compression_level);
|
|
|
}
|
|
|
|
|
|
@@ -764,7 +764,7 @@ repack() {
|
|
|
// the checksum and sizes.
|
|
|
subfile->_flags &= ~SF_data_descriptor;
|
|
|
|
|
|
- if (!subfile->write_header(temp, fpos)) {
|
|
|
+ if (!subfile->write_header(temp, fpos, subfile->_data_alignment)) {
|
|
|
success = false;
|
|
|
continue;
|
|
|
}
|
|
|
@@ -1669,10 +1669,11 @@ write_index(std::ostream &write, std::streampos &fpos) {
|
|
|
* Creates a new subfile record.
|
|
|
*/
|
|
|
ZipArchive::Subfile::
|
|
|
-Subfile(const std::string &name, int compression_level) :
|
|
|
+Subfile(const std::string &name, int compression_level, size_t data_alignment) :
|
|
|
_name(name),
|
|
|
_timestamp(dos_epoch),
|
|
|
- _compression_method((compression_level > 0) ? CM_deflate : CM_store)
|
|
|
+ _compression_method((compression_level > 0) ? CM_deflate : CM_store),
|
|
|
+ _data_alignment(data_alignment)
|
|
|
{
|
|
|
// If the name contains any non-ASCII characters, we set the UTF-8 flag.
|
|
|
for (char c : name) {
|
|
|
@@ -2096,7 +2097,7 @@ write_index(std::ostream &write, streampos &fpos) {
|
|
|
* than the actual size of the subfile).
|
|
|
*/
|
|
|
bool ZipArchive::Subfile::
|
|
|
-write_header(std::ostream &write, std::streampos &fpos) {
|
|
|
+write_header(std::ostream &write, std::streampos &fpos, size_t data_alignment) {
|
|
|
nassertr(write.tellp() == fpos, false);
|
|
|
|
|
|
std::string encoded_name;
|
|
|
@@ -2109,13 +2110,29 @@ write_header(std::ostream &write, std::streampos &fpos) {
|
|
|
std::streamoff header_size = 30 + encoded_name.size();
|
|
|
|
|
|
StreamWriter writer(write);
|
|
|
- int modulo = (fpos + header_size) % 4;
|
|
|
- if (!is_compressed() && modulo != 0) {
|
|
|
+ if (!is_compressed()) {
|
|
|
// Align uncompressed files to 4-byte boundary. We don't really need to do
|
|
|
// this, but it's needed when producing .apk files, and it doesn't really
|
|
|
// cause harm to do it in other cases as well.
|
|
|
- writer.pad_bytes(4 - modulo);
|
|
|
- fpos += (4 - modulo);
|
|
|
+ if (data_alignment < 4) {
|
|
|
+ data_alignment = 4;
|
|
|
+ }
|
|
|
+ else if ((data_alignment % 4) != 0) {
|
|
|
+ data_alignment *= 2;
|
|
|
+ if ((data_alignment % 4) != 0) {
|
|
|
+ data_alignment *= 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data_alignment > 0) {
|
|
|
+ // The data follows the header directly, so the actual padding has to be
|
|
|
+ // inserted before the header.
|
|
|
+ int modulo = (fpos + header_size) % data_alignment;
|
|
|
+ if (modulo != 0) {
|
|
|
+ writer.pad_bytes(data_alignment - modulo);
|
|
|
+ fpos += (data_alignment - modulo);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
_header_start = fpos;
|