(usage): Use EXIT_SUCCESS, not 0, for clarity.
[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 "utimens.h"
36
37 #define ASSIGN_BASENAME_STRDUPA(Dest, File_name)        \
38   do                                                    \
39     {                                                   \
40       char *tmp_abns_;                                  \
41       ASSIGN_STRDUPA (tmp_abns_, (File_name));          \
42       strip_trailing_slashes (tmp_abns_);               \
43       Dest = base_name (tmp_abns_);                     \
44     }                                                   \
45   while (0)
46
47 /* The official name of this program (e.g., no `g' prefix).  */
48 #define PROGRAM_NAME "cp"
49
50 #define AUTHORS "Torbjorn Granlund", "David MacKenzie", "Jim Meyering"
51
52 #ifndef _POSIX_VERSION
53 uid_t geteuid ();
54 #endif
55
56 /* Used by do_copy, make_path_private, and re_protect
57    to keep a list of leading directories whose protections
58    need to be fixed after copying. */
59 struct dir_attr
60 {
61   int is_new_dir;
62   int slash_offset;
63   struct dir_attr *next;
64 };
65
66 /* For long options that have no equivalent short option, use a
67    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
68 enum
69 {
70   COPY_CONTENTS_OPTION = CHAR_MAX + 1,
71   NO_PRESERVE_ATTRIBUTES_OPTION,
72   PARENTS_OPTION,
73   PRESERVE_ATTRIBUTES_OPTION,
74   REPLY_OPTION,
75   SPARSE_OPTION,
76   STRIP_TRAILING_SLASHES_OPTION,
77   TARGET_DIRECTORY_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 nonzero, 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 int flag_path = 0;
93
94 /* Remove any trailing slashes from each SOURCE argument.  */
95 static int 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   {"one-file-system", no_argument, NULL, 'x'},
131   {"parents", no_argument, NULL, PARENTS_OPTION},
132   {"path", no_argument, NULL, PARENTS_OPTION},   /* Deprecated.  */
133   {"preserve", optional_argument, NULL, PRESERVE_ATTRIBUTES_OPTION},
134   {"recursive", no_argument, NULL, 'R'},
135   {"remove-destination", no_argument, NULL, UNLINK_DEST_BEFORE_OPENING},
136   {"reply", required_argument, NULL, REPLY_OPTION},
137   {"sparse", required_argument, NULL, SPARSE_OPTION},
138   {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
139   {"suffix", required_argument, NULL, 'S'},
140   {"symbolic-link", no_argument, NULL, 's'},
141   {"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION},
142   {"update", no_argument, NULL, 'u'},
143   {"verbose", no_argument, NULL, 'v'},
144   {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */
145   {GETOPT_HELP_OPTION_DECL},
146   {GETOPT_VERSION_OPTION_DECL},
147   {NULL, 0, NULL, 0}
148 };
149
150 void
151 usage (int status)
152 {
153   if (status != EXIT_SUCCESS)
154     fprintf (stderr, _("Try `%s --help' for more information.\n"),
155              program_name);
156   else
157     {
158       printf (_("\
159 Usage: %s [OPTION]... SOURCE DEST\n\
160   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
161   or:  %s [OPTION]... --target-directory=DIRECTORY SOURCE...\n\
162 "),
163               program_name, program_name, program_name);
164       fputs (_("\
165 Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
166 \n\
167 "), stdout);
168       fputs (_("\
169 Mandatory arguments to long options are mandatory for short options too.\n\
170 "), stdout);
171       fputs (_("\
172   -a, --archive                same as -dpR\n\
173       --backup[=CONTROL]       make a backup of each existing destination file\n\
174   -b                           like --backup but does not accept an argument\n\
175       --copy-contents          copy contents of special files when recursive\n\
176   -d                           same as --no-dereference --preserve=link\n\
177 "), stdout);
178       fputs (_("\
179       --no-dereference         never follow symbolic links\n\
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   -p                           same as --preserve=mode,ownership,timestamps\n\
189       --preserve[=ATTR_LIST]   preserve the specified attributes (default:\n\
190                                  mode,ownership,timestamps), if possible\n\
191                                  additional attributes: links, all\n\
192 "), stdout);
193       fputs (_("\
194       --no-preserve=ATTR_LIST  don't preserve the specified attributes\n\
195       --parents                append source path to DIRECTORY\n\
196   -P                           same as `--no-dereference'\n\
197 "), stdout);
198       fputs (_("\
199   -R, -r, --recursive          copy directories recursively\n\
200       --remove-destination     remove each existing destination file before\n\
201                                  attempting to open it (contrast with --force)\n\
202 "), stdout);
203       fputs (_("\
204       --reply={yes,no,query}   specify how to handle the prompt about an\n\
205                                  existing destination file\n\
206       --sparse=WHEN            control creation of sparse files\n\
207       --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\
208                                  argument\n\
209 "), stdout);
210       fputs (_("\
211   -s, --symbolic-link          make symbolic links instead of copying\n\
212   -S, --suffix=SUFFIX          override the usual backup suffix\n\
213       --target-directory=DIRECTORY  move all SOURCE arguments into DIRECTORY\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_PATH 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_PATH 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_PATH 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 0 if the parent of CONST_DST_PATH and any intermediate
273    directories specified by ATTR_LIST have the proper permissions
274    when done, otherwise 1. */
275
276 static int
277 re_protect (const char *const_dst_path, int src_offset,
278             struct dir_attr *attr_list, const struct cp_options *x)
279 {
280   struct dir_attr *p;
281   char *dst_path;               /* A copy of CONST_DST_PATH we can change. */
282   char *src_path;               /* The source name in `dst_path'. */
283   uid_t myeuid = geteuid ();
284
285   ASSIGN_STRDUPA (dst_path, const_dst_path);
286   src_path = dst_path + src_offset;
287
288   for (p = attr_list; p; p = p->next)
289     {
290       struct stat src_sb;
291
292       dst_path[p->slash_offset] = '\0';
293
294       if ((*(x->xstat)) (src_path, &src_sb))
295         {
296           error (0, errno, _("failed to get attributes of %s"),
297                  quote (src_path));
298           return 1;
299         }
300
301       /* Adjust the times (and if possible, ownership) for the copy.
302          chown turns off set[ug]id bits for non-root,
303          so do the chmod last.  */
304
305       if (x->preserve_timestamps)
306         {
307           struct timespec timespec[2];
308
309           timespec[0].tv_sec = src_sb.st_atime;
310           timespec[0].tv_nsec = TIMESPEC_NS (src_sb.st_atim);
311           timespec[1].tv_sec = src_sb.st_mtime;
312           timespec[1].tv_nsec = TIMESPEC_NS (src_sb.st_mtim);
313
314           if (utimens (dst_path, timespec))
315             {
316               error (0, errno, _("failed to preserve times for %s"),
317                      quote (dst_path));
318               return 1;
319             }
320         }
321
322       if (x->preserve_ownership)
323         {
324           /* If non-root uses -p, it's ok if we can't preserve ownership.
325              But root probably wants to know, e.g. if NFS disallows it,
326              or if the target system doesn't support file ownership.  */
327           if (chown (dst_path, src_sb.st_uid, src_sb.st_gid)
328               && ((errno != EPERM && errno != EINVAL) || myeuid == 0))
329             {
330               error (0, errno, _("failed to preserve ownership for %s"),
331                      quote (dst_path));
332               return 1;
333             }
334         }
335
336       if (x->preserve_mode || p->is_new_dir)
337         {
338           if (chmod (dst_path, src_sb.st_mode & x->umask_kill))
339             {
340               error (0, errno, _("failed to preserve permissions for %s"),
341                      quote (dst_path));
342               return 1;
343             }
344         }
345
346       dst_path[p->slash_offset] = '/';
347     }
348   return 0;
349 }
350
351 /* Ensure that the parent directory of CONST_DIRPATH exists, for
352    the --parents option.
353
354    SRC_OFFSET is the index in CONST_DIRPATH (which is a destination
355    path) of the beginning of the source directory name.
356    Create any leading directories that don't already exist,
357    giving them permissions MODE.
358    If VERBOSE_FMT_STRING is nonzero, use it as a printf format
359    string for printing a message after successfully making a directory.
360    The format should take two string arguments: the names of the
361    source and destination directories.
362    Creates a linked list of attributes of intermediate directories,
363    *ATTR_LIST, for re_protect to use after calling copy.
364    Sets *NEW_DST to 1 if this function creates parent of CONST_DIRPATH.
365
366    Return 0 if parent of CONST_DIRPATH exists as a directory with the proper
367    permissions when done, otherwise 1. */
368
369 /* FIXME: find a way to synch this function with the one in lib/makepath.c. */
370
371 static int
372 make_path_private (const char *const_dirpath, int src_offset, int mode,
373                    const char *verbose_fmt_string, struct dir_attr **attr_list,
374                    int *new_dst, int (*xstat)())
375 {
376   struct stat stats;
377   char *dirpath;                /* A copy of CONST_DIRPATH we can change. */
378   char *src;                    /* Source name in `dirpath'. */
379   char *dst_dirname;            /* Leading path of `dirpath'. */
380   size_t dirlen;                /* Length of leading path of `dirpath'. */
381
382   ASSIGN_STRDUPA (dirpath, const_dirpath);
383
384   src = dirpath + src_offset;
385
386   dirlen = dir_len (dirpath);
387   dst_dirname = alloca (dirlen + 1);
388   memcpy (dst_dirname, dirpath, dirlen);
389   dst_dirname[dirlen] = '\0';
390
391   *attr_list = NULL;
392
393   if ((*xstat) (dst_dirname, &stats))
394     {
395       /* Parent of CONST_DIRNAME does not exist.
396          Make all missing intermediate directories. */
397       char *slash;
398
399       slash = src;
400       while (*slash == '/')
401         slash++;
402       while ((slash = strchr (slash, '/')))
403         {
404           /* Add this directory to the list of directories whose modes need
405              fixing later. */
406           struct dir_attr *new = xmalloc (sizeof *new);
407           new->slash_offset = slash - dirpath;
408           new->next = *attr_list;
409           *attr_list = new;
410
411           *slash = '\0';
412           if ((*xstat) (dirpath, &stats))
413             {
414               /* This element of the path does not exist.  We must set
415                  *new_dst and new->is_new_dir inside this loop because,
416                  for example, in the command `cp --parents ../a/../b/c e_dir',
417                  make_path_private creates only e_dir/../a if ./b already
418                  exists. */
419               *new_dst = 1;
420               new->is_new_dir = 1;
421               if (mkdir (dirpath, mode))
422                 {
423                   error (0, errno, _("cannot make directory %s"),
424                          quote (dirpath));
425                   return 1;
426                 }
427               else
428                 {
429                   if (verbose_fmt_string != NULL)
430                     printf (verbose_fmt_string, src, dirpath);
431                 }
432             }
433           else if (!S_ISDIR (stats.st_mode))
434             {
435               error (0, 0, _("%s exists but is not a directory"),
436                      quote (dirpath));
437               return 1;
438             }
439           else
440             {
441               new->is_new_dir = 0;
442               *new_dst = 0;
443             }
444           *slash++ = '/';
445
446           /* Avoid unnecessary calls to `stat' when given
447              pathnames containing multiple adjacent slashes.  */
448           while (*slash == '/')
449             slash++;
450         }
451     }
452
453   /* We get here if the parent of `dirpath' already exists. */
454
455   else if (!S_ISDIR (stats.st_mode))
456     {
457       error (0, 0, _("%s exists but is not a directory"), quote (dst_dirname));
458       return 1;
459     }
460   else
461     {
462       *new_dst = 0;
463     }
464   return 0;
465 }
466
467 /* Scan the arguments, and copy each by calling copy.
468    Return 0 if successful, 1 if any errors occur. */
469
470 static int
471 do_copy (int n_files, char **file, const char *target_directory,
472          struct cp_options *x)
473 {
474   const char *dest;
475   struct stat sb;
476   int new_dst = 0;
477   int ret = 0;
478   int dest_is_dir = 0;
479
480   if (n_files <= 0)
481     {
482       error (0, 0, _("missing file argument"));
483       usage (EXIT_FAILURE);
484     }
485   if (n_files == 1 && !target_directory)
486     {
487       error (0, 0, _("missing destination file"));
488       usage (EXIT_FAILURE);
489     }
490
491   if (target_directory)
492     dest = target_directory;
493   else
494     {
495       dest = file[n_files - 1];
496       --n_files;
497     }
498
499   /* Initialize these hash tables only if we'll need them.
500      The problems they're used to detect can arise only if
501      there are two or more files to copy.  */
502   if (n_files >= 2)
503     {
504       dest_info_init (x);
505       src_info_init (x);
506     }
507
508   if (lstat (dest, &sb))
509     {
510       if (errno != ENOENT)
511         {
512           error (0, errno, _("accessing %s"), quote (dest));
513           return 1;
514         }
515
516       new_dst = 1;
517     }
518   else
519     {
520       struct stat sbx;
521
522       /* If `dest' is not a symlink to a nonexistent file, use
523          the results of stat instead of lstat, so we can copy files
524          into symlinks to directories. */
525       if (stat (dest, &sbx) == 0)
526         sb = sbx;
527
528       dest_is_dir = S_ISDIR (sb.st_mode);
529     }
530
531   if (!dest_is_dir)
532     {
533       if (target_directory || 1 < n_files)
534         {
535           char const *msg;
536           if (new_dst)
537             msg = N_("%s: specified destination directory does not exist");
538           else if (target_directory)
539             msg = N_("%s: specified target is not a directory");
540           else /* n_files > 1 */
541             msg =
542           N_("copying multiple files, but last argument %s is not a directory");
543
544           error (0, 0, _(msg), quote (dest));
545           usage (EXIT_FAILURE);
546         }
547     }
548
549   if (dest_is_dir)
550     {
551       /* cp file1...filen edir
552          Copy the files `file1' through `filen'
553          to the existing directory `edir'. */
554       int i;
555
556       for (i = 0; i < n_files; i++)
557         {
558           char *dst_path;
559           int parent_exists = 1; /* True if dir_name (dst_path) exists. */
560           struct dir_attr *attr_list;
561           char *arg_in_concat = NULL;
562           char *arg = file[i];
563
564           /* Trailing slashes are meaningful (i.e., maybe worth preserving)
565              only in the source file names.  */
566           if (remove_trailing_slashes)
567             strip_trailing_slashes (arg);
568
569           if (flag_path)
570             {
571               char *arg_no_trailing_slash;
572
573               /* Use `arg' without trailing slashes in constructing destination
574                  file names.  Otherwise, we can end up trying to create a
575                  directory via `mkdir ("dst/foo/"...', which is not portable.
576                  It fails, due to the trailing slash, on at least
577                  NetBSD 1.[34] systems.  */
578               ASSIGN_STRDUPA (arg_no_trailing_slash, arg);
579               strip_trailing_slashes (arg_no_trailing_slash);
580
581               /* Append all of `arg' (minus any trailing slash) to `dest'.  */
582               dst_path = path_concat (dest, arg_no_trailing_slash,
583                                       &arg_in_concat);
584               if (dst_path == NULL)
585                 xalloc_die ();
586
587               /* For --parents, we have to make sure that the directory
588                  dir_name (dst_path) exists.  We may have to create a few
589                  leading directories. */
590               parent_exists = !make_path_private (dst_path,
591                                                   arg_in_concat - dst_path,
592                                                   S_IRWXU,
593                                                   (x->verbose
594                                                    ? "%s -> %s\n" : NULL),
595                                                   &attr_list, &new_dst,
596                                                   x->xstat);
597             }
598           else
599             {
600               char *arg_base;
601               /* Append the last component of `arg' to `dest'.  */
602
603               ASSIGN_BASENAME_STRDUPA (arg_base, arg);
604               /* For `cp -R source/.. dest', don't copy into `dest/..'. */
605               dst_path = (STREQ (arg_base, "..")
606                           ? xstrdup (dest)
607                           : path_concat (dest, arg_base, NULL));
608             }
609
610           if (!parent_exists)
611             {
612               /* make_path_private failed, so don't even attempt the copy. */
613               ret = 1;
614             }
615           else
616             {
617               int copy_into_self;
618               ret |= copy (arg, dst_path, new_dst, x, &copy_into_self, NULL);
619
620               if (flag_path)
621                 {
622                   ret |= re_protect (dst_path, arg_in_concat - dst_path,
623                                      attr_list, x);
624                 }
625             }
626
627           free (dst_path);
628         }
629       return ret;
630     }
631   else /* if (n_files == 1) */
632     {
633       char *new_dest;
634       char *source;
635       int unused;
636       struct stat source_stats;
637
638       if (flag_path)
639         {
640           error (0, 0,
641                _("when preserving paths, the destination must be a directory"));
642           usage (EXIT_FAILURE);
643         }
644
645       source = file[0];
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 != none
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 `none' so that the normal backup
662              mechanism is not used when performing the actual copy.
663              backup_type must be set to `none' 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 = none;
668           x = &x_tmp;
669
670           if (new_dest == NULL)
671             xalloc_die ();
672         }
673
674       /* When the destination is specified with a trailing slash and the
675          source exists but is not a directory, convert the user's command
676          `cp source dest/' to `cp source dest/basename(source)'.  Doing
677          this ensures that the command `cp non-directory file/' will now
678          fail rather than performing the copy.  COPY diagnoses the case of
679          `cp directory non-directory'.  */
680
681       else if (dest[strlen (dest) - 1] == '/'
682           && lstat (source, &source_stats) == 0
683           && !S_ISDIR (source_stats.st_mode))
684         {
685           char *source_base;
686
687           ASSIGN_BASENAME_STRDUPA (source_base, source);
688           new_dest = alloca (strlen (dest) + strlen (source_base) + 1);
689           stpcpy (stpcpy (new_dest, dest), source_base);
690         }
691       else
692         {
693           new_dest = (char *) dest;
694         }
695
696       return copy (source, new_dest, new_dst, x, &unused, NULL);
697     }
698
699   /* unreachable */
700 }
701
702 static void
703 cp_option_init (struct cp_options *x)
704 {
705   x->copy_as_regular = 1;
706   x->dereference = DEREF_UNDEFINED;
707   x->unlink_dest_before_opening = 0;
708   x->unlink_dest_after_failed_open = 0;
709   x->hard_link = 0;
710   x->interactive = I_UNSPECIFIED;
711   x->myeuid = geteuid ();
712   x->move_mode = 0;
713   x->one_file_system = 0;
714
715   x->preserve_ownership = 0;
716   x->preserve_links = 0;
717   x->preserve_mode = 0;
718   x->preserve_timestamps = 0;
719
720   x->require_preserve = 0;
721   x->recursive = 0;
722   x->sparse_mode = SPARSE_AUTO;
723   x->symbolic_link = 0;
724   x->set_mode = 0;
725   x->mode = 0;
726
727   /* Not used.  */
728   x->stdin_tty = 0;
729
730   /* Find out the current file creation mask, to knock the right bits
731      when using chmod.  The creation mask is set to be liberal, so
732      that created directories can be written, even if it would not
733      have been allowed with the mask this process was started with.  */
734   x->umask_kill = ~ umask (0);
735
736   x->update = 0;
737   x->verbose = 0;
738   x->dest_info = NULL;
739   x->src_info = NULL;
740 }
741
742 /* Given a string, ARG, containing a comma-separated list of arguments
743    to the --preserve option, set the appropriate fields of X to ON_OFF.  */
744 static void
745 decode_preserve_arg (char const *arg, struct cp_options *x, int on_off)
746 {
747   enum File_attribute
748     {
749       PRESERVE_MODE,
750       PRESERVE_TIMESTAMPS,
751       PRESERVE_OWNERSHIP,
752       PRESERVE_LINK,
753       PRESERVE_ALL
754     };
755   static enum File_attribute const preserve_vals[] =
756     {
757       PRESERVE_MODE, PRESERVE_TIMESTAMPS,
758       PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL
759     };
760
761   /* Valid arguments to the `--preserve' option. */
762   static char const* const preserve_args[] =
763     {
764       "mode", "timestamps",
765       "ownership", "links", "all", 0
766     };
767
768   char *arg_writable = xstrdup (arg);
769   char *s = arg_writable;
770   do
771     {
772       /* find next comma */
773       char *comma = strchr (s, ',');
774       enum File_attribute val;
775
776       /* If we found a comma, put a NUL in its place and advance.  */
777       if (comma)
778         *comma++ = 0;
779
780       /* process S.  */
781       val = XARGMATCH ("--preserve", s, preserve_args, preserve_vals);
782       switch (val)
783         {
784         case PRESERVE_MODE:
785           x->preserve_mode = on_off;
786           break;
787
788         case PRESERVE_TIMESTAMPS:
789           x->preserve_timestamps = on_off;
790           break;
791
792         case PRESERVE_OWNERSHIP:
793           x->preserve_ownership = on_off;
794           break;
795
796         case PRESERVE_LINK:
797           x->preserve_links = on_off;
798           break;
799
800         case PRESERVE_ALL:
801           x->preserve_mode = on_off;
802           x->preserve_timestamps = on_off;
803           x->preserve_ownership = on_off;
804           x->preserve_links = on_off;
805           break;
806
807         default:
808           abort ();
809         }
810       s = comma;
811     }
812   while (s);
813
814   free (arg_writable);
815 }
816
817 int
818 main (int argc, char **argv)
819 {
820   int c;
821   int exit_status;
822   int make_backups = 0;
823   char *backup_suffix_string;
824   char *version_control_string = NULL;
825   struct cp_options x;
826   int copy_contents = 0;
827   char *target_directory = NULL;
828
829   initialize_main (&argc, &argv);
830   program_name = argv[0];
831   setlocale (LC_ALL, "");
832   bindtextdomain (PACKAGE, LOCALEDIR);
833   textdomain (PACKAGE);
834
835   atexit (close_stdout);
836
837   cp_option_init (&x);
838
839   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
840      we'll actually use backup_suffix_string.  */
841   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
842
843   while ((c = getopt_long (argc, argv, "abdfHilLprsuvxPRS:V:", long_opts, NULL))
844          != -1)
845     {
846       switch (c)
847         {
848         case 0:
849           break;
850
851         case SPARSE_OPTION:
852           x.sparse_mode = XARGMATCH ("--sparse", optarg,
853                                      sparse_type_string, sparse_type);
854           break;
855
856         case 'a':               /* Like -dpPR. */
857           x.dereference = DEREF_NEVER;
858           x.preserve_links = 1;
859           x.preserve_ownership = 1;
860           x.preserve_mode = 1;
861           x.preserve_timestamps = 1;
862           x.require_preserve = 1;
863           x.recursive = 1;
864           break;
865
866         case 'V':  /* FIXME: this is deprecated.  Remove it in 2001.  */
867           error (0, 0,
868                  _("warning: --version-control (-V) is obsolete;  support for\
869  it\nwill be removed in some future release.  Use --backup=%s instead."
870                    ), optarg);
871           /* Fall through.  */
872
873         case 'b':
874           make_backups = 1;
875           if (optarg)
876             version_control_string = optarg;
877           break;
878
879         case COPY_CONTENTS_OPTION:
880           copy_contents = 1;
881           break;
882
883         case 'd':
884           x.preserve_links = 1;
885           x.dereference = DEREF_NEVER;
886           break;
887
888         case 'f':
889           x.unlink_dest_after_failed_open = 1;
890           break;
891
892         case 'H':
893           x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
894           break;
895
896         case 'i':
897           x.interactive = I_ASK_USER;
898           break;
899
900         case 'l':
901           x.hard_link = 1;
902           break;
903
904         case 'L':
905           x.dereference = DEREF_ALWAYS;
906           break;
907
908         case 'P':
909           x.dereference = DEREF_NEVER;
910           break;
911
912         case NO_PRESERVE_ATTRIBUTES_OPTION:
913           decode_preserve_arg (optarg, &x, 0);
914           break;
915
916         case PRESERVE_ATTRIBUTES_OPTION:
917           if (optarg == NULL)
918             {
919               /* Fall through to the case for `p' below.  */
920             }
921           else
922             {
923               decode_preserve_arg (optarg, &x, 1);
924               x.require_preserve = 1;
925               break;
926             }
927
928         case 'p':
929           x.preserve_ownership = 1;
930           x.preserve_mode = 1;
931           x.preserve_timestamps = 1;
932           x.require_preserve = 1;
933           break;
934
935         case PARENTS_OPTION:
936           flag_path = 1;
937           break;
938
939         case 'r':
940         case 'R':
941           x.recursive = 1;
942           break;
943
944         case REPLY_OPTION:
945           x.interactive = XARGMATCH ("--reply", optarg,
946                                      reply_args, reply_vals);
947           break;
948
949         case UNLINK_DEST_BEFORE_OPENING:
950           x.unlink_dest_before_opening = 1;
951           break;
952
953         case STRIP_TRAILING_SLASHES_OPTION:
954           remove_trailing_slashes = 1;
955           break;
956
957         case 's':
958 #ifdef S_ISLNK
959           x.symbolic_link = 1;
960 #else
961           error (EXIT_FAILURE, 0,
962                  _("symbolic links are not supported on this system"));
963 #endif
964           break;
965
966         case TARGET_DIRECTORY_OPTION:
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.dereference == DEREF_NEVER)
1026     x.xstat = lstat;
1027   else
1028     {
1029       /* For DEREF_COMMAND_LINE_ARGUMENTS, x.xstat must be stat for
1030          each command line argument, but must later be `lstat' for
1031          any symlinks that are found via recursive traversal.  */
1032       x.xstat = stat;
1033     }
1034
1035   if (x.recursive)
1036     x.copy_as_regular = copy_contents;
1037
1038   /* If --force (-f) was specified and we're in link-creation mode,
1039      first remove any existing destination file.  */
1040   if (x.unlink_dest_after_failed_open && (x.hard_link || x.symbolic_link))
1041     x.unlink_dest_before_opening = 1;
1042
1043   /* Allocate space for remembering copied and created files.  */
1044
1045   hash_init ();
1046
1047   exit_status = do_copy (argc - optind, argv + optind, target_directory, &x);
1048
1049   forget_all ();
1050
1051   exit (exit_status);
1052 }