new tar import
This commit is contained in:
parent
c86883cab5
commit
6019a96c78
1 changed files with 194 additions and 62 deletions
256
src/cmd/tar.c
256
src/cmd/tar.c
|
|
@ -16,9 +16,7 @@
|
||||||
* keyletters and options.
|
* keyletters and options.
|
||||||
*/
|
*/
|
||||||
#define TARGBEGIN {\
|
#define TARGBEGIN {\
|
||||||
if (argv0 == nil)\
|
(argv0 || (argv0 = *argv)), argv++, argc--;\
|
||||||
argv0 = *argv;\
|
|
||||||
argv++, argc--;\
|
|
||||||
if (argv[0]) {\
|
if (argv[0]) {\
|
||||||
char *_args, *_argt;\
|
char *_args, *_argt;\
|
||||||
Rune _argc;\
|
Rune _argc;\
|
||||||
|
|
@ -34,6 +32,12 @@
|
||||||
#define ROUNDUP(a, b) (((a) + (b) - 1)/(b))
|
#define ROUNDUP(a, b) (((a) + (b) - 1)/(b))
|
||||||
#define BYTES2TBLKS(bytes) ROUNDUP(bytes, Tblock)
|
#define BYTES2TBLKS(bytes) ROUNDUP(bytes, Tblock)
|
||||||
|
|
||||||
|
/* read big-endian binary integers; args must be (uchar *) */
|
||||||
|
#define G2BEBYTE(x) (((x)[0]<<8) | (x)[1])
|
||||||
|
#define G3BEBYTE(x) (((x)[0]<<16) | ((x)[1]<<8) | (x)[2])
|
||||||
|
#define G4BEBYTE(x) (((x)[0]<<24) | ((x)[1]<<16) | ((x)[2]<<8) | (x)[3])
|
||||||
|
#define G8BEBYTE(x) (((vlong)G4BEBYTE(x)<<32) | (u32int)G4BEBYTE((x)+4))
|
||||||
|
|
||||||
typedef vlong Off;
|
typedef vlong Off;
|
||||||
typedef char *(*Refill)(int ar, char *bufs, int justhdr);
|
typedef char *(*Refill)(int ar, char *bufs, int justhdr);
|
||||||
|
|
||||||
|
|
@ -44,11 +48,14 @@ enum { None, Toc, Xtract, Replace };
|
||||||
enum { Alldata, Justnxthdr };
|
enum { Alldata, Justnxthdr };
|
||||||
enum {
|
enum {
|
||||||
Tblock = 512,
|
Tblock = 512,
|
||||||
Nblock = 40, /* maximum blocksize */
|
|
||||||
Dblock = 20, /* default blocksize */
|
|
||||||
Namsiz = 100,
|
Namsiz = 100,
|
||||||
Maxpfx = 155, /* from POSIX */
|
Maxpfx = 155, /* from POSIX */
|
||||||
Maxname = Namsiz + 1 + Maxpfx,
|
Maxname = Namsiz + 1 + Maxpfx,
|
||||||
|
Binsize = 0x80, /* flag in size[0], from gnu: positive binary size */
|
||||||
|
Binnegsz = 0xff, /* flag in size[0]: negative binary size */
|
||||||
|
|
||||||
|
Nblock = 40, /* maximum blocksize */
|
||||||
|
Dblock = 20, /* default blocksize */
|
||||||
DEBUG = 0,
|
DEBUG = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -58,7 +65,7 @@ enum {
|
||||||
LF_PLAIN2 = '0',
|
LF_PLAIN2 = '0',
|
||||||
LF_LINK = '1',
|
LF_LINK = '1',
|
||||||
LF_SYMLINK1 = '2',
|
LF_SYMLINK1 = '2',
|
||||||
LF_SYMLINK2 = 's',
|
LF_SYMLINK2 = 's', /* 4BSD used this */
|
||||||
LF_CHR = '3',
|
LF_CHR = '3',
|
||||||
LF_BLK = '4',
|
LF_BLK = '4',
|
||||||
LF_DIR = '5',
|
LF_DIR = '5',
|
||||||
|
|
@ -71,25 +78,28 @@ enum {
|
||||||
#define isreallink(lf) ((lf) == LF_LINK)
|
#define isreallink(lf) ((lf) == LF_LINK)
|
||||||
#define issymlink(lf) ((lf) == LF_SYMLINK1 || (lf) == LF_SYMLINK2)
|
#define issymlink(lf) ((lf) == LF_SYMLINK1 || (lf) == LF_SYMLINK2)
|
||||||
|
|
||||||
typedef struct {
|
typedef union {
|
||||||
char name[Namsiz];
|
uchar data[Tblock];
|
||||||
char mode[8];
|
struct {
|
||||||
char uid[8];
|
char name[Namsiz];
|
||||||
char gid[8];
|
char mode[8];
|
||||||
char size[12];
|
char uid[8];
|
||||||
char mtime[12];
|
char gid[8];
|
||||||
char chksum[8];
|
char size[12];
|
||||||
char linkflag;
|
char mtime[12];
|
||||||
char linkname[Namsiz];
|
char chksum[8];
|
||||||
|
char linkflag;
|
||||||
|
char linkname[Namsiz];
|
||||||
|
|
||||||
/* rest are defined by POSIX's ustar format; see p1003.2b */
|
/* rest are defined by POSIX's ustar format; see p1003.2b */
|
||||||
char magic[6]; /* "ustar" */
|
char magic[6]; /* "ustar" */
|
||||||
char version[2];
|
char version[2];
|
||||||
char uname[32];
|
char uname[32];
|
||||||
char gname[32];
|
char gname[32];
|
||||||
char devmajor[8];
|
char devmajor[8];
|
||||||
char devminor[8];
|
char devminor[8];
|
||||||
char prefix[Maxpfx]; /* if non-null, path= prefix "/" name */
|
char prefix[Maxpfx]; /* if non-null, path= prefix "/" name */
|
||||||
|
};
|
||||||
} Hdr;
|
} Hdr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -247,9 +257,9 @@ refill(int ar, char *bufs, int justhdr)
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
seekable = seek(ar, 0, 1) >= 0;
|
seekable = seek(ar, 0, 1) >= 0;
|
||||||
|
blkoff = seek(ar, 0, 1); /* note position for `tar r' */
|
||||||
/* try to size non-pipe input at first read */
|
/* try to size non-pipe input at first read */
|
||||||
if (first && usefile) {
|
if (first && usefile) {
|
||||||
blkoff = seek(ar, 0, 1); /* note position */
|
|
||||||
n = read(ar, bufs, bytes);
|
n = read(ar, bufs, bytes);
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
sysfatal("error reading archive: %r");
|
sysfatal("error reading archive: %r");
|
||||||
|
|
@ -317,7 +327,7 @@ getblkz(int ar)
|
||||||
Hdr *hp = getblke(ar);
|
Hdr *hp = getblke(ar);
|
||||||
|
|
||||||
if (hp != nil)
|
if (hp != nil)
|
||||||
memset(hp, 0, Tblock);
|
memset(hp->data, 0, Tblock);
|
||||||
return hp;
|
return hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -385,12 +395,12 @@ putblkmany(int ar, int blks)
|
||||||
* modifies hp->chksum but restores it; important for the last block of the
|
* modifies hp->chksum but restores it; important for the last block of the
|
||||||
* old archive when updating with `tar rf archive'
|
* old archive when updating with `tar rf archive'
|
||||||
*/
|
*/
|
||||||
long
|
static long
|
||||||
chksum(Hdr *hp)
|
chksum(Hdr *hp)
|
||||||
{
|
{
|
||||||
int n = Tblock;
|
int n = Tblock;
|
||||||
long i = 0;
|
long i = 0;
|
||||||
uchar *cp = (uchar*)hp;
|
uchar *cp = hp->data;
|
||||||
char oldsum[sizeof hp->chksum];
|
char oldsum[sizeof hp->chksum];
|
||||||
|
|
||||||
memmove(oldsum, hp->chksum, sizeof oldsum);
|
memmove(oldsum, hp->chksum, sizeof oldsum);
|
||||||
|
|
@ -458,14 +468,62 @@ eotar(Hdr *hp)
|
||||||
return name(hp)[0] == '\0';
|
return name(hp)[0] == '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
Off
|
/*
|
||||||
|
static uvlong
|
||||||
|
getbe(uchar *src, int size)
|
||||||
|
{
|
||||||
|
uvlong vl = 0;
|
||||||
|
|
||||||
|
while (size-- > 0) {
|
||||||
|
vl <<= 8;
|
||||||
|
vl |= *src++;
|
||||||
|
}
|
||||||
|
return vl;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
putbe(uchar *dest, uvlong vl, int size)
|
||||||
|
{
|
||||||
|
for (dest += size; size-- > 0; vl >>= 8)
|
||||||
|
*--dest = vl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return the nominal size from the header block, which is not always the
|
||||||
|
* size in the archive (the archive size may be zero for some file types
|
||||||
|
* regardless of the nominal size).
|
||||||
|
*
|
||||||
|
* gnu and freebsd tars are now recording vlongs as big-endian binary
|
||||||
|
* with a flag in byte 0 to indicate this, which permits file sizes up to
|
||||||
|
* 2^64-1 (actually 2^80-1 but our file sizes are vlongs) rather than 2^33-1.
|
||||||
|
*/
|
||||||
|
static Off
|
||||||
hdrsize(Hdr *hp)
|
hdrsize(Hdr *hp)
|
||||||
{
|
{
|
||||||
Off bytes = strtoull(hp->size, nil, 8);
|
uchar *p;
|
||||||
|
|
||||||
if(isdir(hp))
|
if((uchar)hp->size[0] == Binnegsz) {
|
||||||
bytes = 0;
|
fprint(2, "%s: %s: negative length, which is insane\n",
|
||||||
return bytes;
|
argv0, name(hp));
|
||||||
|
return 0;
|
||||||
|
} else if((uchar)hp->size[0] == Binsize) {
|
||||||
|
p = (uchar *)hp->size + sizeof hp->size - 1 -
|
||||||
|
sizeof(vlong); /* -1 for terminating space */
|
||||||
|
return G8BEBYTE(p);
|
||||||
|
} else
|
||||||
|
return strtoull(hp->size, nil, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return the number of bytes recorded in the archive.
|
||||||
|
*/
|
||||||
|
static Off
|
||||||
|
arsize(Hdr *hp)
|
||||||
|
{
|
||||||
|
if(isdir(hp) || islink(hp->linkflag))
|
||||||
|
return 0;
|
||||||
|
return hdrsize(hp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Hdr *
|
static Hdr *
|
||||||
|
|
@ -483,7 +541,7 @@ readhdr(int ar)
|
||||||
if (chksum(hp) != hdrcksum)
|
if (chksum(hp) != hdrcksum)
|
||||||
sysfatal("bad archive header checksum: name %.64s...",
|
sysfatal("bad archive header checksum: name %.64s...",
|
||||||
hp->name);
|
hp->name);
|
||||||
nexthdr += Tblock*(1 + BYTES2TBLKS(hdrsize(hp)));
|
nexthdr += Tblock*(1 + BYTES2TBLKS(arsize(hp)));
|
||||||
return hp;
|
return hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -561,16 +619,19 @@ mkhdr(Hdr *hp, Dir *dir, char *file)
|
||||||
sprint(hp->mode, "%6lo ", dir->mode & 0777);
|
sprint(hp->mode, "%6lo ", dir->mode & 0777);
|
||||||
sprint(hp->uid, "%6o ", aruid);
|
sprint(hp->uid, "%6o ", aruid);
|
||||||
sprint(hp->gid, "%6o ", argid);
|
sprint(hp->gid, "%6o ", argid);
|
||||||
/*
|
if (dir->length >= (Off)1<<32) {
|
||||||
* files > 2 bytes can't be described
|
static int printed;
|
||||||
* (unless we resort to xustar or exustar formats).
|
|
||||||
*/
|
if (!printed) {
|
||||||
if (dir->length >= (Off)1<<33) {
|
printed = 1;
|
||||||
fprint(2, "%s: %s: too large for tar header format\n",
|
fprint(2, "%s: storing large sizes in \"base 256\"\n", argv0);
|
||||||
argv0, file);
|
}
|
||||||
return -1;
|
hp->size[0] = Binsize;
|
||||||
}
|
/* emit so-called `base 256' representation of size */
|
||||||
sprint(hp->size, "%11lluo ", dir->length);
|
putbe((uchar *)hp->size+1, dir->length, sizeof hp->size - 2);
|
||||||
|
hp->size[sizeof hp->size - 1] = ' ';
|
||||||
|
} else
|
||||||
|
sprint(hp->size, "%11lluo ", dir->length);
|
||||||
sprint(hp->mtime, "%11luo ", dir->mtime);
|
sprint(hp->mtime, "%11luo ", dir->mtime);
|
||||||
hp->linkflag = (dir->mode&DMDIR? LF_DIR: LF_PLAIN1);
|
hp->linkflag = (dir->mode&DMDIR? LF_DIR: LF_PLAIN1);
|
||||||
putfullname(hp, file);
|
putfullname(hp, file);
|
||||||
|
|
@ -633,10 +694,20 @@ addtoar(int ar, char *file, char *shortf)
|
||||||
ulong blksleft, blksread;
|
ulong blksleft, blksread;
|
||||||
Hdr *hbp;
|
Hdr *hbp;
|
||||||
Dir *dir;
|
Dir *dir;
|
||||||
|
String *name = nil;
|
||||||
|
|
||||||
|
if (shortf[0] == '#') {
|
||||||
|
name = s_new();
|
||||||
|
s_append(name, "./");
|
||||||
|
s_append(name, shortf);
|
||||||
|
shortf = s_to_c(name);
|
||||||
|
}
|
||||||
|
|
||||||
fd = open(shortf, OREAD);
|
fd = open(shortf, OREAD);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprint(2, "%s: can't open %s: %r\n", argv0, file);
|
fprint(2, "%s: can't open %s: %r\n", argv0, file);
|
||||||
|
if (name)
|
||||||
|
s_free(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dir = dirfstat(fd);
|
dir = dirfstat(fd);
|
||||||
|
|
@ -649,6 +720,8 @@ addtoar(int ar, char *file, char *shortf)
|
||||||
putbackblk(ar);
|
putbackblk(ar);
|
||||||
free(dir);
|
free(dir);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
if (name)
|
||||||
|
s_free(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
putblk(ar);
|
putblk(ar);
|
||||||
|
|
@ -663,7 +736,7 @@ addtoar(int ar, char *file, char *shortf)
|
||||||
hbp = getblke(ar);
|
hbp = getblke(ar);
|
||||||
blksread = gothowmany(blksleft);
|
blksread = gothowmany(blksleft);
|
||||||
bytes = blksread * Tblock;
|
bytes = blksread * Tblock;
|
||||||
n = readn(fd, hbp, bytes);
|
n = readn(fd, hbp->data, bytes);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
sysfatal("error reading %s: %r", file);
|
sysfatal("error reading %s: %r", file);
|
||||||
/*
|
/*
|
||||||
|
|
@ -671,13 +744,15 @@ addtoar(int ar, char *file, char *shortf)
|
||||||
* compression and emergency recovery of data.
|
* compression and emergency recovery of data.
|
||||||
*/
|
*/
|
||||||
if (n < Tblock)
|
if (n < Tblock)
|
||||||
memset((uchar*)hbp + n, 0, bytes - n);
|
memset(hbp->data + n, 0, bytes - n);
|
||||||
putblkmany(ar, blksread);
|
putblkmany(ar, blksread);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprint(2, "%s\n", file);
|
fprint(2, "%s\n", file);
|
||||||
}
|
}
|
||||||
|
if (name)
|
||||||
|
s_free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
|
@ -706,7 +781,7 @@ replace(char **argv)
|
||||||
if (usefile && !docreate) {
|
if (usefile && !docreate) {
|
||||||
/* skip quickly to the end */
|
/* skip quickly to the end */
|
||||||
while ((hp = readhdr(ar)) != nil) {
|
while ((hp = readhdr(ar)) != nil) {
|
||||||
bytes = hdrsize(hp);
|
bytes = arsize(hp);
|
||||||
for (blksleft = BYTES2TBLKS(bytes);
|
for (blksleft = BYTES2TBLKS(bytes);
|
||||||
blksleft > 0 && getblkrd(ar, Justnxthdr) != nil;
|
blksleft > 0 && getblkrd(ar, Justnxthdr) != nil;
|
||||||
blksleft -= blksread) {
|
blksleft -= blksread) {
|
||||||
|
|
@ -777,6 +852,34 @@ match(char *name, char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cantcreate(char *s, int mode)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
static char *last;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always print about files. Only print about directories
|
||||||
|
* we haven't printed about. (Assumes archive is ordered
|
||||||
|
* nicely.)
|
||||||
|
*/
|
||||||
|
if(mode&DMDIR){
|
||||||
|
if(last){
|
||||||
|
/* already printed this directory */
|
||||||
|
if(strcmp(s, last) == 0)
|
||||||
|
return;
|
||||||
|
/* printed a higher directory, so printed this one */
|
||||||
|
len = strlen(s);
|
||||||
|
if(memcmp(s, last, len) == 0 && last[len] == '/')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* save */
|
||||||
|
free(last);
|
||||||
|
last = strdup(s);
|
||||||
|
}
|
||||||
|
fprint(2, "%s: can't create %s: %r\n", argv0, s);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
makedir(char *s)
|
makedir(char *s)
|
||||||
{
|
{
|
||||||
|
|
@ -787,20 +890,39 @@ makedir(char *s)
|
||||||
f = create(s, OREAD, DMDIR | 0777);
|
f = create(s, OREAD, DMDIR | 0777);
|
||||||
if (f >= 0)
|
if (f >= 0)
|
||||||
close(f);
|
close(f);
|
||||||
|
else
|
||||||
|
cantcreate(s, DMDIR);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
mkpdirs(char *s)
|
mkpdirs(char *s)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int err;
|
||||||
char *p = s;
|
char *p;
|
||||||
|
|
||||||
while (!done && (p = strchr(p + 1, '/')) != nil) {
|
p = s;
|
||||||
|
err = 0;
|
||||||
|
while (!err && (p = strchr(p+1, '/')) != nil) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
done = (access(s, AEXIST) < 0 && makedir(s) < 0);
|
err = (access(s, AEXIST) < 0 && makedir(s) < 0);
|
||||||
*p = '/';
|
*p = '/';
|
||||||
}
|
}
|
||||||
|
return -err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call access but preserve the error string. */
|
||||||
|
static int
|
||||||
|
xaccess(char *name, int mode)
|
||||||
|
{
|
||||||
|
char err[ERRMAX];
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
err[0] = 0;
|
||||||
|
errstr(err, sizeof err);
|
||||||
|
rv = access(name, mode);
|
||||||
|
errstr(err, sizeof err);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy a file from the archive into the filesystem */
|
/* copy a file from the archive into the filesystem */
|
||||||
|
|
@ -811,8 +933,8 @@ extract1(int ar, Hdr *hp, char *fname)
|
||||||
int wrbytes, fd = -1, dir = 0;
|
int wrbytes, fd = -1, dir = 0;
|
||||||
long mtime = strtol(hp->mtime, nil, 8);
|
long mtime = strtol(hp->mtime, nil, 8);
|
||||||
ulong mode = strtoul(hp->mode, nil, 8) & 0777;
|
ulong mode = strtoul(hp->mode, nil, 8) & 0777;
|
||||||
Off bytes = strtoll(hp->size, nil, 8); /* for printing */
|
Off bytes = hdrsize(hp); /* for printing */
|
||||||
ulong blksread, blksleft = BYTES2TBLKS(hdrsize(hp));
|
ulong blksread, blksleft = BYTES2TBLKS(arsize(hp));
|
||||||
Hdr *hbp;
|
Hdr *hbp;
|
||||||
|
|
||||||
if (isdir(hp)) {
|
if (isdir(hp)) {
|
||||||
|
|
@ -857,9 +979,8 @@ extract1(int ar, Hdr *hp, char *fname)
|
||||||
fd = create(fname, rw, mode);
|
fd = create(fname, rw, mode);
|
||||||
}
|
}
|
||||||
if (fd < 0 &&
|
if (fd < 0 &&
|
||||||
(!dir || access(fname, AEXIST) < 0))
|
(!dir || xaccess(fname, AEXIST) < 0))
|
||||||
fprint(2, "%s: can't create %s: %r\n",
|
cantcreate(fname, mode);
|
||||||
argv0, fname);
|
|
||||||
}
|
}
|
||||||
if (fd >= 0 && verbose)
|
if (fd >= 0 && verbose)
|
||||||
fprint(2, "%s\n", fname);
|
fprint(2, "%s\n", fname);
|
||||||
|
|
@ -873,20 +994,29 @@ extract1(int ar, Hdr *hp, char *fname)
|
||||||
} else
|
} else
|
||||||
print("%s\n", fname);
|
print("%s\n", fname);
|
||||||
|
|
||||||
|
if (blksleft == 0)
|
||||||
|
bytes = 0;
|
||||||
for (; blksleft > 0; blksleft -= blksread) {
|
for (; blksleft > 0; blksleft -= blksread) {
|
||||||
hbp = getblkrd(ar, (fd >= 0? Alldata: Justnxthdr));
|
hbp = getblkrd(ar, (fd >= 0? Alldata: Justnxthdr));
|
||||||
if (hbp == nil)
|
if (hbp == nil)
|
||||||
sysfatal("unexpected EOF on archive extracting %s",
|
sysfatal("unexpected EOF on archive extracting %s",
|
||||||
fname);
|
fname);
|
||||||
blksread = gothowmany(blksleft);
|
blksread = gothowmany(blksleft);
|
||||||
|
if (blksread <= 0)
|
||||||
|
fprint(2, "%s: got %ld blocks reading %s!\n",
|
||||||
|
argv0, blksread, fname);
|
||||||
wrbytes = Tblock*blksread;
|
wrbytes = Tblock*blksread;
|
||||||
if(wrbytes > bytes)
|
if(wrbytes > bytes)
|
||||||
wrbytes = bytes;
|
wrbytes = bytes;
|
||||||
if (fd >= 0 && write(fd, hbp, wrbytes) != wrbytes)
|
if (fd >= 0 && write(fd, hbp->data, wrbytes) != wrbytes)
|
||||||
sysfatal("write error on %s: %r", fname);
|
sysfatal("write error on %s: %r", fname);
|
||||||
putreadblks(ar, blksread);
|
putreadblks(ar, blksread);
|
||||||
bytes -= wrbytes;
|
bytes -= wrbytes;
|
||||||
}
|
}
|
||||||
|
if (bytes > 0)
|
||||||
|
fprint(2,
|
||||||
|
"%s: %lld bytes uncopied at eof; %s not fully extracted\n",
|
||||||
|
argv0, bytes, fname);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
/*
|
/*
|
||||||
* directories should be wstated after we're done
|
* directories should be wstated after we're done
|
||||||
|
|
@ -897,9 +1027,12 @@ extract1(int ar, Hdr *hp, char *fname)
|
||||||
|
|
||||||
nulldir(&nd);
|
nulldir(&nd);
|
||||||
nd.mtime = mtime;
|
nd.mtime = mtime;
|
||||||
if (isustar(hp))
|
|
||||||
nd.gid = hp->gname;
|
|
||||||
dirfwstat(fd, &nd);
|
dirfwstat(fd, &nd);
|
||||||
|
if (isustar(hp)) {
|
||||||
|
nulldir(&nd);
|
||||||
|
nd.gid = hp->gname;
|
||||||
|
dirfwstat(fd, &nd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
@ -911,7 +1044,7 @@ skip(int ar, Hdr *hp, char *fname)
|
||||||
ulong blksleft, blksread;
|
ulong blksleft, blksread;
|
||||||
Hdr *hbp;
|
Hdr *hbp;
|
||||||
|
|
||||||
for (blksleft = BYTES2TBLKS(hdrsize(hp)); blksleft > 0;
|
for (blksleft = BYTES2TBLKS(arsize(hp)); blksleft > 0;
|
||||||
blksleft -= blksread) {
|
blksleft -= blksread) {
|
||||||
hbp = getblkrd(ar, Justnxthdr);
|
hbp = getblkrd(ar, Justnxthdr);
|
||||||
if (hbp == nil)
|
if (hbp == nil)
|
||||||
|
|
@ -962,7 +1095,6 @@ main(int argc, char *argv[])
|
||||||
int errflg = 0;
|
int errflg = 0;
|
||||||
char *ret = nil;
|
char *ret = nil;
|
||||||
|
|
||||||
quotefmtinstall();
|
|
||||||
fmtinstall('M', dirmodefmt);
|
fmtinstall('M', dirmodefmt);
|
||||||
|
|
||||||
TARGBEGIN {
|
TARGBEGIN {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue