tar: support -T - and -X -
[oweals/busybox.git] / libbb / copy_file.c
index ae70cbc0aef8277948d65e360d75064faa84c1a9..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"
 
@@ -30,12 +30,12 @@ static int ask_and_unlink(const char *dest, int flags)
 #if !ENABLE_FEATURE_NON_POSIX_CP
        if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) {
                /* Either it exists, or the *path* doesnt exist */
-               bb_perror_msg("cannot create '%s'", dest);
+               bb_perror_msg("can't create '%s'", dest);
                return -1;
        }
 #endif
        // else: act as if -f is always in effect.
-       // We don't want "cannot create" msg, we want unlink to be done
+       // We don't want "can't create" msg, we want unlink to be done
        // (silently unless -i). Why? POSIX cp usually succeeds with
        // O_TRUNC open of existing file, and user is left ignorantly happy.
        // With above block unconditionally enabled, non-POSIX cp
@@ -56,12 +56,12 @@ static int ask_and_unlink(const char *dest, int flags)
                if (e == errno && e == ENOENT) {
                        /* e == ENOTDIR is similar: path has non-dir component,
                         * but in this case we don't even reach copy_file() */
-                       bb_error_msg("cannot create '%s': Path does not exist", dest);
+                       bb_error_msg("can't create '%s': Path does not exist", dest);
                        return -1; /* error */
                }
 #endif
                errno = e; /* do not use errno from unlink */
-               bb_perror_msg("cannot create '%s'", dest);
+               bb_perror_msg("can't create '%s'", dest);
                return -1; /* error */
        }
        return 1; /* ok (to try again) */
@@ -78,25 +78,25 @@ 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.
                 * Making [sym]links to dangling symlinks works, so... */
                if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK))
                        goto make_links;
-               bb_perror_msg("cannot stat '%s'", source);
+               bb_perror_msg("can't stat '%s'", source);
                return -1;
        }
 
        if (lstat(dest, &dest_stat) < 0) {
                if (errno != ENOENT) {
-                       bb_perror_msg("cannot stat '%s'", dest);
+                       bb_perror_msg("can't stat '%s'", dest);
                        return -1;
                }
        } else {
@@ -114,14 +114,14 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                security_context_t con;
                if (lgetfilecon(source, &con) >= 0) {
                        if (setfscreatecon(con) < 0) {
-                               bb_perror_msg("cannot set setfscreatecon %s", con);
+                               bb_perror_msg("can't set setfscreatecon %s", con);
                                freecon(con);
                                return -1;
                        }
                } else if (errno == ENOTSUP || errno == ENODATA) {
                        setfscreatecon_or_die(NULL);
                } else {
-                       bb_perror_msg("cannot lgetfilecon %s", source);
+                       bb_perror_msg("can't lgetfilecon %s", source);
                        return -1;
                }
        }
@@ -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);
 
@@ -166,13 +166,13 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                        mode |= S_IRWXU;
                        if (mkdir(dest, mode) < 0) {
                                umask(saved_umask);
-                               bb_perror_msg("cannot create directory '%s'", dest);
+                               bb_perror_msg("can't create directory '%s'", dest);
                                return -1;
                        }
                        umask(saved_umask);
                        /* need stat info for add_to_ino_dev_hashtable */
                        if (lstat(dest, &dest_stat) < 0) {
-                               bb_perror_msg("cannot stat '%s'", dest);
+                               bb_perror_msg("can't stat '%s'", dest);
                                return -1;
                        }
                }
@@ -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);
@@ -204,7 +204,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                if (!dest_exists
                 && chmod(dest, source_stat.st_mode & ~saved_umask) < 0
                ) {
-                       bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
+                       bb_perror_msg("can't preserve %s of '%s'", "permissions", dest);
                        /* retval = -1; - WRONG! copy *WAS* made */
                }
                goto preserve_mode_ugid_time;
@@ -222,7 +222,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                        if (ovr <= 0)
                                return ovr;
                        if (lf(source, dest) < 0) {
-                               bb_perror_msg("cannot create link '%s'", dest);
+                               bb_perror_msg("can't create link '%s'", dest);
                                return -1;
                        }
                }
@@ -257,7 +257,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                                        if (ovr <= 0)
                                                return ovr;
                                        if (link(link_target, dest) < 0) {
-                                               bb_perror_msg("cannot create link '%s'", dest);
+                                               bb_perror_msg("can't create link '%s'", dest);
                                                return -1;
                                        }
                                }
@@ -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("cannot close '%s'", dest);
+                       bb_perror_msg("error writing to '%s'", dest);
                        retval = -1;
                }
                /* ...but read size is already checked by bb_copyfd_eof */
@@ -345,12 +345,12 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
                        int r = symlink(lpath, dest);
                        free(lpath);
                        if (r < 0) {
-                               bb_perror_msg("cannot create symlink '%s'", dest);
+                               bb_perror_msg("can't create symlink '%s'", dest);
                                return -1;
                        }
                        if (flags & FILEUTILS_PRESERVE_STATUS)
                                if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
-                                       bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);
+                                       bb_perror_msg("can't preserve %s of '%s'", "ownership", dest);
                }
                /* _Not_ jumping to preserve_mode_ugid_time:
                 * symlinks don't have those */
@@ -360,7 +360,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
         || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode)
        ) {
                if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
-                       bb_perror_msg("cannot create '%s'", dest);
+                       bb_perror_msg("can't create '%s'", dest);
                        return -1;
                }
        } else {
@@ -374,19 +374,19 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
        /* Cannot happen: */
        /* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */
        ) {
-               struct utimbuf times;
+               struct timeval times[2];
 
-               times.actime = source_stat.st_atime;
-               times.modtime = source_stat.st_mtime;
+               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 (utime(dest, &times) < 0)
-                       bb_perror_msg("cannot preserve %s of '%s'", "times", dest);
+               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);
-                       bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);
+                       bb_perror_msg("can't preserve %s of '%s'", "ownership", dest);
                }
                if (chmod(dest, source_stat.st_mode) < 0)
-                       bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
+                       bb_perror_msg("can't preserve %s of '%s'", "permissions", dest);
        }
 
        return retval;