diff options
author | Junio C Hamano <gitster@pobox.com> | 2011-05-13 15:55:00 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2011-05-20 23:16:53 -0700 |
commit | de6182db67d0f53fdc13256042014f2ddf5f8df3 (patch) | |
tree | 177d871672cea8c07f3cc2b6ef30fb8c36b09f08 /entry.c | |
parent | b0d9c69f5ee4a626a779d27a33f5565efccd5802 (diff) | |
download | git-de6182db67d0f53fdc13256042014f2ddf5f8df3.tar.gz |
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>
Diffstat (limited to 'entry.c')
-rw-r--r-- | entry.c | 21 |
1 files changed, 19 insertions, 2 deletions
@@ -123,6 +123,7 @@ static int streaming_write_entry(struct cache_entry *ce, char *path, enum object_type type; unsigned long sz; int result = -1; + ssize_t kept = 0; int fd = -1; 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; for (;;) { - char buf[10240]; - ssize_t wrote; + char buf[1024 * 16]; + ssize_t wrote, holeto; ssize_t readlen = read_istream(st, buf, sizeof(buf)); if (!readlen) 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); if (wrote != readlen) 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); close_and_exit: |