1/* install - copy files and set attributes
2   Copyright (C) 1989-1991, 1995-2010 Free Software Foundation, Inc.
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 3 of the License, or
7   (at your option) 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, see <http://www.gnu.org/licenses/>.  */
16
17/* Written by David MacKenzie <djm@gnu.ai.mit.edu> */
18
19#include <config.h>
20#include <stdio.h>
21#include <getopt.h>
22#include <sys/types.h>
23#include <signal.h>
24#include <pwd.h>
25#include <grp.h>
26#include <selinux/selinux.h>
27
28#include "system.h"
29#include "backupfile.h"
30#include "error.h"
31#include "cp-hash.h"
32#include "copy.h"
33#include "filenamecat.h"
34#include "full-read.h"
35#include "mkancesdirs.h"
36#include "mkdir-p.h"
37#include "modechange.h"
38#include "prog-fprintf.h"
39#include "quote.h"
40#include "quotearg.h"
41#include "savewd.h"
42#include "stat-time.h"
43#include "utimens.h"
44#include "xstrtol.h"
45
46/* The official name of this program (e.g., no `g' prefix).  */
47#define PROGRAM_NAME "install"
48
49#define AUTHORS proper_name ("David MacKenzie")
50
51#if HAVE_SYS_WAIT_H
52# include <sys/wait.h>
53#endif
54
55static int selinux_enabled = 0;
56static bool use_default_selinux_context = true;
57
58#if ! HAVE_ENDGRENT
59# define endgrent() ((void) 0)
60#endif
61
62#if ! HAVE_ENDPWENT
63# define endpwent() ((void) 0)
64#endif
65
66#if ! HAVE_LCHOWN
67# define lchown(name, uid, gid) chown (name, uid, gid)
68#endif
69
70#if ! HAVE_MATCHPATHCON_INIT_PREFIX
71# define matchpathcon_init_prefix(a, p) /* empty */
72#endif
73
74static bool change_timestamps (struct stat const *from_sb, char const *to);
75static bool change_attributes (char const *name);
76static bool copy_file (const char *from, const char *to,
77                       const struct cp_options *x);
78static bool install_file_in_file_parents (char const *from, char *to,
79                                          struct cp_options *x);
80static bool install_file_in_dir (const char *from, const char *to_dir,
81                                 const struct cp_options *x);
82static bool install_file_in_file (const char *from, const char *to,
83                                  const struct cp_options *x);
84static void get_ids (void);
85static void strip (char const *name);
86static void announce_mkdir (char const *dir, void *options);
87static int make_ancestor (char const *dir, char const *component,
88                          void *options);
89void usage (int status);
90
91/* The user name that will own the files, or NULL to make the owner
92   the current user ID. */
93static char *owner_name;
94
95/* The user ID corresponding to `owner_name'. */
96static uid_t owner_id;
97
98/* The group name that will own the files, or NULL to make the group
99   the current group ID. */
100static char *group_name;
101
102/* The group ID corresponding to `group_name'. */
103static gid_t group_id;
104
105#define DEFAULT_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
106
107/* The file mode bits to which non-directory files will be set.  The umask has
108   no effect. */
109static mode_t mode = DEFAULT_MODE;
110
111/* Similar, but for directories.  */
112static mode_t dir_mode = DEFAULT_MODE;
113
114/* The file mode bits that the user cares about.  This should be a
115   superset of DIR_MODE and a subset of CHMOD_MODE_BITS.  This matters
116   for directories, since otherwise directories may keep their S_ISUID
117   or S_ISGID bits.  */
118static mode_t dir_mode_bits = CHMOD_MODE_BITS;
119
120/* Compare files before installing (-C) */
121static bool copy_only_if_needed;
122
123/* If true, strip executable files after copying them. */
124static bool strip_files;
125
126/* If true, install a directory instead of a regular file. */
127static bool dir_arg;
128
129/* Program used to strip binaries, "strip" is default */
130static char const *strip_program = "strip";
131
132/* For long options that have no equivalent short option, use a
133   non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
134enum
135{
136  PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1,
137  PRESERVE_CONTEXT_OPTION_DEPRECATED,
138  STRIP_PROGRAM_OPTION
139};
140
141static struct option const long_options[] =
142{
143  {"backup", optional_argument, NULL, 'b'},
144  {"compare", no_argument, NULL, 'C'},
145  {GETOPT_SELINUX_CONTEXT_OPTION_DECL},
146  {"directory", no_argument, NULL, 'd'},
147  {"group", required_argument, NULL, 'g'},
148  {"mode", required_argument, NULL, 'm'},
149  {"no-target-directory", no_argument, NULL, 'T'},
150  {"owner", required_argument, NULL, 'o'},
151  {"preserve-timestamps", no_argument, NULL, 'p'},
152  {"preserve-context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
153  /* --preserve_context was silently supported until Apr 2009.
154     FIXME: disable altogether in a year or so.  */
155  {"preserve_context", no_argument, NULL, PRESERVE_CONTEXT_OPTION_DEPRECATED},
156  {"strip", no_argument, NULL, 's'},
157  {"strip-program", required_argument, NULL, STRIP_PROGRAM_OPTION},
158  {"suffix", required_argument, NULL, 'S'},
159  {"target-directory", required_argument, NULL, 't'},
160  {"verbose", no_argument, NULL, 'v'},
161  {GETOPT_HELP_OPTION_DECL},
162  {GETOPT_VERSION_OPTION_DECL},
163  {NULL, 0, NULL, 0}
164};
165
166/* Compare content of opened files using file descriptors A_FD and B_FD. Return
167   true if files are equal. */
168static bool
169have_same_content (int a_fd, int b_fd)
170{
171  enum { CMP_BLOCK_SIZE = 4096 };
172  static char a_buff[CMP_BLOCK_SIZE];
173  static char b_buff[CMP_BLOCK_SIZE];
174
175  size_t size;
176  while (0 < (size = full_read (a_fd, a_buff, sizeof a_buff))) {
177    if (size != full_read (b_fd, b_buff, sizeof b_buff))
178      return false;
179
180    if (memcmp (a_buff, b_buff, size) != 0)
181      return false;
182  }
183
184  return size == 0;
185}
186
187/* Return true for mode with non-permission bits. */
188static bool
189extra_mode (mode_t input)
190{
191  const mode_t mask = ~S_IRWXUGO & ~S_IFMT;
192  return !! (input & mask);
193}
194
195/* Return true if copy of file SRC_NAME to file DEST_NAME is necessary. */
196static bool
197need_copy (const char *src_name, const char *dest_name,
198           const struct cp_options *x)
199{
200  struct stat src_sb, dest_sb;
201  int src_fd, dest_fd;
202  bool content_match;
203
204  if (extra_mode (mode))
205    return true;
206
207  /* compare files using stat */
208  if (lstat (src_name, &src_sb) != 0)
209    return true;
210
211  if (lstat (dest_name, &dest_sb) != 0)
212    return true;
213
214  if (!S_ISREG (src_sb.st_mode) || !S_ISREG (dest_sb.st_mode)
215      || extra_mode (src_sb.st_mode) || extra_mode (dest_sb.st_mode))
216    return true;
217
218  if (src_sb.st_size != dest_sb.st_size
219      || (dest_sb.st_mode & CHMOD_MODE_BITS) != mode
220      || dest_sb.st_uid != (owner_id == (uid_t) -1 ? getuid () : owner_id)
221      || dest_sb.st_gid != (group_id == (gid_t) -1 ? getgid () : group_id))
222    return true;
223
224  /* compare SELinux context if preserving */
225  if (selinux_enabled && x->preserve_security_context)
226    {
227      security_context_t file_scontext = NULL;
228      security_context_t to_scontext = NULL;
229      bool scontext_match;
230
231      if (getfilecon (src_name, &file_scontext) == -1)
232        return true;
233
234      if (getfilecon (dest_name, &to_scontext) == -1)
235        {
236          freecon (file_scontext);
237          return true;
238        }
239
240      scontext_match = STREQ (file_scontext, to_scontext);
241
242      freecon (file_scontext);
243      freecon (to_scontext);
244      if (!scontext_match)
245        return true;
246    }
247
248  /* compare files content */
249  src_fd = open (src_name, O_RDONLY | O_BINARY);
250  if (src_fd < 0)
251    return true;
252
253  dest_fd = open (dest_name, O_RDONLY | O_BINARY);
254  if (dest_fd < 0)
255    {
256      close (src_fd);
257      return true;
258    }
259
260  content_match = have_same_content (src_fd, dest_fd);
261
262  close (src_fd);
263  close (dest_fd);
264  return !content_match;
265}
266
267static void
268cp_option_init (struct cp_options *x)
269{
270  cp_options_default (x);
271  x->copy_as_regular = true;
272  x->reflink_mode = REFLINK_NEVER;
273  x->dereference = DEREF_ALWAYS;
274  x->unlink_dest_before_opening = true;
275  x->unlink_dest_after_failed_open = false;
276  x->hard_link = false;
277  x->interactive = I_UNSPECIFIED;
278  x->move_mode = false;
279  x->one_file_system = false;
280  x->preserve_ownership = false;
281  x->preserve_links = false;
282  x->preserve_mode = false;
283  x->preserve_timestamps = false;
284  x->reduce_diagnostics=false;
285  x->require_preserve = false;
286  x->require_preserve_context = false;
287  x->require_preserve_xattr = false;
288  x->recursive = false;
289  x->sparse_mode = SPARSE_AUTO;
290  x->symbolic_link = false;
291  x->backup_type = no_backups;
292
293  /* Create destination files initially writable so we can run strip on them.
294     Although GNU strip works fine on read-only files, some others
295     would fail.  */
296  x->set_mode = true;
297  x->mode = S_IRUSR | S_IWUSR;
298  x->stdin_tty = false;
299
300  x->open_dangling_dest_symlink = false;
301  x->update = false;
302  x->preserve_security_context = false;
303  x->preserve_xattr = false;
304  x->verbose = false;
305  x->dest_info = NULL;
306  x->src_info = NULL;
307}
308
309#ifdef ENABLE_MATCHPATHCON
310/* Modify file context to match the specified policy.
311   If an error occurs the file will remain with the default directory
312   context.  */
313static void
314setdefaultfilecon (char const *file)
315{
316  struct stat st;
317  security_context_t scontext = NULL;
318  static bool first_call = true;
319
320  if (selinux_enabled != 1)
321    {
322      /* Indicate no context found. */
323      return;
324    }
325  if (lstat (file, &st) != 0)
326    return;
327
328  if (first_call && IS_ABSOLUTE_FILE_NAME (file))
329    {
330      /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
331         is an optimization to minimize the expense of the following
332         matchpathcon call.  Do it only once, just before the first
333         matchpathcon call.  We *could* call matchpathcon_fini after
334         the final matchpathcon call, but that's not necessary, since
335         by then we're about to exit, and besides, the buffers it
336         would free are still reachable.  */
337      char const *p0;
338      char const *p = file + 1;
339      while (ISSLASH (*p))
340        ++p;
341
342      /* Record final leading slash, for when FILE starts with two or more.  */
343      p0 = p - 1;
344
345      if (*p)
346        {
347          char *prefix;
348          do
349            {
350              ++p;
351            }
352          while (*p && !ISSLASH (*p));
353
354          prefix = malloc (p - p0 + 2);
355          if (prefix)
356            {
357              stpcpy (stpncpy (prefix, p0, p - p0), "/");
358              matchpathcon_init_prefix (NULL, prefix);
359              free (prefix);
360            }
361        }
362    }
363  first_call = false;
364
365  /* If there's an error determining the context, or it has none,
366     return to allow default context */
367  if ((matchpathcon (file, st.st_mode, &scontext) != 0) ||
368      STREQ (scontext, "<<none>>"))
369    {
370      if (scontext != NULL)
371        freecon (scontext);
372      return;
373    }
374
375  if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
376    error (0, errno,
377           _("warning: %s: failed to change context to %s"),
378           quotearg_colon (file), scontext);
379
380  freecon (scontext);
381  return;
382}
383#else
384static void
385setdefaultfilecon (char const *file)
386{
387  (void) file;
388}
389#endif
390
391/* FILE is the last operand of this command.  Return true if FILE is a
392   directory.  But report an error there is a problem accessing FILE,
393   or if FILE does not exist but would have to refer to an existing
394   directory if it referred to anything at all.  */
395
396static bool
397target_directory_operand (char const *file)
398{
399  char const *b = last_component (file);
400  size_t blen = strlen (b);
401  bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
402  struct stat st;
403  int err = (stat (file, &st) == 0 ? 0 : errno);
404  bool is_a_dir = !err && S_ISDIR (st.st_mode);
405  if (err && err != ENOENT)
406    error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
407  if (is_a_dir < looks_like_a_dir)
408    error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
409  return is_a_dir;
410}
411
412/* Process a command-line file name, for the -d option.  */
413static int
414process_dir (char *dir, struct savewd *wd, void *options)
415{
416  return (make_dir_parents (dir, wd,
417                            make_ancestor, options,
418                            dir_mode, announce_mkdir,
419                            dir_mode_bits, owner_id, group_id, false)
420          ? EXIT_SUCCESS
421          : EXIT_FAILURE);
422}
423
424int
425main (int argc, char **argv)
426{
427  int optc;
428  int exit_status = EXIT_SUCCESS;
429  const char *specified_mode = NULL;
430  bool make_backups = false;
431  char *backup_suffix_string;
432  char *version_control_string = NULL;
433  bool mkdir_and_install = false;
434  struct cp_options x;
435  char const *target_directory = NULL;
436  bool no_target_directory = false;
437  int n_files;
438  char **file;
439  bool strip_program_specified = false;
440  security_context_t scontext = NULL;
441  /* set iff kernel has extra selinux system calls */
442  selinux_enabled = (0 < is_selinux_enabled ());
443
444  initialize_main (&argc, &argv);
445  set_program_name (argv[0]);
446  setlocale (LC_ALL, "");
447  bindtextdomain (PACKAGE, LOCALEDIR);
448  textdomain (PACKAGE);
449
450  atexit (close_stdin);
451
452  cp_option_init (&x);
453
454  owner_name = NULL;
455  group_name = NULL;
456  strip_files = false;
457  dir_arg = false;
458  umask (0);
459
460  /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
461     we'll actually use backup_suffix_string.  */
462  backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
463
464  while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z:", long_options,
465                              NULL)) != -1)
466    {
467      switch (optc)
468        {
469        case 'b':
470          make_backups = true;
471          if (optarg)
472            version_control_string = optarg;
473          break;
474        case 'c':
475          break;
476        case 'C':
477          copy_only_if_needed = true;
478          break;
479        case 's':
480          strip_files = true;
481#ifdef SIGCHLD
482          /* System V fork+wait does not work if SIGCHLD is ignored.  */
483          signal (SIGCHLD, SIG_DFL);
484#endif
485          break;
486        case STRIP_PROGRAM_OPTION:
487          strip_program = xstrdup (optarg);
488          strip_program_specified = true;
489          break;
490        case 'd':
491          dir_arg = true;
492          break;
493        case 'D':
494          mkdir_and_install = true;
495          break;
496        case 'v':
497          x.verbose = true;
498          break;
499        case 'g':
500          group_name = optarg;
501          break;
502        case 'm':
503          specified_mode = optarg;
504          break;
505        case 'o':
506          owner_name = optarg;
507          break;
508        case 'p':
509          x.preserve_timestamps = true;
510          break;
511        case 'S':
512          make_backups = true;
513          backup_suffix_string = optarg;
514          break;
515        case 't':
516          if (target_directory)
517            error (EXIT_FAILURE, 0,
518                   _("multiple target directories specified"));
519          else
520            {
521              struct stat st;
522              if (stat (optarg, &st) != 0)
523                error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
524              if (! S_ISDIR (st.st_mode))
525                error (EXIT_FAILURE, 0, _("target %s is not a directory"),
526                       quote (optarg));
527            }
528          target_directory = optarg;
529          break;
530        case 'T':
531          no_target_directory = true;
532          break;
533
534        case PRESERVE_CONTEXT_OPTION_DEPRECATED:
535          error (0, 0, _("WARNING: --preserve_context is deprecated; "
536                         "use --preserve-context instead"));
537          /* fall through */
538        case PRESERVE_CONTEXT_OPTION:
539          if ( ! selinux_enabled)
540            {
541              error (0, 0, _("WARNING: ignoring --preserve-context; "
542                             "this kernel is not SELinux-enabled"));
543              break;
544            }
545          x.preserve_security_context = true;
546          use_default_selinux_context = false;
547          break;
548        case 'Z':
549          if ( ! selinux_enabled)
550            {
551              error (0, 0, _("WARNING: ignoring --context (-Z); "
552                             "this kernel is not SELinux-enabled"));
553              break;
554            }
555          scontext = optarg;
556          use_default_selinux_context = false;
557          break;
558        case_GETOPT_HELP_CHAR;
559        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
560        default:
561          usage (EXIT_FAILURE);
562        }
563    }
564
565  /* Check for invalid combinations of arguments. */
566  if (dir_arg && strip_files)
567    error (EXIT_FAILURE, 0,
568           _("the strip option may not be used when installing a directory"));
569  if (dir_arg && target_directory)
570    error (EXIT_FAILURE, 0,
571           _("target directory not allowed when installing a directory"));
572
573  if (x.preserve_security_context && scontext != NULL)
574    error (EXIT_FAILURE, 0,
575           _("cannot force target context to %s and preserve it"),
576           quote (scontext));
577
578  if (backup_suffix_string)
579    simple_backup_suffix = xstrdup (backup_suffix_string);
580
581  x.backup_type = (make_backups
582                   ? xget_version (_("backup type"),
583                                   version_control_string)
584                   : no_backups);
585
586  if (scontext && setfscreatecon (scontext) < 0)
587    error (EXIT_FAILURE, errno,
588           _("failed to set default file creation context to %s"),
589           quote (scontext));
590
591  n_files = argc - optind;
592  file = argv + optind;
593
594  if (n_files <= ! (dir_arg || target_directory))
595    {
596      if (n_files <= 0)
597        error (0, 0, _("missing file operand"));
598      else
599        error (0, 0, _("missing destination file operand after %s"),
600               quote (file[0]));
601      usage (EXIT_FAILURE);
602    }
603
604  if (no_target_directory)
605    {
606      if (target_directory)
607        error (EXIT_FAILURE, 0,
608               _("cannot combine --target-directory (-t) "
609                 "and --no-target-directory (-T)"));
610      if (2 < n_files)
611        {
612          error (0, 0, _("extra operand %s"), quote (file[2]));
613          usage (EXIT_FAILURE);
614        }
615    }
616  else if (! (dir_arg || target_directory))
617    {
618      if (2 <= n_files && target_directory_operand (file[n_files - 1]))
619        target_directory = file[--n_files];
620      else if (2 < n_files)
621        error (EXIT_FAILURE, 0, _("target %s is not a directory"),
622               quote (file[n_files - 1]));
623    }
624
625  if (specified_mode)
626    {
627      struct mode_change *change = mode_compile (specified_mode);
628      if (!change)
629        error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
630      mode = mode_adjust (0, false, 0, change, NULL);
631      dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
632      free (change);
633    }
634
635  if (strip_program_specified && !strip_files)
636    error (0, 0, _("WARNING: ignoring --strip-program option as -s option was "
637                   "not specified"));
638
639  if (copy_only_if_needed && x.preserve_timestamps)
640    {
641      error (0, 0, _("options --compare (-C) and --preserve-timestamps are "
642                     "mutually exclusive"));
643      usage (EXIT_FAILURE);
644    }
645
646  if (copy_only_if_needed && strip_files)
647    {
648      error (0, 0, _("options --compare (-C) and --strip are mutually "
649                     "exclusive"));
650      usage (EXIT_FAILURE);
651    }
652
653  if (copy_only_if_needed && extra_mode (mode))
654    error (0, 0, _("the --compare (-C) option is ignored when you"
655                   " specify a mode with non-permission bits"));
656
657  get_ids ();
658
659  if (dir_arg)
660    exit_status = savewd_process_files (n_files, file, process_dir, &x);
661  else
662    {
663      /* FIXME: it's a little gross that this initialization is
664         required by copy.c::copy. */
665      hash_init ();
666
667      if (!target_directory)
668        {
669          if (! (mkdir_and_install
670                 ? install_file_in_file_parents (file[0], file[1], &x)
671                 : install_file_in_file (file[0], file[1], &x)))
672            exit_status = EXIT_FAILURE;
673        }
674      else
675        {
676          int i;
677          dest_info_init (&x);
678          for (i = 0; i < n_files; i++)
679            if (! install_file_in_dir (file[i], target_directory, &x))
680              exit_status = EXIT_FAILURE;
681        }
682    }
683
684  exit (exit_status);
685}
686
687/* Copy file FROM onto file TO, creating any missing parent directories of TO.
688   Return true if successful.  */
689
690static bool
691install_file_in_file_parents (char const *from, char *to,
692                              struct cp_options *x)
693{
694  bool save_working_directory =
695    ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
696  int status = EXIT_SUCCESS;
697
698  struct savewd wd;
699  savewd_init (&wd);
700  if (! save_working_directory)
701    savewd_finish (&wd);
702
703  if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
704    {
705      error (0, errno, _("cannot create directory %s"), to);
706      status = EXIT_FAILURE;
707    }
708
709  if (save_working_directory)
710    {
711      int restore_result = savewd_restore (&wd, status);
712      int restore_errno = errno;
713      savewd_finish (&wd);
714      if (EXIT_SUCCESS < restore_result)
715        return false;
716      if (restore_result < 0 && status == EXIT_SUCCESS)
717        {
718          error (0, restore_errno, _("cannot create directory %s"), to);
719          return false;
720        }
721    }
722
723  return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
724}
725
726/* Copy file FROM onto file TO and give TO the appropriate
727   attributes.
728   Return true if successful.  */
729
730static bool
731install_file_in_file (const char *from, const char *to,
732                      const struct cp_options *x)
733{
734  struct stat from_sb;
735  if (x->preserve_timestamps && stat (from, &from_sb) != 0)
736    {
737      error (0, errno, _("cannot stat %s"), quote (from));
738      return false;
739    }
740  if (! copy_file (from, to, x))
741    return false;
742  if (strip_files)
743    strip (to);
744  if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
745      && ! change_timestamps (&from_sb, to))
746    return false;
747  return change_attributes (to);
748}
749
750/* Copy file FROM into directory TO_DIR, keeping its same name,
751   and give the copy the appropriate attributes.
752   Return true if successful.  */
753
754static bool
755install_file_in_dir (const char *from, const char *to_dir,
756                     const struct cp_options *x)
757{
758  const char *from_base = last_component (from);
759  char *to = file_name_concat (to_dir, from_base, NULL);
760  bool ret = install_file_in_file (from, to, x);
761  free (to);
762  return ret;
763}
764
765/* Copy file FROM onto file TO, creating TO if necessary.
766   Return true if successful.  */
767
768static bool
769copy_file (const char *from, const char *to, const struct cp_options *x)
770{
771  bool copy_into_self;
772
773  if (copy_only_if_needed && !need_copy (from, to, x))
774    return true;
775
776  /* Allow installing from non-regular files like /dev/null.
777     Charles Karney reported that some Sun version of install allows that
778     and that sendmail's installation process relies on the behavior.
779     However, since !x->recursive, the call to "copy" will fail if FROM
780     is a directory.  */
781
782  return copy (from, to, false, x, &copy_into_self, NULL);
783}
784
785/* Set the attributes of file or directory NAME.
786   Return true if successful.  */
787
788static bool
789change_attributes (char const *name)
790{
791  bool ok = false;
792  /* chown must precede chmod because on some systems,
793     chown clears the set[ug]id bits for non-superusers,
794     resulting in incorrect permissions.
795     On System V, users can give away files with chown and then not
796     be able to chmod them.  So don't give files away.
797
798     We don't normally ignore errors from chown because the idea of
799     the install command is that the file is supposed to end up with
800     precisely the attributes that the user specified (or defaulted).
801     If the file doesn't end up with the group they asked for, they'll
802     want to know.  */
803
804  if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
805      && lchown (name, owner_id, group_id) != 0)
806    error (0, errno, _("cannot change ownership of %s"), quote (name));
807  else if (chmod (name, mode) != 0)
808    error (0, errno, _("cannot change permissions of %s"), quote (name));
809  else
810    ok = true;
811
812  if (use_default_selinux_context)
813    setdefaultfilecon (name);
814
815  return ok;
816}
817
818/* Set the timestamps of file TO to match those of file FROM.
819   Return true if successful.  */
820
821static bool
822change_timestamps (struct stat const *from_sb, char const *to)
823{
824  struct timespec timespec[2];
825  timespec[0] = get_stat_atime (from_sb);
826  timespec[1] = get_stat_mtime (from_sb);
827
828  if (utimens (to, timespec))
829    {
830      error (0, errno, _("cannot set time stamps for %s"), quote (to));
831      return false;
832    }
833  return true;
834}
835
836/* Strip the symbol table from the file NAME.
837   We could dig the magic number out of the file first to
838   determine whether to strip it, but the header files and
839   magic numbers vary so much from system to system that making
840   it portable would be very difficult.  Not worth the effort. */
841
842static void
843strip (char const *name)
844{
845  int status;
846  pid_t pid = fork ();
847
848  switch (pid)
849    {
850    case -1:
851      error (EXIT_FAILURE, errno, _("fork system call failed"));
852      break;
853    case 0:			/* Child. */
854      execlp (strip_program, strip_program, name, NULL);
855      error (EXIT_FAILURE, errno, _("cannot run %s"), strip_program);
856      break;
857    default:			/* Parent. */
858      if (waitpid (pid, &status, 0) < 0)
859        error (EXIT_FAILURE, errno, _("waiting for strip"));
860      else if (! WIFEXITED (status) || WEXITSTATUS (status))
861        error (EXIT_FAILURE, 0, _("strip process terminated abnormally"));
862      break;
863    }
864}
865
866/* Initialize the user and group ownership of the files to install. */
867
868static void
869get_ids (void)
870{
871  struct passwd *pw;
872  struct group *gr;
873
874  if (owner_name)
875    {
876      pw = getpwnam (owner_name);
877      if (pw == NULL)
878        {
879          unsigned long int tmp;
880          if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
881              || UID_T_MAX < tmp)
882            error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
883          owner_id = tmp;
884        }
885      else
886        owner_id = pw->pw_uid;
887      endpwent ();
888    }
889  else
890    owner_id = (uid_t) -1;
891
892  if (group_name)
893    {
894      gr = getgrnam (group_name);
895      if (gr == NULL)
896        {
897          unsigned long int tmp;
898          if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
899              || GID_T_MAX < tmp)
900            error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
901          group_id = tmp;
902        }
903      else
904        group_id = gr->gr_gid;
905      endgrent ();
906    }
907  else
908    group_id = (gid_t) -1;
909}
910
911/* Report that directory DIR was made, if OPTIONS requests this.  */
912static void
913announce_mkdir (char const *dir, void *options)
914{
915  struct cp_options const *x = options;
916  if (x->verbose)
917    prog_fprintf (stdout, _("creating directory %s"), quote (dir));
918}
919
920/* Make ancestor directory DIR, whose last file name component is
921   COMPONENT, with options OPTIONS.  Assume the working directory is
922   COMPONENT's parent.  */
923static int
924make_ancestor (char const *dir, char const *component, void *options)
925{
926  int r = mkdir (component, DEFAULT_MODE);
927  if (r == 0)
928    announce_mkdir (dir, options);
929  return r;
930}
931
932void
933usage (int status)
934{
935  if (status != EXIT_SUCCESS)
936    fprintf (stderr, _("Try `%s --help' for more information.\n"),
937             program_name);
938  else
939    {
940      printf (_("\
941Usage: %s [OPTION]... [-T] SOURCE DEST\n\
942  or:  %s [OPTION]... SOURCE... DIRECTORY\n\
943  or:  %s [OPTION]... -t DIRECTORY SOURCE...\n\
944  or:  %s [OPTION]... -d DIRECTORY...\n\
945"),
946              program_name, program_name, program_name, program_name);
947      fputs (_("\
948\n\
949This install program copies files (often just compiled) into destination\n\
950locations you choose.  If you want to download and install a ready-to-use\n\
951package on a GNU/Linux system, you should instead be using a package manager\n\
952like yum(1) or apt-get(1).\n\
953\n\
954In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
955the existing DIRECTORY, while setting permission modes and owner/group.\n\
956In the 4th form, create all components of the given DIRECTORY(ies).\n\
957\n\
958"), stdout);
959      fputs (_("\
960Mandatory arguments to long options are mandatory for short options too.\n\
961"), stdout);
962      fputs (_("\
963      --backup[=CONTROL]  make a backup of each existing destination file\n\
964  -b                  like --backup but does not accept an argument\n\
965  -c                  (ignored)\n\
966  -C, --compare       compare each pair of source and destination files, and\n\
967                        in some cases, do not modify the destination at all\n\
968  -d, --directory     treat all arguments as directory names; create all\n\
969                        components of the specified directories\n\
970"), stdout);
971      fputs (_("\
972  -D                  create all leading components of DEST except the last,\n\
973                        then copy SOURCE to DEST\n\
974  -g, --group=GROUP   set group ownership, instead of process' current group\n\
975  -m, --mode=MODE     set permission mode (as in chmod), instead of rwxr-xr-x\n\
976  -o, --owner=OWNER   set ownership (super-user only)\n\
977"), stdout);
978      fputs (_("\
979  -p, --preserve-timestamps   apply access/modification times of SOURCE files\n\
980                        to corresponding destination files\n\
981  -s, --strip         strip symbol tables\n\
982      --strip-program=PROGRAM  program used to strip binaries\n\
983  -S, --suffix=SUFFIX  override the usual backup suffix\n\
984  -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY\n\
985  -T, --no-target-directory  treat DEST as a normal file\n\
986  -v, --verbose       print the name of each directory as it is created\n\
987"), stdout);
988      fputs (_("\
989      --preserve-context  preserve SELinux security context\n\
990  -Z, --context=CONTEXT  set SELinux security context of files and directories\n\
991"), stdout);
992
993      fputs (HELP_OPTION_DESCRIPTION, stdout);
994      fputs (VERSION_OPTION_DESCRIPTION, stdout);
995      fputs (_("\
996\n\
997The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
998The version control method may be selected via the --backup option or through\n\
999the VERSION_CONTROL environment variable.  Here are the values:\n\
1000\n\
1001"), stdout);
1002      fputs (_("\
1003  none, off       never make backups (even if --backup is given)\n\
1004  numbered, t     make numbered backups\n\
1005  existing, nil   numbered if numbered backups exist, simple otherwise\n\
1006  simple, never   always make simple backups\n\
1007"), stdout);
1008      emit_ancillary_info ();
1009    }
1010  exit (status);
1011}
1012