From de44737ef7451cd204090ff5f1adb4a6130270ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 15 Jul 2004 12:31:49 +0000 Subject: [PATCH] Added attribute copying support to "cp" and "mv". git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8401 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/bin/coreutils-5.0/src/copy.c | 77 +++++++++++++++++++++++++++ src/apps/bin/coreutils-5.0/src/copy.h | 3 ++ src/apps/bin/coreutils-5.0/src/cp.c | 1 + src/apps/bin/coreutils-5.0/src/mv.c | 1 + 4 files changed, 82 insertions(+) diff --git a/src/apps/bin/coreutils-5.0/src/copy.c b/src/apps/bin/coreutils-5.0/src/copy.c index 91ae106f5d..1db66cb41c 100644 --- a/src/apps/bin/coreutils-5.0/src/copy.c +++ b/src/apps/bin/coreutils-5.0/src/copy.c @@ -46,6 +46,12 @@ #include "same.h" #include "xreadlink.h" +#if __BEOS__ +# define bool bool_t +# include +# undef bool +#endif + #define DO_CHOWN(Chown, File, New_uid, New_gid) \ (Chown (File, New_uid, New_gid) \ /* If non-root uses -p, it's ok if we can't preserve ownership. \ @@ -136,6 +142,63 @@ is_ancestor (const struct stat *sb, const struct dir_list *ancestors) return 0; } + +static int +copy_attributes(int fromFd, int toFd) +{ + struct dirent *dirent; + char buffer[65536]; + + DIR *attributes = fs_fopen_attr_dir(fromFd); + if (attributes == NULL) + return -1; + + while ((dirent = fs_read_attr_dir(attributes)) != NULL) { + attr_info info; + off_t pos = 0; + + if (fs_stat_attr(fromFd, dirent->d_name, &info) != 0) + continue; + + while (info.size > 0) { + ssize_t bytesRead, bytesWritten; + + bytesRead = fs_read_attr(fromFd, dirent->d_name, info.type, pos, buffer, sizeof(buffer)); + if (bytesRead < 0) + continue; + + bytesWritten = fs_write_attr(toFd, dirent->d_name, info.type, pos, buffer, bytesRead); + if (bytesWritten != bytesRead) + continue; + + pos += bytesRead; + info.size -= bytesRead; + } + } + + fs_close_attr_dir(attributes); +} + + +static int +copy_attributes_by_name(const char *from, const char *to, int resolveLinks) +{ + int fromFd, toFd; + printf("%s -> %s\n", from, to); + fromFd = open(from, O_RDONLY | (resolveLinks ? 0 : O_NOTRAVERSE)); + if (fromFd < 0) + return -1; + + toFd = open(to, O_RDONLY | (resolveLinks ? 0 : O_NOTRAVERSE)); + if (toFd < 0) { + close(fromFd); + return -1; + } + + return copy_attributes(fromFd, toFd); +} + + /* Read the contents of the directory SRC_PATH_IN, and recursively copy the contents to DST_PATH_IN. NEW_DST is nonzero if DST_PATH_IN is a directory that was created previously in the @@ -163,6 +226,10 @@ copy_dir (const char *src_path_in, const char *dst_path_in, int new_dst, return -1; } + if (x->ignore_attributes == 0 + && copy_attributes_by_name(src_path_in, dst_path_in, true) != 0) + fprintf(stderr, "%s: could not copy attributes\n", src_path_in); + /* For cp's -H option, dereference command line arguments, but do not dereference symlinks that are found via recursive traversal. */ if (x->dereference == DEREF_COMMAND_LINE_ARGUMENTS) @@ -312,6 +379,10 @@ copy_reg (const char *src_path, const char *dst_path, } #endif + if (x->ignore_attributes == 0 + && copy_attributes(source_desc, dest_desc) != 0) + fprintf(stderr, "%s: could not copy attributes\n", src_path); + /* Make a buffer with space for a sentinel at the end. */ buf = (char *) alloca (buf_size + sizeof (int)); @@ -1133,6 +1204,12 @@ copy_internal (const char *src_path, const char *dst_path, quote_n (0, dst_path), quote_n (1, earlier_file)); goto un_backup; } + else + { + if (x->ignore_attributes == 0 + && copy_attributes_by_name(earlier_file, dst_path, false) != 0) + fprintf(stderr, "%s: could not copy attributes\n", earlier_file); + } return 0; } diff --git a/src/apps/bin/coreutils-5.0/src/copy.h b/src/apps/bin/coreutils-5.0/src/copy.h index 10cdce9796..e0fd7fd667 100644 --- a/src/apps/bin/coreutils-5.0/src/copy.h +++ b/src/apps/bin/coreutils-5.0/src/copy.h @@ -124,6 +124,9 @@ struct cp_options it be zero. */ int require_preserve; + /* If nonzero, attributes will be ignored when copying. */ + int ignore_attributes; + /* If nonzero, copy directories recursively and copy special files as themselves rather than copying their contents. */ int recursive; diff --git a/src/apps/bin/coreutils-5.0/src/cp.c b/src/apps/bin/coreutils-5.0/src/cp.c index 1f8a975aa3..78afb4b243 100644 --- a/src/apps/bin/coreutils-5.0/src/cp.c +++ b/src/apps/bin/coreutils-5.0/src/cp.c @@ -730,6 +730,7 @@ cp_option_init (struct cp_options *x) x->preserve_timestamps = 0; x->require_preserve = 0; + x->ignore_attributes = 0; x->recursive = 0; x->sparse_mode = SPARSE_AUTO; x->symbolic_link = 0; diff --git a/src/apps/bin/coreutils-5.0/src/mv.c b/src/apps/bin/coreutils-5.0/src/mv.c index 8c6f3b5ee2..c19edc08af 100644 --- a/src/apps/bin/coreutils-5.0/src/mv.c +++ b/src/apps/bin/coreutils-5.0/src/mv.c @@ -130,6 +130,7 @@ cp_option_init (struct cp_options *x) x->preserve_mode = 1; x->preserve_timestamps = 1; x->require_preserve = 0; /* FIXME: maybe make this an option */ + x->ignore_attributes = 0; x->recursive = 1; x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */ x->symbolic_link = 0;