diff options
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | paludis/fs_merger.cc | 23 |
2 files changed, 43 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index 42077404f..0b9655955 100644 --- a/configure.ac +++ b/configure.ac @@ -186,6 +186,26 @@ if test "x$have_dirent_dtype" = "xyes"; then fi dnl }}} +dnl {{{ check for fallocate +AC_MSG_CHECKING([for fallocate]) +AC_COMPILE_IFELSE([ +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <linux/falloc.h> +int main(int, char **) +{ + fallocate(0, FALLOC_FL_KEEP_SIZE, 0, 100); +} +], + [have_fallocate=yes], + [have_fallocate=no]) +AC_MSG_RESULT([$have_fallocate]) +if test "x$have_fallocate" = "xyes"; then + AC_DEFINE([HAVE_FALLOCATE], [1], [Use fallocate]) +fi +dnl }}} + dnl {{{ check for cxxflags if test x = x"$LET_ME_RICE" then diff --git a/paludis/fs_merger.cc b/paludis/fs_merger.cc index 4205c3b6e..57413f51e 100644 --- a/paludis/fs_merger.cc +++ b/paludis/fs_merger.cc @@ -47,10 +47,15 @@ #include <unordered_map> #include "config.h" + #ifdef HAVE_XATTRS # include <sys/xattr.h> #endif +#ifdef HAVE_FALLOCATE +# include <linux/falloc.h> +#endif + using namespace paludis; #include <paludis/fs_merger-se.cc> @@ -390,6 +395,24 @@ FSMerger::install_file(const FSPath & src, const FSPath & dst_dir, const std::st throw FSMergerError("Cannot fchmod '" + stringify(dst) + "': " + stringify(::strerror(errno))); try_to_copy_xattrs(src, output_fd, result); +#ifdef HAVE_FALLOCATE + if (0 != ::fallocate(output_fd, FALLOC_FL_KEEP_SIZE, 0, src_stat.file_size())) + switch (errno) + { + case EOPNOTSUPP: + case ENOSYS: + break; + + case ENOSPC: + throw FSMergerError("fallocate '" + stringify(dst) + "' returned " + stringify(::strerror(errno))); + + default: + Log::get_instance()->message("merger.file.fallocate_failed", ll_debug, lc_context) << + "fallocate '" + stringify(dst) + "' returned " + stringify(::strerror(errno)); + break; + } +#endif + char buf[4096]; ssize_t count; while ((count = read(input_fd, buf, 4096)) > 0) |