Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-6]: src/bin/pax Pullup rev 1.24-1.41 (requested by rafal in tic...



details:   https://anonhg.NetBSD.org/src/rev/6a3e383c927b
branches:  netbsd-1-6
changeset: 531265:6a3e383c927b
user:      jmc <jmc%NetBSD.org@localhost>
date:      Wed Apr 07 06:57:38 2004 +0000

description:
Pullup rev 1.24-1.41 (requested by rafal in ticket #1021)

Pullup pax to current version on trunk. Includes many fixes.

diffstat:

 bin/pax/file_subs.c |  247 ++++++++++++++++++++++++++++++---------------------
 1 files changed, 143 insertions(+), 104 deletions(-)

diffs (truncated from 522 to 300 lines):

diff -r e5d6852a2083 -r 6a3e383c927b bin/pax/file_subs.c
--- a/bin/pax/file_subs.c       Wed Apr 07 06:57:32 2004 +0000
+++ b/bin/pax/file_subs.c       Wed Apr 07 06:57:38 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: file_subs.c,v 1.23 2002/02/11 11:19:26 wiz Exp $       */
+/*     $NetBSD: file_subs.c,v 1.23.2.1 2004/04/07 06:57:38 jmc Exp $   */
 
 /*-
  * Copyright (c) 1992 Keith Muller.
@@ -16,11 +16,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -37,12 +33,16 @@
  * SUCH DAMAGE.
  */
 
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
 #include <sys/cdefs.h>
-#if defined(__RCSID) && !defined(lint)
+#if !defined(lint)
 #if 0
 static char sccsid[] = "@(#)file_subs.c        8.1 (Berkeley) 5/31/93";
 #else
-__RCSID("$NetBSD: file_subs.c,v 1.23 2002/02/11 11:19:26 wiz Exp $");
+__RCSID("$NetBSD: file_subs.c,v 1.23.2.1 2004/04/07 06:57:38 jmc Exp $");
 #endif
 #endif /* not lint */
 
@@ -60,6 +60,9 @@
 #include <stdlib.h>
 #include "pax.h"
 #include "extern.h"
+#include "options.h"
+
+char *xtmp_name;
 
 static int
 mk_link(char *,struct stat *,char *, int);
@@ -84,45 +87,39 @@
 file_creat(ARCHD *arcn)
 {
        int fd = -1;
-       mode_t file_mode;
        int oerrno;
 
        /*
-        * assume file doesn't exist, so just try to create it, most times this
-        * works. We have to take special handling when the file does exist. To
-        * detect this, we use O_EXCL. For example when trying to create a
-        * file and a character device or fifo exists with the same name, we
-        * can accidently open the device by mistake (or block waiting to open)
-        * If we find that the open has failed, then figure spend the effort to
-        * figure out why. This strategy was found to have better average
-        * performance in common use than checking the file (and the path)
-        * first with lstat.
+        * Create a temporary file name so that the file doesn't have partial
+        * contents while restoring.
         */
-       file_mode = arcn->sb.st_mode & FILEBITS;
-       if ((fd = open(arcn->name, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
-           file_mode)) >= 0)
-               return(fd);
-
-       /*
-        * the file seems to exist. First we try to get rid of it (found to be
-        * the second most common failure when traced). If this fails, only
-        * then we go to the expense to check and create the path to the file
-        */
-       if (unlnk_exist(arcn->name, arcn->type) != 0)
+       arcn->tmp_name = malloc(arcn->nlen + 8);
+       if (arcn->tmp_name == NULL) {
+               syswarn(1, errno, "Cannot malloc %d bytes", arcn->nlen + 8);
                return(-1);
+       }
+       if (xtmp_name)
+               abort();
+       xtmp_name = arcn->tmp_name;
 
        for (;;) {
                /*
-                * try to open it again, if this fails, check all the nodes in
-                * the path and give it a final try. if chk_path() finds that
-                * it cannot fix anything, we will skip the last attempt
+                * try to create the temporary file we use to restore the
+                * contents info.  if this fails, keep checking all the nodes
+                * in the path until chk_path() finds that it cannot fix
+                * anything further.  if that happens we just give up.
                 */
-               if ((fd = open(arcn->name, O_WRONLY | O_CREAT | O_TRUNC,
-                   file_mode)) >= 0)
+               (void)snprintf(arcn->tmp_name, arcn->nlen + 8, "%s.XXXXXX",
+                   arcn->name);
+               fd = mkstemp(arcn->tmp_name);
+               if (fd >= 0)
                        break;
                oerrno = errno;
-               if (chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
-                       syswarn(1, oerrno, "Unable to create %s", arcn->name);
+               if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
+                       (void)fflush(listf);
+                       syswarn(1, oerrno, "Cannot create %s", arcn->tmp_name);
+                       free(arcn->tmp_name);
+                       arcn->tmp_name = NULL;
                        return(-1);
                }
        }
@@ -145,8 +142,8 @@
        if (fd < 0)
                return;
        if (close(fd) < 0)
-               syswarn(0, errno, "Unable to close file descriptor on %s",
-                   arcn->name);
+               syswarn(0, errno, "Cannot close file descriptor on %s",
+                   arcn->tmp_name);
 
        /*
         * set owner/groups first as this may strip off mode bits we want
@@ -154,23 +151,39 @@
         * modification times.
         */
        if (pids)
-               res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid);
+               res = set_ids(arcn->tmp_name, arcn->sb.st_uid, arcn->sb.st_gid);
 
        /*
         * IMPORTANT SECURITY NOTE:
         * if not preserving mode or we cannot set uid/gid, then PROHIBIT
-        * set uid/gid bits
+        * set uid/gid bits but restore the file modes (since mkstemp doesn't).
         */
        if (!pmode || res)
                arcn->sb.st_mode &= ~(SETBITS);
        if (pmode)
-               set_pmode(arcn->name, arcn->sb.st_mode);
+               set_pmode(arcn->tmp_name, arcn->sb.st_mode);
+       else
+               set_pmode(arcn->tmp_name, arcn->sb.st_mode & FILEBITS);
        if (patime || pmtime)
-               set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+               set_ftime(arcn->tmp_name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
 #if HAVE_STRUCT_STAT_ST_FLAGS
        if (pfflags && arcn->type != PAX_SLK)
-               set_chflags(arcn->name, arcn->sb.st_flags);
+               set_chflags(arcn->tmp_name, arcn->sb.st_flags);
 #endif
+
+       /*
+        * Finally, now the temp file is fully instantiated rename it to
+        * the desired file name.
+        */
+       if (rename(arcn->tmp_name, arcn->name) < 0) {
+               syswarn(0, errno, "Cannot rename %s to %s",
+                   arcn->tmp_name, arcn->name);
+               (void)unlink(arcn->tmp_name);
+       }
+
+       free(arcn->tmp_name);
+       arcn->tmp_name = NULL;
+       xtmp_name = NULL;
 }
 
 /*
@@ -191,7 +204,7 @@
         * is not a directory, so we lstat and check
         */
        if (lstat(arcn->ln_name, &sb) < 0) {
-               syswarn(1,errno,"Unable to link to %s from %s", arcn->ln_name,
+               syswarn(1, errno, "Cannot link to %s from %s", arcn->ln_name,
                    arcn->name);
                return(-1);
        }
@@ -294,8 +307,8 @@
                 * make sure it is not the same file, protect the user
                 */
                if ((to_sb->st_dev==sb.st_dev)&&(to_sb->st_ino == sb.st_ino)) {
-                       tty_warn(1, "Unable to link file %s to itself", to);
-                       return(-1);;
+                       tty_warn(1, "Cannot link file %s to itself", to);
+                       return(-1);
                }
 
                /*
@@ -303,12 +316,12 @@
                 */
                if (S_ISDIR(sb.st_mode)) {
                        if (rmdir(from) < 0) {
-                               syswarn(1, errno, "Unable to remove %s", from);
+                               syswarn(1, errno, "Cannot remove %s", from);
                                return(-1);
                        }
                } else if (unlink(from) < 0) {
                        if (!ign) {
-                               syswarn(1, errno, "Unable to remove %s", from);
+                               syswarn(1, errno, "Cannot remove %s", from);
                                return(-1);
                        }
                        return(1);
@@ -327,7 +340,7 @@
                if (chk_path(from, to_sb->st_uid, to_sb->st_gid) == 0)
                        continue;
                if (!ign) {
-                       syswarn(1, oerrno, "Could not link to %s from %s", to,
+                       syswarn(1, oerrno, "Cannot link to %s from %s", to,
                            from);
                        return(-1);
                }
@@ -357,6 +370,9 @@
        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
@@ -369,20 +385,43 @@
        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:
                        /*
@@ -390,10 +429,10 @@
                         */
                        tty_warn(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:
@@ -404,7 +443,7 @@
                         * we should never get here
                         */
                        tty_warn(0, "%s has an unknown file type, skipping",
-                               arcn->name);
+                           nm);
                        return(-1);
                }
 
@@ -420,14 +459,14 @@



Home | Main Index | Thread Index | Old Index