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