PR/36275: john at iastate dot edu: tar -s modifies symlink targets

- This is explained in a comment in pat_rep.c inside mod_name(). I did not
  want to change the default behavior, so I added another modifier "s" which
  when set, the pattern will not modify the symlink destination.
- While here I fixed another bug that was introduced before by the fix in
  PR/35257 where the renaming was happening twice since we called rep_name
  twice.
- Finally if we are renaming hard of soft-link targets print the renames for
  those too.
This commit is contained in:
christos 2007-05-04 21:19:36 +00:00
parent a56ad6a493
commit 206f418235
5 changed files with 51 additions and 29 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ar_subs.c,v 1.53 2007/04/23 18:40:22 christos Exp $ */
/* $NetBSD: ar_subs.c,v 1.54 2007/05/04 21:19:36 christos 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.53 2007/04/23 18:40:22 christos Exp $");
__RCSID("$NetBSD: ar_subs.c,v 1.54 2007/05/04 21:19:36 christos Exp $");
#endif
#endif /* not lint */
@ -60,6 +60,7 @@ __RCSID("$NetBSD: ar_subs.c,v 1.53 2007/04/23 18:40:22 christos Exp $");
#include <unistd.h>
#include <stdlib.h>
#include "pax.h"
#include "pat_rep.h"
#include "extern.h"
static int path_check(ARCHD *, int);
@ -244,7 +245,7 @@ list(void)
* modify the name as requested by the user if name
* survives modification, do a listing of the file
*/
if ((res = mod_name(arcn)) < 0)
if ((res = mod_name(arcn, RENM)) < 0)
break;
if (res == 0) {
if (arcn->name[0] == '/' && !check_Aflag()) {
@ -391,7 +392,7 @@ extract(void)
/*
* this archive member is now been selected. modify the name.
*/
if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0))
if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn, RENM)) < 0))
break;
if (res > 0) {
/*
@ -580,7 +581,13 @@ wr_archive(ARCHD *arcn, int is_app)
*/
if (sel_chk(arcn) != 0)
continue;
if ((res = mod_name(arcn)) < 0)
/*
* Here we handle the exclusion -X gnu style patterns which
* are implemented like a pattern list. We don't modify the
* name as this will be done below again, and we don't want
* to double modify it.
*/
if ((res = mod_name(arcn, 0)) < 0)
break;
if (res == 1)
continue;
@ -623,7 +630,7 @@ wr_archive(ARCHD *arcn, int is_app)
/*
* Now modify the name as requested by the user
*/
if ((res = mod_name(arcn)) < 0) {
if ((res = mod_name(arcn, RENM)) < 0) {
/*
* name modification says to skip this file, close the
* file and purge link table entry
@ -1035,7 +1042,7 @@ copy(void)
* user; set the final destination.
*/
ftree_sel(arcn);
if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0))
if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn, RENM)) < 0))
break;
if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) {
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.52 2007/04/23 18:40:22 christos Exp $ */
/* $NetBSD: extern.h,v 1.53 2007/05/04 21:19:36 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -220,7 +220,7 @@ int pat_add(char *, char *);
void pat_chk(void);
int pat_sel(ARCHD *);
int pat_match(ARCHD *);
int mod_name(ARCHD *);
int mod_name(ARCHD *, int);
int set_dest(ARCHD *, char *, int);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: pat_rep.c,v 1.26 2007/04/29 20:23:34 msaitoh Exp $ */
/* $NetBSD: pat_rep.c,v 1.27 2007/05/04 21:19:36 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94";
#else
__RCSID("$NetBSD: pat_rep.c,v 1.26 2007/04/29 20:23:34 msaitoh Exp $");
__RCSID("$NetBSD: pat_rep.c,v 1.27 2007/05/04 21:19:36 christos Exp $");
#endif
#endif /* not lint */
@ -55,11 +55,6 @@ __RCSID("$NetBSD: pat_rep.c,v 1.26 2007/04/29 20:23:34 msaitoh Exp $");
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef NET2_REGEX
#include <regexp.h>
#else
#include <regex.h>
#endif
#include "pax.h"
#include "pat_rep.h"
#include "extern.h"
@ -220,6 +215,10 @@ rep_add(char *str)
case 'P':
rep->flgs |= PRNT;
break;
case 's':
case 'S':
rep->flgs |= SYML;
break;
default:
#ifdef NET2_REGEX
(void)free((char *)rep->rcmp);
@ -650,7 +649,7 @@ range_match(char *pattern, int test)
*/
int
mod_name(ARCHD *arcn)
mod_name(ARCHD *arcn, int flags)
{
int res = 0;
@ -689,18 +688,20 @@ mod_name(ARCHD *arcn)
* call an oracle here. :)
*/
if (rephead != NULL) {
flags |= (flags & RENM) ? PRNT : 0;
/*
* we have replacement strings, modify the name and the link
* name if any.
*/
if ((res = rep_name(arcn->name, sizeof(arcn->name),
&(arcn->nlen), 1)) != 0)
&(arcn->nlen), flags)) != 0)
return res;
if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
(arcn->type == PAX_HRG)) &&
((res = rep_name(arcn->ln_name, sizeof(arcn->ln_name),
&(arcn->ln_nlen), 0)) != 0))
((res = rep_name(arcn->ln_name,
sizeof(arcn->ln_name), &(arcn->ln_nlen),
flags | (arcn->type == PAX_SLK ? SYML : 0))) != 0))
return res;
}
@ -917,7 +918,7 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
*/
static int
rep_name(char *name, size_t namelen, int *nlen, int prnt)
rep_name(char *name, size_t namelen, int *nlen, int flags)
{
REPLACE *pt;
char *inpt;
@ -951,6 +952,8 @@ rep_name(char *name, size_t namelen, int *nlen, int prnt)
*/
while (pt != NULL) {
do {
if ((flags & SYML) && (pt->flgs & SYML))
continue;
/*
* check for a successful substitution, if not go to
* the next pattern, or cleanup if we were global
@ -994,7 +997,7 @@ rep_name(char *name, size_t namelen, int *nlen, int prnt)
resub(&(pt->rcmp),pm,pt->nstr,inpt, outpt,endpt)
#endif
) < 0) {
if (prnt)
if (flags & PRNT)
tty_warn(1, "Replacement name error %s",
name);
return 1;
@ -1045,7 +1048,7 @@ rep_name(char *name, size_t namelen, int *nlen, int prnt)
*outpt = '\0';
if ((outpt == endpt) && (*inpt != '\0')) {
if (prnt)
if (flags & PRNT)
tty_warn(1,"Replacement name too long %s >> %s",
name, nname);
return 1;
@ -1054,7 +1057,7 @@ rep_name(char *name, size_t namelen, int *nlen, int prnt)
/*
* inform the user of the result if wanted
*/
if (prnt && (pt->flgs & PRNT)) {
if ((flags & PRNT) && (pt->flgs & PRNT)) {
if (*nname == '\0')
(void)fprintf(stderr,"%s >> <empty string>\n",
name);
@ -1068,7 +1071,8 @@ rep_name(char *name, size_t namelen, int *nlen, int prnt)
*/
if (*nname == '\0')
return 1;
*nlen = strlcpy(name, nname, namelen);
if (flags & RENM)
*nlen = strlcpy(name, nname, namelen);
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pat_rep.h,v 1.5 2003/10/13 07:41:22 agc Exp $ */
/* $NetBSD: pat_rep.h,v 1.6 2007/05/04 21:19:36 christos Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@ -35,6 +35,11 @@
* @(#)pat_rep.h 8.1 (Berkeley) 5/31/93
*/
#ifdef NET2_REGEX
#include <regexp.h>
#else
#include <regex.h>
#endif
/*
* data structure for storing user supplied replacement strings (-s)
*/
@ -48,5 +53,7 @@ typedef struct replace {
int flgs; /* print conversions? global in operation? */
#define PRNT 0x1
#define GLOB 0x2
#define RENM 0x4
#define SYML 0x8
struct replace *fow; /* pointer to next pattern */
} REPLACE;

View File

@ -1,4 +1,4 @@
.\" $NetBSD: tar.1,v 1.24 2007/04/23 18:41:11 christos Exp $
.\" $NetBSD: tar.1,v 1.25 2007/05/04 21:19:37 christos Exp $
.\"
.\" Copyright (c) 1996 SigmaSoft, Th. Lockert
.\" All rights reserved.
@ -25,7 +25,7 @@
.\"
.\" OpenBSD: tar.1,v 1.28 2000/11/09 23:58:56 aaron Exp
.\"
.Dd April 23, 2007
.Dd May 4, 2007
.Dt TAR 1
.Os
.Sh NAME
@ -161,7 +161,7 @@ using the syntax of the
.Xr ed 1
utility regular expressions.
The format of these regular expressions are:
.Dl /old/new/[gp]
.Dl /old/new/[gps]
As in
.Xr ed 1 ,
.Cm old
@ -196,6 +196,10 @@ in the following format:
.Dl \*[Lt]original pathname\*[Gt] \*[Gt]\*[Gt] \*[Lt]new pathname\*[Gt]
File or archive member names that substitute to the empty string
are not selected and will be skipped.
The substitutions are applied by default to the destination hard and symbolic
links. The optional trailing
.Cm s
prevents the substitutions from being performed on symbolic link destinations.
.It Fl v
Verbose operation mode.
.It Fl w , -interactive , -confirmation