Tizen 2.0 Release
[external/tizen-coreutils.git] / src / cp.c
1 /* cp.c  -- file copying (main routines)
2    Copyright (C) 89, 90, 91, 1995-2007 Free Software Foundation.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18    Written by Torbjorn Granlund, David MacKenzie, and Jim Meyering. */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <getopt.h>
24
25 #include "system.h"
26 #include "argmatch.h"
27 #include "backupfile.h"
28 #include "copy.h"
29 #include "cp-hash.h"
30 #include "error.h"
31 #include "filenamecat.h"
32 #include "lchmod.h"
33 #include "quote.h"
34 #include "quotearg.h"
35 #include "stat-time.h"
36 #include "utimens.h"
37 #include "acl.h"
38
39 #define ASSIGN_BASENAME_STRDUPA(Dest, File_name)        \
40   do                                                    \
41     {                                                   \
42       char *tmp_abns_;                                  \
43       ASSIGN_STRDUPA (tmp_abns_, (File_name));          \
44       Dest = last_component (tmp_abns_);                \
45       strip_trailing_slashes (Dest);                    \
46     }                                                   \
47   while (0)
48
49 /* The official name of this program (e.g., no `g' prefix).  */
50 #define PROGRAM_NAME "cp"
51
52 #define AUTHORS "Torbjorn Granlund", "David MacKenzie", "Jim Meyering"
53
54 /* Used by do_copy, make_dir_parents_private, and re_protect
55    to keep a list of leading directories whose protections
56    need to be fixed after copying. */
57 struct dir_attr
58 {
59   mode_t mode;
60   bool restore_mode;
61   size_t slash_offset;
62   struct dir_attr *next;
63 };
64
65 /* For long options that have no equivalent short option, use a
66    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
67 enum
68 {
69   COPY_CONTENTS_OPTION = CHAR_MAX + 1,
70   NO_PRESERVE_ATTRIBUTES_OPTION,
71   PARENTS_OPTION,
72   PRESERVE_ATTRIBUTES_OPTION,
73   REPLY_OPTION,
74   SPARSE_OPTION,
75   STRIP_TRAILING_SLASHES_OPTION,
76   UNLINK_DEST_BEFORE_OPENING
77 };
78
79 /* Initial number of entries in each hash table entry's table of inodes.  */
80 #define INITIAL_HASH_MODULE 100
81
82 /* Initial number of entries in the inode hash table.  */
83 #define INITIAL_ENTRY_TAB_SIZE 70
84
85 /* The invocation name of this program.  */
86 char *program_name;
87
88 /* If true, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
89    as its destination instead of the usual "e_dir/e_file." */
90 static bool parents_option = false;
91
92 /* Remove any trailing slashes from each SOURCE argument.  */
93 static bool remove_trailing_slashes;
94
95 static char const *const sparse_type_string[] =
96 {
97   "never", "auto", "always", NULL
98 };
99 static enum Sparse_type const sparse_type[] =
100 {
101   SPARSE_NEVER, SPARSE_AUTO, SPARSE_ALWAYS
102 };
103 ARGMATCH_VERIFY (sparse_type_string, sparse_type);
104
105 /* Valid arguments to the `--reply' option. */
106 static char const* const reply_args[] =
107 {
108   "yes", "no", "query", NULL
109 };
110 /* The values that correspond to the above strings. */
111 static int const reply_vals[] =
112 {
113   I_ALWAYS_YES, I_ALWAYS_NO, I_ASK_USER
114 };
115 ARGMATCH_VERIFY (reply_args, reply_vals);
116
117 static struct option const long_opts[] =
118 {
119   {"archive", no_argument, NULL, 'a'},
120   {"backup", optional_argument, NULL, 'b'},
121   {"copy-contents", no_argument, NULL, COPY_CONTENTS_OPTION},
122   {"dereference", no_argument, NULL, 'L'},
123   {"force", no_argument, NULL, 'f'},
124   {"interactive", no_argument, NULL, 'i'},
125   {"link", no_argument, NULL, 'l'},
126   {"no-dereference", no_argument, NULL, 'P'},
127   {"no-preserve", required_argument, NULL, NO_PRESERVE_ATTRIBUTES_OPTION},
128   {"no-target-directory", no_argument, NULL, 'T'},
129   {"one-file-system", no_argument, NULL, 'x'},
130   {"parents", no_argument, NULL, PARENTS_OPTION},
131   {"path", no_argument, NULL, PARENTS_OPTION},   /* Deprecated.  */
132   {"preserve", optional_argument, NULL, PRESERVE_ATTRIBUTES_OPTION},
133   {"recursive", no_argument, NULL, 'R'},
134   {"remove-destination", no_argument, NULL, UNLINK_DEST_BEFORE_OPENING},
135   {"reply", required_argument, NULL, REPLY_OPTION}, /* Deprecated 2005-07-03,
136                                                        remove in 2008. */
137   {"sparse", required_argument, NULL, SPARSE_OPTION},
138   {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
139   {"suffix", required_argument, NULL, 'S'},
140   {"symbolic-link", no_argument, NULL, 's'},
141   {"target-directory", required_argument, NULL, 't'},
142   {"update", no_argument, NULL, 'u'},
143   {"verbose", no_argument, NULL, 'v'},
144   {GETOPT_HELP_OPTION_DECL},
145   {GETOPT_VERSION_OPTION_DECL},
146   {NULL, 0, NULL, 0}
147 };
148
149 void
150 usage (int status)
151 {
152   if (status != EXIT_SUCCESS)
153     fprintf (stderr, _("Try `%s --help' for more information.\n"),
154              program_name);
155   else
156     {
157       printf (_("\
158 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
159   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
160   or:  %s [OPTION]... -t DIRECTORY SOURCE...\n\
161 "),
162               program_name, program_name, program_name);
163       fputs (_("\
164 Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
165 \n\
166 "), stdout);
167       fputs (_("\
168 Mandatory arguments to long options are mandatory for short options too.\n\
169 "), stdout);
170       fputs (_("\
171   -a, --archive                same as -dpPR\n\
172       --backup[=CONTROL]       make a backup of each existing destination file\n\
173   -b                           like --backup but does not accept an argument\n\
174       --copy-contents          copy contents of special files when recursive\n\
175   -d                           same as --no-dereference --preserve=link\n\
176 "), stdout);
177       fputs (_("\
178   -f, --force                  if an existing destination file cannot be\n\
179                                  opened, remove it and try again\n\
180   -i, --interactive            prompt before overwrite\n\
181   -H                           follow command-line symbolic links\n\
182 "), stdout);
183       fputs (_("\
184   -l, --link                   link files instead of copying\n\
185   -L, --dereference            always follow symbolic links\n\
186 "), stdout);
187       fputs (_("\
188   -P, --no-dereference         never follow symbolic links\n\
189 "), stdout);
190       fputs (_("\
191   -p                           same as --preserve=mode,ownership,timestamps\n\
192       --preserve[=ATTR_LIST]   preserve the specified attributes (default:\n\
193                                  mode,ownership,timestamps), if possible\n\
194                                  additional attributes: links, all\n\
195 "), stdout);
196       fputs (_("\
197       --no-preserve=ATTR_LIST  don't preserve the specified attributes\n\
198       --parents                use full source file name under DIRECTORY\n\
199 "), stdout);
200       fputs (_("\
201   -R, -r, --recursive          copy directories recursively\n\
202       --remove-destination     remove each existing destination file before\n\
203                                  attempting to open it (contrast with --force)\n\
204 "), stdout);
205       fputs (_("\
206       --sparse=WHEN            control creation of sparse files\n\
207       --strip-trailing-slashes  remove any trailing slashes from each SOURCE\n\
208                                  argument\n\
209 "), stdout);
210       fputs (_("\
211   -s, --symbolic-link          make symbolic links instead of copying\n\
212   -S, --suffix=SUFFIX          override the usual backup suffix\n\
213   -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY\n\
214   -T, --no-target-directory    treat DEST as a normal file\n\
215 "), stdout);
216       fputs (_("\
217   -u, --update                 copy only when the SOURCE file is newer\n\
218                                  than the destination file or when the\n\
219                                  destination file is missing\n\
220   -v, --verbose                explain what is being done\n\
221   -x, --one-file-system        stay on this file system\n\
222 "), stdout);
223       fputs (HELP_OPTION_DESCRIPTION, stdout);
224       fputs (VERSION_OPTION_DESCRIPTION, stdout);
225       fputs (_("\
226 \n\
227 By default, sparse SOURCE files are detected by a crude heuristic and the\n\
228 corresponding DEST file is made sparse as well.  That is the behavior\n\
229 selected by --sparse=auto.  Specify --sparse=always to create a sparse DEST\n\
230 file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\
231 Use --sparse=never to inhibit creation of sparse files.\n\
232 \n\
233 "), stdout);
234       fputs (_("\
235 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
236 The version control method may be selected via the --backup option or through\n\
237 the VERSION_CONTROL environment variable.  Here are the values:\n\
238 \n\
239 "), stdout);
240       fputs (_("\
241   none, off       never make backups (even if --backup is given)\n\
242   numbered, t     make numbered backups\n\
243   existing, nil   numbered if numbered backups exist, simple otherwise\n\
244   simple, never   always make simple backups\n\
245 "), stdout);
246       fputs (_("\
247 \n\
248 As a special case, cp makes a backup of SOURCE when the force and backup\n\
249 options are given and SOURCE and DEST are the same name for an existing,\n\
250 regular file.\n\
251 "), stdout);
252       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
253     }
254   exit (status);
255 }
256
257 /* Ensure that the parent directories of CONST_DST_NAME have the
258    correct protections, for the --parents option.  This is done
259    after all copying has been completed, to allow permissions
260    that don't include user write/execute.
261
262    SRC_OFFSET is the index in CONST_DST_NAME of the beginning of the
263    source directory name.
264
265    ATTR_LIST is a null-terminated linked list of structures that
266    indicates the end of the filename of each intermediate directory
267    in CONST_DST_NAME that may need to have its attributes changed.
268    The command `cp --parents --preserve a/b/c d/e_dir' changes the
269    attributes of the directories d/e_dir/a and d/e_dir/a/b to match
270    the corresponding source directories regardless of whether they
271    existed before the `cp' command was given.
272
273    Return true if the parent of CONST_DST_NAME and any intermediate
274    directories specified by ATTR_LIST have the proper permissions
275    when done.  */
276
277 static bool
278 re_protect (char const *const_dst_name, size_t src_offset,
279             struct dir_attr *attr_list, const struct cp_options *x)
280 {
281   struct dir_attr *p;
282   char *dst_name;               /* A copy of CONST_DST_NAME we can change. */
283   char *src_name;               /* The source name in `dst_name'. */
284
285   ASSIGN_STRDUPA (dst_name, const_dst_name);
286   src_name = dst_name + src_offset;
287
288   for (p = attr_list; p; p = p->next)
289     {
290       struct stat src_sb;
291
292       dst_name[p->slash_offset] = '\0';
293
294       if (XSTAT (x, src_name, &src_sb))
295         {
296           error (0, errno, _("failed to get attributes of %s"),
297                  quote (src_name));
298           return false;
299         }
300
301       /* Adjust the times (and if possible, ownership) for the copy.
302          chown turns off set[ug]id bits for non-root,
303          so do the chmod last.  */
304
305       if (x->preserve_timestamps)
306         {
307           struct timespec timespec[2];
308
309           timespec[0] = get_stat_atime (&src_sb);
310           timespec[1] = get_stat_mtime (&src_sb);
311
312           if (utimens (dst_name, timespec))
313             {
314               error (0, errno, _("failed to preserve times for %s"),
315                      quote (dst_name));
316               return false;
317             }
318         }
319
320       if (x->preserve_ownership)
321         {
322           if (chown (dst_name, src_sb.st_uid, src_sb.st_gid) != 0
323               && ! chown_failure_ok (x))
324             {
325               error (0, errno, _("failed to preserve ownership for %s"),
326                      quote (dst_name));
327               return false;
328             }
329         }
330
331       if (x->preserve_mode)
332         {
333           if (copy_acl (src_name, -1, dst_name, -1, src_sb.st_mode))
334             return false;
335         }
336       else if (p->restore_mode)
337         {
338           if (lchmod (dst_name, p->mode) != 0)
339             {
340               error (0, errno, _("failed to preserve permissions for %s"),
341                      quote (dst_name));
342               return false;
343             }
344         }
345
346       dst_name[p->slash_offset] = '/';
347     }
348   return true;
349 }
350
351 /* Ensure that the parent directory of CONST_DIR exists, for
352    the --parents option.
353
354    SRC_OFFSET is the index in CONST_DIR (which is a destination
355    directory) of the beginning of the source directory name.
356    Create any leading directories that don't already exist.
357    If VERBOSE_FMT_STRING is nonzero, use it as a printf format
358    string for printing a message after successfully making a directory.
359    The format should take two string arguments: the names of the
360    source and destination directories.
361    Creates a linked list of attributes of intermediate directories,
362    *ATTR_LIST, for re_protect to use after calling copy.
363    Sets *NEW_DST if this function creates parent of CONST_DIR.
364
365    Return true if parent of CONST_DIR exists as a directory with the proper
366    permissions when done.  */
367
368 /* FIXME: Synch this function with the one in ../lib/mkdir-p.c.  */
369
370 static bool
371 make_dir_parents_private (char const *const_dir, size_t src_offset,
372                           char const *verbose_fmt_string,
373                           struct dir_attr **attr_list, bool *new_dst,
374                           const struct cp_options *x)
375 {
376   struct stat stats;
377   char *dir;            /* A copy of CONST_DIR we can change.  */
378   char *src;            /* Source name in DIR.  */
379   char *dst_dir;        /* Leading directory of DIR.  */
380   size_t dirlen;        /* Length of DIR.  */
381
382   ASSIGN_STRDUPA (dir, const_dir);
383
384   src = dir + src_offset;
385
386   dirlen = dir_len (dir);
387   dst_dir = alloca (dirlen + 1);
388   memcpy (dst_dir, dir, dirlen);
389   dst_dir[dirlen] = '\0';
390
391   *attr_list = NULL;
392
393   if (XSTAT (x, dst_dir, &stats))
394     {
395       /* A parent of CONST_DIR does not exist.
396          Make all missing intermediate directories. */
397       char *slash;
398
399       slash = src;
400       while (*slash == '/')
401         slash++;
402       while ((slash = strchr (slash, '/')))
403         {
404           /* Add this directory to the list of directories whose modes need
405              fixing later. */
406           struct dir_attr *new = xmalloc (sizeof *new);
407           new->slash_offset = slash - dir;
408           new->restore_mode = false;
409           new->next = *attr_list;
410           *attr_list = new;
411
412           *slash = '\0';
413           if (XSTAT (x, dir, &stats))
414             {
415               mode_t src_mode;
416               mode_t omitted_permissions;
417               mode_t mkdir_mode;
418               int src_errno;
419
420               /* This component does not exist.  We must set
421                  *new_dst and new->mode inside this loop because,
422                  for example, in the command `cp --parents ../a/../b/c e_dir',
423                  make_dir_parents_private creates only e_dir/../a if
424                  ./b already exists. */
425               *new_dst = true;
426               src_errno = (XSTAT (x, src, &stats) != 0
427                            ? errno
428                            : S_ISDIR (stats.st_mode)
429                            ? 0
430                            : ENOTDIR);
431               if (src_errno)
432                 {
433                   error (0, src_errno, _("failed to get attributes of %s"),
434                          quote (src));
435                   return false;
436                 }
437               src_mode = stats.st_mode;
438
439               /* If the ownership or special mode bits might change,
440                  omit some permissions at first, so unauthorized users
441                  cannot nip in before the file is ready.  */
442               omitted_permissions = (src_mode
443                                      & (x->preserve_ownership
444                                         ? S_IRWXG | S_IRWXO
445                                         : x->preserve_mode
446                                         ? S_IWGRP | S_IWOTH
447                                         : 0));
448
449               /* POSIX says mkdir's behavior is implementation-defined when
450                  (src_mode & ~S_IRWXUGO) != 0.  However, common practice is
451                  to ask mkdir to copy all the CHMOD_MODE_BITS, letting mkdir
452                  decide what to do with S_ISUID | S_ISGID | S_ISVTX.  */
453               mkdir_mode = src_mode & CHMOD_MODE_BITS & ~omitted_permissions;
454               if (mkdir (dir, mkdir_mode) != 0)
455                 {
456                   error (0, errno, _("cannot make directory %s"),
457                          quote (dir));
458                   return false;
459                 }
460               else
461                 {
462                   if (verbose_fmt_string != NULL)
463                     printf (verbose_fmt_string, src, dir);
464                 }
465
466               /* We need search and write permissions to the new directory
467                  for writing the directory's contents. Check if these
468                  permissions are there.  */
469
470               if (lstat (dir, &stats))
471                 {
472                   error (0, errno, _("failed to get attributes of %s"),
473                          quote (dir));
474                   return false;
475                 }
476
477
478               if (! x->preserve_mode)
479                 {
480                   if (omitted_permissions & ~stats.st_mode)
481                     omitted_permissions &= ~ cached_umask ();
482                   if (omitted_permissions & ~stats.st_mode
483                       || (stats.st_mode & S_IRWXU) != S_IRWXU)
484                     {
485                       new->mode = stats.st_mode | omitted_permissions;
486                       new->restore_mode = true;
487                     }
488                 }
489
490               if ((stats.st_mode & S_IRWXU) != S_IRWXU)
491                 {
492                   /* Make the new directory searchable and writable.
493                      The original permissions will be restored later.  */
494
495                   if (lchmod (dir, stats.st_mode | S_IRWXU) != 0)
496                     {
497                       error (0, errno, _("setting permissions for %s"),
498                              quote (dir));
499                       return false;
500                     }
501                 }
502             }
503           else if (!S_ISDIR (stats.st_mode))
504             {
505               error (0, 0, _("%s exists but is not a directory"),
506                      quote (dir));
507               return false;
508             }
509           else
510             *new_dst = false;
511           *slash++ = '/';
512
513           /* Avoid unnecessary calls to `stat' when given
514              file names containing multiple adjacent slashes.  */
515           while (*slash == '/')
516             slash++;
517         }
518     }
519
520   /* We get here if the parent of DIR already exists.  */
521
522   else if (!S_ISDIR (stats.st_mode))
523     {
524       error (0, 0, _("%s exists but is not a directory"), quote (dst_dir));
525       return false;
526     }
527   else
528     {
529       *new_dst = false;
530     }
531   return true;
532 }
533
534 /* FILE is the last operand of this command.
535    Return true if FILE is a directory.
536    But report an error and exit if there is a problem accessing FILE,
537    or if FILE does not exist but would have to refer to an existing
538    directory if it referred to anything at all.
539
540    If the file exists, store the file's status into *ST.
541    Otherwise, set *NEW_DST.  */
542
543 static bool
544 target_directory_operand (char const *file, struct stat *st, bool *new_dst)
545 {
546   int err = (stat (file, st) == 0 ? 0 : errno);
547   bool is_a_dir = !err && S_ISDIR (st->st_mode);
548   if (err)
549     {
550       if (err != ENOENT)
551         error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
552       *new_dst = true;
553     }
554   return is_a_dir;
555 }
556
557 /* Scan the arguments, and copy each by calling copy.
558    Return true if successful.  */
559
560 static bool
561 do_copy (int n_files, char **file, const char *target_directory,
562          bool no_target_directory, struct cp_options *x)
563 {
564   struct stat sb;
565   bool new_dst = false;
566   bool ok = true;
567
568   if (n_files <= !target_directory)
569     {
570       if (n_files <= 0)
571         error (0, 0, _("missing file operand"));
572       else
573         error (0, 0, _("missing destination file operand after %s"),
574                quote (file[0]));
575       usage (EXIT_FAILURE);
576     }
577
578   if (no_target_directory)
579     {
580       if (target_directory)
581         error (EXIT_FAILURE, 0,
582                _("Cannot combine --target-directory (-t) "
583                  "and --no-target-directory (-T)"));
584       if (2 < n_files)
585         {
586           error (0, 0, _("extra operand %s"), quote (file[2]));
587           usage (EXIT_FAILURE);
588         }
589     }
590   else if (!target_directory)
591     {
592       if (2 <= n_files
593           && target_directory_operand (file[n_files - 1], &sb, &new_dst))
594         target_directory = file[--n_files];
595       else if (2 < n_files)
596         error (EXIT_FAILURE, 0, _("target %s is not a directory"),
597                quote (file[n_files - 1]));
598     }
599
600   if (target_directory)
601     {
602       /* cp file1...filen edir
603          Copy the files `file1' through `filen'
604          to the existing directory `edir'. */
605       int i;
606
607       /* Initialize these hash tables only if we'll need them.
608          The problems they're used to detect can arise only if
609          there are two or more files to copy.  */
610       if (2 <= n_files)
611         {
612           dest_info_init (x);
613           src_info_init (x);
614         }
615
616       for (i = 0; i < n_files; i++)
617         {
618           char *dst_name;
619           bool parent_exists = true;  /* True if dir_name (dst_name) exists. */
620           struct dir_attr *attr_list;
621           char *arg_in_concat = NULL;
622           char *arg = file[i];
623
624           /* Trailing slashes are meaningful (i.e., maybe worth preserving)
625              only in the source file names.  */
626           if (remove_trailing_slashes)
627             strip_trailing_slashes (arg);
628
629           if (parents_option)
630             {
631               char *arg_no_trailing_slash;
632
633               /* Use `arg' without trailing slashes in constructing destination
634                  file names.  Otherwise, we can end up trying to create a
635                  directory via `mkdir ("dst/foo/"...', which is not portable.
636                  It fails, due to the trailing slash, on at least
637                  NetBSD 1.[34] systems.  */
638               ASSIGN_STRDUPA (arg_no_trailing_slash, arg);
639               strip_trailing_slashes (arg_no_trailing_slash);
640
641               /* Append all of `arg' (minus any trailing slash) to `dest'.  */
642               dst_name = file_name_concat (target_directory,
643                                            arg_no_trailing_slash,
644                                            &arg_in_concat);
645
646               /* For --parents, we have to make sure that the directory
647                  dir_name (dst_name) exists.  We may have to create a few
648                  leading directories. */
649               parent_exists =
650                 (make_dir_parents_private
651                  (dst_name, arg_in_concat - dst_name,
652                   (x->verbose ? "%s -> %s\n" : NULL),
653                   &attr_list, &new_dst, x));
654             }
655           else
656             {
657               char *arg_base;
658               /* Append the last component of `arg' to `target_directory'.  */
659
660               ASSIGN_BASENAME_STRDUPA (arg_base, arg);
661               /* For `cp -R source/.. dest', don't copy into `dest/..'. */
662               dst_name = (STREQ (arg_base, "..")
663                           ? xstrdup (target_directory)
664                           : file_name_concat (target_directory, arg_base,
665                                               NULL));
666             }
667
668           if (!parent_exists)
669             {
670               /* make_dir_parents_private failed, so don't even
671                  attempt the copy.  */
672               ok = false;
673             }
674           else
675             {
676               bool copy_into_self;
677               ok &= copy (arg, dst_name, new_dst, x, &copy_into_self, NULL);
678
679               if (parents_option)
680                 ok &= re_protect (dst_name, arg_in_concat - dst_name,
681                                   attr_list, x);
682             }
683
684           free (dst_name);
685         }
686     }
687   else /* !target_directory */
688     {
689       char const *new_dest;
690       char const *source = file[0];
691       char const *dest = file[1];
692       bool unused;
693
694       if (parents_option)
695         {
696           error (0, 0,
697                  _("with --parents, the destination must be a directory"));
698           usage (EXIT_FAILURE);
699         }
700
701       /* When the force and backup options have been specified and
702          the source and destination are the same name for an existing
703          regular file, convert the user's command, e.g.,
704          `cp --force --backup foo foo' to `cp --force foo fooSUFFIX'
705          where SUFFIX is determined by any version control options used.  */
706
707       if (x->unlink_dest_after_failed_open
708           && x->backup_type != no_backups
709           && STREQ (source, dest)
710           && !new_dst && S_ISREG (sb.st_mode))
711         {
712           static struct cp_options x_tmp;
713
714           new_dest = find_backup_file_name (dest, x->backup_type);
715           /* Set x->backup_type to `no_backups' so that the normal backup
716              mechanism is not used when performing the actual copy.
717              backup_type must be set to `no_backups' only *after* the above
718              call to find_backup_file_name -- that function uses
719              backup_type to determine the suffix it applies.  */
720           x_tmp = *x;
721           x_tmp.backup_type = no_backups;
722           x = &x_tmp;
723         }
724       else
725         {
726           new_dest = dest;
727         }
728
729       ok = copy (source, new_dest, 0, x, &unused, NULL);
730     }
731
732   return ok;
733 }
734
735 static void
736 cp_option_init (struct cp_options *x)
737 {
738   x->copy_as_regular = true;
739   x->dereference = DEREF_UNDEFINED;
740   x->unlink_dest_before_opening = false;
741   x->unlink_dest_after_failed_open = false;
742   x->hard_link = false;
743   x->interactive = I_UNSPECIFIED;
744   x->chown_privileges = chown_privileges ();
745   x->move_mode = false;
746   x->one_file_system = false;
747
748   x->preserve_ownership = false;
749   x->preserve_links = false;
750   x->preserve_mode = false;
751   x->preserve_timestamps = false;
752
753   x->require_preserve = false;
754   x->recursive = false;
755   x->sparse_mode = SPARSE_AUTO;
756   x->symbolic_link = false;
757   x->set_mode = false;
758   x->mode = 0;
759
760   /* Not used.  */
761   x->stdin_tty = false;
762
763   x->update = false;
764   x->verbose = false;
765   x->dest_info = NULL;
766   x->src_info = NULL;
767 }
768
769 /* Given a string, ARG, containing a comma-separated list of arguments
770    to the --preserve option, set the appropriate fields of X to ON_OFF.  */
771 static void
772 decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
773 {
774   enum File_attribute
775     {
776       PRESERVE_MODE,
777       PRESERVE_TIMESTAMPS,
778       PRESERVE_OWNERSHIP,
779       PRESERVE_LINK,
780       PRESERVE_ALL
781     };
782   static enum File_attribute const preserve_vals[] =
783     {
784       PRESERVE_MODE, PRESERVE_TIMESTAMPS,
785       PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL
786     };
787   /* Valid arguments to the `--preserve' option. */
788   static char const* const preserve_args[] =
789     {
790       "mode", "timestamps",
791       "ownership", "links", "all", NULL
792     };
793   ARGMATCH_VERIFY (preserve_args, preserve_vals);
794
795   char *arg_writable = xstrdup (arg);
796   char *s = arg_writable;
797   do
798     {
799       /* find next comma */
800       char *comma = strchr (s, ',');
801       enum File_attribute val;
802
803       /* If we found a comma, put a NUL in its place and advance.  */
804       if (comma)
805         *comma++ = 0;
806
807       /* process S.  */
808       val = XARGMATCH ("--preserve", s, preserve_args, preserve_vals);
809       switch (val)
810         {
811         case PRESERVE_MODE:
812           x->preserve_mode = on_off;
813           break;
814
815         case PRESERVE_TIMESTAMPS:
816           x->preserve_timestamps = on_off;
817           break;
818
819         case PRESERVE_OWNERSHIP:
820           x->preserve_ownership = on_off;
821           break;
822
823         case PRESERVE_LINK:
824           x->preserve_links = on_off;
825           break;
826
827         case PRESERVE_ALL:
828           x->preserve_mode = on_off;
829           x->preserve_timestamps = on_off;
830           x->preserve_ownership = on_off;
831           x->preserve_links = on_off;
832           break;
833
834         default:
835           abort ();
836         }
837       s = comma;
838     }
839   while (s);
840
841   free (arg_writable);
842 }
843
844 int
845 main (int argc, char **argv)
846 {
847   int c;
848   bool ok;
849   bool make_backups = false;
850   char *backup_suffix_string;
851   char *version_control_string = NULL;
852   struct cp_options x;
853   bool copy_contents = false;
854   char *target_directory = NULL;
855   bool no_target_directory = false;
856
857   initialize_main (&argc, &argv);
858   program_name = argv[0];
859   setlocale (LC_ALL, "");
860   bindtextdomain (PACKAGE, LOCALEDIR);
861   textdomain (PACKAGE);
862
863   atexit (close_stdout);
864
865   cp_option_init (&x);
866
867   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
868      we'll actually use backup_suffix_string.  */
869   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
870
871   while ((c = getopt_long (argc, argv, "abdfHilLprst:uvxPRS:T",
872                            long_opts, NULL))
873          != -1)
874     {
875       switch (c)
876         {
877         case SPARSE_OPTION:
878           x.sparse_mode = XARGMATCH ("--sparse", optarg,
879                                      sparse_type_string, sparse_type);
880           break;
881
882         case 'a':               /* Like -dpPR. */
883           x.dereference = DEREF_NEVER;
884           x.preserve_links = true;
885           x.preserve_ownership = true;
886           x.preserve_mode = true;
887           x.preserve_timestamps = true;
888           x.require_preserve = true;
889           x.recursive = true;
890           break;
891
892         case 'b':
893           make_backups = true;
894           if (optarg)
895             version_control_string = optarg;
896           break;
897
898         case COPY_CONTENTS_OPTION:
899           copy_contents = true;
900           break;
901
902         case 'd':
903           x.preserve_links = true;
904           x.dereference = DEREF_NEVER;
905           break;
906
907         case 'f':
908           x.unlink_dest_after_failed_open = true;
909           break;
910
911         case 'H':
912           x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
913           break;
914
915         case 'i':
916           x.interactive = I_ASK_USER;
917           break;
918
919         case 'l':
920           x.hard_link = true;
921           break;
922
923         case 'L':
924           x.dereference = DEREF_ALWAYS;
925           break;
926
927         case 'P':
928           x.dereference = DEREF_NEVER;
929           break;
930
931         case NO_PRESERVE_ATTRIBUTES_OPTION:
932           decode_preserve_arg (optarg, &x, false);
933           break;
934
935         case PRESERVE_ATTRIBUTES_OPTION:
936           if (optarg == NULL)
937             {
938               /* Fall through to the case for `p' below.  */
939             }
940           else
941             {
942               decode_preserve_arg (optarg, &x, true);
943               x.require_preserve = true;
944               break;
945             }
946
947         case 'p':
948           x.preserve_ownership = true;
949           x.preserve_mode = true;
950           x.preserve_timestamps = true;
951           x.require_preserve = true;
952           break;
953
954         case PARENTS_OPTION:
955           parents_option = true;
956           break;
957
958         case 'r':
959         case 'R':
960           x.recursive = true;
961           break;
962
963         case REPLY_OPTION: /* Deprecated */
964           x.interactive = XARGMATCH ("--reply", optarg,
965                                      reply_args, reply_vals);
966           error (0, 0,
967                  _("the --reply option is deprecated; use -i or -f instead"));
968           break;
969
970         case UNLINK_DEST_BEFORE_OPENING:
971           x.unlink_dest_before_opening = true;
972           break;
973
974         case STRIP_TRAILING_SLASHES_OPTION:
975           remove_trailing_slashes = true;
976           break;
977
978         case 's':
979           x.symbolic_link = true;
980           break;
981
982         case 't':
983           if (target_directory)
984             error (EXIT_FAILURE, 0,
985                    _("multiple target directories specified"));
986           else
987             {
988               struct stat st;
989               if (stat (optarg, &st) != 0)
990                 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
991               if (! S_ISDIR (st.st_mode))
992                 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
993                        quote (optarg));
994             }
995           target_directory = optarg;
996           break;
997
998         case 'T':
999           no_target_directory = true;
1000           break;
1001
1002         case 'u':
1003           x.update = true;
1004           break;
1005
1006         case 'v':
1007           x.verbose = true;
1008           break;
1009
1010         case 'x':
1011           x.one_file_system = true;
1012           break;
1013
1014         case 'S':
1015           make_backups = true;
1016           backup_suffix_string = optarg;
1017           break;
1018
1019         case_GETOPT_HELP_CHAR;
1020
1021         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1022
1023         default:
1024           usage (EXIT_FAILURE);
1025         }
1026     }
1027
1028   if (x.hard_link & x.symbolic_link)
1029     {
1030       error (0, 0, _("cannot make both hard and symbolic links"));
1031       usage (EXIT_FAILURE);
1032     }
1033
1034   if (backup_suffix_string)
1035     simple_backup_suffix = xstrdup (backup_suffix_string);
1036
1037   x.backup_type = (make_backups
1038                    ? xget_version (_("backup type"),
1039                                    version_control_string)
1040                    : no_backups);
1041
1042   if (x.dereference == DEREF_UNDEFINED)
1043     {
1044       if (x.recursive)
1045         /* This is compatible with FreeBSD.  */
1046         x.dereference = DEREF_NEVER;
1047       else
1048         x.dereference = DEREF_ALWAYS;
1049     }
1050
1051   /* The key difference between -d (--no-dereference) and not is the version
1052      of `stat' to call.  */
1053
1054   if (x.recursive)
1055     x.copy_as_regular = copy_contents;
1056
1057   /* If --force (-f) was specified and we're in link-creation mode,
1058      first remove any existing destination file.  */
1059   if (x.unlink_dest_after_failed_open & (x.hard_link | x.symbolic_link))
1060     x.unlink_dest_before_opening = true;
1061
1062   /* Allocate space for remembering copied and created files.  */
1063
1064   hash_init ();
1065
1066   ok = do_copy (argc - optind, argv + optind,
1067                 target_directory, no_target_directory, &x);
1068
1069   forget_all ();
1070
1071   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
1072 }