From 9c81f8de38df940559d13a3ea9591d63cbe970bb Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 15 Oct 2014 04:18:07 +0200 Subject: check for available space, excluding root reserved blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are checking the space requirements for ages, but the check uses the free blocks count, which includes the blocks reserved for usage by root. Now that we use an unprivileged user it has no access to these blocks anymore – and more importantly these blocks are a reserve, they shouldn't be used by apt without special encouragement by the user as it would be bad to have dpkg run out of diskspace and maintainerscripts like man-db skip certain actions if not enough space is available freely. --- apt-private/private-download.cc | 39 +++++++++++++++++++++++++++++++++++++++ apt-private/private-download.h | 2 ++ apt-private/private-install.cc | 33 +++------------------------------ apt-private/private-install.h | 2 -- cmdline/apt-get.cc | 28 +++------------------------- 5 files changed, 47 insertions(+), 57 deletions(-) diff --git a/apt-private/private-download.cc b/apt-private/private-download.cc index 3ded9e0b9..8cabf14b5 100644 --- a/apt-private/private-download.cc +++ b/apt-private/private-download.cc @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include /*}}}*/ @@ -146,3 +149,39 @@ bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failu return true; } /*}}}*/ +bool CheckFreeSpaceBeforeDownload(std::string const &Dir, unsigned long long FetchBytes)/*{{{*/ +{ + uint32_t const RAMFS_MAGIC = 0x858458f6; + /* Check for enough free space, but only if we are actually going to + download */ + if (_config->FindB("APT::Get::Print-URIs", false) == true || + _config->FindB("APT::Get::Download", true) == false) + return true; + + struct statvfs Buf; + if (statvfs(Dir.c_str(),&Buf) != 0) { + if (errno == EOVERFLOW) + return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), + Dir.c_str()); + else + return _error->Errno("statvfs",_("Couldn't determine free space in %s"), + Dir.c_str()); + } + else + { + unsigned long long const FreeBlocks = _config->Find("APT::Sandbox::User").empty() ? Buf.f_bfree : Buf.f_bavail; + if (FreeBlocks < (FetchBytes / Buf.f_bsize)) + { + struct statfs Stat; + if (statfs(Dir.c_str(),&Stat) != 0 +#if HAVE_STRUCT_STATFS_F_TYPE + || Stat.f_type != RAMFS_MAGIC +#endif + ) + return _error->Error(_("You don't have enough free space in %s."), + Dir.c_str()); + } + } + return true; +} + /*}}}*/ diff --git a/apt-private/private-download.h b/apt-private/private-download.h index 809650a97..0a0ac6b95 100644 --- a/apt-private/private-download.h +++ b/apt-private/private-download.h @@ -18,4 +18,6 @@ APT_PUBLIC bool AuthPrompt(std::string const &UntrustedList, bool const PromptUs APT_PUBLIC bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure); +APT_PUBLIC bool CheckFreeSpaceBeforeDownload(std::string const &Dir, unsigned long long FetchBytes); + #endif diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index c06caeedd..2a4c3eea5 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -22,11 +22,8 @@ #include #include -#include #include #include -#include -#include #include #include #include @@ -177,33 +174,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) if (_error->PendingError() == true) return false; - /* Check for enough free space, but only if we are actually going to - download */ - if (_config->FindB("APT::Get::Print-URIs") == false && - _config->FindB("APT::Get::Download",true) == true) - { - struct statvfs Buf; - std::string OutputDir = _config->FindDir("Dir::Cache::Archives"); - if (statvfs(OutputDir.c_str(),&Buf) != 0) { - if (errno == EOVERFLOW) - return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - else - return _error->Errno("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize) - { - struct statfs Stat; - if (statfs(OutputDir.c_str(),&Stat) != 0 -#if HAVE_STRUCT_STATFS_F_TYPE - || unsigned(Stat.f_type) != RAMFS_MAGIC -#endif - ) - return _error->Error(_("You don't have enough free space in %s."), - OutputDir.c_str()); - } - } - + if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false) + return false; + // Fail safe check if (_config->FindI("quiet",0) >= 2 || _config->FindB("APT::Get::Assume-Yes",false) == true) diff --git a/apt-private/private-install.h b/apt-private/private-install.h index 8daa4a776..62276fbff 100644 --- a/apt-private/private-install.h +++ b/apt-private/private-install.h @@ -16,8 +16,6 @@ class CacheFile; class CommandLine; class pkgProblemResolver; -#define RAMFS_MAGIC 0x858458f6 - APT_PUBLIC bool DoInstall(CommandLine &Cmd); bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 8c0c50f83..e176a3350 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -78,8 +78,6 @@ #include #include #include -#include -#include #include #include #include @@ -866,29 +864,9 @@ static bool DoSource(CommandLine &CmdL) unsigned long long FetchPBytes = Fetcher.PartialPresent(); unsigned long long DebBytes = Fetcher.TotalNeeded(); - // Check for enough free space - struct statvfs Buf; - string OutputDir = "."; - if (statvfs(OutputDir.c_str(),&Buf) != 0) { - if (errno == EOVERFLOW) - return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - else - return _error->Errno("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize) - { - struct statfs Stat; - if (statfs(OutputDir.c_str(),&Stat) != 0 -#if HAVE_STRUCT_STATFS_F_TYPE - || unsigned(Stat.f_type) != RAMFS_MAGIC -#endif - ) { - return _error->Error(_("You don't have enough free space in %s"), - OutputDir.c_str()); - } - } - + if (CheckFreeSpaceBeforeDownload(".", (FetchBytes - FetchPBytes)) == false) + return false; + // Number of bytes if (DebBytes != FetchBytes) //TRANSLATOR: The required space between number and unit is already included -- cgit v1.2.3