summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-06-02 10:25:22 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2015-06-22 18:23:54 +0200
commit0b4e8ab2a785c04186b4a34e5e9f7c8afd5f3df5 (patch)
tree163619c30d81c327cc85a6cfbfe396b374a9c644
parentb494e763d8e56547f70044fe12e06df7b9879555 (diff)
downloadlibgit2-0b4e8ab2a785c04186b4a34e5e9f7c8afd5f3df5.tar.gz
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.
-rw-r--r--src/indexer.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/src/indexer.c b/src/indexer.c
index 28268ff04..f83935ada 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -469,13 +469,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;
}