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