📄 cp.c
字号:
this ensures that the command `cp non-directory file/' will now
fail rather than performing the copy. COPY diagnoses the case of
`cp directory non-directory'. */
else if (dest[strlen (dest) - 1] == '/'
&& lstat (source, &source_stats) == 0
&& !S_ISDIR (source_stats.st_mode))
{
char *source_base;
ASSIGN_BASENAME_STRDUPA (source_base, source);
new_dest = (char *) alloca (strlen (dest)
+ strlen (source_base) + 1);
stpcpy (stpcpy (new_dest, dest), source_base);
}
else
{
new_dest = (char *) dest;
}
return copy (source, new_dest, new_dst, x, &unused, NULL);
}
/* unreachable */
}
static void
cp_option_init (struct cp_options *x)
{
x->copy_as_regular = 1;
x->dereference = DEREF_UNDEFINED;
x->unlink_dest_before_opening = 0;
x->unlink_dest_after_failed_open = 0;
x->hard_link = 0;
x->interactive = I_UNSPECIFIED;
x->myeuid = geteuid ();
x->move_mode = 0;
x->one_file_system = 0;
x->preserve_ownership = 0;
x->preserve_links = 0;
x->preserve_mode = 0;
x->preserve_timestamps = 0;
x->require_preserve = 0;
x->recursive = 0;
x->sparse_mode = SPARSE_AUTO;
x->symbolic_link = 0;
x->set_mode = 0;
x->mode = 0;
/* Not used. */
x->stdin_tty = 0;
x->update = 0;
x->verbose = 0;
x->dest_info = NULL;
x->src_info = NULL;
}
/* Given a string, ARG, containing a comma-separated list of arguments
to the --preserve option, set the appropriate fields of X to ON_OFF. */
static void
decode_preserve_arg (char const *arg, struct cp_options *x, int on_off)
{
enum File_attribute
{
PRESERVE_MODE,
PRESERVE_TIMESTAMPS,
PRESERVE_OWNERSHIP,
PRESERVE_LINK,
PRESERVE_ALL
};
static enum File_attribute const preserve_vals[] =
{
PRESERVE_MODE, PRESERVE_TIMESTAMPS,
PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL
};
/* Valid arguments to the `--reply' option. */
static char const* const preserve_args[] =
{
"mode", "timestamps",
"ownership", "links", "all", 0
};
char *arg_writable = xstrdup (arg);
char *s = arg_writable;
do
{
/* find next comma */
char *comma = strchr (s, ',');
enum File_attribute val;
/* put a NUL in its place */
if (comma)
*comma++ = 0;
/* process S. */
val = XARGMATCH ("--preserve", s, preserve_args, preserve_vals);
switch (val)
{
case PRESERVE_MODE:
x->preserve_mode = on_off;
break;
case PRESERVE_TIMESTAMPS:
x->preserve_timestamps = on_off;
break;
case PRESERVE_OWNERSHIP:
x->preserve_ownership = on_off;
break;
case PRESERVE_LINK:
x->preserve_links = on_off;
break;
case PRESERVE_ALL:
x->preserve_mode = on_off;
x->preserve_timestamps = on_off;
x->preserve_ownership = on_off;
x->preserve_links = on_off;
break;
default:
abort ();
}
s = comma;
}
while (s);
free (arg_writable);
}
int
main (int argc, char **argv)
{
int c;
int make_backups = 0;
char *backup_suffix_string;
char *version_control_string = NULL;
struct cp_options x;
int copy_contents = 0;
char *target_directory = NULL;
program_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
cp_option_init (&x);
/* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
we'll actually use backup_suffix_string. */
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
while ((c = getopt_long (argc, argv, "abdfHilLprsuvxPRS:V:", long_opts, NULL))
!= -1)
{
switch (c)
{
case 0:
break;
case SPARSE_OPTION:
x.sparse_mode = XARGMATCH ("--sparse", optarg,
sparse_type_string, sparse_type);
break;
case 'a': /* Like -dpPR. */
x.dereference = DEREF_NEVER;
x.preserve_links = 1;
x.preserve_ownership = 1;
x.preserve_mode = 1;
x.preserve_timestamps = 1;
x.require_preserve = 1;
x.recursive = 1;
break;
case 'V': /* FIXME: this is deprecated. Remove it in 2001. */
error (0, 0,
_("warning: --version-control (-V) is obsolete; support for\
it\nwill be removed in some future release. Use --backup=%s instead."
), optarg);
/* Fall through. */
case 'b':
make_backups = 1;
if (optarg)
version_control_string = optarg;
break;
case COPY_CONTENTS_OPTION:
copy_contents = 1;
break;
case 'd':
x.preserve_links = 1;
x.dereference = DEREF_NEVER;
break;
case 'f':
x.interactive = 0;
x.unlink_dest_after_failed_open = 1;
break;
case 'H':
x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
break;
case 'i':
x.interactive = I_ASK_USER;
break;
case 'l':
x.hard_link = 1;
break;
case 'L':
x.dereference = DEREF_ALWAYS;
break;
case 'P':
x.dereference = DEREF_NEVER;
break;
case NO_PRESERVE_ATTRIBUTES_OPTION:
decode_preserve_arg (optarg, &x, 0);
break;
case PRESERVE_ATTRIBUTES_OPTION:
if (optarg == NULL)
{
/* Fall through to the case for `p' below. */
}
else
{
decode_preserve_arg (optarg, &x, 1);
x.require_preserve = 1;
break;
}
case 'p':
x.preserve_ownership = 1;
x.preserve_mode = 1;
x.preserve_timestamps = 1;
x.require_preserve = 1;
break;
case PARENTS_OPTION:
flag_path = 1;
break;
case 'r':
case 'R':
x.recursive = 1;
break;
case REPLY_OPTION:
x.interactive = XARGMATCH ("--reply", optarg,
reply_args, reply_vals);
break;
case UNLINK_DEST_BEFORE_OPENING:
x.unlink_dest_before_opening = 1;
break;
case STRIP_TRAILING_SLASHES_OPTION:
remove_trailing_slashes = 1;
break;
case 's':
#ifdef S_ISLNK
x.symbolic_link = 1;
#else
error (EXIT_FAILURE, 0,
_("symbolic links are not supported on this system"));
#endif
break;
case TARGET_DIRECTORY_OPTION:
target_directory = optarg;
break;
case 'u':
x.update = 1;
break;
case 'v':
x.verbose = 1;
break;
case 'x':
x.one_file_system = 1;
break;
case 'S':
make_backups = 1;
backup_suffix_string = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (EXIT_FAILURE);
}
}
if (x.hard_link && x.symbolic_link)
{
error (0, 0, _("cannot make both hard and symbolic links"));
usage (EXIT_FAILURE);
}
if (backup_suffix_string)
simple_backup_suffix = xstrdup (backup_suffix_string);
x.backup_type = (make_backups
? xget_version (_("backup type"),
version_control_string)
: none);
if (x.dereference == DEREF_UNDEFINED)
{
if (x.recursive)
/* This is compatible with FreeBSD. */
x.dereference = DEREF_NEVER;
else
x.dereference = DEREF_ALWAYS;
}
/* The key difference between -d (--no-dereference) and not is the version
of `stat' to call. */
if (x.dereference == DEREF_NEVER)
x.xstat = lstat;
else
{
/* For DEREF_COMMAND_LINE_ARGUMENTS, x.xstat must be stat for
each command line argument, but must later be `lstat' for
any symlinks that are found via recursive traversal. */
x.xstat = stat;
}
if (x.recursive)
x.copy_as_regular = copy_contents;
/* If --force (-f) was specified and we're in link-creation mode,
first remove any existing destination file. */
if (x.unlink_dest_after_failed_open && (x.hard_link || x.symbolic_link))
x.unlink_dest_before_opening = 1;
/* Allocate space for remembering copied and created files. */
hash_init ();
exit_status |= do_copy (argc - optind, argv + optind, target_directory, &x);
forget_all ();
exit (exit_status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -