maint: with split lines, don't leave an operator at end of line
[platform/upstream/coreutils.git] / src / install.c
1 /* install - copy files and set attributes
2    Copyright (C) 1989-2012 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     emit_try_help ();
591   else
592     {
593       printf (_("\
594 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
595   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
596   or:  %s [OPTION]... -t DIRECTORY SOURCE...\n\
597   or:  %s [OPTION]... -d DIRECTORY...\n\
598 "),
599               program_name, program_name, program_name, program_name);
600       fputs (_("\
601 \n\
602 This install program copies files (often just compiled) into destination\n\
603 locations you choose.  If you want to download and install a ready-to-use\n\
604 package on a GNU/Linux system, you should instead be using a package manager\n\
605 like yum(1) or apt-get(1).\n\
606 \n\
607 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
608 the existing DIRECTORY, while setting permission modes and owner/group.\n\
609 In the 4th form, create all components of the given DIRECTORY(ies).\n\
610 \n\
611 "), stdout);
612       fputs (_("\
613 Mandatory arguments to long options are mandatory for short options too.\n\
614 "), stdout);
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, _("accessing %s"), quote (optarg));
845               if (! S_ISDIR (st.st_mode))
846                 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
847                        quote (optarg));
848             }
849           target_directory = optarg;
850           break;
851         case 'T':
852           no_target_directory = true;
853           break;
854
855         case PRESERVE_CONTEXT_OPTION:
856           if ( ! selinux_enabled)
857             {
858               error (0, 0, _("WARNING: ignoring --preserve-context; "
859                              "this kernel is not SELinux-enabled"));
860               break;
861             }
862           x.preserve_security_context = true;
863           use_default_selinux_context = false;
864           break;
865         case 'Z':
866           if ( ! selinux_enabled)
867             {
868               error (0, 0, _("WARNING: ignoring --context (-Z); "
869                              "this kernel is not SELinux-enabled"));
870               break;
871             }
872           scontext = optarg;
873           use_default_selinux_context = false;
874           break;
875         case_GETOPT_HELP_CHAR;
876         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
877         default:
878           usage (EXIT_FAILURE);
879         }
880     }
881
882   /* Check for invalid combinations of arguments. */
883   if (dir_arg && strip_files)
884     error (EXIT_FAILURE, 0,
885            _("the strip option may not be used when installing a directory"));
886   if (dir_arg && target_directory)
887     error (EXIT_FAILURE, 0,
888            _("target directory not allowed when installing a directory"));
889
890   if (x.preserve_security_context && scontext != NULL)
891     error (EXIT_FAILURE, 0,
892            _("cannot force target context to %s and preserve it"),
893            quote (scontext));
894
895   if (backup_suffix_string)
896     simple_backup_suffix = xstrdup (backup_suffix_string);
897
898   x.backup_type = (make_backups
899                    ? xget_version (_("backup type"),
900                                    version_control_string)
901                    : no_backups);
902
903   if (scontext && setfscreatecon (scontext) < 0)
904     error (EXIT_FAILURE, errno,
905            _("failed to set default file creation context to %s"),
906            quote (scontext));
907
908   n_files = argc - optind;
909   file = argv + optind;
910
911   if (n_files <= ! (dir_arg || target_directory))
912     {
913       if (n_files <= 0)
914         error (0, 0, _("missing file operand"));
915       else
916         error (0, 0, _("missing destination file operand after %s"),
917                quote (file[0]));
918       usage (EXIT_FAILURE);
919     }
920
921   if (no_target_directory)
922     {
923       if (target_directory)
924         error (EXIT_FAILURE, 0,
925                _("cannot combine --target-directory (-t) "
926                  "and --no-target-directory (-T)"));
927       if (2 < n_files)
928         {
929           error (0, 0, _("extra operand %s"), quote (file[2]));
930           usage (EXIT_FAILURE);
931         }
932     }
933   else if (! (dir_arg || target_directory))
934     {
935       if (2 <= n_files && target_directory_operand (file[n_files - 1]))
936         target_directory = file[--n_files];
937       else if (2 < n_files)
938         error (EXIT_FAILURE, 0, _("target %s is not a directory"),
939                quote (file[n_files - 1]));
940     }
941
942   if (specified_mode)
943     {
944       struct mode_change *change = mode_compile (specified_mode);
945       if (!change)
946         error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
947       mode = mode_adjust (0, false, 0, change, NULL);
948       dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
949       free (change);
950     }
951
952   if (strip_program_specified && !strip_files)
953     error (0, 0, _("WARNING: ignoring --strip-program option as -s option was "
954                    "not specified"));
955
956   if (copy_only_if_needed && x.preserve_timestamps)
957     {
958       error (0, 0, _("options --compare (-C) and --preserve-timestamps are "
959                      "mutually exclusive"));
960       usage (EXIT_FAILURE);
961     }
962
963   if (copy_only_if_needed && strip_files)
964     {
965       error (0, 0, _("options --compare (-C) and --strip are mutually "
966                      "exclusive"));
967       usage (EXIT_FAILURE);
968     }
969
970   if (copy_only_if_needed && extra_mode (mode))
971     error (0, 0, _("the --compare (-C) option is ignored when you"
972                    " specify a mode with non-permission bits"));
973
974   get_ids ();
975
976   if (dir_arg)
977     exit_status = savewd_process_files (n_files, file, process_dir, &x);
978   else
979     {
980       /* FIXME: it's a little gross that this initialization is
981          required by copy.c::copy. */
982       hash_init ();
983
984       if (!target_directory)
985         {
986           if (! (mkdir_and_install
987                  ? install_file_in_file_parents (file[0], file[1], &x)
988                  : install_file_in_file (file[0], file[1], &x)))
989             exit_status = EXIT_FAILURE;
990         }
991       else
992         {
993           int i;
994           dest_info_init (&x);
995           for (i = 0; i < n_files; i++)
996             if (! install_file_in_dir (file[i], target_directory, &x))
997               exit_status = EXIT_FAILURE;
998         }
999     }
1000
1001   exit (exit_status);
1002 }