]> git.saurik.com Git - apt.git/blobdiff - apt-inst/contrib/extracttar.cc
Move sysconf(_SC_OPEN_MAX); out of the for() loop to avoid unneeded syscalls
[apt.git] / apt-inst / contrib / extracttar.cc
index 1a358d57e6fb34280edef6136d74d1738a088ccd..0ba3f05215d0190ebced2195a15269ced5939f26 100644 (file)
@@ -6,7 +6,7 @@
    Extract a Tar - Tar Extractor
 
    Some performance measurements showed that zlib performed quite poorly
    Extract a Tar - Tar Extractor
 
    Some performance measurements showed that zlib performed quite poorly
-   in comparision to a forked gzip process. This tar extractor makes use
+   in comparison to a forked gzip process. This tar extractor makes use
    of the fact that dup'd file descriptors have the same seek pointer
    and that gzip will not read past the end of a compressed stream, 
    even if there is more data. We use the dup property to track extraction
    of the fact that dup'd file descriptors have the same seek pointer
    and that gzip will not read past the end of a compressed stream, 
    even if there is more data. We use the dup property to track extraction
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
-#include <apt-pkg/extracttar.h>
+#include<config.h>
 
 
+#include <apt-pkg/dirstream.h>
+#include <apt-pkg/extracttar.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
-#include <apt-pkg/macros.h>
+#include <apt-pkg/fileutl.h>
 
 
-#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <string>
 #include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <iostream>
 #include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <iostream>
+
 #include <apti18n.h>
                                                                        /*}}}*/
 
 #include <apti18n.h>
                                                                        /*}}}*/
 
@@ -60,7 +65,6 @@ ExtractTar::ExtractTar(FileFd &Fd,unsigned long Max,string DecompressionProgram)
 
 {
    GZPid = -1;
 
 {
    GZPid = -1;
-   InFd = -1;
    Eof = false;
 }
                                                                        /*}}}*/
    Eof = false;
 }
                                                                        /*}}}*/
@@ -109,10 +113,16 @@ bool ExtractTar::Done(bool Force)
    gzip will efficiently ignore the extra bits. */
 bool ExtractTar::StartGzip()
 {
    gzip will efficiently ignore the extra bits. */
 bool ExtractTar::StartGzip()
 {
+   if (DecompressProg.empty())
+   {
+      InFd.OpenDescriptor(File.Fd(), FileFd::ReadOnly, FileFd::None, false);
+      return true;
+   }
+
    int Pipes[2];
    if (pipe(Pipes) != 0)
       return _error->Errno("pipe",_("Failed to create pipes"));
    int Pipes[2];
    if (pipe(Pipes) != 0)
       return _error->Errno("pipe",_("Failed to create pipes"));
-   
+
    // Fork off the process
    GZPid = ExecFork();
 
    // Fork off the process
    GZPid = ExecFork();
 
@@ -128,9 +138,9 @@ bool ExtractTar::StartGzip()
       dup2(Fd,STDERR_FILENO);
       close(Fd);
       SetCloseExec(STDOUT_FILENO,false);
       dup2(Fd,STDERR_FILENO);
       close(Fd);
       SetCloseExec(STDOUT_FILENO,false);
-      SetCloseExec(STDIN_FILENO,false);      
+      SetCloseExec(STDIN_FILENO,false);
       SetCloseExec(STDERR_FILENO,false);
       SetCloseExec(STDERR_FILENO,false);
-      
+
       const char *Args[3];
       string confvar = string("dir::bin::") + DecompressProg;
       string argv0 = _config->Find(confvar.c_str(),DecompressProg.c_str());
       const char *Args[3];
       string confvar = string("dir::bin::") + DecompressProg;
       string argv0 = _config->Find(confvar.c_str(),DecompressProg.c_str());
@@ -143,7 +153,7 @@ bool ExtractTar::StartGzip()
    }
 
    // Fix up our FDs
    }
 
    // Fix up our FDs
-   InFd.Fd(Pipes[0]);
+   InFd.OpenDescriptor(Pipes[0], FileFd::ReadOnly, FileFd::None, true);
    close(Pipes[1]);
    return true;
 }
    close(Pipes[1]);
    return true;
 }
@@ -159,8 +169,8 @@ bool ExtractTar::Go(pkgDirStream &Stream)
       return false;
    
    // Loop over all blocks
       return false;
    
    // Loop over all blocks
-   string LastLongLink;
-   string LastLongName;
+   string LastLongLink, ItemLink;
+   string LastLongName, ItemName;
    while (1)
    {
       bool BadRecord = false;      
    while (1)
    {
       bool BadRecord = false;      
@@ -206,25 +216,23 @@ bool ExtractTar::Go(pkgDirStream &Stream)
          StrToNum(Tar->Major,Itm.Major,sizeof(Tar->Major),8) == false ||
          StrToNum(Tar->Minor,Itm.Minor,sizeof(Tar->Minor),8) == false)
         return _error->Error(_("Corrupted archive"));
          StrToNum(Tar->Major,Itm.Major,sizeof(Tar->Major),8) == false ||
          StrToNum(Tar->Minor,Itm.Minor,sizeof(Tar->Minor),8) == false)
         return _error->Error(_("Corrupted archive"));
-      
-      // Grab the filename
+
+      // Grab the filename and link target: use last long name if one was
+      // set, otherwise use the header value as-is, but remember that it may
+      // fill the entire 100-byte block and needs to be zero-terminated.
+      // See Debian Bug #689582.
       if (LastLongName.empty() == false)
         Itm.Name = (char *)LastLongName.c_str();
       else
       if (LastLongName.empty() == false)
         Itm.Name = (char *)LastLongName.c_str();
       else
-      {
-        Tar->Name[sizeof(Tar->Name)-1] = 0;
-        Itm.Name = Tar->Name;
-      }      
+        Itm.Name = (char *)ItemName.assign(Tar->Name, sizeof(Tar->Name)).c_str();
       if (Itm.Name[0] == '.' && Itm.Name[1] == '/' && Itm.Name[2] != 0)
         Itm.Name += 2;
       if (Itm.Name[0] == '.' && Itm.Name[1] == '/' && Itm.Name[2] != 0)
         Itm.Name += 2;
-      
-      // Grab the link target
-      Tar->Name[sizeof(Tar->LinkName)-1] = 0;
-      Itm.LinkTarget = Tar->LinkName;
 
       if (LastLongLink.empty() == false)
         Itm.LinkTarget = (char *)LastLongLink.c_str();
 
       if (LastLongLink.empty() == false)
         Itm.LinkTarget = (char *)LastLongLink.c_str();
-      
+      else
+        Itm.LinkTarget = (char *)ItemLink.assign(Tar->LinkName, sizeof(Tar->LinkName)).c_str();
+
       // Convert the type over
       switch (Tar->LinkFlag)
       {
       // Convert the type over
       switch (Tar->LinkFlag)
       {
@@ -336,7 +344,7 @@ bool ExtractTar::Go(pkgDirStream &Stream)
       }
       
       // And finish up
       }
       
       // And finish up
-      if (Itm.Size >= 0 && BadRecord == false)
+      if (BadRecord == false)
         if (Stream.FinishedFile(Itm,Fd) == false)
            return false;
       
         if (Stream.FinishedFile(Itm,Fd) == false)
            return false;