Пример #1
0
/**
 * \brief Apply a \ref gloss_delta to a \ref gloss_basis to recreate
 * the new file.
 *
 * This gives you back a ::rs_job_t object, which can be cranked by
 * calling rs_job_iter() and updating the stream pointers.  When
 * finished, call rs_job_finish() to dispose of it.
 *
 * \param stream Contains pointers to input and output buffers, to be
 * adjusted by caller on each iteration.
 *
 * \param copy_cb Callback used to retrieve content from the basis
 * file.
 *
 * \param copy_arg Opaque environment pointer passed through to the
 * callback.
 *
 * \todo As output is produced, accumulate the MD4 checksum of the
 * output.  Then if we find a CHECKSUM command we can check it's
 * contents against the output.
 *
 * \todo Implement COPY commands.
 *
 * \sa rs_patch_file()
 */
rs_job_t *
rs_patch_begin(rs_copy_cb *copy_cb, void *copy_arg)
{
    rs_job_t *job = rs_job_new("patch", rs_patch_s_header);
        
    job->copy_cb = copy_cb;
    job->copy_arg = copy_arg;

    rs_mdfour_begin(&job->output_md4);

    return job;
}
Пример #2
0
void DLL_EXPORT get_file_digest (file_reader & reader
								, uchar_t digest[DIGEST_BYTES])
{
	const int buf_len = XDELTA_BUFFER_LEN; // four times of block.
	char_buffer <uchar_t> buf (XDELTA_BUFFER_LEN);
	rs_mdfour_t ctx;
	rs_mdfour_begin(&ctx);

	while (true) {
		int size = reader.read_file (buf.begin (), buf_len);
		if (size <= 0)
			break;
		rs_mdfour_update(&ctx, buf.begin (), size);
	}

	rs_mdfour_result (&ctx, digest);
}
Пример #3
0
int32_t multiround_hash_table::_haser_first_round (file_reader & reader
										, hasher_stream & stream
										, std::set<hole_t> & holes) const
{
	if (!holes.empty ()) {
		std::string errmsg = fmt_string ("Holes must be empty.");
		THROW_XDELTA_EXCEPTION (errmsg);
	}

	hole_t hole;
	hole.offset = 0;
	bool round = true;
	try {
		reader.open_file (); // sometimes this will throw.
		hole.length = reader.get_file_size ();
		holes.insert (hole);
	}
	catch (...) {
		round = false;
	}

	if (!round) {
		hash_table::hash_it (reader, stream);
		return -1;
	}

	int32_t blk_len = (uint32_t)(hole.length / multiround_base ());
	if (blk_len > MULTIROUND_MAX_BLOCK_SIZE)
		blk_len = MULTIROUND_MAX_BLOCK_SIZE;
	if (blk_len < XDELTA_BLOCK_SIZE)
		blk_len = XDELTA_BLOCK_SIZE;

	stream.start_hash_stream (reader.get_fname (), blk_len);
	rs_mdfour_t ctx;
	rs_mdfour_begin(&ctx);

	read_and_hash (reader, stream, hole.length, blk_len, hole.offset, &ctx);
	
	uchar_t file_hash[DIGEST_BYTES];
	memset (&file_hash, 0, sizeof (file_hash));
	rs_mdfour_result (&ctx, file_hash);

	bool neednextround = stream.end_first_round (file_hash);
	return (neednextround ? blk_len : -1);
}
Пример #4
0
//
// used the hash_table object receive from remote host 
// and send a hash stream to the remote host.
//
void hash_table::hash_it (file_reader & reader, hasher_stream & stream) const
{
	rs_mdfour_t ctx;
	rs_mdfour_begin(&ctx);
	uint64_t filsize = 0;
	try {
		int32_t f_blk_len = 0;
		if (reader.exist_file ()) {
			try {
				reader.open_file (); // sometimes this will throw.
				filsize = reader.get_file_size ();
				f_blk_len = get_xdelta_block_size (filsize);
			}
			catch (...) {
				stream.start_hash_stream (reader.get_fname (), 0);
				throw;
			}
			stream.start_hash_stream (reader.get_fname (), f_blk_len);
		}
		else {
			std::string mesg = fmt_string ("File %s not exists."
				, reader.get_fname ().c_str ());
			stream.start_hash_stream (reader.get_fname (), 0);
			stream.on_error (mesg, ENOENT);
			goto end;
		}
		read_and_hash (reader, stream, filsize, f_blk_len, 0, &ctx);
	}
	catch (xdelta_exception &e) {
		stream.on_error (e.what (), e.get_errno ());
	}

end:
	uchar_t file_hash[DIGEST_BYTES];
	memset (file_hash, 0, sizeof (file_hash));
	rs_mdfour_result (&ctx, file_hash);

	reader.close_file ();
	stream.end_hash_stream (file_hash, filsize);
	return;
}