]> git.saurik.com Git - apt.git/commitdiff
always download changelogs into /tmp first
authorDavid Kalnischkies <david@kalnischkies.de>
Thu, 11 Feb 2016 21:54:49 +0000 (22:54 +0100)
committerDavid Kalnischkies <david@kalnischkies.de>
Thu, 11 Feb 2016 22:13:47 +0000 (23:13 +0100)
pkgAcqChangelog has the default behaviour of downloading a changelog to
a temporary directory (inside /tmp, not /tmp directly), which is cleaned
up on shutdown, but this can be overridden to store the changelog more
permanently – but that caries a permission problem.

For changelog we can 'easily' solve this by always downloading to a
temporary directory and only move it out of there on done.

apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
apt-pkg/acquire.cc
test/integration/test-apt-get-changelog

index 2057b728781213b2e66c227a0694d3e7312d9a4e..03baa97518060d35712a48b0aa3702d01cc0a2aa 100644 (file)
@@ -3076,9 +3076,14 @@ std::string pkgAcqArchive::ShortDesc() const                             /*{{{*/
 pkgAcqArchive::~pkgAcqArchive() {}
 
 // AcqChangelog::pkgAcqChangelog - Constructors                                /*{{{*/
+class pkgAcqChangelog::Private
+{
+   public:
+   std::string FinalFile;
+};
 pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver,
       std::string const &DestDir, std::string const &DestFilename) :
-   pkgAcquire::Item(Owner), d(NULL), SrcName(Ver.SourcePkgName()), SrcVersion(Ver.SourceVerStr())
+   pkgAcquire::Item(Owner), d(new pkgAcqChangelog::Private()), SrcName(Ver.SourcePkgName()), SrcVersion(Ver.SourceVerStr())
 {
    Desc.URI = URI(Ver);
    Init(DestDir, DestFilename);
@@ -3087,7 +3092,7 @@ pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator
 pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIterator const &RlsFile,
       char const * const Component, char const * const SrcName, char const * const SrcVersion,
       const string &DestDir, const string &DestFilename) :
-   pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion)
+   pkgAcquire::Item(Owner), d(new pkgAcqChangelog::Private()), SrcName(SrcName), SrcVersion(SrcVersion)
 {
    Desc.URI = URI(RlsFile, Component, SrcName, SrcVersion);
    Init(DestDir, DestFilename);
@@ -3095,7 +3100,7 @@ pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIter
 pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner,
       std::string const &URI, char const * const SrcName, char const * const SrcVersion,
       const string &DestDir, const string &DestFilename) :
-   pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion)
+   pkgAcquire::Item(Owner), d(new pkgAcqChangelog::Private()), SrcName(SrcName), SrcVersion(SrcVersion)
 {
    Desc.URI = URI;
    Init(DestDir, DestFilename);
@@ -3116,30 +3121,30 @@ void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFi
       return;
    }
 
-   if (DestDir.empty())
-   {
-      std::string const SandboxUser = _config->Find("APT::Sandbox::User");
-      std::string const systemTemp = GetTempDir(SandboxUser);
-      char tmpname[100];
-      snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", systemTemp.c_str());
-      if (NULL == mkdtemp(tmpname))
-      {
-        _error->Errno("mkdtemp", "mkdtemp failed in changelog acquire of %s %s", SrcName.c_str(), SrcVersion.c_str());
-        Status = StatError;
-        return;
-      }
-      DestFile = TemporaryDirectory = tmpname;
+   std::string DestFileName;
+   if (DestFilename.empty())
+      DestFileName = flCombine(DestFile, SrcName + ".changelog");
+   else
+      DestFileName = flCombine(DestFile, DestFilename);
 
-      ChangeOwnerAndPermissionOfFile("Item::QueueURI", DestFile.c_str(),
-                                     SandboxUser.c_str(), "root", 0700);
+   std::string const SandboxUser = _config->Find("APT::Sandbox::User");
+   std::string const systemTemp = GetTempDir(SandboxUser);
+   char tmpname[1000];
+   snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", systemTemp.c_str());
+   if (NULL == mkdtemp(tmpname))
+   {
+      _error->Errno("mkdtemp", "mkdtemp failed in changelog acquire of %s %s", SrcName.c_str(), SrcVersion.c_str());
+      Status = StatError;
+      return;
    }
-   else
-      DestFile = DestDir;
+   TemporaryDirectory = tmpname;
 
-   if (DestFilename.empty())
-      DestFile = flCombine(DestFile, SrcName + ".changelog");
-   else
-      DestFile = flCombine(DestFile, DestFilename);
+   ChangeOwnerAndPermissionOfFile("Item::QueueURI", TemporaryDirectory.c_str(),
+        SandboxUser.c_str(), "root", 0700);
+
+   DestFile = flCombine(TemporaryDirectory, DestFileName);
+   if (DestDir.empty() == false)
+      d->FinalFile = flCombine(DestDir, DestFileName);
 
    Desc.ShortDesc = "Changelog";
    strprintf(Desc.Description, "%s %s %s Changelog", URI::SiteOnly(Desc.URI).c_str(), SrcName.c_str(), SrcVersion.c_str());
@@ -3294,6 +3299,8 @@ void pkgAcqChangelog::Done(string const &Message,HashStringList const &CalcHashe
                      pkgAcquire::MethodConfig const * const Cnf)
 {
    Item::Done(Message,CalcHashes,Cnf);
+   if (d->FinalFile.empty() == false)
+      Rename(DestFile, d->FinalFile);
 
    Complete = true;
 }
@@ -3305,6 +3312,7 @@ pkgAcqChangelog::~pkgAcqChangelog()                                       /*{{{*/
       RemoveFile("~pkgAcqChangelog", DestFile);
       rmdir(TemporaryDirectory.c_str());
    }
+   delete d;
 }
                                                                        /*}}}*/
 
index 306b1772a77be02c52d99bb7e9c3afe7ce595267..61f64c3a94da346af6ffbcfa2c59577fae20735a 100644 (file)
@@ -1055,7 +1055,8 @@ class pkgAcqArchive : public pkgAcquire::Item
  */
 class pkgAcqChangelog : public pkgAcquire::Item
 {
-   void * const d;
+   class Private;
+   Private * const d;
    std::string TemporaryDirectory;
    std::string const SrcName;
    std::string const SrcVersion;
index e515255aee3a73babd4d6036a12018b78bf07e71..17ee691d72715580b3679c33cf1649550fb9c56f 100644 (file)
@@ -559,7 +559,7 @@ static void CheckDropPrivsMustBeDisabled(pkgAcquire const &Fetcher)
        I != Fetcher.ItemsEnd(); ++I)
    {
       // no need to drop privileges for a complete file
-      if ((*I)->Complete == true)
+      if ((*I)->Complete == true || (*I)->Status != pkgAcquire::Item::StatIdle)
         continue;
 
       // if destination file is inaccessible all hope is lost for privilege dropping
index 3de1c5c5c3b5b7c400dd3b52ea597eed19abb040..d65c9530e081750e5c3c20bddac5330898b912f4 100755 (executable)
@@ -48,12 +48,7 @@ testsuccessequal "'http://localhost:${APTHTTPPORT}/main/f/foo/foo_1.0.changelog'
 'http://localhost:${APTHTTPPORT}/main/libb/libbar/libbar_1.0.changelog' libbar.changelog" aptget changelog foo libbar --print-uris -o Acquire::Changelogs::URI::Override::Label::Debian="http://localhost:${APTHTTPPORT}/@CHANGEPATH@.changelog"
 
 releasechanger 'Changelogs' 'no'
-if [ "$(id -u)" = '0' ]; then
-       testfailuremsg "W: Can't drop privileges for downloading as file 'foo.changelog' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)
-E: Failed to fetch changelog:/foo.changelog  Changelog unavailable for foo=1.0" aptget changelog foo -d
-else
-       testfailuremsg 'E: Failed to fetch changelog:/foo.changelog  Changelog unavailable for foo=1.0' aptget changelog foo -d
-fi
+testfailuremsg 'E: Failed to fetch changelog:/foo.changelog  Changelog unavailable for foo=1.0' aptget changelog foo -d
 
 sed -i '/^Changelogs: / d' $(find rootdir/var/lib/apt/lists -name '*Release')
 releasechanger 'Label' 'Testcases'
@@ -73,29 +68,35 @@ testsuccess aptget changelog foo libbar -qq
 testfileequal 'rootdir/tmp/testsuccess.output' "$(cat aptarchive/pool/main/f/foo/foo_1.0/changelog)
 $(cat aptarchive/pool/main/libb/libbar/libbar_1.0/changelog)"
 
-cd downloaded
-
 testsuccess aptget changelog foo -d
 testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
-testfileequal 'foo.changelog' "$(cat  ../aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+testfileequal 'foo.changelog' "$(cat  aptarchive/pool/main/f/foo/foo_1.0/changelog)"
 rm -f foo.changelog
 
 testsuccess aptget changelog libbar foo -d
 testfilestats 'libbar.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
 testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
-testfileequal 'libbar.changelog' "$(cat  ../aptarchive/pool/main/libb/libbar/libbar_1.0/changelog)"
-testfileequal 'foo.changelog' "$(cat  ../aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+testfileequal 'libbar.changelog' "$(cat  aptarchive/pool/main/libb/libbar/libbar_1.0/changelog)"
+testfileequal 'foo.changelog' "$(cat  aptarchive/pool/main/f/foo/foo_1.0/changelog)"
 rm -f libbar.changelog foo.changelog
 
 # as such bogus, but can happen with multiple binaries from the same source
 testsuccessequal "'http://localhost:${APTHTTPPORT}/pool/main/f/foo/foo_1.0/changelog' foo.changelog
 'http://localhost:${APTHTTPPORT}/pool/main/f/foo/foo_1.0/changelog' foo.changelog" aptget changelog foo foo --print-uris
 testsuccess aptget changelog foo foo -qq
-testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)
-$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+testfileequal 'rootdir/tmp/testsuccess.output' "$(cat aptarchive/pool/main/f/foo/foo_1.0/changelog)
+$(cat aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+testsuccess aptget changelog foo foo -d
+testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
+testfileequal 'foo.changelog' "$(cat  aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+# we have the file already, confused?
+testsuccess aptget changelog foo foo -d
+testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
+testfileequal 'foo.changelog' "$(cat  aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+echo 'bogus' > foo.changelog
 testsuccess aptget changelog foo foo -d
 testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
-testfileequal 'foo.changelog' "$(cat  ../aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+testfileequal 'foo.changelog' "$(cat  aptarchive/pool/main/f/foo/foo_1.0/changelog)"
 rm -f foo.changelog
 
 # no @CHANGEPATH@ in the URI
@@ -106,7 +107,6 @@ testfailure test -e foo.changelog
 testequal "E: Failed to fetch http://localhost:${APTHTTPPORT}/does/not/exist/main/f/foo/foo_1.0/change.txt  Changelog unavailable for foo=1.0 (404  Not Found)
 " aptget changelog foo -qq -d -o Acquire::Changelogs::URI::Label::Testcases="http://localhost:${APTHTTPPORT}/does/not/exist/@CHANGEPATH@/change.txt"
 testfailure test -e foo.changelog
-cd ..
 
 testdpkgnotinstalled 'foo'
 testsuccessequal "'http://localhost:${APTHTTPPORT}/pool/main/f/foo/foo_1.0/changelog' foo.changelog" apt changelog foo --print-uris -o Acquire::Changelogs::AlwaysOnline=false
@@ -121,10 +121,8 @@ testsuccessequal "'http://localhost:${APTHTTPPORT}/pool/main/d/dpkg/dpkg_42/chan
 testsuccessequal "'http://localhost:${APTHTTPPORT}/pool/main/d/dpkg/dpkg_42/changelog' dpkg.changelog" apt changelog dpkg --print-uris -o Acquire::Changelogs::AlwaysOnline=false -o Acquire::Changelogs::AlwaysOnline::Origin::Ubuntu=true
 testsuccessequal "'gzip:///usr/share/doc/dpkg/changelog.Debian.gz' dpkg.changelog" apt changelog dpkg --print-uris -o Acquire::Changelogs::AlwaysOnline=false -o Acquire::Changelogs::AlwaysOnline::Origin::Debian=true
 
-cd downloaded
 testsuccess apt changelog dpkg -d
 testfilestats 'dpkg.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
 head -n 3 dpkg.changelog > dpkg.change
 testfileequal 'dpkg.change' "$(apthelper cat-file '/usr/share/doc/dpkg/changelog.Debian.gz' | head -n 3)"
 rm -f dpkg.change dpkg.changelog
-cd ..