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