diff options
Diffstat (limited to 'bin/pax/tables.c')
-rw-r--r-- | bin/pax/tables.c | 60 |
1 files changed, 55 insertions, 5 deletions
diff --git a/bin/pax/tables.c b/bin/pax/tables.c index b99dbbe4534..79db2a5e63f 100644 --- a/bin/pax/tables.c +++ b/bin/pax/tables.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tables.c,v 1.42 2015/02/12 23:44:57 guenther Exp $ */ +/* $OpenBSD: tables.c,v 1.43 2015/02/15 22:18:29 millert Exp $ */ /* $NetBSD: tables.c,v 1.4 1995/03/21 09:07:45 cgd Exp $ */ /*- @@ -556,7 +556,13 @@ sltab_add_sym(const char *path0, const char *value0, mode_t mode) } close(fd); - if ((path = strdup(path0)) == NULL) { + 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); @@ -640,7 +646,14 @@ sltab_add_link(const char *path, const struct stat *sb) syswarn(1, errno, "deferred symlink hardlink"); return (-1); } - if ((p->sp_path = strdup(path)) == NULL) { + 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); @@ -1372,7 +1385,8 @@ do_atdir(const char *name, dev_t dev, ino_t ino) /* * return if we did not find it. */ - if (pt == NULL || strcmp(name, pt->ft.ft_name) == 0) + if (pt == NULL || pt->ft.ft_name == NULL || + strcmp(name, pt->ft.ft_name) == 0) return(-1); /* @@ -1489,6 +1503,35 @@ 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 @@ -1508,11 +1551,18 @@ 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) */ - dblk = &dirp[cnt]; set_attr(&dblk->ft, 0, dblk->mode, pmode || dblk->frc_mode, in_sig); if (!in_sig) |