main: free suid_config list after use
[oweals/busybox.git] / libbb / copy_file.c
index adcfe2111f23dc68bb7b8619779fb2abce6b6862..9333a8d4992b833db6ecea304e59f3ed767a5f8c 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
  * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 #include "libbb.h"
 
@@ -78,12 +78,12 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
        /* NB: each struct stat is ~100 bytes */
        struct stat source_stat;
        struct stat dest_stat;
-       signed char retval = 0;
-       signed char dest_exists = 0;
-       signed char ovr;
+       smallint retval = 0;
+       smallint dest_exists = 0;
+       smallint ovr;
 
 /* Inverse of cp -d ("cp without -d") */
-#define FLAGS_DEREF (flags & FILEUTILS_DEREFERENCE)
+#define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0))
 
        if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) {
                /* This may be a dangling symlink.
@@ -147,7 +147,6 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                        return -1;
                }
 
-               /* Create DEST */
                if (dest_exists) {
                        if (!S_ISDIR(dest_stat.st_mode)) {
                                bb_error_msg("target '%s' is not a directory", dest);
@@ -156,6 +155,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                        /* race here: user can substitute a symlink between
                         * this check and actual creation of files inside dest */
                } else {
+                       /* Create DEST */
                        mode_t mode;
                        saved_umask = umask(0);
 
@@ -194,7 +194,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                        if (new_source == NULL)
                                continue;
                        new_dest = concat_path_file(dest, d->d_name);
-                       if (copy_file(new_source, new_dest, flags) < 0)
+                       if (copy_file(new_source, new_dest, flags & ~FILEUTILS_DEREFERENCE_L0) < 0)
                                retval = -1;
                        free(new_source);
                        free(new_dest);
@@ -316,9 +316,9 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
 #endif
                if (bb_copyfd_eof(src_fd, dst_fd) == -1)
                        retval = -1;
-               /* Ok, writing side I can understand... */
+               /* Careful with writing... */
                if (close(dst_fd) < 0) {
-                       bb_perror_msg("can't close '%s'", dest);
+                       bb_perror_msg("error writing to '%s'", dest);
                        retval = -1;
                }
                /* ...but read size is already checked by bb_copyfd_eof */
@@ -374,12 +374,12 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
        /* Cannot happen: */
        /* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */
        ) {
-               struct timeval times;
+               struct timeval times[2];
 
-               times.tv_sec = source_stat.st_mtime;
-               times.tv_usec = 0;
+               times[1].tv_sec = times[0].tv_sec = source_stat.st_mtime;
+               times[1].tv_usec = times[0].tv_usec = 0;
                /* BTW, utimes sets usec-precision time - just FYI */
-               if (utimes(dest, &times) < 0)
+               if (utimes(dest, times) < 0)
                        bb_perror_msg("can't preserve %s of '%s'", "times", dest);
                if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
                        source_stat.st_mode &= ~(S_ISUID | S_ISGID);