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