diff options
Diffstat (limited to 'bin/pax/file_subs.c')
-rw-r--r-- | bin/pax/file_subs.c | 36 |
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) { |