示例#1
0
文件: runzip.c 项目: lweijin/lrzip
static i64 read_fdhist(rzip_control *control, void *buf, i64 len)
{
	if (!TMP_OUTBUF)
		return read_1g(control, control->fd_hist, buf, len);
	if (unlikely(len + control->hist_ofs > control->out_maxlen)) {
		print_err("Trying to read beyond end of tmpoutbuf in read_fdhist\n");
		return -1;
	}
	memcpy(buf, control->tmp_outbuf + control->hist_ofs, len);
	return len;
}
示例#2
0
文件: stream.c 项目: epa/lrzip
static int read_buf(int f, uchar *p, i64 len)
{
	ssize_t ret;

	ret = read_1g(f, p, (size_t)len);
	if (ret == -1) {
		err_msg("Read of length %d failed - %s\n", len, strerror(errno));
		return -1;
	}
	if (ret != (ssize_t)len) {
		err_msg("Partial read!? asked for %d bytes but got %d\n", len, ret);
		return -1;
	}
	return 0;
}
示例#3
0
文件: runzip.c 项目: lweijin/lrzip
/* Decompress an open file. Call fatal_return(() on error
   return the number of bytes that have been retrieved
 */
i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 expected_size)
{
	uchar md5_stored[MD5_DIGEST_SIZE];
	struct timeval start,end;
	i64 total = 0, u;
	double tdiff;

	if (!NO_MD5)
		md5_init_ctx (&control->ctx);
	gettimeofday(&start,NULL);

	do {
		u = runzip_chunk(control, fd_in, expected_size, total);
		if (unlikely(u == -1)) {
			print_err("Failed to runzip_chunk in runzip_fd\n");
			return -1;
		}
		total += u;
		if (TMP_OUTBUF) {
			if (unlikely(!flush_tmpoutbuf(control))) {
				print_err("Failed to flush_tmpoutbuf in runzip_fd\n");
				return -1;
			}
		} else if (STDOUT) {
			if (unlikely(!dump_tmpoutfile(control, fd_out))) {
				print_err("Failed to dump_tmpoutfile in runzip_fd\n");
				return -1;
			}
		}
		if (TMP_INBUF)
			clear_tmpinbuf(control);
		else if (STDIN && !DECOMPRESS) {
			if (unlikely(!clear_tmpinfile(control))) {
				print_err("Failed to clear_tmpinfile in runzip_fd\n");
				return -1;
			}
		}
	} while (total < expected_size || (!expected_size && !control->eof));

	gettimeofday(&end,NULL);
	if (!ENCRYPT) {
		tdiff = end.tv_sec - start.tv_sec;
		if (!tdiff)
			tdiff = 1;
		print_progress("\nAverage DeCompression Speed: %6.3fMB/s\n",
			       (total / 1024 / 1024) / tdiff);
	}

	if (!NO_MD5) {
		int i,j;

		md5_finish_ctx (&control->ctx, control->md5_resblock);
		if (HAS_MD5) {
			i64 fdinend = seekto_fdinend(control);

			if (unlikely(fdinend == -1))
				failure_return(("Failed to seekto_fdinend in rzip_fd\n"), -1);
			if (unlikely(seekto_fdin(control, fdinend - MD5_DIGEST_SIZE) == -1))
				failure_return(("Failed to seekto_fdin in rzip_fd\n"), -1);

			if (unlikely(read_1g(control, fd_in, md5_stored, MD5_DIGEST_SIZE) != MD5_DIGEST_SIZE))
				fatal_return(("Failed to read md5 data in runzip_fd\n"), -1);
			if (ENCRYPT)
				if (unlikely(!lrz_decrypt(control, md5_stored, MD5_DIGEST_SIZE, control->salt_pass)))
					return -1;
			for (i = 0; i < MD5_DIGEST_SIZE; i++)
				if (md5_stored[i] != control->md5_resblock[i]) {
					print_output("MD5 CHECK FAILED.\nStored:");
					for (j = 0; j < MD5_DIGEST_SIZE; j++)
						print_output("%02x", md5_stored[j] & 0xFF);
					print_output("\nOutput file:");
					for (j = 0; j < MD5_DIGEST_SIZE; j++)
						print_output("%02x", control->md5_resblock[j] & 0xFF);
					failure_return(("\n"), -1);
				}
		}

		if (HASH_CHECK || MAX_VERBOSE) {
			print_output("MD5: ");
			for (i = 0; i < MD5_DIGEST_SIZE; i++)
				print_output("%02x", control->md5_resblock[i] & 0xFF);
			print_output("\n");
		}

		if (CHECK_FILE) {
			FILE *md5_fstream;
			int i, j;

			if (TMP_OUTBUF)
				close_tmpoutbuf(control);
			memcpy(md5_stored, control->md5_resblock, MD5_DIGEST_SIZE);
			if (unlikely(seekto_fdhist(control, 0) == -1))
				fatal_return(("Failed to seekto_fdhist in runzip_fd\n"), -1);
			if (unlikely((md5_fstream = fdopen(fd_hist, "r")) == NULL))
				fatal_return(("Failed to fdopen fd_hist in runzip_fd\n"), -1);
			if (unlikely(md5_stream(md5_fstream, control->md5_resblock)))
				fatal_return(("Failed to md5_stream in runzip_fd\n"), -1);
			/* We don't close the file here as it's closed in main */
			for (i = 0; i < MD5_DIGEST_SIZE; i++)
				if (md5_stored[i] != control->md5_resblock[i]) {
					print_output("MD5 CHECK FAILED.\nStored:");
					for (j = 0; j < MD5_DIGEST_SIZE; j++)
						print_output("%02x", md5_stored[j] & 0xFF);
					print_output("\nOutput file:");
					for (j = 0; j < MD5_DIGEST_SIZE; j++)
						print_output("%02x", control->md5_resblock[j] & 0xFF);
					failure_return(("\n"), -1);
				}
			print_output("MD5 integrity of written file matches archive\n");
			if (!HAS_MD5)
				print_output("Note this lrzip archive did not have a stored md5 value.\n"
				"The archive decompression was validated with crc32 and the md5 hash was "
				"calculated on decompression\n");
		}
	}

	return total;
}
示例#4
0
文件: runzip.c 项目: lweijin/lrzip
/* decompress a section of an open file. Call fatal_return(() on error
   return the number of bytes that have been retrieved
 */
static i64 runzip_chunk(rzip_control *control, int fd_in, i64 expected_size, i64 tally)
{
	uint32 good_cksum, cksum = 0;
	i64 len, ofs, total = 0;
	int l = -1, p = 0;
	char chunk_bytes;
	struct stat st;
	uchar head;
	void *ss;
	bool err = false;

	/* for display of progress */
	unsigned long divisor[] = {1,1024,1048576,1073741824U};
	char *suffix[] = {"","KB","MB","GB"};
	double prog_done, prog_tsize;
	int divisor_index;

	if (expected_size > (i64)10737418240ULL)	/* > 10GB */
		divisor_index = 3;
	else if (expected_size > 10485760)	/* > 10MB */
		divisor_index = 2;
	else if (expected_size > 10240)	/* > 10KB */
		divisor_index = 1;
	else
		divisor_index = 0;

	prog_tsize = (long double)expected_size / (long double)divisor[divisor_index];

	/* Determine the chunk_byte width size. Versions < 0.4 used 4
	 * bytes for all offsets, version 0.4 used 8 bytes. Versions 0.5+ use
	 * a variable number of bytes depending on chunk size.*/
	if (control->major_version == 0 && control->minor_version < 4)
		chunk_bytes = 4;
	else if (control->major_version == 0 && control->minor_version == 4)
		chunk_bytes = 8;
	else {
		print_maxverbose("Reading chunk_bytes at %lld\n", get_readseek(control, fd_in));
		/* Read in the stored chunk byte width from the file */
		if (unlikely(read_1g(control, fd_in, &chunk_bytes, 1) != 1))
			fatal_return(("Failed to read chunk_bytes size in runzip_chunk\n"), -1);
		if (unlikely(chunk_bytes < 1 || chunk_bytes > 8))
			failure_return(("chunk_bytes %d is invalid in runzip_chunk\n", chunk_bytes), -1);
	}
	if (!tally && expected_size)
		print_maxverbose("Expected size: %lld\n", expected_size);
	print_maxverbose("Chunk byte width: %d\n", chunk_bytes);

	ofs = seekcur_fdin(control);
	if (unlikely(ofs == -1))
		fatal_return(("Failed to seek input file in runzip_fd\n"), -1);

	if (fstat(fd_in, &st) || st.st_size - ofs == 0)
		return 0;

	ss = open_stream_in(control, fd_in, NUM_STREAMS, chunk_bytes);
	if (unlikely(!ss))
		failure_return(("Failed to open_stream_in in runzip_chunk\n"), -1);

	/* All chunks were unnecessarily encoded 8 bytes wide version 0.4x */
	if (control->major_version == 0 && control->minor_version == 4)
		control->chunk_bytes = 8;
	else
		control->chunk_bytes = 2;

	while ((len = read_header(control, ss, &head)) || head) {
		i64 u;
		if (unlikely(len == -1))
			return -1;
		switch (head) {
			case 0:
				u = unzip_literal(control, ss, len, &cksum);
				if (unlikely(u == -1)) {
					close_stream_in(control, ss);
					return -1;
				}
				total += u;
				break;

			default:
				u = unzip_match(control, ss, len, &cksum, chunk_bytes);
				if (unlikely(u == -1)) {
					close_stream_in(control, ss);
					return -1;
				}
				total += u;
				break;
		}
		if (expected_size) {
			p = 100 * ((double)(tally + total) / (double)expected_size);
			if (p / 10 != l / 10)  {
				prog_done = (double)(tally + total) / (double)divisor[divisor_index];
				print_progress("%3d%%  %9.2f / %9.2f %s\r",
						p, prog_done, prog_tsize, suffix[divisor_index] );
				l = p;
			}
		}
	}

	if (!HAS_MD5) {
		good_cksum = read_u32(control, ss, 0, &err);
		if (unlikely(err)) {
			close_stream_in(control, ss);
			return -1;
		}
		if (unlikely(good_cksum != cksum)) {
			close_stream_in(control, ss);
			failure_return(("Bad checksum: 0x%08x - expected: 0x%08x\n", cksum, good_cksum), -1);
		}
		print_maxverbose("Checksum for block: 0x%08x\n", cksum);
	}

	if (unlikely(close_stream_in(control, ss)))
		fatal("Failed to close stream!\n");

	return total;
}