aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorMichael Raskin <7c6f434c@mail.ru>2009-05-04 08:10:24 +0000
committerMichael Raskin <7c6f434c@mail.ru>2009-05-04 08:10:24 +0000
commit098cb9d233ff7e1568b55e88dacf52e1dc8eebab (patch)
treeeb700b94450c279a81689c004721ac6c579e969d /src/libutil
parentc710fe540e3763d821eab74621b43d9422cb7e92 (diff)
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)
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/archive.cc8
-rw-r--r--src/libutil/archive.hh1
2 files changed, 9 insertions, 0 deletions
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index 8f100da4c..4899fbaa4 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 fff620313..f358a2a6b 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) { };
};