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