summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>2001-10-25 16:59:04 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>2001-10-25 16:59:04 +0000
commit18c63dec1c4a84e38d4d642f7150d1a4dc3768e8 (patch)
tree16d3e8d8cf988412b4a4a070990644098ffb7494
parentbb1dad844e3f323cc1fd72c6cda30c387916153e (diff)
Make -h and -L follow symlinks on extraction of directories.
This means that existing symbolic links won't get overwritten with a directory, but instead the directory is created/updated with the privs from the archive at the end of the symlink chain. Great for unpacking OpenBSD release tarballs, where you have linked away stuff due to lack of space on a certain partition etc.
-rw-r--r--bin/pax/file_subs.c70
-rw-r--r--bin/pax/tar.110
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 /