support ././@LongLink extraction, as created by GNU tar.

This commit is contained in:
mrg 1999-10-22 10:43:11 +00:00
parent 222397ee58
commit 78e294d1bc
7 changed files with 92 additions and 33 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ar_subs.c,v 1.12 1999/08/24 07:57:06 tron Exp $ */
/* $NetBSD: ar_subs.c,v 1.13 1999/10/22 10:43:11 mrg Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: ar_subs.c,v 1.12 1999/08/24 07:57:06 tron Exp $");
__RCSID("$NetBSD: ar_subs.c,v 1.13 1999/10/22 10:43:11 mrg Exp $");
#endif
#endif /* not lint */
@ -199,6 +199,8 @@ extract()
* says it is done
*/
while (next_head(arcn) == 0) {
int gnu_longlink_hack =
(arcn->type == PAX_GLL || arcn->type == PAX_GLF);
if (arcn->name[0] == '/' && !check_Aflag()) {
memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
@ -207,16 +209,19 @@ extract()
* check for pattern, and user specified options match. When
* all the patterns are matched we are done
*/
if ((res = pat_match(arcn)) < 0)
break;
if (!gnu_longlink_hack) {
if ((res = pat_match(arcn)) < 0)
break;
if ((res > 0) || (sel_chk(arcn) != 0)) {
/*
* file is not selected. skip past any file data and
* padding and go back for the next archive member
*/
(void)rd_skip(arcn->skip + arcn->pad);
continue;
if ((res > 0) || (sel_chk(arcn) != 0)) {
/*
* file is not selected. skip past any file
* data and padding and go back for the next
* archive member
*/
(void)rd_skip(arcn->skip + arcn->pad);
continue;
}
}
/*
@ -227,9 +232,10 @@ extract()
* specified by pax. this operation can be confusing to the
* user who might expect the test to be done on an existing
* file AFTER the name mod. In honesty the pax spec is probably
* flawed in this respect.
* flawed in this respect. ignore this for GNU long links.
*/
if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) {
if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0)) &&
!gnu_longlink_hack) {
if (uflag && Dflag) {
if ((arcn->sb.st_mtime <= sb.st_mtime) &&
(arcn->sb.st_ctime <= sb.st_ctime)) {
@ -263,9 +269,10 @@ extract()
/*
* Non standard -Y and -Z flag. When the exisiting file is
* same age or newer skip
* same age or newer skip; ignore this for GNU long links.
*/
if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0)) &&
!gnu_longlink_hack) {
if (Yflag && Zflag) {
if ((arcn->sb.st_mtime <= sb.st_mtime) &&
(arcn->sb.st_ctime <= sb.st_ctime)) {
@ -291,7 +298,8 @@ extract()
/*
* all ok, extract this member based on type
*/
if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG) &&
!gnu_longlink_hack) {
/*
* process archive members that are not regular files.
* throw out padding and any data that might follow the
@ -316,7 +324,9 @@ extract()
* we have a file with data here. If we can not create it, skip
* over the data and purge the name from hard link table
*/
if ((fd = file_creat(arcn)) < 0) {
if (gnu_longlink_hack)
fd = -1; /* this tells the pax internals to DTRT */
else if ((fd = file_creat(arcn)) < 0) {
(void)rd_skip(arcn->skip + arcn->pad);
purg_lnk(arcn);
continue;
@ -326,7 +336,8 @@ extract()
* any unprocessed data
*/
res = (*frmt->rd_data)(arcn, fd, &cnt);
file_close(arcn, fd);
if (!gnu_longlink_hack)
file_close(arcn, fd);
if (vflag && vfpart) {
(void)putc('\n', stderr);
vfpart = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf_subs.c,v 1.10 1999/10/22 10:38:40 mrg Exp $ */
/* $NetBSD: buf_subs.c,v 1.11 1999/10/22 10:43:11 mrg Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: buf_subs.c,v 1.10 1999/10/22 10:38:40 mrg Exp $");
__RCSID("$NetBSD: buf_subs.c,v 1.11 1999/10/22 10:43:11 mrg Exp $");
#endif
#endif /* not lint */
@ -767,7 +767,9 @@ rd_wrfile(arcn, ofd, left)
* pass the blocksize of the file being written to the write routine,
* if the size is zero, use the default MINFBSZ
*/
if (fstat(ofd, &sb) == 0) {
if (ofd == -1)
sz = PAXPATHLEN+1;
else if (fstat(ofd, &sb) == 0) {
if (sb.st_blksize > 0)
sz = (int)sb.st_blksize;
} else
@ -813,7 +815,7 @@ rd_wrfile(arcn, ofd, left)
* written. just closing with the file offset moved foward may not put
* a hole at the end of the file.
*/
if (isem && (arcn->sb.st_size > 0L))
if (ofd != -1 && isem && (arcn->sb.st_size > 0L))
file_flush(ofd, fnm, isem);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.17 1999/08/24 07:57:06 tron Exp $ */
/* $NetBSD: extern.h,v 1.18 1999/10/22 10:43:11 mrg Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -129,6 +129,7 @@ int bcpio_wr __P((ARCHD *));
/*
* file_subs.c
*/
extern char *gnu_hack_string;
int file_creat __P((ARCHD *));
void file_close __P((ARCHD *, int));
int lnk_creat __P((ARCHD *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: file_subs.c,v 1.11 1999/10/22 10:38:41 mrg Exp $ */
/* $NetBSD: file_subs.c,v 1.12 1999/10/22 10:43:11 mrg Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: file_subs.c,v 1.11 1999/10/22 10:38:41 mrg Exp $");
__RCSID("$NetBSD: file_subs.c,v 1.12 1999/10/22 10:43:11 mrg Exp $");
#endif
#endif /* not lint */
@ -51,6 +51,7 @@ __RCSID("$NetBSD: file_subs.c,v 1.11 1999/10/22 10:38:41 mrg Exp $");
#include <sys/stat.h>
#include <unistd.h>
#include <sys/param.h>
#include <err.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
@ -893,7 +894,8 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
/*
* skip, buf is empty so far
*/
if (lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) {
if (fd > -1 &&
lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) {
syswarn(1,errno,"File seek on %s",
name);
return(-1);
@ -910,7 +912,18 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
/*
* have non-zero data in this file system block, have to write
*/
if (write(fd, st, wcnt) != wcnt) {
if (fd == -1) {
/* GNU hack */
if (gnu_hack_string)
err(1, "WARNING! Major Internal Error! GNU hack Failing!");
gnu_hack_string = malloc(wcnt + 1);
if (gnu_hack_string == NULL) {
tty_warn(1, "Out of memory");
return(-1);
}
strncpy(gnu_hack_string, st, wcnt);
gnu_hack_string[wcnt] = 0;
} else if (write(fd, st, wcnt) != wcnt) {
syswarn(1, errno, "Failed write to file %s", name);
return(-1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pax.h,v 1.6 1999/07/03 14:42:39 kleink Exp $ */
/* $NetBSD: pax.h,v 1.7 1999/10/22 10:43:12 mrg Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -125,6 +125,8 @@ typedef struct {
#define PAX_HLK 8 /* hard link */
#define PAX_HRG 9 /* hard link to a regular file */
#define PAX_CTG 10 /* high performance file */
#define PAX_GLL 11 /* GNU long symlink */
#define PAX_GLF 12 /* GNU long file */
} ARCHD;
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: tar.c,v 1.15 1999/08/18 17:46:28 kleink Exp $ */
/* $NetBSD: tar.c,v 1.16 1999/10/22 10:43:12 mrg Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: tar.c,v 1.15 1999/08/18 17:46:28 kleink Exp $");
__RCSID("$NetBSD: tar.c,v 1.16 1999/10/22 10:43:12 mrg Exp $");
#endif
#endif /* not lint */
@ -81,6 +81,7 @@ static int uqd_oct __P((u_quad_t, char *, int, int));
static int tar_nodir; /* do not write dirs under old tar */
int is_oldgnutar; /* skip end-ofvolume checks */
char *gnu_hack_string; /* ././@LongLink hackery */
/*
* tar_endwr()
@ -466,8 +467,16 @@ tar_rd(arcn, buf)
* copy out the name and values in the stat buffer
*/
hd = (HD_TAR *)buf;
arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name));
arcn->name[arcn->nlen] = '\0';
if (gnu_hack_string) {
int len = MAX(strlen(gnu_hack_string), PAXPATHLEN);
arcn->nlen = l_strncpy(arcn->name, gnu_hack_string, len);
arcn->name[len] = '\0';
free(gnu_hack_string);
gnu_hack_string = NULL;
} else {
arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(hd->name));
arcn->name[arcn->nlen] = '\0';
}
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
0xfff);
arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
@ -512,6 +521,21 @@ tar_rd(arcn, buf)
*/
arcn->sb.st_mode |= S_IFREG;
break;
case LONGLINKTYPE:
arcn->type = PAX_GLL;
/* FALLTHROUGH */
case LONGNAMETYPE:
/*
* GNU long link/file; we tag these here and let the
* pax internals deal with it -- too ugly otherwise.
*/
if (hd->linkflag != LONGLINKTYPE)
arcn->type = PAX_GLF;
arcn->pad = TAR_PAD(arcn->sb.st_size);
arcn->skip = arcn->sb.st_size;
arcn->ln_name[0] = '\0';
arcn->ln_nlen = 0;
break;
case AREGTYPE:
case REGTYPE:
case DIRTYPE: /* see below */

View File

@ -1,4 +1,4 @@
/* $NetBSD: tar.h,v 1.3 1995/03/21 09:07:51 cgd Exp $ */
/* $NetBSD: tar.h,v 1.4 1999/10/22 10:43:12 mrg Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -64,6 +64,12 @@
#define FIFOTYPE '6' /* FIFO */
#define CONTTYPE '7' /* high perf file */
/*
* GNU tar compatibility;
*/
#define LONGLINKTYPE 'K' /* Long Symlink */
#define LONGNAMETYPE 'L' /* Long File */
/*
* Mode field encoding of the different file types - values in octal
*/