Added attribute copying support to "cp" and "mv".
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8401 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -46,6 +46,12 @@
|
|||||||
#include "same.h"
|
#include "same.h"
|
||||||
#include "xreadlink.h"
|
#include "xreadlink.h"
|
||||||
|
|
||||||
|
#if __BEOS__
|
||||||
|
# define bool bool_t
|
||||||
|
# include <fs_attr.h>
|
||||||
|
# undef bool
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DO_CHOWN(Chown, File, New_uid, New_gid) \
|
#define DO_CHOWN(Chown, File, New_uid, New_gid) \
|
||||||
(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. \
|
/* 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;
|
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
|
/* Read the contents of the directory SRC_PATH_IN, and recursively
|
||||||
copy the contents to DST_PATH_IN. NEW_DST is nonzero if
|
copy the contents to DST_PATH_IN. NEW_DST is nonzero if
|
||||||
DST_PATH_IN is a directory that was created previously in the
|
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;
|
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
|
/* For cp's -H option, dereference command line arguments, but do not
|
||||||
dereference symlinks that are found via recursive traversal. */
|
dereference symlinks that are found via recursive traversal. */
|
||||||
if (x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)
|
if (x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)
|
||||||
@@ -312,6 +379,10 @@ copy_reg (const char *src_path, const char *dst_path,
|
|||||||
}
|
}
|
||||||
#endif
|
#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. */
|
/* Make a buffer with space for a sentinel at the end. */
|
||||||
|
|
||||||
buf = (char *) alloca (buf_size + sizeof (int));
|
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));
|
quote_n (0, dst_path), quote_n (1, earlier_file));
|
||||||
goto un_backup;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ struct cp_options
|
|||||||
it be zero. */
|
it be zero. */
|
||||||
int require_preserve;
|
int require_preserve;
|
||||||
|
|
||||||
|
/* If nonzero, attributes will be ignored when copying. */
|
||||||
|
int ignore_attributes;
|
||||||
|
|
||||||
/* If nonzero, copy directories recursively and copy special files
|
/* If nonzero, copy directories recursively and copy special files
|
||||||
as themselves rather than copying their contents. */
|
as themselves rather than copying their contents. */
|
||||||
int recursive;
|
int recursive;
|
||||||
|
|||||||
@@ -730,6 +730,7 @@ cp_option_init (struct cp_options *x)
|
|||||||
x->preserve_timestamps = 0;
|
x->preserve_timestamps = 0;
|
||||||
|
|
||||||
x->require_preserve = 0;
|
x->require_preserve = 0;
|
||||||
|
x->ignore_attributes = 0;
|
||||||
x->recursive = 0;
|
x->recursive = 0;
|
||||||
x->sparse_mode = SPARSE_AUTO;
|
x->sparse_mode = SPARSE_AUTO;
|
||||||
x->symbolic_link = 0;
|
x->symbolic_link = 0;
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ cp_option_init (struct cp_options *x)
|
|||||||
x->preserve_mode = 1;
|
x->preserve_mode = 1;
|
||||||
x->preserve_timestamps = 1;
|
x->preserve_timestamps = 1;
|
||||||
x->require_preserve = 0; /* FIXME: maybe make this an option */
|
x->require_preserve = 0; /* FIXME: maybe make this an option */
|
||||||
|
x->ignore_attributes = 0;
|
||||||
x->recursive = 1;
|
x->recursive = 1;
|
||||||
x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */
|
x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */
|
||||||
x->symbolic_link = 0;
|
x->symbolic_link = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user