X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/f43dd43912990f736b7fe7cad941f3deb3429af5..9fa247dc9ba2aa28ae564e96cba5b2b23bcac91b:/apt-pkg/contrib/fileutl.cc?ds=sidebyside diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 9990b753a..dd36ffa79 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -694,6 +694,25 @@ string flAbsPath(string File) return AbsPath; } /*}}}*/ +std::string flNormalize(std::string file) /*{{{*/ +{ + if (file.empty()) + return file; + // do some normalisation by removing // and /./ from the path + size_t found = string::npos; + while ((found = file.find("/./")) != string::npos) + file.replace(found, 3, "/"); + while ((found = file.find("//")) != string::npos) + file.replace(found, 2, "/"); + + if (APT::String::Startswith(file, "/dev/null")) + { + file.erase(strlen("/dev/null")); + return file; + } + return file; +} + /*}}}*/ // SetCloseExec - Set the close on exec flag /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -916,9 +935,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; @@ -1255,9 +1277,8 @@ public: writebuffer.bufferstart += written; } - writebuffer.reset(); - return true; + return wrapped->InternalFlush(); } virtual ssize_t InternalWrite(void const * const From, unsigned long long const Size) APT_OVERRIDE { @@ -1535,7 +1556,7 @@ public: return false; unsigned int flags = (Mode & (FileFd::WriteOnly|FileFd::ReadOnly)); - if (backend.OpenDescriptor(iFd, flags) == false) + if (backend.OpenDescriptor(iFd, flags, FileFd::None, true) == false) return false; // Write the file header @@ -1646,6 +1667,11 @@ public: res = LZ4F_freeDecompressionContext(dctx); dctx = nullptr; } + if (backend.IsOpen()) + { + backend.Close(); + filefd->iFd = -1; + } return LZ4F_isError(res) == false; } @@ -1877,13 +1903,17 @@ public: if ((Mode & FileFd::ReadWrite) == FileFd::ReadWrite) return filefd->FileFdError("ReadWrite mode is not supported for file %s", filefd->FileName.c_str()); + if (compressor.Binary == "false") + return filefd->FileFdError("libapt has inbuilt support for the %s compression," + " but was forced to ignore it in favor of an external binary – which isn't installed.", compressor.Name.c_str()); bool const Comp = (Mode & FileFd::WriteOnly) == FileFd::WriteOnly; - if (Comp == false) + if (Comp == false && filefd->iFd != -1) { // Handle 'decompression' of empty files struct stat Buf; - fstat(filefd->iFd, &Buf); + if (fstat(filefd->iFd, &Buf) != 0) + return filefd->FileFdErrno("fstat", "Could not stat fd %d for file %s", filefd->iFd, filefd->FileName.c_str()); if (Buf.st_size == 0 && S_ISFIFO(Buf.st_mode) == false) return true; @@ -1926,12 +1956,6 @@ public: dup2(compressed_fd,STDIN_FILENO); dup2(Pipe[1],STDOUT_FILENO); } - int const nullfd = open("/dev/null", O_WRONLY); - if (nullfd != -1) - { - dup2(nullfd,STDERR_FILENO); - close(nullfd); - } SetCloseExec(STDOUT_FILENO,false); SetCloseExec(STDIN_FILENO,false); @@ -1978,6 +2002,11 @@ public: virtual bool InternalClose(std::string const &) APT_OVERRIDE { bool Ret = true; + if (filefd->iFd != -1) + { + close(filefd->iFd); + filefd->iFd = -1; + } if (compressor_pid > 0) Ret &= ExecWait(compressor_pid, "FileFdCompressor", true); compressor_pid = -1; @@ -2367,7 +2396,7 @@ FileFd::~FileFd() gracefully. */ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) { - if (d == nullptr) + if (d == nullptr || Failed()) return false; ssize_t Res = 1; errno = 0; @@ -2409,6 +2438,37 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) } return FileFdError(_("read, still have %llu to read but none left"), Size); +} +bool FileFd::Read(int const Fd, void *To, unsigned long long Size, unsigned long long * const Actual) +{ + ssize_t Res = 1; + errno = 0; + if (Actual != nullptr) + *Actual = 0; + *static_cast(To) = '\0'; + while (Res > 0 && Size > 0) + { + Res = read(Fd, To, Size); + if (Res < 0) + { + if (errno == EINTR) + { + Res = 1; + errno = 0; + continue; + } + return _error->Errno("read", _("Read error")); + } + To = static_cast(To) + Res; + Size -= Res; + if (Actual != 0) + *Actual += Res; + } + if (Size == 0) + return true; + if (Actual != nullptr) + return true; + return _error->Error(_("read, still have %llu to read but none left"), Size); } /*}}}*/ // FileFd::ReadLine - Read a complete line from the file /*{{{*/ @@ -2418,7 +2478,7 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) char* FileFd::ReadLine(char *To, unsigned long long const Size) { *To = '\0'; - if (d == nullptr) + if (d == nullptr || Failed()) return nullptr; return d->InternalReadLine(To, Size); } @@ -2426,6 +2486,8 @@ char* FileFd::ReadLine(char *To, unsigned long long const Size) // FileFd::Flush - Flush the file /*{{{*/ bool FileFd::Flush() { + if (Failed()) + return false; if (d == nullptr) return true; @@ -2435,7 +2497,7 @@ bool FileFd::Flush() // FileFd::Write - Write to the file /*{{{*/ bool FileFd::Write(const void *From,unsigned long long Size) { - if (d == nullptr) + if (d == nullptr || Failed()) return false; ssize_t Res = 1; errno = 0; @@ -2491,7 +2553,7 @@ bool FileFd::Write(int Fd, const void *From, unsigned long long Size) // FileFd::Seek - Seek in the file /*{{{*/ bool FileFd::Seek(unsigned long long To) { - if (d == nullptr) + if (d == nullptr || Failed()) return false; Flags &= ~HitEof; return d->InternalSeek(To); @@ -2500,7 +2562,7 @@ bool FileFd::Seek(unsigned long long To) // FileFd::Skip - Skip over data in the file /*{{{*/ bool FileFd::Skip(unsigned long long Over) { - if (d == nullptr) + if (d == nullptr || Failed()) return false; return d->InternalSkip(Over); } @@ -2508,7 +2570,7 @@ bool FileFd::Skip(unsigned long long Over) // FileFd::Truncate - Truncate the file /*{{{*/ bool FileFd::Truncate(unsigned long long To) { - if (d == nullptr) + if (d == nullptr || Failed()) return false; // truncating /dev/null is always successful - as we get an error otherwise if (To == 0 && FileName == "/dev/null") @@ -2521,7 +2583,7 @@ bool FileFd::Truncate(unsigned long long To) /* */ unsigned long long FileFd::Tell() { - if (d == nullptr) + if (d == nullptr || Failed()) return false; off_t const Res = d->InternalTell(); if (Res == (off_t)-1) @@ -2584,7 +2646,7 @@ time_t FileFd::ModificationTime() unsigned long long FileFd::Size() { if (d == nullptr) - return false; + return 0; return d->InternalSize(); } /*}}}*/ @@ -2613,7 +2675,7 @@ bool FileFd::Close() } if ((Flags & Replace) == Replace) { - if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0) + if (Failed() == false && rename(TemporaryFileName.c_str(), FileName.c_str()) != 0) Res &= _error->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName.c_str(), FileName.c_str()); FileName = TemporaryFileName; // for the unlink() below. @@ -2648,13 +2710,12 @@ bool FileFd::FileFdErrno(const char *Function, const char *Description,...) va_list args; size_t msgSize = 400; int const errsv = errno; - while (true) - { + bool retry; + do { va_start(args,Description); - if (_error->InsertErrno(GlobalError::ERROR, Function, Description, args, errsv, msgSize) == false) - break; + retry = _error->InsertErrno(GlobalError::ERROR, Function, Description, args, errsv, msgSize); va_end(args); - } + } while (retry); return false; } /*}}}*/ @@ -2663,13 +2724,12 @@ bool FileFd::FileFdError(const char *Description,...) { Flags |= Fail; va_list args; size_t msgSize = 400; - while (true) - { + bool retry; + do { va_start(args,Description); - if (_error->Insert(GlobalError::ERROR, Description, args, msgSize) == false) - break; + retry = _error->Insert(GlobalError::ERROR, Description, args, msgSize); va_end(args); - } + } while (retry); return false; } /*}}}*/ @@ -2712,9 +2772,9 @@ std::vector Glob(std::string const &pattern, int flags) return result; } /*}}}*/ -std::string GetTempDir() /*{{{*/ +static std::string APT_NONNULL(1) GetTempDirEnv(char const * const env) /*{{{*/ { - const char *tmpdir = getenv("TMPDIR"); + const char *tmpdir = getenv(env); #ifdef P_tmpdir if (!tmpdir) @@ -2730,6 +2790,11 @@ std::string GetTempDir() /*{{{*/ tmpdir = "/tmp"; return string(tmpdir); +} + /*}}}*/ +std::string GetTempDir() /*{{{*/ +{ + return GetTempDirEnv("TMPDIR"); } std::string GetTempDir(std::string const &User) { @@ -2794,6 +2859,11 @@ bool Rename(std::string From, std::string To) /*{{{*/ } /*}}}*/ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)/*{{{*/ +{ + return Popen(Args, Fd, Child, Mode, true); +} + /*}}}*/ +bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode, bool CaptureStderr)/*{{{*/ { int fd; if (Mode != FileFd::ReadOnly && Mode != FileFd::WriteOnly) @@ -2825,7 +2895,8 @@ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)/ if(Mode == FileFd::ReadOnly) { dup2(fd, 1); - dup2(fd, 2); + if (CaptureStderr == true) + dup2(fd, 2); } else if(Mode == FileFd::WriteOnly) dup2(fd, 0); @@ -2979,6 +3050,32 @@ bool DropPrivileges() /*{{{*/ return _error->Error("Could restore a uid to root, privilege dropping did not work"); } + if (_config->FindB("APT::Sandbox::ResetEnvironment", true)) + { + setenv("HOME", pw->pw_dir, 1); + setenv("USER", pw->pw_name, 1); + setenv("USERNAME", pw->pw_name, 1); + setenv("LOGNAME", pw->pw_name, 1); + auto const shell = flNotDir(pw->pw_shell); + if (shell == "false" || shell == "nologin") + setenv("SHELL", "/bin/sh", 1); + else + setenv("SHELL", pw->pw_shell, 1); + auto const apt_setenv_tmp = [](char const * const env) { + auto const tmpdir = getenv(env); + if (tmpdir != nullptr) + { + auto const ourtmpdir = GetTempDirEnv(env); + if (ourtmpdir != tmpdir) + setenv(env, ourtmpdir.c_str(), 1); + } + }; + apt_setenv_tmp("TMPDIR"); + apt_setenv_tmp("TEMPDIR"); + apt_setenv_tmp("TMP"); + apt_setenv_tmp("TEMP"); + } + return true; } /*}}}*/