diff options
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 5 | ||||
-rw-r--r-- | methods/aptmethod.h | 31 | ||||
-rw-r--r-- | methods/copy.cc | 9 | ||||
-rw-r--r-- | methods/store.cc | 16 | ||||
-rw-r--r-- | test/integration/framework | 9 | ||||
-rwxr-xr-x | test/integration/test-apt-update-file | 6 | ||||
-rwxr-xr-x | test/integration/test-apt-update-ims | 7 |
7 files changed, 60 insertions, 23 deletions
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index c623f1a2a..e410f52d6 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -916,9 +916,12 @@ bool ChangeOwnerAndPermissionOfFile(char const * const requester, char const * c // ensure the file is owned by root and has good permissions struct passwd const * const pw = getpwnam(user); struct group const * const gr = getgrnam(group); - if (pw != NULL && gr != NULL && chown(file, pw->pw_uid, gr->gr_gid) != 0) + if (pw != NULL && gr != NULL && lchown(file, pw->pw_uid, gr->gr_gid) != 0) Res &= _error->WarningE(requester, "chown to %s:%s of file %s failed", user, group, file); } + struct stat Buf; + if (lstat(file, &Buf) != 0 || S_ISLNK(Buf.st_mode)) + return Res; if (chmod(file, mode) != 0) Res &= _error->WarningE(requester, "chmod 0%o of file %s failed", mode, file); return Res; diff --git a/methods/aptmethod.h b/methods/aptmethod.h index bef61a8bc..d3c948636 100644 --- a/methods/aptmethod.h +++ b/methods/aptmethod.h @@ -3,10 +3,18 @@ #include <apt-pkg/acquire-method.h> #include <apt-pkg/configuration.h> +#include <apt-pkg/error.h> #include <locale> #include <string> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <apti18n.h> + class aptMethod : public pkgAcqMethod { char const * const Binary; @@ -43,6 +51,29 @@ public: va_end(args); } + bool TransferModificationTimes(char const * const From, char const * const To, time_t &LastModified) + { + if (strcmp(To, "/dev/null") == 0) + return true; + + struct stat Buf2; + if (lstat(To, &Buf2) != 0 || S_ISLNK(Buf2.st_mode)) + return true; + + struct stat Buf; + if (stat(From, &Buf) != 0) + return _error->Errno("stat",_("Failed to stat")); + + // we don't use utimensat here for compatibility reasons: #738567 + struct timeval times[2]; + times[0].tv_sec = Buf.st_atime; + LastModified = times[1].tv_sec = Buf.st_mtime; + times[0].tv_usec = times[1].tv_usec = 0; + if (utimes(To, times) != 0) + return _error->Errno("utimes",_("Failed to set modification time")); + return true; + } + aptMethod(char const * const Binary, char const * const Ver, unsigned long const Flags) : pkgAcqMethod(Ver, Flags), Binary(Binary) { diff --git a/methods/copy.cc b/methods/copy.cc index 5e3654389..810fc2f38 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -78,13 +78,8 @@ bool CopyMethod::Fetch(FetchItem *Itm) From.Close(); To.Close(); - // Transfer the modification times - struct timeval times[2]; - times[0].tv_sec = Buf.st_atime; - times[1].tv_sec = Buf.st_mtime; - times[0].tv_usec = times[1].tv_usec = 0; - if (utimes(Res.Filename.c_str(), times) != 0) - return _error->Errno("utimes",_("Failed to set modification time")); + if (TransferModificationTimes(File.c_str(), Res.Filename.c_str(), Res.LastModified) == false) + return false; CalculateHashes(Itm, Res); URIDone(Res); diff --git a/methods/store.cc b/methods/store.cc index 934e1a188..fa02d4597 100644 --- a/methods/store.cc +++ b/methods/store.cc @@ -126,20 +126,8 @@ bool StoreMethod::Fetch(FetchItem *Itm) /*{{{*/ if (Failed == true) return false; - // Transfer the modification times - if (Itm->DestFile != "/dev/null") - { - struct stat Buf; - if (stat(Path.c_str(),&Buf) != 0) - return _error->Errno("stat",_("Failed to stat")); - - struct timeval times[2]; - times[0].tv_sec = Buf.st_atime; - Res.LastModified = times[1].tv_sec = Buf.st_mtime; - times[0].tv_usec = times[1].tv_usec = 0; - if (utimes(Itm->DestFile.c_str(), times) != 0) - return _error->Errno("utimes",_("Failed to set modification time")); - } + if (TransferModificationTimes(Path.c_str(), Itm->DestFile.c_str(), Res.LastModified) == false) + return false; // Return a Done response Res.TakeHashes(Hash); diff --git a/test/integration/framework b/test/integration/framework index fe6f82ac9..ea9402d61 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1886,6 +1886,11 @@ pause() { read IGNORE } +logcurrentarchivedirectory() { + find "${TMPWORKINGDIRECTORY}/aptarchive/dists" -type f | while read line; do + stat --format '%U:%G:%a:%n' "$line" + done | sort > "${TMPWORKINGDIRECTORY}/rootdir/var/log/aptgetupdate.before.lst" +} listcurrentlistsdirectory() { { find rootdir/var/lib/apt/lists -maxdepth 1 -type d | while read line; do @@ -1964,6 +1969,10 @@ aptautotest_aptget_update() { # failure cases can retain partial files and such testempty find "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial" -mindepth 1 ! \( -name 'lock' -o -name '*.FAILED' \) fi + if [ -s "${TMPWORKINGDIRECTORY}/rootdir/var/log/aptgetupdate.before.lst" ]; then + testfileequal "${TMPWORKINGDIRECTORY}/rootdir/var/log/aptgetupdate.before.lst" \ + "$(find "${TMPWORKINGDIRECTORY}/aptarchive/dists" -type f | while read line; do stat --format '%U:%G:%a:%n' "$line"; done | sort)" + fi } aptautotest_apt_update() { aptautotest_aptget_update "$@"; } aptautotest_aptcdrom_add() { aptautotest_aptget_update "$@"; } diff --git a/test/integration/test-apt-update-file b/test/integration/test-apt-update-file index 20f604695..8da4ec35b 100755 --- a/test/integration/test-apt-update-file +++ b/test/integration/test-apt-update-file @@ -18,6 +18,7 @@ insertpackage 'unstable' 'bar' 'amd64' '1' insertsource 'unstable' 'foo' 'all' '1' setupaptarchive --no-update +logcurrentarchivedirectory # ensure the archive is not writable addtrap 'prefix' 'chmod 755 aptarchive/dists/unstable/main/binary-all;' @@ -37,8 +38,11 @@ if [ "$(id -u)" = '0' ]; then rm -rf rootdir/var/lib/apt/lists chmod 500 aptarchive/dists/ testsuccesswithnotice aptget update - exit + chmod 755 aptarchive/dists/ +else + testsuccess aptget update fi +mv rootdir/var/lib/apt/lists/_* rootdir/var/lib/apt/lists/partial chmod 555 aptarchive/dists/unstable/main/binary-all testsuccess aptget update -o Debug::pkgAcquire::Worker=1 cp -a rootdir/tmp/testsuccess.output rootdir/tmp/update.output diff --git a/test/integration/test-apt-update-ims b/test/integration/test-apt-update-ims index f118f7c11..1894c3adf 100755 --- a/test/integration/test-apt-update-ims +++ b/test/integration/test-apt-update-ims @@ -12,6 +12,7 @@ insertsource 'unstable' 'unrelated' 'all' '0.5~squeeze1' export APT_DONT_SIGN="" setupaptarchive --no-update +logcurrentarchivedirectory changetowebserver runtest() { @@ -71,6 +72,7 @@ EXPECT="Ign:1 http://localhost:${APTHTTPPORT} unstable InRelease Hit:2 http://localhost:${APTHTTPPORT} unstable Release Reading package lists..." find aptarchive -name 'InRelease' -delete +logcurrentarchivedirectory echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex @@ -87,6 +89,7 @@ W: The repository 'http://localhost:${APTHTTPPORT} unstable Release' is not sign N: Data from such a repository can't be authenticated and is therefore potentially dangerous to use. N: See apt-secure(8) manpage for repository creation and user configuration details." find aptarchive -name 'Release.gpg' -delete +logcurrentarchivedirectory echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest 'warning' echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex @@ -99,6 +102,7 @@ find aptarchive -name '*Release' -exec sed -i \ -e '/^Valid-Until: / d' -e "/^Date: / a\ Valid-Until: $(date -ud '-1 weeks' '+%a, %d %b %Y %H:%M:%S %Z')" '{}' \; signreleasefiles +logcurrentarchivedirectory msgmsg 'expired InRelease' EXPECT="Hit:1 http://localhost:${APTHTTPPORT} unstable InRelease @@ -116,6 +120,7 @@ Hit:2 http://localhost:${APTHTTPPORT} unstable Release Reading package lists... E: Release file for http://localhost:${APTHTTPPORT}/dists/unstable/Release is expired (invalid since). Updates for this repository will not be applied." find aptarchive -name 'InRelease' -delete +logcurrentarchivedirectory echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest 'failure' echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex @@ -133,6 +138,7 @@ N: Data from such a repository can't be authenticated and is therefore potential N: See apt-secure(8) manpage for repository creation and user configuration details. E: Release file for http://localhost:${APTHTTPPORT}/dists/unstable/Release is expired (invalid since). Updates for this repository will not be applied." find aptarchive -name 'Release.gpg' -delete +logcurrentarchivedirectory echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest 'failure' 'warning' echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex @@ -177,6 +183,7 @@ W: The repository 'http://localhost:${APTHTTPPORT} unstable Release' does not ha N: Data from such a repository can't be authenticated and is therefore potentially dangerous to use. N: See apt-secure(8) manpage for repository creation and user configuration details." find aptarchive -name '*Release*' -delete +logcurrentarchivedirectory echo 'Acquire::GzipIndexes "0"; Acquire::PDiffs "0";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest 'warning' |