]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/fileutl.cc
implement socks5h proxy support for http method
[apt.git] / apt-pkg / contrib / fileutl.cc
index cde005eb52bc674bfdeff6efaa6c883e52ca9bcb..a9d51a6bfdfb1625826d5f23e2ec4d886251350e 100644 (file)
@@ -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
@@ -1626,11 +1647,14 @@ public:
 
       if (cctx != nullptr)
       {
-        res = LZ4F_compressEnd(cctx, lz4_buffer.buffer, lz4_buffer.buffersize_max, nullptr);
-        if (LZ4F_isError(res) || backend.Write(lz4_buffer.buffer, res) == false)
-           return false;
-        if (!backend.Flush())
-           return false;
+        if (filefd->Failed() == false)
+        {
+           res = LZ4F_compressEnd(cctx, lz4_buffer.buffer, lz4_buffer.buffersize_max, nullptr);
+           if (LZ4F_isError(res) || backend.Write(lz4_buffer.buffer, res) == false)
+              return false;
+           if (!backend.Flush())
+              return false;
+        }
         if (!backend.Close())
            return false;
 
@@ -1643,6 +1667,11 @@ public:
         res = LZ4F_freeDecompressionContext(dctx);
         dctx = nullptr;
       }
+      if (backend.IsOpen())
+      {
+        backend.Close();
+        filefd->iFd = -1;
+      }
 
       return LZ4F_isError(res) == false;
    }
@@ -1658,16 +1687,17 @@ class APT_HIDDEN LzmaFileFdPrivate: public FileFdPrivate {                              /*{{{*/
 #ifdef HAVE_LZMA
    struct LZMAFILE {
       FILE* file;
+      FileFd * const filefd;
       uint8_t buffer[4096];
       lzma_stream stream;
       lzma_ret err;
       bool eof;
       bool compressing;
 
-      LZMAFILE() : file(nullptr), eof(false), compressing(false) { buffer[0] = '\0'; }
+      LZMAFILE(FileFd * const fd) : file(nullptr), filefd(fd), eof(false), compressing(false) { buffer[0] = '\0'; }
       ~LZMAFILE()
       {
-        if (compressing == true)
+        if (compressing == true && filefd->Failed() == false)
         {
            size_t constexpr buffersize = sizeof(buffer)/sizeof(buffer[0]);
            while(true)
@@ -1728,7 +1758,7 @@ public:
         return filefd->FileFdError("ReadWrite mode is not supported for lzma/xz files %s", filefd->FileName.c_str());
 
       if (lzma == nullptr)
-        lzma = new LzmaFileFdPrivate::LZMAFILE;
+        lzma = new LzmaFileFdPrivate::LZMAFILE(filefd);
       if ((Mode & FileFd::WriteOnly) == FileFd::WriteOnly)
         lzma->file = fdopen(iFd, "w");
       else
@@ -1873,6 +1903,9 @@ 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)
@@ -1974,6 +2007,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;
@@ -2363,7 +2401,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;
@@ -2405,6 +2443,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<char *>(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<char *>(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               /*{{{*/
@@ -2414,7 +2483,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);
 }
@@ -2422,6 +2491,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;
 
@@ -2431,7 +2502,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;
@@ -2487,7 +2558,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);
@@ -2496,7 +2567,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);
 }
@@ -2504,7 +2575,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")
@@ -2517,7 +2588,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)
@@ -2580,7 +2651,7 @@ time_t FileFd::ModificationTime()
 unsigned long long FileFd::Size()
 {
    if (d == nullptr)
-      return false;
+      return 0;
    return d->InternalSize();
 }
                                                                        /*}}}*/
@@ -2589,7 +2660,7 @@ unsigned long long FileFd::Size()
 /* */
 bool FileFd::Close()
 {
-   if (Flush() == false)
+   if (Failed() == false && Flush() == false)
       return false;
    if (iFd == -1)
       return true;
@@ -2609,7 +2680,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.
@@ -2644,13 +2715,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;
 }
                                                                        /*}}}*/
@@ -2659,13 +2729,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;
 }
                                                                        /*}}}*/