Fix file size recording in the magic header when stdin is used.

This commit is contained in:
Con Kolivas 2010-11-01 19:18:20 +11:00
parent 43dd72b9e1
commit 232b268367
3 changed files with 30 additions and 15 deletions

2
main.c
View file

@ -69,7 +69,7 @@ static void write_magic(int fd_in, int fd_out)
if (fstat(fd_in, &st) != 0) if (fstat(fd_in, &st) != 0)
fatal("bad magic file descriptor!?\n"); fatal("bad magic file descriptor!?\n");
memcpy(&magic[6], &st.st_size, 8); memcpy(&magic[6], &control.st_size, 8);
/* save LZMA compression flags */ /* save LZMA compression flags */
if (LZMA_COMPRESS(control.flags)) { if (LZMA_COMPRESS(control.flags)) {

42
rzip.c
View file

@ -548,6 +548,8 @@ static void mmap_stdin(uchar *buf, struct rzip_state *st)
/* Should be EOF */ /* Should be EOF */
print_maxverbose("Shrinking chunk to %lld\n", total); print_maxverbose("Shrinking chunk to %lld\n", total);
buf = mremap(buf, st->chunk_size, total, 0); buf = mremap(buf, st->chunk_size, total, 0);
if (buf == MAP_FAILED)
fatal("Failed to remap to smaller buf in mmap_stdin\n");
st->chunk_size = total; st->chunk_size = total;
st->stdin_eof = 1; st->stdin_eof = 1;
break; break;
@ -563,20 +565,20 @@ static void rzip_chunk(struct rzip_state *st, int fd_in, int fd_out, i64 offset,
double pct_base, double pct_multiple, i64 limit) double pct_base, double pct_multiple, i64 limit)
{ {
i64 prealloc_size = st->chunk_size; i64 prealloc_size = st->chunk_size;
uchar *buf = (void *)-1; uchar *buf = MAP_FAILED;
/* Malloc'ing first will tell us if we can allocate this much ram /* Mmapping first will tell us if we can allocate this much ram
* faster than slowly reading in the file and then failing. Filling * faster than slowly reading in the file and then failing. Filling
* it with zeroes has a defragmenting effect on ram before the real * it with zeroes has a defragmenting effect on ram before the real
* read in. */ * read in. */
print_verbose("Preallocating ram...\n"); print_verbose("Preallocating ram...\n");
while (buf == (void*)-1) { while (buf == MAP_FAILED) {
/* If we fail to mmap the full amount, it is worth trying to /* If we fail to mmap the full amount, it is worth trying to
* mmap ever smaller sizes till we succeed as we may be able * mmap ever smaller sizes till we succeed as we may be able
* to continue with file backed mmap in the presence of swap * to continue with file backed mmap in the presence of swap
* and defragmentation */ * and defragmentation */
buf = mmap(NULL, prealloc_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); buf = mmap(NULL, prealloc_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (buf == (void *)-1) { if (buf == MAP_FAILED) {
prealloc_size = prealloc_size / 10 * 9; prealloc_size = prealloc_size / 10 * 9;
continue; continue;
} }
@ -584,6 +586,7 @@ static void rzip_chunk(struct rzip_state *st, int fd_in, int fd_out, i64 offset,
if (!memset(buf, 0, prealloc_size)) if (!memset(buf, 0, prealloc_size))
fatal("Failed to memset in rzip_chunk\n"); fatal("Failed to memset in rzip_chunk\n");
if (!STDIN) { if (!STDIN) {
/* STDIN will use this already allocated ram */
if (munmap(buf, prealloc_size) != 0) if (munmap(buf, prealloc_size) != 0)
fatal("Failed to munmap in rzip_chunk\n"); fatal("Failed to munmap in rzip_chunk\n");
} else } else
@ -591,12 +594,19 @@ static void rzip_chunk(struct rzip_state *st, int fd_in, int fd_out, i64 offset,
} }
if (!STDIN) { if (!STDIN) {
print_verbose("Reading file into mmapped ram...\n"); print_verbose("Reading file into mmapped ram...\n");
retry:
buf = (uchar *)mmap(buf, st->chunk_size, PROT_READ, MAP_SHARED, fd_in, offset); buf = (uchar *)mmap(buf, st->chunk_size, PROT_READ, MAP_SHARED, fd_in, offset);
} /* Better to shrink the window to the largest size that works than fail */
if (buf == (uchar *)-1) if (buf == MAP_FAILED) {
fatal("Failed to map buffer in rzip_chunk\n"); st->chunk_size = st->chunk_size / 10 * 9;
if (STDIN) goto retry;
}
print_verbose("Mmapped %lld ram...\n", st->chunk_size);
} else {
/* We don't know how big the data will be so we add it up here */
mmap_stdin(buf, st); mmap_stdin(buf, st);
control.st_size += st->chunk_size;
}
st->ss = open_stream_out(fd_out, NUM_STREAMS, limit); st->ss = open_stream_out(fd_out, NUM_STREAMS, limit);
if (!st->ss) if (!st->ss)
@ -622,7 +632,7 @@ void rzip_fd(int fd_in, int fd_out)
struct timeval current, start, last; struct timeval current, start, last;
struct stat s, s2; struct stat s, s2;
struct rzip_state *st; struct rzip_state *st;
i64 len, chunk_window, last_chunk = 0; i64 len = 0, chunk_window, last_chunk = 0;
int pass = 0, passes; int pass = 0, passes;
unsigned int eta_hours, eta_minutes, eta_seconds, elapsed_hours, unsigned int eta_hours, eta_minutes, eta_seconds, elapsed_hours,
elapsed_minutes, elapsed_seconds; elapsed_minutes, elapsed_seconds;
@ -640,8 +650,11 @@ void rzip_fd(int fd_in, int fd_out)
if (fstat(fd_in, &s)) if (fstat(fd_in, &s))
fatal("Failed to stat fd_in in rzip_fd - %s\n", strerror(errno)); fatal("Failed to stat fd_in in rzip_fd - %s\n", strerror(errno));
len = s.st_size; if (!STDIN) {
print_verbose("File size: %lld\n", len); len = control.st_size = s.st_size;
print_verbose("File size: %lld\n", len);
} else
control.st_size = 0;
chunk_window = control.window * CHUNK_MULTIPLE; chunk_window = control.window * CHUNK_MULTIPLE;
@ -697,7 +710,7 @@ void rzip_fd(int fd_in, int fd_out)
gettimeofday(&current, NULL); gettimeofday(&current, NULL);
/* this will count only when size > window */ /* this will count only when size > window */
if (last.tv_sec > 0) { if (!STDIN && last.tv_sec > 0) {
elapsed_time = current.tv_sec - start.tv_sec; elapsed_time = current.tv_sec - start.tv_sec;
finish_time = elapsed_time / (pct_base / 100.0); finish_time = elapsed_time / (pct_base / 100.0);
elapsed_hours = (unsigned int)(elapsed_time) / 3600; elapsed_hours = (unsigned int)(elapsed_time) / 3600;
@ -733,10 +746,11 @@ void rzip_fd(int fd_in, int fd_out)
(unsigned int)st->stats.inserts, (unsigned int)st->stats.inserts,
(1.0 + st->stats.match_bytes) / st->stats.literal_bytes); (1.0 + st->stats.match_bytes) / st->stats.literal_bytes);
if (!STDIN) if (!STDIN) {
print_progress("%s - ", control.infile); print_progress("%s - ", control.infile);
print_progress("Compression Ratio: %.3f. Average Compression Speed: %6.3fMB/s.\n", print_progress("Compression Ratio: %.3f. Average Compression Speed: %6.3fMB/s.\n",
1.0 * s.st_size / s2.st_size, chunkmbs); 1.0 * s.st_size / s2.st_size, chunkmbs);
}
if (st->hash_table) if (st->hash_table)
free(st->hash_table); free(st->hash_table);

1
rzip.h
View file

@ -182,6 +182,7 @@ struct rzip_control {
int nice_val; // added for consistency int nice_val; // added for consistency
int major_version; int major_version;
int minor_version; int minor_version;
i64 st_size;
}; };
extern struct rzip_control control; extern struct rzip_control control;