diff options
-rw-r--r-- | bin/pax/file_subs.c | 70 | ||||
-rw-r--r-- | bin/pax/tar.1 | 10 |
2 files changed, 56 insertions, 24 deletions
diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c index 670a2fdb309..5288e390c2a 100644 --- a/bin/pax/file_subs.c +++ b/bin/pax/file_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file_subs.c,v 1.14 2001/05/16 03:04:56 mickey Exp $ */ +/* $OpenBSD: file_subs.c,v 1.15 2001/10/25 16:59:03 niklas Exp $ */ /* $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $ */ /*- @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93"; #else -static char rcsid[] = "$OpenBSD: file_subs.c,v 1.14 2001/05/16 03:04:56 mickey Exp $"; +static char rcsid[] = "$OpenBSD: file_subs.c,v 1.15 2001/10/25 16:59:03 niklas Exp $"; #endif #endif /* not lint */ @@ -400,6 +400,9 @@ node_creat(arcn) register int pass = 0; mode_t file_mode; struct stat sb; + char target[MAXPATHLEN]; + char *nm = arcn->name; + int len; /* * create node based on type, if that fails try to unlink the node and @@ -412,20 +415,43 @@ node_creat(arcn) for (;;) { switch(arcn->type) { case PAX_DIR: - res = mkdir(arcn->name, file_mode); + /* + * If -h (or -L) was given in tar-mode, follow the + * potential symlink chain before trying to create the + * directory. + */ + if (strcmp(NM_TAR, argv0) == 0 && Lflag) { + while (lstat(nm, &sb) == 0 && + S_ISLNK(sb.st_mode)) { + len = readlink(nm, target, + sizeof target - 1); + if (len == -1) { + syswarn(0, errno, + "cannot follow symlink %s in chain for %s", + nm, arcn->name); + res = -1; + goto badlink; + } + target[len] = '\0'; + nm = target; + } + } + res = mkdir(nm, file_mode); + +badlink: if (ign) res = 0; break; case PAX_CHR: file_mode |= S_IFCHR; - res = mknod(arcn->name, file_mode, arcn->sb.st_rdev); + res = mknod(nm, file_mode, arcn->sb.st_rdev); break; case PAX_BLK: file_mode |= S_IFBLK; - res = mknod(arcn->name, file_mode, arcn->sb.st_rdev); + res = mknod(nm, file_mode, arcn->sb.st_rdev); break; case PAX_FIF: - res = mkfifo(arcn->name, file_mode); + res = mkfifo(nm, file_mode); break; case PAX_SCK: /* @@ -433,10 +459,10 @@ node_creat(arcn) */ paxwarn(0, "%s skipped. Sockets cannot be copied or extracted", - arcn->name); + nm); return(-1); case PAX_SLK: - res = symlink(arcn->ln_name, arcn->name); + res = symlink(arcn->ln_name, nm); break; case PAX_CTG: case PAX_HLK: @@ -447,7 +473,7 @@ node_creat(arcn) * we should never get here */ paxwarn(0, "%s has an unknown file type, skipping", - arcn->name); + nm); return(-1); } @@ -463,14 +489,14 @@ node_creat(arcn) * we failed to make the node */ oerrno = errno; - if ((ign = unlnk_exist(arcn->name, arcn->type)) < 0) + if ((ign = unlnk_exist(nm, arcn->type)) < 0) return(-1); if (++pass <= 1) continue; - if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) { - syswarn(1, oerrno, "Could not create: %s", arcn->name); + if (nodirs || chk_path(nm,arcn->sb.st_uid,arcn->sb.st_gid) < 0) { + syswarn(1, oerrno, "Could not create: %s", nm); return(-1); } } @@ -480,8 +506,8 @@ node_creat(arcn) */ if (pids) res = ((arcn->type == PAX_SLK) ? - set_lids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid) : - set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid)); + set_lids(nm, arcn->sb.st_uid, arcn->sb.st_gid) : + set_ids(nm, arcn->sb.st_uid, arcn->sb.st_gid)); else res = 0; @@ -499,7 +525,7 @@ node_creat(arcn) if (!pmode || res) arcn->sb.st_mode &= ~(SETBITS); if (pmode) - set_pmode(arcn->name, arcn->sb.st_mode); + set_pmode(nm, arcn->sb.st_mode); if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) { /* @@ -511,11 +537,11 @@ node_creat(arcn) * and modes will be fixed after the entire archive is read and * before pax exits. */ - if (access(arcn->name, R_OK | W_OK | X_OK) < 0) { - if (lstat(arcn->name, &sb) < 0) { + if (access(nm, R_OK | W_OK | X_OK) < 0) { + if (lstat(nm, &sb) < 0) { syswarn(0, errno,"Could not access %s (stat)", arcn->name); - set_pmode(arcn->name,file_mode | S_IRWXU); + set_pmode(nm,file_mode | S_IRWXU); } else { /* * We have to add rights to the dir, so we make @@ -523,7 +549,7 @@ node_creat(arcn) * restored AS CREATED and not as stored if * pmode is not set. */ - set_pmode(arcn->name, + set_pmode(nm, ((sb.st_mode & FILEBITS) | S_IRWXU)); if (!pmode) arcn->sb.st_mode = sb.st_mode; @@ -533,13 +559,13 @@ node_creat(arcn) * we have to force the mode to what was set here, * since we changed it from the default as created. */ - add_dir(arcn->name, arcn->nlen, &(arcn->sb), 1); + add_dir(nm, strlen(nm), &(arcn->sb), 1); } else if (pmode || patime || pmtime) - add_dir(arcn->name, arcn->nlen, &(arcn->sb), 0); + add_dir(nm, strlen(nm), &(arcn->sb), 0); } if (patime || pmtime) - set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0); + set_ftime(nm, arcn->sb.st_mtime, arcn->sb.st_atime, 0); return(0); } diff --git a/bin/pax/tar.1 b/bin/pax/tar.1 index e5c45997cbc..f81b49e4ce7 100644 --- a/bin/pax/tar.1 +++ b/bin/pax/tar.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tar.1,v 1.34 2001/05/11 20:02:16 mickey Exp $ +.\" $OpenBSD: tar.1,v 1.35 2001/10/25 16:59:03 niklas Exp $ .\" .\" Copyright (c) 1996 SigmaSoft, Th. Lockert .\" All rights reserved. @@ -28,7 +28,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: tar.1,v 1.34 2001/05/11 20:02:16 mickey Exp $ +.\" $OpenBSD: tar.1,v 1.35 2001/10/25 16:59:03 niklas Exp $ .\" .Dd February 7, 2001 .Dt TAR 1 @@ -108,6 +108,9 @@ Defaults to .It Fl h Follow symbolic links as if they were normal files or directories. +In extract mode this means that a directory entry in the archive +will not overwrite an existing symbolic link, but rather what the +link ultimately points to. .It Fl m Do not preserve modification time. .It Fl O @@ -202,6 +205,9 @@ from the directory. Follow symlinks given on command line only. .It Fl L Follow all symlinks. +In extract mode this means that a directory entry in the archive +will not overwrite an existing symbolic link, but rather what the +link ultimately points to. .It Fl P Do not strip leading slashes .Pq Sq / |