fix problems patching

This commit is contained in:
David Rose 2002-10-29 00:38:44 +00:00
parent 892a01a4cf
commit 67d32fc172
6 changed files with 92 additions and 69 deletions

View File

@ -149,6 +149,12 @@ const int patchfile_buffer_size =
const int patchfile_zone_size =
config_express.GetInt("patchfile-zone-size", 10000);
// Set this true to keep around the temporary files from downloading,
// decompressing, and patching, or false (the default) to delete
// these. Mainly useful for debugging when the process goes wrong.
const bool keep_temporary_files =
config_express.GetBool("keep-temporary-files", false);
// Set this true to use the VirtualFileSystem mechanism for loading
// models, etc. Since the VirtualFileSystem maps to the same as the
// actual file system by default, there is probably no reason to set

View File

@ -46,6 +46,8 @@ extern const int patchfile_increment_size;
extern const int patchfile_buffer_size;
extern const int patchfile_zone_size;
extern const bool keep_temporary_files;
extern EXPCL_PANDAEXPRESS const bool use_vfs;
// Expose the Config variable for Python access.

View File

@ -41,6 +41,16 @@ operator == (const HashVal &other) const {
hv[3] == other.hv[3]);
}
////////////////////////////////////////////////////////////////////
// Function: HashVal::operator !=
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool HashVal::
operator != (const HashVal &other) const {
return !operator == (other);
}
////////////////////////////////////////////////////////////////////
// Function: HashVal::get_value
// Access: Public

View File

@ -31,6 +31,7 @@ class EXPCL_PANDAEXPRESS HashVal {
PUBLISHED:
INLINE HashVal();
INLINE bool operator == (const HashVal &other) const;
INLINE bool operator != (const HashVal &other) const;
INLINE uint get_value(int val) const;
INLINE void set_value(int val, uint hash);
INLINE void output(ostream &out) const;

View File

@ -18,10 +18,12 @@
#include "config_express.h"
#include "error_utils.h"
#include <stdio.h> // for tempnam
#include "patchfile.h"
#include "crypto_utils.h" // MD5 stuff
#include "streamReader.h"
#include "streamWriter.h"
#include <stdio.h> // for tempnam
// PROFILING ///////////////////////////////////////////////////////
//#define PROFILE_PATCH_BUILD
@ -108,8 +110,6 @@ init(PT(Buffer) buffer) {
_buffer = buffer;
reset_footprint_length();
_datagram.clear();
}
////////////////////////////////////////////////////////////////////
@ -198,11 +198,11 @@ initiate(Filename &patch_file, Filename &file) {
<< "Patchfile::initiate() - Failed to create temp file name, using default" << endl;
_temp_file = "patcher_temp_file";
} else {
//cout << tempfilename << endl;
_temp_file = tempfilename;
free(tempfilename);
}
}
_temp_file.set_binary();
if (!_temp_file.open_write(_write_stream)) {
express_cat.error()
@ -210,16 +210,19 @@ initiate(Filename &patch_file, Filename &file) {
return get_write_error();
}
if (express_cat.is_debug()) {
express_cat.debug()
<< "Using temporary file " << _temp_file << "\n";
}
/////////////
// read header, make sure the patch file is valid
StreamReader patch_reader(_patch_stream);
// check the magic number
nassertr(_buffer->get_length() >= _header_length, false);
_patch_stream.read(_buffer->_buffer, _header_length);
_datagram.clear();
_datagram.append_data(_buffer->_buffer, _header_length);
DatagramIterator di(_datagram);
PN_uint32 magic_number = di.get_uint32();
PN_uint32 magic_number = patch_reader.get_uint32();
if (magic_number != _magic_number) {
express_cat.error()
<< "Patchfile::initiate() - invalid patch file: " << _patch_file << endl;
@ -227,20 +230,16 @@ initiate(Filename &patch_file, Filename &file) {
}
// get the length of the patched result file
_result_file_length = di.get_uint32();
_result_file_length = patch_reader.get_uint32();
// get the MD5 of the resultant patched file
_MD5_ofResult.set_value(0, di.get_uint32());
_MD5_ofResult.set_value(1, di.get_uint32());
_MD5_ofResult.set_value(2, di.get_uint32());
_MD5_ofResult.set_value(3, di.get_uint32());
_MD5_ofResult.set_value(0, patch_reader.get_uint32());
_MD5_ofResult.set_value(1, patch_reader.get_uint32());
_MD5_ofResult.set_value(2, patch_reader.get_uint32());
_MD5_ofResult.set_value(3, patch_reader.get_uint32());
express_cat.debug()
<< "Patchfile::initiate() - valid patchfile" << endl;
/*
express_cat.debug()
<< "Patchfile::initiate() - valid patchfile for file: " << name << endl;
*/
_total_bytes_processed = 0;
@ -270,6 +269,8 @@ run(void) {
return EU_error_abort;
}
StreamReader patch_reader(_patch_stream);
buflen = _buffer->get_length();
bytes_read = 0;
@ -277,11 +278,7 @@ run(void) {
///////////
// read # of ADD bytes
nassertr(_buffer->get_length() >= (int)sizeof(ADD_length), false);
_patch_stream.read(_buffer->_buffer, sizeof(ADD_length));
_datagram.clear();
_datagram.append_data(_buffer->_buffer, sizeof(ADD_length));
DatagramIterator di(_datagram);
ADD_length = di.get_uint16();
ADD_length = patch_reader.get_uint16();
bytes_read += (int)ADD_length;
_total_bytes_processed += (int)ADD_length;
@ -290,7 +287,10 @@ run(void) {
if (0 != ADD_length) {
PN_uint32 bytes_left = (PN_uint32)ADD_length;
//cout << "ADD: " << ADD_length << endl;
if (express_cat.is_spam()) {
express_cat.spam()
<< "ADD: " << ADD_length << endl;
}
while (bytes_left > 0) {
PN_uint32 bytes_this_time = (PN_uint32) min(bytes_left, (PN_uint32) buflen);
@ -303,11 +303,7 @@ run(void) {
///////////
// read # of COPY bytes
nassertr(_buffer->get_length() >= (int)sizeof(COPY_length), false);
_patch_stream.read(_buffer->_buffer, sizeof(COPY_length));
_datagram.clear();
_datagram.append_data(_buffer->_buffer, sizeof(COPY_length));
DatagramIterator di2(_datagram);
COPY_length = di2.get_uint16();
COPY_length = patch_reader.get_uint16();
bytes_read += (int)COPY_length;
_total_bytes_processed += (int)COPY_length;
@ -316,13 +312,13 @@ run(void) {
if (0 != COPY_length) {
// read copy offset
nassertr(_buffer->get_length() >= (int)sizeof(COPY_offset), false);
_patch_stream.read(_buffer->_buffer, sizeof(COPY_offset));
_datagram.clear();
_datagram.append_data(_buffer->_buffer, sizeof(COPY_offset));
DatagramIterator di(_datagram);
COPY_offset = di.get_uint32();
COPY_offset = patch_reader.get_uint32();
//cout << "COPY: " << COPY_length << " bytes at offset " << COPY_offset << endl;
if (express_cat.is_spam()) {
express_cat.spam()
<< "COPY: " << COPY_length << " bytes at offset " << COPY_offset
<< endl;
}
// seek to the offset
_origfile_stream.seekg(COPY_offset, ios::beg);
@ -342,24 +338,46 @@ run(void) {
if ((0 == ADD_length) && (0 == COPY_length)) {
cleanup();
//cout << _result_file_length << " " << _total_bytes_processed << endl;
if (express_cat.is_spam()) {
express_cat.spam()
<< "result file = " << _result_file_length
<< " total bytes = " << _total_bytes_processed << endl;
}
// check the MD5 from the patch file against the newly patched file
{
HashVal MD5_actual;
md5_a_file(_temp_file, MD5_actual);
if (memcmp((const void*)&_MD5_ofResult, (const void*)&MD5_actual, sizeof(HashVal))) {
if (_MD5_ofResult != MD5_actual) {
express_cat.info()
<< "Patching produced incorrect checksum. Got:\n"
<< " " << MD5_actual
<< "\nExpected:\n"
<< " " << _MD5_ofResult
<< "\n";
// delete the temp file and the patch file
_temp_file.unlink();
_patch_file.unlink();
if (!keep_temporary_files) {
_temp_file.unlink();
_patch_file.unlink();
}
// return "invalid checksum"
return EU_error_invalid_checksum;
}
}
// delete the patch file and the original file
_patch_file.unlink();
_orig_file.unlink();
if (!keep_temporary_files) {
_patch_file.unlink();
_orig_file.unlink();
} else {
// If we're keeping temporary files, rename the orig file to a
// backup.
Filename orig_backup = _orig_file.get_fullpath() + ".orig";
orig_backup.unlink();
_orig_file.rename_to(orig_backup);
}
// rename the temp file to the original file name
if (!_temp_file.rename_to(_orig_file)) {
@ -618,17 +636,12 @@ emit_ADD(ofstream &write_stream, PN_uint16 length, const char* buffer) {
//cout << "ADD: " << length << " bytes" << endl;
// write ADD length
_datagram.clear();
_datagram.add_uint16(length);
string msg = _datagram.get_message();
write_stream.write((char *)msg.data(), msg.length());
StreamWriter patch_writer(write_stream);
patch_writer.add_uint16(length);
// if there are bytes to add, add them
if (length > 0) {
_datagram.clear();
_datagram.append_data(buffer, length);
string msg = _datagram.get_message();
write_stream.write((char *)msg.data(), msg.length());
patch_writer.append_data(buffer, length);
}
}
@ -642,17 +655,12 @@ emit_COPY(ofstream &write_stream, PN_uint16 length, PN_uint32 offset) {
//cout << "COPY: " << length << " bytes at offset " << offset << endl;
// write COPY length
_datagram.clear();
_datagram.add_uint16(length);
string msg = _datagram.get_message();
write_stream.write((char *)msg.data(), msg.length());
StreamWriter patch_writer(write_stream);
patch_writer.add_uint16(length);
if(length > 0) {
// write COPY offset
_datagram.clear();
_datagram.add_uint32(offset);
string msg2 = _datagram.get_message();
write_stream.write((char *)msg2.data(), msg2.length());
patch_writer.add_uint32(offset);
}
}
@ -744,21 +752,19 @@ build(Filename &file_orig, Filename &file_new) {
START_PROFILE(writeHeader);
// write the patch file header
_datagram.clear();
_datagram.add_uint32(_magic_number);
_datagram.add_uint32(length_new);
StreamWriter patch_writer(write_stream);
patch_writer.add_uint32(_magic_number);
patch_writer.add_uint32(length_new);
{
// calc MD5 of resultant patched file
HashVal md5New;
md5_a_buffer((const unsigned char*)buffer_new, (int)length_new, md5New);
// add it to the header
_datagram.add_uint32(md5New.get_value(0));
_datagram.add_uint32(md5New.get_value(1));
_datagram.add_uint32(md5New.get_value(2));
_datagram.add_uint32(md5New.get_value(3));
patch_writer.add_uint32(md5New.get_value(0));
patch_writer.add_uint32(md5New.get_value(1));
patch_writer.add_uint32(md5New.get_value(2));
patch_writer.add_uint32(md5New.get_value(3));
}
string msg = _datagram.get_message();
write_stream.write((char *)msg.data(), msg.length());
END_PROFILE(writeHeader, "writing patch file header");

View File

@ -113,8 +113,6 @@ protected:
Filename _orig_file;
Filename _temp_file;
Datagram _datagram; // used to eliminate endian problems
static const PN_uint32 _magic_number;
};