]> err.no Git - dpkg/commitdiff
Add support for GNU tar extension for long filenames
authorWichert Akkerman <wakkerma@debian.org>
Thu, 21 Oct 1999 13:36:28 +0000 (13:36 +0000)
committerWichert Akkerman <wakkerma@debian.org>
Thu, 21 Oct 1999 13:36:28 +0000 (13:36 +0000)
ChangeLog
debian/changelog
include/tarfn.h
lib/tarfn.c

index 6adcdf3b0c6a30b69f91c14a5810242e34de6857..16a315a438700d9f095a55194c972bfb7613a327 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,8 @@
 Thu Oct 21 13:22:42 CEST 1999 Wichert Akkerman <wakkerma@debian.org>
 
   * Update copyright (taken from dpkg-iwj tree, with Ben added)
+  * Add support for long filenames in tarfiles. Based on a patch
+    from Andrew Hobson <ahobson@eng.mindspring.net>
 
 Thu Oct 21 06:37:24 EDT 1999 Ben Collins <bcollins.debian.org>
 
index b303b6de3c96454c00fe98cadd614dcd8fe1a841..a4cb39e826adac189c6a6b4556b3a1fcc2073e86 100644 (file)
@@ -1,5 +1,6 @@
 dpkg (1.4.1.17) unstable; urgency=low
 
+  * Add support for long filenames
   * Added --chuid option to start-stop-daemon to allow switching to
     a different uid when starting a process
   * Add mipseb and mipsel to the archtable too, since mips and mipseb are
index 5e387b07b665185a99506beae4f45b5f2c5b139e..1ffa3ea42096d8ec93ca747d2e3e62765be0eeaa 100644 (file)
@@ -20,7 +20,9 @@ enum TarFileType {
        CharacterDevice = '3',
        BlockDevice = '4',
        Directory = '5',
-       FIFO = '6'
+       FIFO = '6',
+       GNU_LONGLINK = 'K',
+       GNU_LONGNAME = 'L'
 };
 typedef enum TarFileType       TarFileType;
 
index 8b049005f4a6d6a412af546f93efd8a4f15d90de..799f0c6bb32c4305edc24885d8f6ef97cb7d09a4 100644 (file)
@@ -54,13 +54,13 @@ OtoL(const char * s, int size)
 static int
 DecodeTarHeader(char * block, TarInfo * d)
 {
-       TarHeader *                     h = (TarHeader *)block;
+       TarHeader *             h = (TarHeader *)block;
        unsigned char *         s = (unsigned char *)block;
        struct passwd *         passwd = 0;
        struct group *          group = 0;
        unsigned int            i;
-       long                            sum;
-       long                            checksum;
+       long                    sum;
+       long                    checksum;
 
        if ( *h->UserName )
                passwd = getpwnam(h->UserName);
@@ -106,6 +106,15 @@ TarExtractor(
        char    buffer[512];
        TarInfo h;
 
+       char    *next_long_name, *next_long_link;
+       char    *bp;
+       char    **longp;
+       int     long_read;
+
+       next_long_name = 0;
+       next_long_link = 0;
+       long_read = 0;
+
        h.UserData = userData;
 
        while ( (status = functions->Read(userData, buffer, 512)) == 512 ) {
@@ -119,6 +128,17 @@ TarExtractor(
                                return -1;      /* Header checksum error */
                        }
                }
+               if (next_long_name) {
+                 h.Name = next_long_name;
+               }
+
+               if (next_long_link) {
+                 h.LinkName = next_long_link;
+               }
+
+               next_long_name = 0;
+               next_long_link = 0;
+
                if ( h.Name[0] == '\0' ) {
                        errno = 0;      /* Indicates broken tarfile */
                        return -1;      /* Bad header data */
@@ -150,6 +170,54 @@ TarExtractor(
                case FIFO:
                        status = (*functions->MakeSpecialFile)(&h);
                        break;
+               case GNU_LONGLINK:
+               case GNU_LONGNAME:
+                 // set longp to the location of the long filename or link
+                 // we're trying to deal with
+                 longp = ((h.Type == GNU_LONGNAME)
+                          ? &next_long_name
+                          : &next_long_link);
+
+                 if (*longp)
+                   free(*longp);
+
+                 if (NULL == (*longp = (char *)malloc(h.Size))) {
+                   /* malloc failed, so bail */
+                   errno = 0;
+                   return -1;
+                 }
+                 bp = *longp;
+
+                 // the way the GNU long{link,name} stuff works is like this:  
+                // The first header is a "dummy" header that contains the size
+                // of the filename.  The next N headers contain the filename.
+                // After the headers with the filename comes the "real" header
+                // with a bogus name or link.
+                 for (long_read = h.Size; long_read > 0;
+                      long_read -= 512) {
+
+                   int copysize;
+
+                   status = functions->Read(userData, buffer, 512);
+                   // if we didn't get 512 bytes read, punt
+                   if (512 != status)
+                    if ( status > 0 ) { /* Read partial header record */
+                      errno = 0;
+                      return -1;
+                    } else {
+                       return status;
+                     }
+
+                   copysize = long_read > 512 ? 512 : long_read;
+                   memcpy (bp, buffer, copysize);
+                   bp += copysize;
+
+                 };
+                 // This decode function expects status to be 0 after
+                 // the case statement if we successfully decoded.  I
+                 // guess what we just did was successful.
+                 status = 0;
+                 break;
                default:
                        errno = 0;      /* Indicates broken tarfile */
                        return -1;      /* Bad header field */