Skip to content

Commit de6182d

Browse files
committed
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 <[email protected]>
1 parent b0d9c69 commit de6182d

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

entry.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
123123
enum object_type type;
124124
unsigned long sz;
125125
int result = -1;
126+
ssize_t kept = 0;
126127
int fd = -1;
127128

128129
st = open_istream(ce->sha1, &type, &sz);
@@ -136,18 +137,34 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
136137
goto close_and_exit;
137138

138139
for (;;) {
139-
char buf[10240];
140-
ssize_t wrote;
140+
char buf[1024 * 16];
141+
ssize_t wrote, holeto;
141142
ssize_t readlen = read_istream(st, buf, sizeof(buf));
142143

143144
if (!readlen)
144145
break;
146+
if (sizeof(buf) == readlen) {
147+
for (holeto = 0; holeto < readlen; holeto++)
148+
if (buf[holeto])
149+
break;
150+
if (readlen == holeto) {
151+
kept += holeto;
152+
continue;
153+
}
154+
}
145155

156+
if (kept && lseek(fd, kept, SEEK_CUR) == (off_t) -1)
157+
goto close_and_exit;
158+
else
159+
kept = 0;
146160
wrote = write_in_full(fd, buf, readlen);
147161

148162
if (wrote != readlen)
149163
goto close_and_exit;
150164
}
165+
if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
166+
write(fd, "", 1) != 1))
167+
goto close_and_exit;
151168
*fstat_done = fstat_output(fd, state, statbuf);
152169

153170
close_and_exit:

0 commit comments

Comments
 (0)