streaming_write_entry(): support files with holes

One typical use of a large binary file is to hold a sparse on-disk hash
table with a lot of holes. Help preserving the holes with lseek().

Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Junio C Hamano 2011-05-13 15:55:00 -07:00
parent b0d9c69f5e
commit de6182db67

21
entry.c
View File

@ -123,6 +123,7 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
enum object_type type; enum object_type type;
unsigned long sz; unsigned long sz;
int result = -1; int result = -1;
ssize_t kept = 0;
int fd = -1; int fd = -1;
st = open_istream(ce->sha1, &type, &sz); st = open_istream(ce->sha1, &type, &sz);
@ -136,18 +137,34 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
goto close_and_exit; goto close_and_exit;
for (;;) { for (;;) {
char buf[10240]; char buf[1024 * 16];
ssize_t wrote; ssize_t wrote, holeto;
ssize_t readlen = read_istream(st, buf, sizeof(buf)); ssize_t readlen = read_istream(st, buf, sizeof(buf));
if (!readlen) if (!readlen)
break; break;
if (sizeof(buf) == readlen) {
for (holeto = 0; holeto < readlen; holeto++)
if (buf[holeto])
break;
if (readlen == holeto) {
kept += holeto;
continue;
}
}
if (kept && lseek(fd, kept, SEEK_CUR) == (off_t) -1)
goto close_and_exit;
else
kept = 0;
wrote = write_in_full(fd, buf, readlen); wrote = write_in_full(fd, buf, readlen);
if (wrote != readlen) if (wrote != readlen)
goto close_and_exit; goto close_and_exit;
} }
if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
write(fd, "", 1) != 1))
goto close_and_exit;
*fstat_done = fstat_output(fd, state, statbuf); *fstat_done = fstat_output(fd, state, statbuf);
close_and_exit: close_and_exit: