summaryrefslogtreecommitdiff
path: root/bin/pax
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2015-02-21 22:48:24 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2015-02-21 22:48:24 +0000
commit7eb32e92a3df5f0bcefdb58e386414c1e7d3e6da (patch)
treefae8ecb2f40763278a08a7eeaa738150b380eea5 /bin/pax
parent0d78e3742c523340ed11e8491851ca6e38258bc5 (diff)
Recent changes haven't been completely stable, so revert for the 5.7 release
requested by deraadt@
Diffstat (limited to 'bin/pax')
-rw-r--r--bin/pax/ar_subs.c8
-rw-r--r--bin/pax/extern.h18
-rw-r--r--bin/pax/file_subs.c153
-rw-r--r--bin/pax/ftree.c10
-rw-r--r--bin/pax/pat_rep.c45
-rw-r--r--bin/pax/pax.c3
-rw-r--r--bin/pax/pax.h20
-rw-r--r--bin/pax/tables.c438
-rw-r--r--bin/pax/tables.h15
-rw-r--r--bin/pax/tar.c117
10 files changed, 127 insertions, 700 deletions
diff --git a/bin/pax/ar_subs.c b/bin/pax/ar_subs.c
index 6c2a9c8abca..4330abf0b05 100644
--- a/bin/pax/ar_subs.c
+++ b/bin/pax/ar_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar_subs.c,v 1.40 2015/02/12 23:44:57 guenther Exp $ */
+/* $OpenBSD: ar_subs.c,v 1.41 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $ */
/*-
@@ -165,8 +165,6 @@ extract(void)
int fd;
time_t now;
- sltab_start();
-
arcn = &archd;
/*
* figure out archive type; pass any format specific options to the
@@ -362,7 +360,6 @@ popd:
(void)(*frmt->end_rd)();
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
ar_close(0);
- sltab_process(0);
proc_dir(0);
pat_chk();
}
@@ -761,8 +758,6 @@ copy(void)
ARCHD archd;
char dirbuf[PAXPATHLEN+1];
- sltab_start();
-
arcn = &archd;
/*
* set up the destination dir path and make sure it is a directory. We
@@ -974,7 +969,6 @@ copy(void)
*/
(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
ar_close(0);
- sltab_process(0);
proc_dir(0);
ftree_chk();
}
diff --git a/bin/pax/extern.h b/bin/pax/extern.h
index 3b3400b26d1..2bdb6325045 100644
--- a/bin/pax/extern.h
+++ b/bin/pax/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.48 2015/02/15 22:18:29 millert Exp $ */
+/* $OpenBSD: extern.h,v 1.49 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $ */
/*-
@@ -147,8 +147,6 @@ int set_ids(char *, uid_t, gid_t);
int fset_ids(char *, int, uid_t, gid_t);
void set_pmode(char *, mode_t);
void fset_pmode(char *, int, mode_t);
-int set_attr(const struct file_times *, int _force_times, mode_t, int _do_mode,
- int _in_sig);
int file_write(int, char *, int, int *, int *, int, char *);
void file_flush(int, char *, int);
void rdfile_close(ARCHD *, int *);
@@ -202,7 +200,6 @@ int pat_sel(ARCHD *);
int pat_match(ARCHD *);
int mod_name(ARCHD *);
int set_dest(ARCHD *, char *, int);
-int has_dotdot(const char *);
/*
* pax.c
@@ -264,29 +261,18 @@ void purg_lnk(ARCHD *);
void lnk_end(void);
int ftime_start(void);
int chk_ftime(ARCHD *);
-int sltab_start(void);
-int sltab_add_sym(const char *_path, const char *_value, mode_t _mode);
-int sltab_add_link(const char *, const struct stat *);
-void sltab_process(int _in_sig);
int name_start(void);
int add_name(char *, int, char *);
void sub_name(char *, int *, size_t);
-#ifndef NOCPIO
int dev_start(void);
int add_dev(ARCHD *);
int map_dev(ARCHD *, u_long, u_long);
-#else
-# define dev_start() 0
-# define add_dev(x) 0
-# define map_dev(x,y,z) 0
-#endif /* NOCPIO */
int atdir_start(void);
void atdir_end(void);
void add_atdir(char *, dev_t, ino_t, time_t, time_t);
-int do_atdir(const char *, dev_t, ino_t);
+int get_atdir(dev_t, ino_t, time_t *, time_t *);
int dir_start(void);
void add_dir(char *, struct stat *, int);
-void delete_dir(dev_t, ino_t);
void proc_dir(int _in_sig);
u_int st_hash(const char *, int, int);
diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c
index b71575bdfd6..ca09acabab8 100644
--- a/bin/pax/file_subs.c
+++ b/bin/pax/file_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file_subs.c,v 1.43 2015/02/15 22:18:29 millert Exp $ */
+/* $OpenBSD: file_subs.c,v 1.44 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $ */
/*-
@@ -56,6 +56,10 @@ mk_link(char *, struct stat *, char *, int);
* and setting access modes, uid/gid and times of files
*/
+#define FILEBITS (S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+#define SETBITS (S_ISUID | S_ISGID)
+#define ABITS (FILEBITS | SETBITS)
+
/*
* file_creat()
* Create and open a file.
@@ -166,7 +170,6 @@ 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
@@ -184,18 +187,7 @@ lnk_creat(ARCHD *arcn)
return(-1);
}
- 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);
+ return(mk_link(arcn->ln_name, &sb, arcn->name, 0));
}
/*
@@ -299,7 +291,6 @@ mk_link(char *to, struct stat *to_sb, char *from, int ign)
syswarn(1, errno, "Unable to remove %s", from);
return(-1);
}
- delete_dir(sb.st_dev, sb.st_ino);
} else if (unlink(from) < 0) {
if (!ign) {
syswarn(1, errno, "Unable to remove %s", from);
@@ -353,7 +344,7 @@ node_creat(ARCHD *arcn)
struct stat sb;
char target[PATH_MAX];
char *nm = arcn->name;
- int len, defer_pmode = 0;
+ int len;
/*
* create node based on type, if that fails try to unlink the node and
@@ -413,21 +404,7 @@ badlink:
nm);
return(-1);
case PAX_SLK:
- 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;
- }
+ res = symlink(arcn->ln_name, nm);
break;
case PAX_CTG:
case PAX_HLK:
@@ -481,7 +458,7 @@ badlink:
*/
if (!pmode || res)
arcn->sb.st_mode &= ~(SETBITS);
- if (pmode && !defer_pmode)
+ if (pmode)
set_pmode(nm, arcn->sb.st_mode);
if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) {
@@ -492,36 +469,33 @@ badlink:
* rights. This allows nodes in the archive that are children
* of this directory to be extracted without failure. Both time
* and modes will be fixed after the entire archive is read and
- * before pax exits. To do that safely, we want the dev+ino
- * of the directory we created.
+ * before pax exits.
*/
- if (lstat(nm, &sb) < 0) {
- syswarn(0, errno,"Could not access %s (stat)", nm);
- } else if (access(nm, R_OK | W_OK | X_OK) < 0) {
- /*
- * We have to add rights to the dir, so we make
- * sure to restore the mode. The mode must be
- * restored AS CREATED and not as stored if
- * pmode is not set.
- */
- set_pmode(nm,
- ((sb.st_mode & FILEBITS) | S_IRWXU));
- if (!pmode)
- arcn->sb.st_mode = sb.st_mode;
+ 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(nm,file_mode | S_IRWXU);
+ } else {
+ /*
+ * We have to add rights to the dir, so we make
+ * sure to restore the mode. The mode must be
+ * restored AS CREATED and not as stored if
+ * pmode is not set.
+ */
+ set_pmode(nm,
+ ((sb.st_mode & FILEBITS) | S_IRWXU));
+ if (!pmode)
+ arcn->sb.st_mode = sb.st_mode;
+ }
/*
- * we have to force the mode to what was set
- * here, since we changed it from the default
- * as created.
+ * we have to force the mode to what was set here,
+ * since we changed it from the default as created.
*/
- arcn->sb.st_dev = sb.st_dev;
- arcn->sb.st_ino = sb.st_ino;
add_dir(nm, &(arcn->sb), 1);
- } else if (pmode || patime || pmtime) {
- arcn->sb.st_dev = sb.st_dev;
- arcn->sb.st_ino = sb.st_ino;
+ } else if (pmode || patime || pmtime)
add_dir(nm, &(arcn->sb), 0);
- }
}
if (patime || pmtime)
@@ -565,7 +539,6 @@ unlnk_exist(char *name, int type)
syswarn(1,errno,"Unable to remove directory %s", name);
return(-1);
}
- delete_dir(sb.st_dev, sb.st_ino);
return(0);
}
@@ -793,60 +766,6 @@ fset_pmode(char *fnm, int fd, mode_t mode)
}
/*
- * set_attr()
- * Given a DIRDATA, restore the mode and times as indicated, but
- * only after verifying that it's the directory that we wanted.
- */
-int
-set_attr(const struct file_times *ft, int force_times, mode_t mode,
- int do_mode, int in_sig)
-{
- struct stat sb;
- int fd, r;
-
- if (!do_mode && !force_times && !patime && !pmtime)
- return (0);
-
- /*
- * We could legitimately go through a symlink here,
- * so do *not* use O_NOFOLLOW. The dev+ino check will
- * protect us from evil.
- */
- fd = open(ft->ft_name, O_RDONLY | O_DIRECTORY);
- if (fd == -1) {
- if (!in_sig)
- syswarn(1, errno, "Unable to restore mode and times"
- " for directory: %s", ft->ft_name);
- return (-1);
- }
-
- if (fstat(fd, &sb) == -1) {
- if (!in_sig)
- syswarn(1, errno, "Unable to stat directory: %s",
- ft->ft_name);
- r = -1;
- } else if (ft->ft_ino != sb.st_ino || ft->ft_dev != sb.st_dev) {
- if (!in_sig)
- paxwarn(1, "Directory vanished before restoring"
- " mode and times: %s", ft->ft_name);
- r = -1;
- } else {
- /* Whew, it's a match! Is there anything to change? */
- if (do_mode && (mode & ABITS) != (sb.st_mode & ABITS))
- fset_pmode(ft->ft_name, fd, mode);
- if (((force_times || patime) && ft->ft_atime != sb.st_atime) ||
- ((force_times || pmtime) && ft->ft_mtime != sb.st_mtime))
- fset_ftime(ft->ft_name, fd, ft->ft_mtime,
- ft->ft_atime, force_times);
- r = 0;
- }
- close(fd);
-
- return (r);
-}
-
-
-/*
* file_write()
* Write/copy a file (during copy or archive extract). This routine knows
* how to copy files with lseek holes in it. (Which are read as file
@@ -1038,15 +957,15 @@ rdfile_close(ARCHD *arcn, int *fd)
if (*fd < 0)
return;
+ (void)close(*fd);
+ *fd = -1;
+ if (!tflag)
+ return;
+
/*
* user wants last access time reset
*/
- if (tflag)
- fset_ftime(arcn->org_name, *fd, arcn->sb.st_mtime,
- arcn->sb.st_atime, 1);
-
- (void)close(*fd);
- *fd = -1;
+ set_ftime(arcn->org_name, arcn->sb.st_mtime, arcn->sb.st_atime, 1);
}
/*
diff --git a/bin/pax/ftree.c b/bin/pax/ftree.c
index cab8723bef0..00f811e358d 100644
--- a/bin/pax/ftree.c
+++ b/bin/pax/ftree.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ftree.c,v 1.35 2015/02/11 23:14:46 guenther Exp $ */
+/* $OpenBSD: ftree.c,v 1.36 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: ftree.c,v 1.4 1995/03/21 09:07:21 cgd Exp $ */
/*-
@@ -337,6 +337,8 @@ int
next_file(ARCHD *arcn)
{
int cnt;
+ time_t atime;
+ time_t mtime;
/*
* ftree_sel() might have set the ftree_skip flag if the user has the
@@ -391,10 +393,10 @@ next_file(ARCHD *arcn)
* remember to force the time (this is -t on a read
* directory, not a created directory).
*/
- if (!tflag)
+ if (!tflag || (get_atdir(ftent->fts_statp->st_dev,
+ ftent->fts_statp->st_ino, &mtime, &atime) < 0))
continue;
- do_atdir(ftent->fts_path, ftent->fts_statp->st_dev,
- ftent->fts_statp->st_ino);
+ set_ftime(ftent->fts_path, mtime, atime, 1);
continue;
case FTS_DC:
/*
diff --git a/bin/pax/pat_rep.c b/bin/pax/pat_rep.c
index 8094ee3a3e8..55def38fa9c 100644
--- a/bin/pax/pat_rep.c
+++ b/bin/pax/pat_rep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pat_rep.c,v 1.36 2015/02/12 23:44:57 guenther Exp $ */
+/* $OpenBSD: pat_rep.c,v 1.37 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: pat_rep.c,v 1.4 1995/03/21 09:07:33 cgd Exp $ */
/*-
@@ -583,25 +583,6 @@ range_match(char *pattern, int test)
}
/*
- * has_dotdot()
- * Returns true iff the supplied path contains a ".." component.
- */
-
-int
-has_dotdot(const char *path)
-{
- const char *p = path;
-
- while ((p = strstr(p, "..")) != NULL) {
- if ((p == path || p[-1] == '/') &&
- (p[2] == '/' || p[2] == '\0'))
- return (1);
- p += 2;
- }
- return (0);
-}
-
-/*
* mod_name()
* modify a selected file name. first attempt to apply replacement string
* expressions, then apply interactive file rename. We apply replacement
@@ -651,30 +632,6 @@ mod_name(ARCHD *arcn)
paxwarn(0, "Removing leading / from absolute path names in the archive");
}
}
- if (rmleadslash) {
- const char *last = NULL;
- const char *p = arcn->name;
-
- while ((p = strstr(p, "..")) != NULL) {
- if ((p == arcn->name || p[-1] == '/') &&
- (p[2] == '/' || p[2] == '\0'))
- last = p + 2;
- p += 2;
- }
- if (last != NULL) {
- last++;
- paxwarn(1, "Removing leading \"%.*s\"",
- (int)(last - arcn->name), arcn->name);
- arcn->nlen = strlen(last);
- if (arcn->nlen > 0)
- memmove(arcn->name, last, arcn->nlen + 1);
- else {
- arcn->name[0] = '.';
- arcn->name[1] = '\0';
- arcn->nlen = 1;
- }
- }
- }
/*
* IMPORTANT: We have a problem. what do we do with symlinks?
diff --git a/bin/pax/pax.c b/bin/pax/pax.c
index 67a1c47bbd8..8e2bf4c439a 100644
--- a/bin/pax/pax.c
+++ b/bin/pax/pax.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pax.c,v 1.39 2015/02/12 23:44:57 guenther Exp $ */
+/* $OpenBSD: pax.c,v 1.40 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: pax.c,v 1.5 1996/03/26 23:54:20 mrg Exp $ */
/*-
@@ -311,7 +311,6 @@ sig_cleanup(int which_sig)
(void) write(STDERR_FILENO, errbuf, strlen(errbuf));
ar_close(1);
- sltab_process(1);
proc_dir(1);
if (tflag)
atdir_end();
diff --git a/bin/pax/pax.h b/bin/pax/pax.h
index 4ef7dcdfa3e..ef2c78f49f4 100644
--- a/bin/pax/pax.h
+++ b/bin/pax/pax.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pax.h,v 1.23 2015/02/11 23:14:46 guenther Exp $ */
+/* $OpenBSD: pax.h,v 1.24 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: pax.h,v 1.3 1995/03/21 09:07:41 cgd Exp $ */
/*-
@@ -211,20 +211,6 @@ typedef struct {
} FSUB;
/*
- * Time data for a given file. This is usually embedded in a structure
- * indexed by dev+ino, by name, by order in the archive, etc. set_attr()
- * takes one of these and will only change the times or mode if the file
- * at the given name has the indicated dev+ino.
- */
-struct file_times {
- ino_t ft_ino; /* inode number to verify */
- time_t ft_mtime; /* times to set */
- time_t ft_atime;
- char *ft_name; /* name of file to set the times on */
- dev_t ft_dev; /* device number to verify */
-};
-
-/*
* Format Specific Options List
*
* Used to pass format options to the format options handler
@@ -243,10 +229,6 @@ typedef struct oplist {
#define MINOR(x) minor(x)
#define TODEV(x, y) makedev((x), (y))
-#define FILEBITS (S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
-#define SETBITS (S_ISUID | S_ISGID)
-#define ABITS (FILEBITS | SETBITS)
-
/*
* General Defines
*/
diff --git a/bin/pax/tables.c b/bin/pax/tables.c
index 79db2a5e63f..abc0ab4ff8f 100644
--- a/bin/pax/tables.c
+++ b/bin/pax/tables.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tables.c,v 1.43 2015/02/15 22:18:29 millert Exp $ */
+/* $OpenBSD: tables.c,v 1.44 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: tables.c,v 1.4 1995/03/21 09:07:45 cgd Exp $ */
/*-
@@ -37,7 +37,6 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
-#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
@@ -74,6 +73,8 @@ static size_t dirsize; /* size of dirp table */
static size_t dircnt = 0; /* entries in dir time/mode storage */
static int ffd = -1; /* tmp file for file time table name storage */
+static DEVT *chk_dev(dev_t, int);
+
/*
* hard link table routines
*
@@ -462,343 +463,6 @@ chk_ftime(ARCHD *arcn)
}
/*
- * escaping (absolute or w/"..") symlink table routines
- *
- * By default, an archive shouldn't be able extract to outside of the
- * current directory. What should we do if the archive contains a symlink
- * whose value is either absolute or contains ".." components? What we'll
- * do is initially create the path as an empty file (to block attempts to
- * reference _through_ it) and instead record its path and desired
- * final value and mode. Then once all the other archive
- * members are created (but before the pass to set timestamps on
- * directories) we'll process those records, replacing the placeholder with
- * the correct symlink and setting them to the correct mode, owner, group,
- * and timestamps.
- *
- * Note: we also need to handle hardlinks to symlinks (barf) as well as
- * hardlinks whose target is replaced by a later entry in the archive (barf^2).
- *
- * So we track things by dev+ino of the placeholder file, associating with
- * that the value and mode of the final symlink and a list of paths that
- * should all be hardlinks of that. We'll 'store' the symlink's desired
- * timestamps, owner, and group by setting them on the placeholder file.
- *
- * The operations are:
- * a) create an escaping symlink: create the placeholder file and add an entry
- * for the new link
- * b) create a hardlink: do the link. If the target turns out to be a
- * zero-length file whose dev+ino are in the symlink table, then add this
- * path to the list of names for that link
- * c) perform deferred processing: for each entry, check each associated path:
- * if it's a zero-length file with the correct dev+ino then recreate it as
- * the specified symlink or hardlink to the first such
- */
-
-struct slpath {
- char *sp_path;
- struct slpath *sp_next;
-};
-struct slinode {
- ino_t sli_ino;
- char *sli_value;
- struct slpath sli_paths;
- struct slinode *sli_fow; /* hash table chain */
- dev_t sli_dev;
- mode_t sli_mode;
-};
-
-static struct slinode **slitab = NULL;
-
-/*
- * sltab_start()
- * create the hash table
- * Return:
- * 0 if the table and file was created ok, -1 otherwise
- */
-
-int
-sltab_start(void)
-{
-
- if ((slitab = calloc(SL_TAB_SZ, sizeof *slitab)) == NULL) {
- syswarn(1, errno, "symlink table");
- return(-1);
- }
-
- return(0);
-}
-
-/*
- * sltab_add_sym()
- * Create the placeholder and tracking info for an escaping symlink.
- * Return:
- * 0 on success, -1 otherwise
- */
-
-int
-sltab_add_sym(const char *path0, const char *value0, mode_t mode)
-{
- struct stat sb;
- struct slinode *s;
- struct slpath *p;
- char *path, *value;
- u_int indx;
- int fd;
-
- /* create the placeholder */
- fd = open(path0, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0600);
- if (fd == -1)
- return (-1);
- if (fstat(fd, &sb) == -1) {
- unlink(path0);
- close(fd);
- return (-1);
- }
- close(fd);
-
- if (havechd && *path0 != '/') {
- if ((path = realpath(path0, NULL)) == NULL) {
- syswarn(1, errno, "Cannot canonicalize %s", path0);
- unlink(path0);
- return (-1);
- }
- } else if ((path = strdup(path0)) == NULL) {
- syswarn(1, errno, "defered symlink path");
- unlink(path0);
- return (-1);
- }
- if ((value = strdup(value0)) == NULL) {
- syswarn(1, errno, "defered symlink value");
- unlink(path);
- free(path);
- return (-1);
- }
-
- /* now check the hash table for conflicting entry */
- indx = (sb.st_ino ^ sb.st_dev) % SL_TAB_SZ;
- for (s = slitab[indx]; s != NULL; s = s->sli_fow) {
- if (s->sli_ino != sb.st_ino || s->sli_dev != sb.st_dev)
- continue;
-
- /*
- * One of our placeholders got removed behind our back and
- * we've reused the inode. Weird, but clean up the mess.
- */
- free(s->sli_value);
- free(s->sli_paths.sp_path);
- p = s->sli_paths.sp_next;
- while (p != NULL) {
- struct slpath *next_p = p->sp_next;
-
- free(p->sp_path);
- free(p);
- p = next_p;
- }
- goto set_value;
- }
-
- /* Normal case: create a new node */
- if ((s = malloc(sizeof *s)) == NULL) {
- syswarn(1, errno, "defered symlink");
- unlink(path);
- free(path);
- free(value);
- return (-1);
- }
- s->sli_ino = sb.st_ino;
- s->sli_dev = sb.st_dev;
- s->sli_fow = slitab[indx];
- slitab[indx] = s;
-
-set_value:
- s->sli_paths.sp_path = path;
- s->sli_paths.sp_next = NULL;
- s->sli_value = value;
- s->sli_mode = mode;
- return (0);
-}
-
-/*
- * sltab_add_link()
- * A hardlink was created; if it looks like a placeholder, handle the
- * tracking.
- * Return:
- * 0 if things are ok, -1 if something went wrong
- */
-
-int
-sltab_add_link(const char *path, const struct stat *sb)
-{
- struct slinode *s;
- struct slpath *p;
- u_int indx;
-
- if (!S_ISREG(sb->st_mode) || sb->st_size != 0)
- return (1);
-
- /* find the hash table entry for this hardlink */
- indx = (sb->st_ino ^ sb->st_dev) % SL_TAB_SZ;
- for (s = slitab[indx]; s != NULL; s = s->sli_fow) {
- if (s->sli_ino != sb->st_ino || s->sli_dev != sb->st_dev)
- continue;
-
- if ((p = malloc(sizeof *p)) == NULL) {
- syswarn(1, errno, "deferred symlink hardlink");
- return (-1);
- }
- if (havechd && *path != '/') {
- if ((p->sp_path = realpath(path, NULL)) == NULL) {
- syswarn(1, errno, "Cannot canonicalize %s",
- path);
- free(p);
- return (-1);
- }
- } else if ((p->sp_path = strdup(path)) == NULL) {
- syswarn(1, errno, "defered symlink hardlink path");
- free(p);
- return (-1);
- }
-
- /* link it in */
- p->sp_next = s->sli_paths.sp_next;
- s->sli_paths.sp_next = p;
- return (0);
- }
-
- /* not found */
- return (1);
-}
-
-
-static int
-sltab_process_one(struct slinode *s, struct slpath *p, const char *first,
- int in_sig)
-{
- struct stat sb;
- char *path = p->sp_path;
- mode_t mode;
- int err;
-
- /*
- * is it the expected placeholder? This can fail legimately
- * if the archive overwrote the link with another, later entry,
- * so don't warn.
- */
- if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode) || sb.st_size != 0 ||
- sb.st_ino != s->sli_ino || sb.st_dev != s->sli_dev)
- return (0);
-
- if (unlink(path) && errno != ENOENT) {
- if (!in_sig)
- syswarn(1, errno, "deferred symlink removal");
- return (0);
- }
-
- err = 0;
- if (first != NULL) {
- /* add another hardlink to the existing symlink */
- if (linkat(AT_FDCWD, first, AT_FDCWD, path, 0) == 0)
- return (0);
-
- /*
- * Couldn't hardlink the symlink for some reason, so we'll
- * try creating it as its own symlink, but save the error
- * for reporting if that fails.
- */
- err = errno;
- }
-
- if (symlink(s->sli_value, path)) {
- if (!in_sig) {
- const char *qualifier = "";
- if (err)
- qualifier = " hardlink";
- else
- err = errno;
-
- syswarn(1, err, "deferred symlink%s: %s",
- qualifier, path);
- }
- return (0);
- }
-
- /* success, so set the id, mode, and times */
- mode = s->sli_mode;
- if (pids) {
- /* if can't set the ids, force the set[ug]id bits off */
- if (set_ids(path, sb.st_uid, sb.st_gid))
- mode &= ~(SETBITS);
- }
-
- if (pmode)
- set_pmode(path, mode);
-
- if (patime || pmtime)
- set_ftime(path, sb.st_mtime, sb.st_atime, 0);
-
- /*
- * If we tried to link to first but failed, then this new symlink
- * might be a better one to try in the future. Guess from the errno.
- */
- if (err == 0 || err == ENOENT || err == EMLINK || err == EOPNOTSUPP)
- return (1);
- return (0);
-}
-
-/*
- * sltab_process()
- * Do all the delayed process for escape symlinks
- */
-
-void
-sltab_process(int in_sig)
-{
- struct slinode *s;
- struct slpath *p;
- char *first;
- u_int indx;
-
- if (slitab == NULL)
- return;
-
- /* walk across the entire hash table */
- for (indx = 0; indx < SL_TAB_SZ; indx++) {
- while ((s = slitab[indx]) != NULL) {
- /* pop this entry */
- slitab[indx] = s->sli_fow;
-
- first = NULL;
- p = &s->sli_paths;
- while (1) {
- struct slpath *next_p;
-
- if (sltab_process_one(s, p, first, in_sig)) {
- if (!in_sig)
- free(first);
- first = p->sp_path;
- } else if (!in_sig)
- free(p->sp_path);
-
- if ((next_p = p->sp_next) == NULL)
- break;
- *p = *next_p;
- if (!in_sig)
- free(next_p);
- }
- if (!in_sig) {
- free(first);
- free(s->sli_value);
- free(s);
- }
- }
- }
- if (!in_sig)
- free(slitab);
- slitab = NULL;
-}
-
-
-/*
* Interactive rename table routines
*
* The interactive rename table keeps track of the new names that the user
@@ -943,7 +607,6 @@ sub_name(char *oname, int *onamelen, size_t onamesize)
*/
}
-#ifndef NOCPIO
/*
* device/inode mapping table routines
* (used with formats that store device and inodes fields)
@@ -984,8 +647,6 @@ sub_name(char *oname, int *onamelen, size_t onamesize)
* (for more info see table.h for the data structures involved).
*/
-static DEVT *chk_dev(dev_t, int);
-
/*
* dev_start()
* create the device mapping table
@@ -1211,7 +872,6 @@ map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
paxwarn(0, "Archive may create improper hard links when extracted");
return(0);
}
-#endif /* NOCPIO */
/*
* directory access/mod time reset table routines (for directories READ by pax)
@@ -1278,7 +938,7 @@ atdir_end(void)
* not read by pax. Read time reset is controlled by -t.
*/
for (; pt != NULL; pt = pt->fow)
- set_attr(&pt->ft, 1, 0, 0, 0);
+ set_ftime(pt->name, pt->mtime, pt->atime, 1);
}
}
@@ -1308,7 +968,7 @@ add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
indx = ((unsigned)ino) % A_TAB_SZ;
if ((pt = atab[indx]) != NULL) {
while (pt != NULL) {
- if ((pt->ft.ft_ino == ino) && (pt->ft.ft_dev == dev))
+ if ((pt->ino == ino) && (pt->dev == dev))
break;
pt = pt->fow;
}
@@ -1326,11 +986,11 @@ add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
sigfillset(&allsigs);
sigprocmask(SIG_BLOCK, &allsigs, &savedsigs);
if ((pt = malloc(sizeof *pt)) != NULL) {
- if ((pt->ft.ft_name = strdup(fname)) != NULL) {
- pt->ft.ft_dev = dev;
- pt->ft.ft_ino = ino;
- pt->ft.ft_mtime = mtime;
- pt->ft.ft_atime = atime;
+ if ((pt->name = strdup(fname)) != NULL) {
+ pt->dev = dev;
+ pt->ino = ino;
+ pt->mtime = mtime;
+ pt->atime = atime;
pt->fow = atab[indx];
atab[indx] = pt;
sigprocmask(SIG_SETMASK, &savedsigs, NULL);
@@ -1355,7 +1015,7 @@ add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
*/
int
-do_atdir(const char *name, dev_t dev, ino_t ino)
+get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
{
ATDIR *pt;
ATDIR **ppt;
@@ -1373,7 +1033,7 @@ do_atdir(const char *name, dev_t dev, ino_t ino)
ppt = &(atab[indx]);
while (pt != NULL) {
- if ((pt->ft.ft_ino == ino) && (pt->ft.ft_dev == dev))
+ if ((pt->ino == ino) && (pt->dev == dev))
break;
/*
* no match, go to next one
@@ -1385,19 +1045,19 @@ do_atdir(const char *name, dev_t dev, ino_t ino)
/*
* return if we did not find it.
*/
- if (pt == NULL || pt->ft.ft_name == NULL ||
- strcmp(name, pt->ft.ft_name) == 0)
+ if (pt == NULL)
return(-1);
/*
- * found it. set the times and remove the entry from the table.
+ * found it. return the times and remove the entry from the table.
*/
- set_attr(&pt->ft, 1, 0, 0, 0);
sigfillset(&allsigs);
sigprocmask(SIG_BLOCK, &allsigs, &savedsigs);
*ppt = pt->fow;
sigprocmask(SIG_SETMASK, &savedsigs, NULL);
- free(pt->ft.ft_name);
+ *mtime = pt->mtime;
+ *atime = pt->atime;
+ free(pt->name);
free(pt);
return(0);
}
@@ -1417,8 +1077,12 @@ do_atdir(const char *name, dev_t dev, ino_t ino)
* times and file permissions specified by the archive are stored. After all
* files have been extracted (or copied), these directories have their times
* and file modes reset to the stored values. The directory info is restored in
- * reverse order as entries were added from root to leaf: to restore atime
- * properly, we must go backwards.
+ * reverse order as entries were added to the data file from root to leaf. To
+ * restore atime properly, we must go backwards. The data file consists of
+ * records with two parts, the file name followed by a DIRDATA trailer. The
+ * fixed sized trailer contains the size of the name plus the off_t location in
+ * the file. To restore we work backwards through the file reading the trailer
+ * then the file name.
*/
/*
@@ -1486,16 +1150,14 @@ add_dir(char *name, struct stat *psb, int frc_mode)
sigprocmask(SIG_SETMASK, &savedsigs, NULL);
}
dblk = &dirp[dircnt];
- if ((dblk->ft.ft_name = strdup(name)) == NULL) {
+ if ((dblk->name = strdup(name)) == NULL) {
paxwarn(1, "Unable to store mode and times for created"
" directory: %s", name);
return;
}
- dblk->ft.ft_mtime = psb->st_mtime;
- dblk->ft.ft_atime = psb->st_atime;
- dblk->ft.ft_ino = psb->st_ino;
- dblk->ft.ft_dev = psb->st_dev;
- dblk->mode = psb->st_mode & ABITS;
+ dblk->mode = psb->st_mode & 0xffff;
+ dblk->mtime = psb->st_mtime;
+ dblk->atime = psb->st_atime;
dblk->frc_mode = frc_mode;
sigprocmask(SIG_BLOCK, &allsigs, &savedsigs);
++dircnt;
@@ -1503,35 +1165,6 @@ add_dir(char *name, struct stat *psb, int frc_mode)
}
/*
- * delete_dir()
- * When we rmdir a directory, we may want to make sure we don't
- * later warn about being unable to set its mode and times.
- */
-
-void
-delete_dir(dev_t dev, ino_t ino)
-{
- DIRDATA *dblk;
- char *name;
- size_t i;
-
- if (dirp == NULL)
- return;
- for (i = 0; i < dircnt; i++) {
- dblk = &dirp[i];
-
- if (dblk->ft.ft_name == NULL)
- continue;
- if (dblk->ft.ft_dev == dev && dblk->ft.ft_ino == ino) {
- name = dblk->ft.ft_name;
- dblk->ft.ft_name = NULL;
- free(name);
- break;
- }
- }
-}
-
-/*
* proc_dir(int in_sig)
* process all file modes and times stored for directories CREATED
* by pax. If in_sig is set, we're in a signal handler and can't
@@ -1551,22 +1184,17 @@ proc_dir(int in_sig)
*/
cnt = dircnt;
while (cnt-- > 0) {
- dblk = &dirp[cnt];
- /*
- * If we remove a directory we created, we replace the
- * ft_name with NULL. Ignore those.
- */
- if (dblk->ft.ft_name == NULL)
- continue;
-
/*
* frc_mode set, make sure we set the file modes even if
* the user didn't ask for it (see file_subs.c for more info)
*/
- set_attr(&dblk->ft, 0, dblk->mode, pmode || dblk->frc_mode,
- in_sig);
+ dblk = &dirp[cnt];
+ if (pmode || dblk->frc_mode)
+ set_pmode(dblk->name, dblk->mode);
+ if (patime || pmtime)
+ set_ftime(dblk->name, dblk->mtime, dblk->atime, 0);
if (!in_sig)
- free(dblk->ft.ft_name);
+ free(dblk->name);
}
if (!in_sig)
diff --git a/bin/pax/tables.h b/bin/pax/tables.h
index 45dc40aed60..57fe2528e3c 100644
--- a/bin/pax/tables.h
+++ b/bin/pax/tables.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tables.h,v 1.13 2015/02/12 23:44:57 guenther Exp $ */
+/* $OpenBSD: tables.h,v 1.14 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: tables.h,v 1.3 1995/03/21 09:07:47 cgd Exp $ */
/*-
@@ -50,7 +50,6 @@
#define N_TAB_SZ 541 /* interactive rename hash table */
#define D_TAB_SZ 317 /* unique device mapping table */
#define A_TAB_SZ 317 /* ftree dir access time reset table */
-#define SL_TAB_SZ 317 /* escape symlink tables */
#define MAXKEYLEN 64 /* max number of chars for hash */
#define DIRP_SIZE 64 /* initial size of created dir table */
@@ -144,8 +143,12 @@ typedef struct dlist {
*/
typedef struct atdir {
- struct file_times ft;
+ ino_t ino;
+ time_t mtime; /* access and mod time to reset to */
+ time_t atime;
+ char *name; /* name of directory to reset */
struct atdir *fow;
+ dev_t dev; /* dev and inode for fast lookup */
} ATDIR;
/*
@@ -159,7 +162,9 @@ typedef struct atdir {
*/
typedef struct dirdata {
- struct file_times ft;
- u_int16_t mode; /* file mode to restore */
+ time_t mtime; /* mtime to set */
+ time_t atime; /* atime to set */
+ char *name; /* file name */
+ u_int16_t mode; /* file mode to restore */
u_int16_t frc_mode; /* do we force mode settings? */
} DIRDATA;
diff --git a/bin/pax/tar.c b/bin/pax/tar.c
index 900c906c497..671c61e70c7 100644
--- a/bin/pax/tar.c
+++ b/bin/pax/tar.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tar.c,v 1.54 2015/01/29 19:41:49 guenther Exp $ */
+/* $OpenBSD: tar.c,v 1.55 2015/02/21 22:48:23 guenther Exp $ */
/* $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $ */
/*-
@@ -58,7 +58,7 @@ static char *name_split(char *, int);
static int ul_oct(u_long, char *, int, int);
static int uqd_oct(u_quad_t, char *, int, int);
#ifndef SMALL
-static int rd_xheader(ARCHD *arcn, int, off_t);
+static int rd_xheader(ARCHD *, char *, off_t, char);
#endif
static uid_t uid_nobody;
@@ -734,7 +734,7 @@ ustar_id(char *blk, int size)
int
ustar_rd(ARCHD *arcn, char *buf)
{
- HD_USTAR *hd = (HD_USTAR *)buf;
+ HD_USTAR *hd;
char *dest;
int cnt = 0;
dev_t devmajor;
@@ -746,30 +746,18 @@ ustar_rd(ARCHD *arcn, char *buf)
*/
if (ustar_id(buf, BLKMULT) < 0)
return(-1);
-
-#ifndef SMALL
-reset:
-#endif
memset(arcn, 0, sizeof(*arcn));
arcn->org_name = arcn->name;
arcn->sb.st_nlink = 1;
+ hd = (HD_USTAR *)buf;
#ifndef SMALL
- /* Process Extended headers. */
+ /* Process the Extended header. */
if (hd->typeflag == XHDRTYPE || hd->typeflag == GHDRTYPE) {
- if (rd_xheader(arcn, hd->typeflag == GHDRTYPE,
- (off_t)asc_ul(hd->size, sizeof(hd->size), OCT)) < 0)
+ if (rd_xheader(arcn, buf,
+ (off_t)asc_ul(hd->size, sizeof(hd->size), OCT),
+ hd->typeflag) < 0)
return (-1);
-
- /* Update and check the ustar header. */
- if (rd_wrbuf(buf, BLKMULT) != BLKMULT)
- return (-1);
- if (ustar_id(buf, BLKMULT) < 0)
- return(-1);
-
- /* if the next block is another extension, reset the values */
- if (hd->typeflag == XHDRTYPE || hd->typeflag == GHDRTYPE)
- goto reset;
}
#endif
@@ -1205,84 +1193,51 @@ expandname(char *buf, size_t len, char **gnu_name, const char *name,
#ifndef SMALL
-/* shortest possible extended record: "5 a=\n" */
-#define MINXHDRSZ 5
-
-/* longest record we'll accept */
-#define MAXXHDRSZ BLKMULT
+#define MINXHDRSZ 6
static int
-rd_xheader(ARCHD *arcn, int global, off_t size)
+rd_xheader(ARCHD *arcn, char *buf, off_t size, char typeflag)
{
- char buf[MAXXHDRSZ];
- unsigned long len;
+ off_t len;
char *delim, *keyword;
- char *nextp, *p, *end;
- int pad, ret = 0;
-
- /* before we alter size, make note of how much we have to skip */
- pad = TAR_PAD((unsigned)size);
-
- p = end = buf;
- while (size > 0 || p < end) {
- if (size > 0) {
- int rdlen;
-
- /* shift stuff down */
- if (p > buf) {
- memmove(buf, p, end - p);
- end -= p - buf;
- p = buf;
- }
+ char *nextp, *p;
- /* fill starting at end */
- rdlen = MINIMUM(size, (buf + sizeof buf) - end);
- if (rd_wrbuf(end, rdlen) != rdlen) {
- ret = -1;
- break;
- }
- size -= rdlen;
- end += rdlen;
- }
+ if (size < MINXHDRSZ) {
+ paxwarn(1, "Invalid extended header length");
+ return (-1);
+ }
+ if (rd_wrbuf(buf, size) != size)
+ return (-1);
+ if (rd_skip((off_t)BLKMULT - size) < 0)
+ return (-1);
- /* [p, end) is good */
- if (memchr(p, ' ', end - p) == NULL ||
- !isdigit((unsigned char)*p)) {
+ for (p = buf; size > 0; size -= len, p = nextp) {
+ if (!isdigit((unsigned char)*p)) {
paxwarn(1, "Invalid extended header record");
- ret = -1;
- break;
+ return (-1);
}
errno = 0;
- len = strtoul(p, &delim, 10);
- if (*delim != ' ' || (errno == ERANGE && len == ULONG_MAX) ||
+ len = strtoll(p, &delim, 10);
+ if (*delim != ' ' || (errno == ERANGE &&
+ (len == LLONG_MIN || len == LLONG_MAX)) ||
len < MINXHDRSZ) {
paxwarn(1, "Invalid extended header record length");
- ret = -1;
- break;
+ return (-1);
}
- if (len > end - p) {
- paxwarn(1, "Extended header record length %lu is "
- "out of range", len);
- /* if we can just toss this record, do so */
- len -= end - p;
- if (len <= size && rd_skip(len) == 0) {
- size -= len;
- p = end = buf;
- continue;
- }
- ret = -1;
- break;
+ if (len > size) {
+ paxwarn(1, "Extended header record length %lld is "
+ "out of range", (long long)len);
+ return (-1);
}
nextp = p + len;
keyword = p = delim + 1;
p = memchr(p, '=', len);
if (!p || nextp[-1] != '\n') {
paxwarn(1, "Malformed extended header record");
- ret = -1;
- break;
+ return (-1);
}
*p++ = nextp[-1] = '\0';
- if (!global) {
+ if (typeflag == XHDRTYPE) {
if (!strcmp(keyword, "path")) {
arcn->nlen = strlcpy(arcn->name, p,
sizeof(arcn->name));
@@ -1291,11 +1246,11 @@ rd_xheader(ARCHD *arcn, int global, off_t size)
sizeof(arcn->ln_name));
}
}
- p = nextp;
}
- if (rd_skip(size + pad) < 0)
+ /* Update the ustar header. */
+ if (rd_wrbuf(buf, BLKMULT) != BLKMULT)
return (-1);
- return (ret);
+ return (0);
}
#endif