diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-05-19 12:39:45 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-05-19 12:39:45 +0200 |
commit | 041d732be72a13b9b7250fdab0ea4c46ad9d8326 (patch) | |
tree | 5159f39f9fde25e87066dc8ce863216fdfe60c13 /sys/src/cmd/tapefs | |
parent | 76ee4c3988f4f4e89514c203d8b7781abd29f24a (diff) |
tar, tarfs: implement longname support
this allows extracting tar archives that use longnames extension,
where the real filename is stored in a special entry with
linkflag == 'L' before the file entry. also skip longlink entries
with linkflag == 'K'.
Diffstat (limited to 'sys/src/cmd/tapefs')
-rw-r--r-- | sys/src/cmd/tapefs/tarfs.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/src/cmd/tapefs/tarfs.c b/sys/src/cmd/tapefs/tarfs.c index c58db4bbb..e694b8781 100644 --- a/sys/src/cmd/tapefs/tarfs.c +++ b/sys/src/cmd/tapefs/tarfs.c @@ -14,6 +14,7 @@ enum { Namsiz = 100, Maxpfx = 155, /* from POSIX */ Maxname = Namsiz + 1 + Maxpfx, + Maxlongname = 65535, Binsize = 0x80, /* flag in size[0], from gnu: positive binary size */ Binnegsz = 0xff, /* flag in size[0]: negative binary size */ }; @@ -30,7 +31,12 @@ enum { LF_DIR = '5', LF_FIFO = '6', LF_CONTIG = '7', + /* 'A' - 'Z' are reserved for custom implementations */ + + LF_LONGNAME = 'L', /* GNU extension */ + LF_LONGLINK = 'K', + }; typedef union { @@ -106,7 +112,9 @@ tarname(Hdr *hp) void populate(char *name) { - long chksum, linkflg; + char longname[Maxlongname+1]; + char *nextname = nil; + long chksum, linkflg, namelen; vlong blkno; char *fname; Fileinf f; @@ -121,7 +129,9 @@ populate(char *name) seek(tapefile, Tblock*blkno, 0); if (readn(tapefile, hp->dummy, sizeof hp->dummy) < sizeof hp->dummy) break; - fname = tarname(hp); + fname = nextname, nextname = nil; + if(fname == nil || fname[0] == '\0') + fname = tarname(hp); if (fname[0] == '\0') break; @@ -162,6 +172,16 @@ populate(char *name) if (linkflg) { /*fprint(2, "link %s->%s skipped\n", fname, hp->linkname);*/ f.size = 0; + } else if (hp->linkflag == LF_LONGLINK) { + ; + } else if (hp->linkflag == LF_LONGNAME) { + namelen = Maxlongname; + if(f.size < namelen) + namelen = f.size; + namelen = readn(tapefile, longname, namelen); + if(namelen < 0) namelen = 0; + longname[namelen] = '\0'; + nextname = longname; } else { /* accept this file */ f.name = fname; @@ -169,8 +189,8 @@ populate(char *name) fprint(2, "%s: null name skipped\n", argv0); else poppath(f, 1); - blkno += (f.size + Tblock - 1)/Tblock; } + blkno += (f.size + Tblock - 1)/Tblock; } } |