summaryrefslogtreecommitdiff
path: root/sys/src/cmd/tapefs
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-05-19 12:39:45 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2015-05-19 12:39:45 +0200
commit041d732be72a13b9b7250fdab0ea4c46ad9d8326 (patch)
tree5159f39f9fde25e87066dc8ce863216fdfe60c13 /sys/src/cmd/tapefs
parent76ee4c3988f4f4e89514c203d8b7781abd29f24a (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.c26
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;
}
}