X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/152ab79e05f077440d76c1c423b013eaeb3fe2ff..93c6ec104dcd445e39e6bda177b5734198fb3b78:/apt-pkg/contrib/fileutl.cc

diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 5d294c36a..a5976cf3a 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -8,15 +8,15 @@
    CopyFile - Buffered copy of a single file
    GetLock - dpkg compatible lock file manipulation (fcntl)
    
-   This source is placed in the Public Domain, do with it what you will
+   Most of this source is placed in the Public Domain, do with it what 
+   you will
    It was originally written by Jason Gunthorpe <jgg@debian.org>.
    
+   The exception is RunScripts() it is under the GPLv2
+
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/fileutl.h"
-#endif 
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sptr.h>
@@ -25,6 +25,8 @@
 #include <apti18n.h>
 
 #include <cstdlib>
+#include <cstring>
+
 #include <iostream>
 #include <unistd.h>
 #include <fcntl.h>
@@ -39,6 +41,68 @@
 
 using namespace std;
 
+// RunScripts - Run a set of scripts from a configuration subtree	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool RunScripts(const char *Cnf)
+{
+   Configuration::Item const *Opts = _config->Tree(Cnf);
+   if (Opts == 0 || Opts->Child == 0)
+      return true;
+   Opts = Opts->Child;
+
+   // Fork for running the system calls
+   pid_t Child = ExecFork();
+   
+   // This is the child
+   if (Child == 0)
+   {
+      if (chdir("/tmp/") != 0)
+	 _exit(100);
+	 
+      unsigned int Count = 1;
+      for (; Opts != 0; Opts = Opts->Next, Count++)
+      {
+	 if (Opts->Value.empty() == true)
+	    continue;
+	 
+	 if (system(Opts->Value.c_str()) != 0)
+	    _exit(100+Count);
+      }
+      _exit(0);
+   }      
+
+   // Wait for the child
+   int Status = 0;
+   while (waitpid(Child,&Status,0) != Child)
+   {
+      if (errno == EINTR)
+	 continue;
+      return _error->Errno("waitpid","Couldn't wait for subprocess");
+   }
+
+   // Restore sig int/quit
+   signal(SIGQUIT,SIG_DFL);
+   signal(SIGINT,SIG_DFL);   
+
+   // Check for an error code.
+   if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
+   {
+      unsigned int Count = WEXITSTATUS(Status);
+      if (Count > 100)
+      {
+	 Count -= 100;
+	 for (; Opts != 0 && Count != 1; Opts = Opts->Next, Count--);
+	 _error->Error("Problem executing scripts %s '%s'",Cnf,Opts->Value.c_str());
+      }
+      
+      return _error->Error("Sub-process returned an error code");
+   }
+   
+   return true;
+}
+									/*}}}*/
+
 // CopyFile - Buffered copy of a file					/*{{{*/
 // ---------------------------------------------------------------------
 /* The caller is expected to set things so that failure causes erasure */
@@ -74,7 +138,9 @@ bool CopyFile(FileFd &From,FileFd &To)
    close at some time. */
 int GetLock(string File,bool Errors)
 {
-   int FD = open(File.c_str(),O_RDWR | O_CREAT | O_TRUNC,0640);
+   // GetLock() is used in aptitude on directories with public-write access
+   // Use O_NOFOLLOW here to prevent symlink traversal attacks
+   int FD = open(File.c_str(),O_RDWR | O_CREAT | O_NOFOLLOW,0640);
    if (FD < 0)
    {
       // Read only .. cant have locking problems there.