summaryrefslogtreecommitdiff
path: root/bin/pax/file_subs.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/pax/file_subs.c')
-rw-r--r--bin/pax/file_subs.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c
index ca546c080a6..2c5475b963c 100644
--- a/bin/pax/file_subs.c
+++ b/bin/pax/file_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file_subs.c,v 1.41 2015/02/11 23:14:46 guenther Exp $ */
+/* $OpenBSD: file_subs.c,v 1.42 2015/02/12 23:44:57 guenther Exp $ */
/* $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $ */
/*-
@@ -166,6 +166,7 @@ int
lnk_creat(ARCHD *arcn)
{
struct stat sb;
+ int res;
/*
* we may be running as root, so we have to be sure that link target
@@ -183,7 +184,18 @@ lnk_creat(ARCHD *arcn)
return(-1);
}
- return(mk_link(arcn->ln_name, &sb, arcn->name, 0));
+ res = mk_link(arcn->ln_name, &sb, arcn->name, 0);
+ if (res == 0) {
+ /* check for a hardlink to a placeholder symlink */
+ res = sltab_add_link(arcn->name, &sb);
+
+ if (res < 0) {
+ /* arrgh, it failed, clean up */
+ unlink(arcn->name);
+ }
+ }
+
+ return (res);
}
/*
@@ -340,7 +352,7 @@ node_creat(ARCHD *arcn)
struct stat sb;
char target[PATH_MAX];
char *nm = arcn->name;
- int len;
+ int len, defer_pmode = 0;
/*
* create node based on type, if that fails try to unlink the node and
@@ -400,7 +412,21 @@ badlink:
nm);
return(-1);
case PAX_SLK:
- res = symlink(arcn->ln_name, nm);
+ if (arcn->ln_name[0] != '/' &&
+ !has_dotdot(arcn->ln_name))
+ res = symlink(arcn->ln_name, nm);
+ else {
+ /*
+ * absolute symlinks and symlinks with ".."
+ * have to be deferred to prevent the archive
+ * from bootstrapping itself to outside the
+ * working directory.
+ */
+ res = sltab_add_sym(nm, arcn->ln_name,
+ arcn->sb.st_mode);
+ if (res == 0)
+ defer_pmode = 1;
+ }
break;
case PAX_CTG:
case PAX_HLK:
@@ -454,7 +480,7 @@ badlink:
*/
if (!pmode || res)
arcn->sb.st_mode &= ~(SETBITS);
- if (pmode)
+ if (pmode && !defer_pmode)
set_pmode(nm, arcn->sb.st_mode);
if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) {