From 3252594427f5285ab4091a6beca2adaa5082a883 Mon Sep 17 00:00:00 2001 From: Wichert Akkerman Date: Thu, 21 Oct 1999 13:36:28 +0000 Subject: [PATCH] Add support for GNU tar extension for long filenames --- ChangeLog | 2 ++ debian/changelog | 1 + include/tarfn.h | 4 ++- lib/tarfn.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6adcdf3b..16a315a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ Thu Oct 21 13:22:42 CEST 1999 Wichert Akkerman * Update copyright (taken from dpkg-iwj tree, with Ben added) + * Add support for long filenames in tarfiles. Based on a patch + from Andrew Hobson Thu Oct 21 06:37:24 EDT 1999 Ben Collins diff --git a/debian/changelog b/debian/changelog index b303b6de..a4cb39e8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 diff --git a/include/tarfn.h b/include/tarfn.h index 5e387b07..1ffa3ea4 100644 --- a/include/tarfn.h +++ b/include/tarfn.h @@ -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; diff --git a/lib/tarfn.c b/lib/tarfn.c index 8b049005..799f0c6b 100644 --- a/lib/tarfn.c +++ b/lib/tarfn.c @@ -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 */ -- 2.39.5