X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/b84fa7158d04f8b2136f01dda106ba0272027887..76fcbe5c97849dcbbe67434d08e0a22c02fedd51:/apt-pkg/contrib/fileutl.cc diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index d19a92e62..a7de09c44 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -8,9 +8,12 @@ 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 . + The exception is RunScripts() it is under the GPLv2 + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -22,6 +25,8 @@ #include #include +#include + #include #include #include @@ -36,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 */ @@ -71,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. @@ -381,8 +450,11 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap) { if (Reap == true) return false; - if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV) - return _error->Error(_("Sub-process %s received a segmentation fault."),Name); + if (WIFSIGNALED(Status) != 0) + if( WTERMSIG(Status) == SIGSEGV) + return _error->Error(_("Sub-process %s received a segmentation fault."),Name); + else + return _error->Error(_("Sub-process %s received signal %u."),Name, WTERMSIG(Status)); if (WIFEXITED(Status) != 0) return _error->Error(_("Sub-process %s returned an error code (%u)"),Name,WEXITSTATUS(Status));