maint: improve error messages upon failed read, write, access, close
[platform/upstream/coreutils.git] / src / install.c
1 /* install - copy files and set attributes
2    Copyright (C) 1989-2013 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->explicit_no_preserve_mode = false;
279   x->reduce_diagnostics=false;
280   x->data_copy_required = true;
281   x->require_preserve = false;
282   x->require_preserve_context = false;
283   x->require_preserve_xattr = false;
284   x->recursive = false;
285   x->sparse_mode = SPARSE_AUTO;
286   x->symbolic_link = false;
287   x->backup_type = no_backups;
288
289   /* Create destination files initially writable so we can run strip on them.
290      Although GNU strip works fine on read-only files, some others
291      would fail.  */
292   x->set_mode = true;
293   x->mode = S_IRUSR | S_IWUSR;
294   x->stdin_tty = false;
295
296   x->open_dangling_dest_symlink = false;
297   x->update = false;
298   x->preserve_security_context = false;
299   x->preserve_xattr = false;
300   x->verbose = false;
301   x->dest_info = NULL;
302   x->src_info = NULL;
303 }
304
305 #ifdef ENABLE_MATCHPATHCON
306 /* Modify file context to match the specified policy.
307    If an error occurs the file will remain with the default directory
308    context.  */
309 static void
310 setdefaultfilecon (char const *file)
311 {
312   struct stat st;
313   security_context_t scontext = NULL;
314   static bool first_call = true;
315
316   if (selinux_enabled != 1)
317     {
318       /* Indicate no context found. */
319       return;
320     }
321   if (lstat (file, &st) != 0)
322     return;
323
324   if (first_call && IS_ABSOLUTE_FILE_NAME (file))
325     {
326       /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
327          is an optimization to minimize the expense of the following
328          matchpathcon call.  Do it only once, just before the first
329          matchpathcon call.  We *could* call matchpathcon_fini after
330          the final matchpathcon call, but that's not necessary, since
331          by then we're about to exit, and besides, the buffers it
332          would free are still reachable.  */
333       char const *p0;
334       char const *p = file + 1;
335       while (ISSLASH (*p))
336         ++p;
337
338       /* Record final leading slash, for when FILE starts with two or more.  */
339       p0 = p - 1;
340
341       if (*p)
342         {
343           char *prefix;
344           do
345             {
346               ++p;
347             }
348           while (*p && !ISSLASH (*p));
349
350           prefix = malloc (p - p0 + 2);
351           if (prefix)
352             {
353               stpcpy (stpncpy (prefix, p0, p - p0), "/");
354               matchpathcon_init_prefix (NULL, prefix);
355               free (prefix);
356             }
357         }
358     }
359   first_call = false;
360
361   /* If there's an error determining the context, or it has none,
362      return to allow default context */
363   if ((matchpathcon (file, st.st_mode, &scontext) != 0)
364       || STREQ (scontext, "<<none>>"))
365     {
366       if (scontext != NULL)
367         freecon (scontext);
368       return;
369     }
370
371   if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
372     error (0, errno,
373            _("warning: %s: failed to change context to %s"),
374            quotearg_colon (file), scontext);
375
376   freecon (scontext);
377   return;
378 }
379 #else
380 static void
381 setdefaultfilecon (char const *file)
382 {
383   (void) file;
384 }
385 #endif
386
387 /* FILE is the last operand of this command.  Return true if FILE is a
388    directory.  But report an error there is a problem accessing FILE,
389    or if FILE does not exist but would have to refer to an existing
390    directory if it referred to anything at all.  */
391
392 static bool
393 target_directory_operand (char const *file)
394 {
395   char const *b = last_component (file);
396   size_t blen = strlen (b);
397   bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
398   struct stat st;
399   int err = (stat (file, &st) == 0 ? 0 : errno);
400   bool is_a_dir = !err && S_ISDIR (st.st_mode);
401   if (err && err != ENOENT)
402     error (EXIT_FAILURE, err, _("failed to access %s"), quote (file));
403   if (is_a_dir < looks_like_a_dir)
404     error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
405   return is_a_dir;
406 }
407
408 /* Report that directory DIR was made, if OPTIONS requests this.  */
409 static void
410 announce_mkdir (char const *dir, void *options)
411 {
412   struct cp_options const *x = options;
413   if (x->verbose)
414     prog_fprintf (stdout, _("creating directory %s"), quote (dir));
415 }
416
417 /* Make ancestor directory DIR, whose last file name component is
418    COMPONENT, with options OPTIONS.  Assume the working directory is
419    COMPONENT's parent.  */
420 static int
421 make_ancestor (char const *dir, char const *component, void *options)
422 {
423   int r = mkdir (component, DEFAULT_MODE);
424   if (r == 0)
425     announce_mkdir (dir, options);
426   return r;
427 }
428
429 /* Process a command-line file name, for the -d option.  */
430 static int
431 process_dir (char *dir, struct savewd *wd, void *options)
432 {
433   return (make_dir_parents (dir, wd,
434                             make_ancestor, options,
435                             dir_mode, announce_mkdir,
436                             dir_mode_bits, owner_id, group_id, false)
437           ? EXIT_SUCCESS
438           : EXIT_FAILURE);
439 }
440
441 /* Copy file FROM onto file TO, creating TO if necessary.
442    Return true if successful.  */
443
444 static bool
445 copy_file (const char *from, const char *to, const struct cp_options *x)
446 {
447   bool copy_into_self;
448
449   if (copy_only_if_needed && !need_copy (from, to, x))
450     return true;
451
452   /* Allow installing from non-regular files like /dev/null.
453      Charles Karney reported that some Sun version of install allows that
454      and that sendmail's installation process relies on the behavior.
455      However, since !x->recursive, the call to "copy" will fail if FROM
456      is a directory.  */
457
458   return copy (from, to, false, x, &copy_into_self, NULL);
459 }
460
461 /* Set the attributes of file or directory NAME.
462    Return true if successful.  */
463
464 static bool
465 change_attributes (char const *name)
466 {
467   bool ok = false;
468   /* chown must precede chmod because on some systems,
469      chown clears the set[ug]id bits for non-superusers,
470      resulting in incorrect permissions.
471      On System V, users can give away files with chown and then not
472      be able to chmod them.  So don't give files away.
473
474      We don't normally ignore errors from chown because the idea of
475      the install command is that the file is supposed to end up with
476      precisely the attributes that the user specified (or defaulted).
477      If the file doesn't end up with the group they asked for, they'll
478      want to know.  */
479
480   if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
481       && lchown (name, owner_id, group_id) != 0)
482     error (0, errno, _("cannot change ownership of %s"), quote (name));
483   else if (chmod (name, mode) != 0)
484     error (0, errno, _("cannot change permissions of %s"), quote (name));
485   else
486     ok = true;
487
488   if (use_default_selinux_context)
489     setdefaultfilecon (name);
490
491   return ok;
492 }
493
494 /* Set the timestamps of file DEST to match those of SRC_SB.
495    Return true if successful.  */
496
497 static bool
498 change_timestamps (struct stat const *src_sb, char const *dest)
499 {
500   struct timespec timespec[2];
501   timespec[0] = get_stat_atime (src_sb);
502   timespec[1] = get_stat_mtime (src_sb);
503
504   if (utimens (dest, timespec))
505     {
506       error (0, errno, _("cannot set time stamps for %s"), quote (dest));
507       return false;
508     }
509   return true;
510 }
511
512 /* Strip the symbol table from the file NAME.
513    We could dig the magic number out of the file first to
514    determine whether to strip it, but the header files and
515    magic numbers vary so much from system to system that making
516    it portable would be very difficult.  Not worth the effort. */
517
518 static void
519 strip (char const *name)
520 {
521   int status;
522   pid_t pid = fork ();
523
524   switch (pid)
525     {
526     case -1:
527       error (EXIT_FAILURE, errno, _("fork system call failed"));
528       break;
529     case 0:                     /* Child. */
530       execlp (strip_program, strip_program, name, NULL);
531       error (EXIT_FAILURE, errno, _("cannot run %s"), strip_program);
532       break;
533     default:                    /* Parent. */
534       if (waitpid (pid, &status, 0) < 0)
535         error (EXIT_FAILURE, errno, _("waiting for strip"));
536       else if (! WIFEXITED (status) || WEXITSTATUS (status))
537         error (EXIT_FAILURE, 0, _("strip process terminated abnormally"));
538       break;
539     }
540 }
541
542 /* Initialize the user and group ownership of the files to install. */
543
544 static void
545 get_ids (void)
546 {
547   struct passwd *pw;
548   struct group *gr;
549
550   if (owner_name)
551     {
552       pw = getpwnam (owner_name);
553       if (pw == NULL)
554         {
555           unsigned long int tmp;
556           if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
557               || UID_T_MAX < tmp)
558             error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
559           owner_id = tmp;
560         }
561       else
562         owner_id = pw->pw_uid;
563       endpwent ();
564     }
565   else
566     owner_id = (uid_t) -1;
567
568   if (group_name)
569     {
570       gr = getgrnam (group_name);
571       if (gr == NULL)
572         {
573           unsigned long int tmp;
574           if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
575               || GID_T_MAX < tmp)
576             error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
577           group_id = tmp;
578         }
579       else
580         group_id = gr->gr_gid;
581       endgrent ();
582     }
583   else
584     group_id = (gid_t) -1;
585 }
586
587 void
588 usage (int status)
589 {
590   if (status != EXIT_SUCCESS)
591     emit_try_help ();
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 "), stdout);
612
613       emit_mandatory_arg_note ();
614
615       fputs (_("\
616       --backup[=CONTROL]  make a backup of each existing destination file\n\
617   -b                  like --backup but does not accept an argument\n\
618   -c                  (ignored)\n\
619   -C, --compare       compare each pair of source and destination files, and\n\
620                         in some cases, do not modify the destination at all\n\
621   -d, --directory     treat all arguments as directory names; create all\n\
622                         components of the specified directories\n\
623 "), stdout);
624       fputs (_("\
625   -D                  create all leading components of DEST except the last,\n\
626                         then copy SOURCE to DEST\n\
627   -g, --group=GROUP   set group ownership, instead of process' current group\n\
628   -m, --mode=MODE     set permission mode (as in chmod), instead of rwxr-xr-x\n\
629   -o, --owner=OWNER   set ownership (super-user only)\n\
630 "), stdout);
631       fputs (_("\
632   -p, --preserve-timestamps   apply access/modification times of SOURCE files\n\
633                         to corresponding destination files\n\
634   -s, --strip         strip symbol tables\n\
635       --strip-program=PROGRAM  program used to strip binaries\n\
636   -S, --suffix=SUFFIX  override the usual backup suffix\n\
637   -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY\n\
638   -T, --no-target-directory  treat DEST as a normal file\n\
639   -v, --verbose       print the name of each directory as it is created\n\
640 "), stdout);
641       fputs (_("\
642       --preserve-context  preserve SELinux security context\n\
643   -Z, --context=CONTEXT  set SELinux security context of files and directories\
644 \n\
645 "), stdout);
646
647       fputs (HELP_OPTION_DESCRIPTION, stdout);
648       fputs (VERSION_OPTION_DESCRIPTION, stdout);
649       fputs (_("\
650 \n\
651 The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
652 The version control method may be selected via the --backup option or through\n\
653 the VERSION_CONTROL environment variable.  Here are the values:\n\
654 \n\
655 "), stdout);
656       fputs (_("\
657   none, off       never make backups (even if --backup is given)\n\
658   numbered, t     make numbered backups\n\
659   existing, nil   numbered if numbered backups exist, simple otherwise\n\
660   simple, never   always make simple backups\n\
661 "), stdout);
662       emit_ancillary_info ();
663     }
664   exit (status);
665 }
666
667 /* Copy file FROM onto file TO and give TO the appropriate
668    attributes.
669    Return true if successful.  */
670
671 static bool
672 install_file_in_file (const char *from, const char *to,
673                       const struct cp_options *x)
674 {
675   struct stat from_sb;
676   if (x->preserve_timestamps && stat (from, &from_sb) != 0)
677     {
678       error (0, errno, _("cannot stat %s"), quote (from));
679       return false;
680     }
681   if (! copy_file (from, to, x))
682     return false;
683   if (strip_files)
684     strip (to);
685   if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
686       && ! change_timestamps (&from_sb, to))
687     return false;
688   return change_attributes (to);
689 }
690
691 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
692    Return true if successful.  */
693
694 static bool
695 install_file_in_file_parents (char const *from, char *to,
696                               struct cp_options *x)
697 {
698   bool save_working_directory =
699     ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
700   int status = EXIT_SUCCESS;
701
702   struct savewd wd;
703   savewd_init (&wd);
704   if (! save_working_directory)
705     savewd_finish (&wd);
706
707   if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
708     {
709       error (0, errno, _("cannot create directory %s"), to);
710       status = EXIT_FAILURE;
711     }
712
713   if (save_working_directory)
714     {
715       int restore_result = savewd_restore (&wd, status);
716       int restore_errno = errno;
717       savewd_finish (&wd);
718       if (EXIT_SUCCESS < restore_result)
719         return false;
720       if (restore_result < 0 && status == EXIT_SUCCESS)
721         {
722           error (0, restore_errno, _("cannot create directory %s"), to);
723           return false;
724         }
725     }
726
727   return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
728 }
729
730 /* Copy file FROM into directory TO_DIR, keeping its same name,
731    and give the copy the appropriate attributes.
732    Return true if successful.  */
733
734 static bool
735 install_file_in_dir (const char *from, const char *to_dir,
736                      const struct cp_options *x)
737 {
738   const char *from_base = last_component (from);
739   char *to = file_name_concat (to_dir, from_base, NULL);
740   bool ret = install_file_in_file (from, to, x);
741   free (to);
742   return ret;
743 }
744
745 int
746 main (int argc, char **argv)
747 {
748   int optc;
749   int exit_status = EXIT_SUCCESS;
750   const char *specified_mode = NULL;
751   bool make_backups = false;
752   char *backup_suffix_string;
753   char *version_control_string = NULL;
754   bool mkdir_and_install = false;
755   struct cp_options x;
756   char const *target_directory = NULL;
757   bool no_target_directory = false;
758   int n_files;
759   char **file;
760   bool strip_program_specified = false;
761   security_context_t scontext = NULL;
762   /* set iff kernel has extra selinux system calls */
763   selinux_enabled = (0 < is_selinux_enabled ());
764
765   initialize_main (&argc, &argv);
766   set_program_name (argv[0]);
767   setlocale (LC_ALL, "");
768   bindtextdomain (PACKAGE, LOCALEDIR);
769   textdomain (PACKAGE);
770
771   atexit (close_stdin);
772
773   cp_option_init (&x);
774
775   owner_name = NULL;
776   group_name = NULL;
777   strip_files = false;
778   dir_arg = false;
779   umask (0);
780
781   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
782      we'll actually use backup_suffix_string.  */
783   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
784
785   while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z:", long_options,
786                               NULL)) != -1)
787     {
788       switch (optc)
789         {
790         case 'b':
791           make_backups = true;
792           if (optarg)
793             version_control_string = optarg;
794           break;
795         case 'c':
796           break;
797         case 'C':
798           copy_only_if_needed = true;
799           break;
800         case 's':
801           strip_files = true;
802 #ifdef SIGCHLD
803           /* System V fork+wait does not work if SIGCHLD is ignored.  */
804           signal (SIGCHLD, SIG_DFL);
805 #endif
806           break;
807         case STRIP_PROGRAM_OPTION:
808           strip_program = xstrdup (optarg);
809           strip_program_specified = true;
810           break;
811         case 'd':
812           dir_arg = true;
813           break;
814         case 'D':
815           mkdir_and_install = true;
816           break;
817         case 'v':
818           x.verbose = true;
819           break;
820         case 'g':
821           group_name = optarg;
822           break;
823         case 'm':
824           specified_mode = optarg;
825           break;
826         case 'o':
827           owner_name = optarg;
828           break;
829         case 'p':
830           x.preserve_timestamps = true;
831           break;
832         case 'S':
833           make_backups = true;
834           backup_suffix_string = optarg;
835           break;
836         case 't':
837           if (target_directory)
838             error (EXIT_FAILURE, 0,
839                    _("multiple target directories specified"));
840           else
841             {
842               struct stat st;
843               if (stat (optarg, &st) != 0)
844                 error (EXIT_FAILURE, errno, _("failed to access %s"),
845                        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 }