Browse Source

check for available space, excluding root reserved blocks

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.
debian/1.8.y
David Kalnischkies 7 years ago
parent
commit
9c81f8de38
  1. 39
      apt-private/private-download.cc
  2. 2
      apt-private/private-download.h
  3. 33
      apt-private/private-install.cc
  4. 2
      apt-private/private-install.h
  5. 28
      cmdline/apt-get.cc

39
apt-private/private-download.cc

@ -19,6 +19,9 @@
#include <sys/types.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/vfs.h>
#include <sys/statvfs.h>
#include <errno.h>
#include <apti18n.h>
/*}}}*/
@ -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;
}
/*}}}*/

2
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

33
apt-private/private-install.cc

@ -22,11 +22,8 @@
#include <apt-pkg/upgrade.h>
#include <apt-pkg/install-progress.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
#include <algorithm>
#include <iostream>
#include <set>
@ -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)

2
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,

28
cmdline/apt-get.cc

@ -78,8 +78,6 @@
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
#include <sys/wait.h>
#include <unistd.h>
#include <algorithm>
@ -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

Loading…
Cancel
Save