(long_opts): Add --dereference, -L.
[platform/upstream/coreutils.git] / src / cp.c
1 /* cp.c  -- file copying (main routines)
2    Copyright (C) 89, 90, 91, 1995-2000 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 "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   TARGET_DIRECTORY_OPTION = CHAR_MAX + 1,
74   SPARSE_OPTION,
75   STRIP_TRAILING_SLASHES_OPTION,
76   PARENTS_OPTION
77 };
78
79 int stat ();
80 int lstat ();
81
82 /* Arrange to make lstat calls go through the wrapper function
83    on systems with an lstat function that does not dereference symlinks
84    that are specified with a trailing slash.  */
85 #if ! LSTAT_FOLLOWS_SLASHED_SYMLINK
86 int rpl_lstat PARAMS((const char *, struct stat *));
87 # undef lstat
88 # define lstat rpl_lstat
89 #endif
90
91 void strip_trailing_slashes ();
92
93 /* Initial number of entries in each hash table entry's table of inodes.  */
94 #define INITIAL_HASH_MODULE 100
95
96 /* Initial number of entries in the inode hash table.  */
97 #define INITIAL_ENTRY_TAB_SIZE 70
98
99 /* The invocation name of this program.  */
100 char *program_name;
101
102 /* If nonzero, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
103    as its destination instead of the usual "e_dir/e_file." */
104 static int flag_path = 0;
105
106 /* Remove any trailing slashes from each SOURCE argument.  */
107 static int remove_trailing_slashes;
108
109 static char const *const sparse_type_string[] =
110 {
111   "never", "auto", "always", 0
112 };
113
114 static enum Sparse_type const sparse_type[] =
115 {
116   SPARSE_NEVER, SPARSE_AUTO, SPARSE_ALWAYS
117 };
118
119 /* The error code to return to the system. */
120 static int exit_status = 0;
121
122 static struct option const long_opts[] =
123 {
124   {"archive", no_argument, NULL, 'a'},
125   {"backup", optional_argument, NULL, 'b'},
126   {"dereference", no_argument, NULL, 'L'},
127   {"force", no_argument, NULL, 'f'},
128   {"sparse", required_argument, NULL, SPARSE_OPTION},
129   {"interactive", no_argument, NULL, 'i'},
130   {"link", no_argument, NULL, 'l'},
131   {"no-dereference", no_argument, NULL, 'd'},
132   {"one-file-system", no_argument, NULL, 'x'},
133   {"parents", no_argument, NULL, PARENTS_OPTION},
134   {"path", no_argument, NULL, PARENTS_OPTION},   /* Deprecated.  */
135   {"preserve", no_argument, NULL, 'p'},
136   {"recursive", no_argument, NULL, 'R'},
137   {"strip-trailing-slash", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
138   {"suffix", required_argument, NULL, 'S'},
139   {"symbolic-link", no_argument, NULL, 's'},
140   {"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION},
141   {"update", no_argument, NULL, 'u'},
142   {"verbose", no_argument, NULL, 'v'},
143   {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */
144   {GETOPT_HELP_OPTION_DECL},
145   {GETOPT_VERSION_OPTION_DECL},
146   {NULL, 0, NULL, 0}
147 };
148
149 void
150 usage (int status)
151 {
152   if (status != 0)
153     fprintf (stderr, _("Try `%s --help' for more information.\n"),
154              program_name);
155   else
156     {
157       printf (_("\
158 Usage: %s [OPTION]... SOURCE DEST\n\
159   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
160   or:  %s [OPTION]... --target-directory=DIRECTORY SOURCE...\n\
161 "),
162               program_name, program_name, program_name);
163       printf (_("\
164 Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
165 \n\
166   -a, --archive                same as -dpR\n\
167       --backup[=CONTROL]       make a backup of each existing destination file\n\
168   -b                           like --backup but does not accept an argument\n\
169   -d, --no-dereference         preserve links\n\
170   -f, --force                  remove existing destinations, never prompt\n\
171   -i, --interactive            prompt before overwrite\n\
172   -H                           follow symbolic links that are explicitly\n\
173                                  specified in the command line, but do not\n\
174                                  follow symlinks that are found via recursive\n\
175                                  traversal\n\
176   -l, --link                   link files instead of copying\n\
177   -L, --dereference            always follow symbolic links\n\
178   -p, --preserve               preserve file attributes if possible\n\
179       --parents                append source path to DIRECTORY\n\
180   -P                           same as `--parents' for now; soon to change to\n\
181                                  `--no-dereference' to conform to POSIX\n\
182   -r                           copy recursively, non-directories as files\n\
183                                  WARNING: use -R instead when you might copy\n\
184                                  special files like FIFOs or /dev/zero\n\
185       --sparse=WHEN            control creation of sparse files\n\
186   -R, --recursive              copy directories recursively\n\
187       --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\
188                                  argument\n\
189   -s, --symbolic-link          make symbolic links instead of copying\n\
190   -S, --suffix=SUFFIX          override the usual backup suffix\n\
191       --target-directory=DIRECTORY  move all SOURCE arguments into DIRECTORY\n\
192   -u, --update                 copy only when the SOURCE file is newer\n\
193                                  than the destination file or when the\n\
194                                  destination file is missing\n\
195   -v, --verbose                explain what is being done\n\
196   -x, --one-file-system        stay on this file system\n\
197       --help                   display this help and exit\n\
198       --version                output version information and exit\n\
199 \n\
200 By default, sparse SOURCE files are detected by a crude heuristic and the\n\
201 corresponding DEST file is made sparse as well.  That is the behavior\n\
202 selected by --sparse=auto.  Specify --sparse=always to create a sparse DEST\n\
203 file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\
204 Use --sparse=never to inhibit creation of sparse files.\n\
205 \n\
206 "));
207       printf (_("\
208 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
209 The version control method may be selected via the --backup option or through\n\
210 the VERSION_CONTROL environment variable.  Here are the values:\n\
211 \n\
212   none, off       never make backups (even if --backup is given)\n\
213   numbered, t     make numbered backups\n\
214   existing, nil   numbered if numbered backups exist, simple otherwise\n\
215   simple, never   always make simple backups\n\
216 "));
217       printf (_("\
218 \n\
219 As a special case, cp makes a backup of SOURCE when the force and backup\n\
220 options are given and SOURCE and DEST are the same name for an existing,\n\
221 regular file.\n\
222 "));
223       puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
224     }
225   exit (status);
226 }
227
228 /* Ensure that the parent directories of CONST_DST_PATH have the
229    correct protections, for the --parents option.  This is done
230    after all copying has been completed, to allow permissions
231    that don't include user write/execute.
232
233    SRC_OFFSET is the index in CONST_DST_PATH of the beginning of the
234    source directory name.
235
236    ATTR_LIST is a null-terminated linked list of structures that
237    indicates the end of the filename of each intermediate directory
238    in CONST_DST_PATH that may need to have its attributes changed.
239    The command `cp --parents --preserve a/b/c d/e_dir' changes the
240    attributes of the directories d/e_dir/a and d/e_dir/a/b to match
241    the corresponding source directories regardless of whether they
242    existed before the `cp' command was given.
243
244    Return 0 if the parent of CONST_DST_PATH and any intermediate
245    directories specified by ATTR_LIST have the proper permissions
246    when done, otherwise 1. */
247
248 static int
249 re_protect (const char *const_dst_path, int src_offset,
250             struct dir_attr *attr_list, const struct cp_options *x)
251 {
252   struct dir_attr *p;
253   char *dst_path;               /* A copy of CONST_DST_PATH we can change. */
254   char *src_path;               /* The source name in `dst_path'. */
255   uid_t myeuid = geteuid ();
256
257   dst_path = (char *) alloca (strlen (const_dst_path) + 1);
258   strcpy (dst_path, const_dst_path);
259   src_path = dst_path + src_offset;
260
261   for (p = attr_list; p; p = p->next)
262     {
263       struct stat src_sb;
264
265       dst_path[p->slash_offset] = '\0';
266
267       if ((*(x->xstat)) (src_path, &src_sb))
268         {
269           error (0, errno, _("getting attributes of %s"),
270                  quote (src_path));
271           return 1;
272         }
273
274       /* Adjust the times (and if possible, ownership) for the copy.
275          chown turns off set[ug]id bits for non-root,
276          so do the chmod last.  */
277
278       if (x->preserve_timestamps)
279         {
280           struct utimbuf utb;
281
282           /* There's currently no interface to set file timestamps with
283              better than 1-second resolution, so discard any fractional
284              part of the source timestamp.  */
285
286           utb.actime = src_sb.st_atime;
287           utb.modtime = src_sb.st_mtime;
288
289           if (utime (dst_path, &utb))
290             {
291               error (0, errno, _("preserving times for %s"), quote (dst_path));
292               return 1;
293             }
294         }
295
296       if (x->preserve_owner_and_group)
297         {
298           /* If non-root uses -p, it's ok if we can't preserve ownership.
299              But root probably wants to know, e.g. if NFS disallows it,
300              or if the target system doesn't support file ownership.  */
301           if (chown (dst_path, src_sb.st_uid, src_sb.st_gid)
302               && ((errno != EPERM && errno != EINVAL) || myeuid == 0))
303             {
304               error (0, errno, _("preserving ownership for %s"),
305                      quote (dst_path));
306               return 1;
307             }
308         }
309
310       if (x->preserve_chmod_bits || p->is_new_dir)
311         {
312           if (chmod (dst_path, src_sb.st_mode & x->umask_kill))
313             {
314               error (0, errno, _("preserving permissions for %s"),
315                      quote (dst_path));
316               return 1;
317             }
318         }
319
320       dst_path[p->slash_offset] = '/';
321     }
322   return 0;
323 }
324
325 /* Ensure that the parent directory of CONST_DIRPATH exists, for
326    the --parents option.
327
328    SRC_OFFSET is the index in CONST_DIRPATH (which is a destination
329    path) of the beginning of the source directory name.
330    Create any leading directories that don't already exist,
331    giving them permissions MODE.
332    If VERBOSE_FMT_STRING is nonzero, use it as a printf format
333    string for printing a message after successfully making a directory.
334    The format should take two string arguments: the names of the
335    source and destination directories.
336    Creates a linked list of attributes of intermediate directories,
337    *ATTR_LIST, for re_protect to use after calling copy.
338    Sets *NEW_DST to 1 if this function creates parent of CONST_DIRPATH.
339
340    Return 0 if parent of CONST_DIRPATH exists as a directory with the proper
341    permissions when done, otherwise 1. */
342
343 static int
344 make_path_private (const char *const_dirpath, int src_offset, int mode,
345                    const char *verbose_fmt_string, struct dir_attr **attr_list,
346                    int *new_dst, int (*xstat)())
347 {
348   struct stat stats;
349   char *dirpath;                /* A copy of CONST_DIRPATH we can change. */
350   char *src;                    /* Source name in `dirpath'. */
351   char *tmp_dst_dirname;        /* Leading path of `dirpath', malloc. */
352   char *dst_dirname;            /* Leading path of `dirpath', alloca. */
353
354   dirpath = (char *) alloca (strlen (const_dirpath) + 1);
355   strcpy (dirpath, const_dirpath);
356
357   src = dirpath + src_offset;
358
359   tmp_dst_dirname = dir_name (dirpath);
360   dst_dirname = (char *) alloca (strlen (tmp_dst_dirname) + 1);
361   strcpy (dst_dirname, tmp_dst_dirname);
362   free (tmp_dst_dirname);
363
364   *attr_list = NULL;
365
366   if ((*xstat) (dst_dirname, &stats))
367     {
368       /* Parent of CONST_DIRNAME does not exist.
369          Make all missing intermediate directories. */
370       char *slash;
371
372       slash = src;
373       while (*slash == '/')
374         slash++;
375       while ((slash = strchr (slash, '/')))
376         {
377           /* Add this directory to the list of directories whose modes need
378              fixing later. */
379           struct dir_attr *new =
380             (struct dir_attr *) xmalloc (sizeof (struct dir_attr));
381           new->slash_offset = slash - dirpath;
382           new->next = *attr_list;
383           *attr_list = new;
384
385           *slash = '\0';
386           if ((*xstat) (dirpath, &stats))
387             {
388               /* This element of the path does not exist.  We must set
389                  *new_dst and new->is_new_dir inside this loop because,
390                  for example, in the command `cp --parents ../a/../b/c e_dir',
391                  make_path_private creates only e_dir/../a if ./b already
392                  exists. */
393               *new_dst = 1;
394               new->is_new_dir = 1;
395               if (mkdir (dirpath, mode))
396                 {
397                   error (0, errno, _("cannot make directory %s"),
398                          quote (dirpath));
399                   return 1;
400                 }
401               else
402                 {
403                   if (verbose_fmt_string != NULL)
404                     printf (verbose_fmt_string, src, dirpath);
405                 }
406             }
407           else if (!S_ISDIR (stats.st_mode))
408             {
409               error (0, 0, _("%s exists but is not a directory"),
410                      quote (dirpath));
411               return 1;
412             }
413           else
414             {
415               new->is_new_dir = 0;
416               *new_dst = 0;
417             }
418           *slash++ = '/';
419
420           /* Avoid unnecessary calls to `stat' when given
421              pathnames containing multiple adjacent slashes.  */
422           while (*slash == '/')
423             slash++;
424         }
425     }
426
427   /* We get here if the parent of `dirpath' already exists. */
428
429   else if (!S_ISDIR (stats.st_mode))
430     {
431       error (0, 0, _("%s exists but is not a directory"), quote (dst_dirname));
432       return 1;
433     }
434   else
435     {
436       *new_dst = 0;
437     }
438   return 0;
439 }
440
441 /* Scan the arguments, and copy each by calling copy.
442    Return 0 if successful, 1 if any errors occur. */
443
444 static int
445 do_copy (int n_files, char **file, const char *target_directory,
446          const struct cp_options *x)
447 {
448   const char *dest;
449   struct stat sb;
450   int new_dst = 0;
451   int ret = 0;
452   int dest_is_dir = 0;
453
454   if (n_files <= 0)
455     {
456       error (0, 0, _("missing file arguments"));
457       usage (1);
458     }
459   if (n_files == 1 && !target_directory)
460     {
461       error (0, 0, _("missing destination file"));
462       usage (1);
463     }
464
465   if (target_directory)
466     dest = target_directory;
467   else
468     {
469       dest = file[n_files - 1];
470       --n_files;
471     }
472
473   if (lstat (dest, &sb))
474     {
475       if (errno != ENOENT)
476         {
477           error (0, errno, _("accessing %s"), quote (dest));
478           return 1;
479         }
480
481       new_dst = 1;
482     }
483   else
484     {
485       struct stat sbx;
486
487       /* If `dest' is not a symlink to a nonexistent file, use
488          the results of stat instead of lstat, so we can copy files
489          into symlinks to directories. */
490       if (stat (dest, &sbx) == 0)
491         sb = sbx;
492
493       dest_is_dir = S_ISDIR (sb.st_mode);
494     }
495
496   if (!dest_is_dir)
497     {
498       if (target_directory)
499         {
500           error (0, 0, _("specified target, %s is not a directory"),
501                  quote (dest));
502           usage (1);
503         }
504
505       if (n_files > 1)
506         {
507           error (0, 0,
508          _("copying multiple files, but last argument %s is not a directory"),
509              quote (dest));
510           usage (1);
511         }
512     }
513
514   if (dest_is_dir)
515     {
516       /* cp file1...filen edir
517          Copy the files `file1' through `filen'
518          to the existing directory `edir'. */
519       int i;
520
521       for (i = 0; i < n_files; i++)
522         {
523           char *dst_path;
524           int parent_exists = 1; /* True if dir_name (dst_path) exists. */
525           struct dir_attr *attr_list;
526           char *arg_in_concat = NULL;
527           char *arg = file[i];
528
529           if (remove_trailing_slashes)
530             strip_trailing_slashes (arg);
531
532           if (flag_path)
533             {
534               /* Append all of `arg' to `dest'.  */
535               dst_path = path_concat (dest, arg, &arg_in_concat);
536               if (dst_path == NULL)
537                 xalloc_die ();
538
539               /* For --parents, we have to make sure that the directory
540                  dir_name (dst_path) exists.  We may have to create a few
541                  leading directories. */
542               parent_exists = !make_path_private (dst_path,
543                                                   arg_in_concat - dst_path,
544                                                   S_IRWXU,
545                                                   (x->verbose
546                                                    ? "%s -> %s\n" : NULL),
547                                                   &attr_list, &new_dst,
548                                                   x->xstat);
549             }
550           else
551             {
552               char *arg_base;
553               /* Append the last component of `arg' to `dest'.  */
554
555               ASSIGN_BASENAME_STRDUPA (arg_base, arg);
556               /* For `cp -R source/.. dest', don't copy into `dest/..'. */
557               dst_path = (STREQ (arg_base, "..")
558                           ? xstrdup (dest)
559                           : path_concat (dest, arg_base, NULL));
560             }
561
562           if (!parent_exists)
563             {
564               /* make_path_private failed, so don't even attempt the copy. */
565               ret = 1;
566             }
567           else
568             {
569               int copy_into_self;
570               ret |= copy (arg, dst_path, new_dst, x, &copy_into_self, NULL);
571               forget_all ();
572
573               if (flag_path)
574                 {
575                   ret |= re_protect (dst_path, arg_in_concat - dst_path,
576                                      attr_list, x);
577                 }
578             }
579
580           free (dst_path);
581         }
582       return ret;
583     }
584   else /* if (n_files == 1) */
585     {
586       char *new_dest;
587       char *source;
588       int unused;
589       struct stat source_stats;
590
591       if (flag_path)
592         {
593           error (0, 0,
594                _("when preserving paths, the destination must be a directory"));
595           usage (1);
596         }
597
598       source = file[0];
599
600       /* When the force and backup options have been specified and
601          the source and destination are the same name for an existing
602          regular file, convert the user's command, e.g.,
603          `cp --force --backup foo foo' to `cp --force foo fooSUFFIX'
604          where SUFFIX is determined by any version control options used.  */
605
606       if (x->force
607           && x->backup_type != none
608           && STREQ (source, dest)
609           && !new_dst && S_ISREG (sb.st_mode))
610         {
611           static struct cp_options x_tmp;
612
613           new_dest = find_backup_file_name (dest, x->backup_type);
614           /* Set x->backup_type to `none' so that the normal backup
615              mechanism is not used when performing the actual copy.
616              backup_type must be set to `none' only *after* the above
617              call to find_backup_file_name -- that function uses
618              backup_type to determine the suffix it applies.  */
619           x_tmp = *x;
620           x_tmp.backup_type = none;
621           x = &x_tmp;
622
623           if (new_dest == NULL)
624             xalloc_die ();
625         }
626
627       /* When the destination is specified with a trailing slash and the
628          source exists but is not a directory, convert the user's command
629          `cp source dest/' to `cp source dest/basename(source)'.  Doing
630          this ensures that the command `cp non-directory file/' will now
631          fail rather than performing the copy.  COPY diagnoses the case of
632          `cp directory non-directory'.  */
633
634       else if (dest[strlen (dest) - 1] == '/'
635           && lstat (source, &source_stats) == 0
636           && !S_ISDIR (source_stats.st_mode))
637         {
638           char *source_base;
639
640           ASSIGN_BASENAME_STRDUPA (source_base, source);
641           new_dest = (char *) alloca (strlen (dest)
642                                       + strlen (source_base) + 1);
643           stpcpy (stpcpy (new_dest, dest), source_base);
644         }
645       else
646         {
647           new_dest = (char *) dest;
648         }
649
650       return copy (source, new_dest, new_dst, x, &unused, NULL);
651     }
652
653   /* unreachable */
654 }
655
656 static void
657 cp_option_init (struct cp_options *x)
658 {
659   x->copy_as_regular = 1;
660   x->dereference = DEREF_UNDEFINED;
661   x->force = 0;
662   x->failed_unlink_is_fatal = 1;
663   x->hard_link = 0;
664   x->interactive = 0;
665   x->myeuid = geteuid ();
666   x->move_mode = 0;
667   x->one_file_system = 0;
668
669   x->preserve_owner_and_group = 0;
670   x->preserve_chmod_bits = 0;
671   x->preserve_timestamps = 0;
672
673   x->require_preserve = 0;
674   x->recursive = 0;
675   x->sparse_mode = SPARSE_AUTO;
676   x->symbolic_link = 0;
677   x->set_mode = 0;
678   x->mode = 0;
679
680   /* Find out the current file creation mask, to knock the right bits
681      when using chmod.  The creation mask is set to be liberal, so
682      that created directories can be written, even if it would not
683      have been allowed with the mask this process was started with.  */
684   x->umask_kill = ~ umask (0);
685
686   x->update = 0;
687   x->verbose = 0;
688 }
689
690 int
691 main (int argc, char **argv)
692 {
693   int c;
694   int make_backups = 0;
695   char *backup_suffix_string;
696   char *version_control_string = NULL;
697   struct cp_options x;
698   char *target_directory = NULL;
699   int used_P_option = 0;
700
701   program_name = argv[0];
702   setlocale (LC_ALL, "");
703   bindtextdomain (PACKAGE, LOCALEDIR);
704   textdomain (PACKAGE);
705
706   atexit (close_stdout);
707
708   cp_option_init (&x);
709
710   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
711      we'll actually use backup_suffix_string.  */
712   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
713
714   while ((c = getopt_long (argc, argv, "abdfHilLprsuvxPRS:V:", long_opts, NULL))
715          != -1)
716     {
717       switch (c)
718         {
719         case 0:
720           break;
721
722         case SPARSE_OPTION:
723           x.sparse_mode = XARGMATCH ("--sparse", optarg,
724                                      sparse_type_string, sparse_type);
725           break;
726
727         case 'a':               /* Like -dpR. */
728           x.dereference = DEREF_NEVER;
729           x.preserve_owner_and_group = 1;
730           x.preserve_chmod_bits = 1;
731           x.preserve_timestamps = 1;
732           x.require_preserve = 1;
733           x.recursive = 1;
734           x.copy_as_regular = 0;
735           break;
736
737         case 'V':  /* FIXME: this is deprecated.  Remove it in 2001.  */
738           error (0, 0,
739                  _("warning: --version-control (-V) is obsolete;  support for\
740  it\nwill be removed in some future release.  Use --backup=%s instead."
741                    ), optarg);
742           /* Fall through.  */
743
744         case 'b':
745           make_backups = 1;
746           if (optarg)
747             version_control_string = optarg;
748           break;
749
750         case 'd':
751           x.dereference = DEREF_NEVER;
752           break;
753
754         case 'f':
755           x.force = 1;
756           break;
757
758         case 'H':
759           x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
760           break;
761
762         case 'i':
763           x.interactive = 1;
764           break;
765
766         case 'l':
767           x.hard_link = 1;
768           break;
769
770         case 'L':
771           x.dereference = DEREF_ALWAYS;
772           break;
773
774         case 'p':
775           x.preserve_owner_and_group = 1;
776           x.preserve_chmod_bits = 1;
777           x.preserve_timestamps = 1;
778           x.require_preserve = 1;
779           break;
780
781         case 'P':
782           used_P_option = 1;
783           /* fall through */
784         case PARENTS_OPTION:
785           flag_path = 1;
786           break;
787
788         case 'r':
789           x.recursive = 1;
790           x.copy_as_regular = 1;
791           break;
792
793         case 'R':
794           x.recursive = 1;
795           x.copy_as_regular = 0;
796           break;
797
798         case STRIP_TRAILING_SLASHES_OPTION:
799           remove_trailing_slashes = 1;
800           break;
801
802         case 's':
803 #ifdef S_ISLNK
804           x.symbolic_link = 1;
805 #else
806           error (1, 0, _("symbolic links are not supported on this system"));
807 #endif
808           break;
809
810         case TARGET_DIRECTORY_OPTION:
811           target_directory = optarg;
812           break;
813
814         case 'u':
815           x.update = 1;
816           break;
817
818         case 'v':
819           x.verbose = 1;
820           break;
821
822         case 'x':
823           x.one_file_system = 1;
824           break;
825
826         case 'S':
827           make_backups = 1;
828           backup_suffix_string = optarg;
829           break;
830
831         case_GETOPT_HELP_CHAR;
832
833         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
834
835         default:
836           usage (1);
837         }
838     }
839
840   if (x.hard_link && x.symbolic_link)
841     {
842       error (0, 0, _("cannot make both hard and symbolic links"));
843       usage (1);
844     }
845
846   if (used_P_option)
847     {
848       error (0, 0,
849              _("\
850 Warning: the meaning of `-P' will change in the future to conform to POSIX.\n\
851 Use `--parents' for the old meaning, and `--no-dereference' for the new."));
852     }
853
854   if (backup_suffix_string)
855     simple_backup_suffix = xstrdup (backup_suffix_string);
856
857   x.backup_type = (make_backups
858                    ? xget_version (_("backup type"),
859                                    version_control_string)
860                    : none);
861
862   if (x.preserve_chmod_bits == 1)
863     x.umask_kill = ~ (mode_t) 0;
864
865   if (x.dereference == DEREF_UNDEFINED)
866     {
867       if (x.recursive)
868         /* This is compatible with FreeBSD.  */
869         x.dereference = DEREF_NEVER;
870       else
871         x.dereference = DEREF_ALWAYS;
872     }
873
874   /* The key difference between -d (--no-dereference) and not is the version
875      of `stat' to call.  */
876
877   if (x.dereference == DEREF_NEVER)
878     x.xstat = lstat;
879   else
880     {
881       /* For DEREF_COMMAND_LINE_ARGUMENTS, x.xstat must be stat for
882          each command line argument, but must later be `lstat' for
883          any symlinks that are found via recursive traversal.  */
884       x.xstat = stat;
885     }
886
887   /* Allocate space for remembering copied and created files.  */
888
889   hash_init (INITIAL_HASH_MODULE, INITIAL_ENTRY_TAB_SIZE);
890
891   exit_status |= do_copy (argc - optind, argv + optind, target_directory, &x);
892
893   exit (exit_status);
894 }