From 098cb9d233ff7e1568b55e88dacf52e1dc8eebab Mon Sep 17 00:00:00 2001 From: Michael Raskin <7c6f434c@mail.ru> Date: Mon, 4 May 2009 08:10:24 +0000 Subject: [PATCH] Add an ftruncate call paired with fallocate to play safe with some FSes (namely, BtrFS fallocate sets file size to allocated size, i.e. multiple of block size) --- src/libutil/archive.cc | 8 ++++++++ src/libutil/archive.hh | 1 + 2 files changed, 9 insertions(+) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 8f100da4c3..4899fbaa45 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -181,6 +181,8 @@ static void parseContents(ParseSink & sink, Source & source, const Path & path) left -= n; } + sink.finalizeContents(size); + readPadding(size, source); } @@ -310,6 +312,12 @@ struct RestoreSink : ParseSink writeFull(fd, data, len); } + void finalizeContents(unsigned long long size) + { + errno = ftruncate(fd, size); + if (errno) throw SysError(format("truncating file to its allocated length of %1% bytes") % size); + } + void createSymlink(const Path & path, const string & target) { Path p = dstPath + path; diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh index fff6203139..f358a2a6be 100644 --- a/src/libutil/archive.hh +++ b/src/libutil/archive.hh @@ -64,6 +64,7 @@ struct ParseSink virtual void isExecutable() { }; virtual void preallocateContents(unsigned long long size) { }; virtual void receiveContents(unsigned char * data, unsigned int len) { }; + virtual void finalizeContents(unsigned long long size) { }; virtual void createSymlink(const Path & path, const string & target) { }; };