summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWichert Akkerman <wakkerma@debian.org>1999-10-21 13:36:28 +0000
committerWichert Akkerman <wakkerma@debian.org>1999-10-21 13:36:28 +0000
commit3252594427f5285ab4091a6beca2adaa5082a883 (patch)
tree61f85a5498d76bb3411b8d7a6c8e07ea82e6a91c /lib
parent0f88f4d306a470aa810f683d462d94872c30aae4 (diff)
downloaddpkg-3252594427f5285ab4091a6beca2adaa5082a883.tar.gz
Add support for GNU tar extension for long filenames
Diffstat (limited to 'lib')
-rw-r--r--lib/tarfn.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/lib/tarfn.c b/lib/tarfn.c
index 8b049005f..799f0c6bb 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 */