Commit aa57231fca5897c0779d5bcfc5d9183b454792eb

Carlos Martín Nieto 2015-06-02T10:25:22

indexer: use lseek to extend the packfile We've been using `p_ftruncate()` to extend the packfile in order to mmap it and write the new data into it. This works well in the general case, but as truncation does not allocate space in the filesystem, it must do so when we write data to it. The only way the OS has to indicate a failure to allocate space is via SIGBUS which means we tried to write outside the file. This will cause everyone to crash as they don't expect to handle this signal. Switch to using `p_lseek()` and `p_write()` to extend the file in a way which tells the filesystem to allocate the space for the missing data. We can then be sure that we have space to write into.

diff --git a/src/indexer.c b/src/indexer.c
index e39345c..1890b00 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -478,13 +478,14 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
 static int append_to_pack(git_indexer *idx, const void *data, size_t size)
 {
 	git_off_t current_size = idx->pack->mwf.size;
+	int fd = idx->pack->mwf.fd;
 
 	if (!size)
 		return 0;
 
-	/* add the extra space we need at the end */
-	if (p_ftruncate(idx->pack->mwf.fd, current_size + size) < 0) {
-		giterr_set(GITERR_OS, "Failed to increase size of pack file '%s'", idx->pack->pack_name);
+	if (p_lseek(fd, current_size + size - 1, SEEK_SET) < 0 ||
+	    p_write(idx->pack->mwf.fd, data, 1) < 0) {
+		giterr_set(GITERR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
 		return -1;
 	}