summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2016-07-05 20:04:27 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2016-07-06 02:25:51 +0200
commit3465138575e1fd0d5892d9b6be1ae232eb873460 (patch)
tree07f541a2c958f8b67b392da360bb38aa9fd9c59d /methods
parent68151307d42ed64cd6258f94a0d748abe9efb8e0 (diff)
don't change owner/perms/times through file:// symlinks
If we have files in partial/ from a previous invocation or similar such those could be symlinks created by file:// sources. The code is expecting only real files through and happily changes owner, modification times and permission on the file the symlink points to which tend to be files we have no business in touching in this way. Permissions of symlinks shouldn't be changed, changing owner is usually pointless to, but just to be sure we pick the easy way out and use lchown, check for symlinks before chmod/utimes. Reported-By: Mattia Rizzolo on IRC
Diffstat (limited to 'methods')
-rw-r--r--methods/aptmethod.h31
-rw-r--r--methods/copy.cc9
-rw-r--r--methods/store.cc16
3 files changed, 35 insertions, 21 deletions
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);