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