support ././@LongLink extraction, as created by GNU tar.
This commit is contained in:
parent
222397ee58
commit
78e294d1bc
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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 *));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user