]> git.saurik.com Git - apt.git/blobdiff - apt-private/private-download.cc
Merge remote-tracking branch 'donkult/debian/experimental' into debian/experimental
[apt.git] / apt-private / private-download.cc
index 3ded9e0b9b20e64e6286e00d97071aa00510147d..37fae18e91633c9d22bd3bbff375744b9186566e 100644 (file)
@@ -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>
                                                                        /*}}}*/
@@ -46,16 +49,23 @@ bool CheckDropPrivsMustBeDisabled(pkgAcquire &Fetcher)                      /*{{{*/
    for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin();
        I != Fetcher.ItemsEnd() && res == true; ++I)
    {
-      int fd = open((*I)->DestFile.c_str(), O_CREAT | O_RDWR, 0600);
+      if ((*I)->DestFile.empty())
+        continue;
+      // we assume that an existing (partial) file means that we have sufficient rights
+      if (RealFileExists((*I)->DestFile))
+        continue;
+      int fd = open((*I)->DestFile.c_str(), O_CREAT | O_EXCL | O_RDWR, 0600);
       if (fd < 0)
       {
         res = false;
         std::string msg;
         strprintf(msg, _("Can't drop privileges for downloading as file '%s' couldn't be accessed by user '%s'."),
               (*I)->DestFile.c_str(), SandboxUser.c_str());
-        c0out << msg << std::endl;
+        std::cerr << "W: " << msg << std::endl;
         _config->Set("APT::Sandbox::User", "");
+        break;
       }
+      unlink((*I)->DestFile.c_str());
       close(fd);
    }
 
@@ -146,3 +156,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;
+}
+                                                                       /*}}}*/