Exemple #1
0
void multiround_hash_table::_next_round (file_reader & reader
										, hasher_stream & stream
										, std::set<hole_t> & holes
										, const int32_t blk_len) const
{
	if (holes.empty ()) {
		std::string errmsg = fmt_string ("Holes mustn't be empty.");
		THROW_XDELTA_EXCEPTION (errmsg);
	}

	try {
		stream.next_round (blk_len);
		typedef std::set<hole_t>::const_iterator cit_t;

		for (cit_t begin = holes.begin (); begin != holes.end (); ++begin) {
			const hole_t & hole = *begin;
			if (hole.length < (uint32_t)blk_len)
				continue;

			uint64_t offset = reader.seek_file (hole.offset, FILE_BEGIN);
			if (offset != hole.offset) {
				std::string errmsg = fmt_string ("Can't seek file %s(%s)."
					, reader.get_fname ().c_str (), error_msg ().c_str ());
				THROW_XDELTA_EXCEPTION (errmsg);
			}

			read_and_hash (reader, stream, hole.length, blk_len, hole.offset, 0);
		}
		stream.end_one_round ();
	}
	catch (xdelta_exception &e) {
		stream.on_error (e.what (), e.get_errno ());
	}
}
Exemple #2
0
uint32_t seek_and_read (file_reader & reader, uint64_t offset, uint32_t length, uchar_t * data)
{
	uint64_t s_offset = reader.seek_file (offset, FILE_BEGIN);
	if (offset != s_offset) {
		std::string errmsg = fmt_string ("Can't seek file %s(%s)."
			, reader.get_fname ().c_str (), error_msg ().c_str ());
		THROW_XDELTA_EXCEPTION (errmsg);
	}

	uint32_t ret = reader.read_file (data, length);
	if (ret < length) {
		std::string errmsg = fmt_string ("Bytes read from %s(%s) is less than demand."
			, reader.get_fname ().c_str (), error_msg ().c_str ());
		THROW_XDELTA_EXCEPTION (errmsg);
	}

	return ret;
}
Exemple #3
0
void read_and_delta (file_reader & reader
					, xdelta_stream & stream
					, const hash_table & hashes
					, std::set<hole_t> & hole_set
					, const int blk_len
					, bool need_split_hole)
{
	bool adddiff = !need_split_hole;
	char_buffer<uchar_t> buf (XDELTA_BUFFER_LEN);
	typedef std::set<hole_t>::iterator it_t;
	std::list<hole_t> holes2remove;

	for (it_t begin = hole_set.begin (); begin != hole_set.end (); ++begin) {
		const hole_t & hole = *begin;
		uint64_t offset = reader.seek_file (hole.offset, FILE_BEGIN);
		if (offset != hole.offset) {
			std::string errmsg = fmt_string ("Can't seek file %s(%s)."
				, reader.get_fname ().c_str (), error_msg ().c_str ());
			THROW_XDELTA_EXCEPTION (errmsg);
		}

		uint32_t buflen = XDELTA_BUFFER_LEN;
		uint32_t to_read_bytes = (uint32_t)hole.length;

		buflen = to_read_bytes > buflen ? buflen : to_read_bytes;
		uchar_t * rdbuf = buf.begin ();

		uint32_t size = reader.read_file (rdbuf, buflen);
		if (size != buflen) {
			std::string errmsg = fmt_string ("Can't read file %s(%s)."
				, reader.get_fname ().c_str (), error_msg ().c_str ());
			THROW_XDELTA_EXCEPTION (errmsg);
		}

		to_read_bytes -= size;
		const uchar_t * endbuf = rdbuf + size;
		rdbuf = buf.begin ();

		if ((int32_t)(endbuf - rdbuf) >= blk_len) {
			uchar_t * sentrybuf = rdbuf;
			rolling_hasher hasher;
			hasher.eat_hash (rdbuf, blk_len);

			while (true) {
				bool newhash = false;
				const slow_hash * bsh = hashes.find_block (hasher.hash_value (), rdbuf, blk_len);
				uchar_t outchar = 0;

				if (bsh) {
					// a match was found.
					uint32_t slipsize = (uint32_t)(rdbuf - sentrybuf);
					if (slipsize > 0 && adddiff)
						stream.add_block (sentrybuf, slipsize, offset);

					offset += slipsize;

					stream.add_block (bsh->tpos, blk_len, offset);
					if (need_split_hole) {
						hole_t newhole;
						newhole.offset = offset;
						newhole.length = blk_len;
						holes2remove.push_back (newhole);
					}

					rdbuf += blk_len;
					sentrybuf = rdbuf;
					newhash = true;
					offset += blk_len;
				}
				else {
					// slip the window by one bytes which size is blk_len.
					outchar = *rdbuf;
					++rdbuf;
				}

				//
				// beyond the buffer.
				int remain = (int)(endbuf - rdbuf);
				if (remain < blk_len) {
					if (to_read_bytes == 0) {
						// no more to read.
						uint32_t slipsize = (uint32_t)(endbuf - sentrybuf);
						if (slipsize > 0 && adddiff)
							stream.add_block (sentrybuf, slipsize, offset);
						goto end;
					}
					else {
						memmove (buf.begin (), rdbuf, remain);
						rdbuf = buf.begin ();
						sentrybuf = rdbuf;

						buflen = XDELTA_BUFFER_LEN - remain;
						buflen = to_read_bytes > buflen ? buflen : to_read_bytes;
						size = reader.read_file (rdbuf + remain, buflen);

						if (size != buflen) {
							std::string errmsg = fmt_string ("Can't read file %s(%s)."
								, reader.get_fname ().c_str (), error_msg ().c_str ());
							THROW_XDELTA_EXCEPTION (errmsg);
						}

						to_read_bytes -= size;
						endbuf = rdbuf + remain + size;
						remain += size;

						if (remain >= blk_len) {
							if (newhash)
								hasher.eat_hash (rdbuf, blk_len);
							else
								hasher.update (outchar, *(rdbuf + blk_len));
						}
						else {
							//
							// one read must complement data which length plus
							// remain must be more than one block length of @f_blk_len,
							// so if remain less than that, it must be reach the end of
							// file
							//
							if (adddiff)
								stream.add_block (rdbuf, remain, offset);
							offset += remain;
							goto end;
						}
					}
				}
				else {
					if (newhash)
						hasher.eat_hash (rdbuf, blk_len);
					else
						hasher.update (outchar, *(rdbuf + blk_len - 1));
				}
			}
		}
		else {
			if (adddiff)
				stream.add_block (rdbuf, size, offset);
		}
end:
		continue;
	}

	if (need_split_hole) {
		typedef std::list<hole_t>::iterator it_t;
		for (it_t begin = holes2remove.begin (); begin != holes2remove.end (); ++begin)
			split_hole (hole_set, *begin);
	}
	return;
}