build: update gnulib submodule to latest
[coreutils.git] / src / install.c
blobd338cbb29d20d9263960619a1996a7359da3ec01
1 /* install - copy files and set attributes
2 Copyright (C) 1989-2015 Free Software Foundation, Inc.
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.
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.
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/>. */
17 /* Written by David MacKenzie <djm@gnu.ai.mit.edu> */
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>
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 "savewd.h"
42 #include "stat-time.h"
43 #include "utimens.h"
44 #include "xstrtol.h"
46 /* The official name of this program (e.g., no 'g' prefix). */
47 #define PROGRAM_NAME "install"
49 #define AUTHORS proper_name ("David MacKenzie")
51 static int selinux_enabled = 0;
52 static bool use_default_selinux_context = true;
54 #if ! HAVE_ENDGRENT
55 # define endgrent() ((void) 0)
56 #endif
58 #if ! HAVE_ENDPWENT
59 # define endpwent() ((void) 0)
60 #endif
62 #if ! HAVE_LCHOWN
63 # define lchown(name, uid, gid) chown (name, uid, gid)
64 #endif
66 #if ! HAVE_MATCHPATHCON_INIT_PREFIX
67 # define matchpathcon_init_prefix(a, p) /* empty */
68 #endif
70 /* The user name that will own the files, or NULL to make the owner
71 the current user ID. */
72 static char *owner_name;
74 /* The user ID corresponding to 'owner_name'. */
75 static uid_t owner_id;
77 /* The group name that will own the files, or NULL to make the group
78 the current group ID. */
79 static char *group_name;
81 /* The group ID corresponding to 'group_name'. */
82 static gid_t group_id;
84 #define DEFAULT_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
86 /* The file mode bits to which non-directory files will be set. The umask has
87 no effect. */
88 static mode_t mode = DEFAULT_MODE;
90 /* Similar, but for directories. */
91 static mode_t dir_mode = DEFAULT_MODE;
93 /* The file mode bits that the user cares about. This should be a
94 superset of DIR_MODE and a subset of CHMOD_MODE_BITS. This matters
95 for directories, since otherwise directories may keep their S_ISUID
96 or S_ISGID bits. */
97 static mode_t dir_mode_bits = CHMOD_MODE_BITS;
99 /* Compare files before installing (-C) */
100 static bool copy_only_if_needed;
102 /* If true, strip executable files after copying them. */
103 static bool strip_files;
105 /* If true, install a directory instead of a regular file. */
106 static bool dir_arg;
108 /* Program used to strip binaries, "strip" is default */
109 static char const *strip_program = "strip";
111 /* For long options that have no equivalent short option, use a
112 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
113 enum
115 PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1,
116 STRIP_PROGRAM_OPTION
119 static struct option const long_options[] =
121 {"backup", optional_argument, NULL, 'b'},
122 {"compare", no_argument, NULL, 'C'},
123 {GETOPT_SELINUX_CONTEXT_OPTION_DECL},
124 {"directory", no_argument, NULL, 'd'},
125 {"group", required_argument, NULL, 'g'},
126 {"mode", required_argument, NULL, 'm'},
127 {"no-target-directory", no_argument, NULL, 'T'},
128 {"owner", required_argument, NULL, 'o'},
129 {"preserve-timestamps", no_argument, NULL, 'p'},
130 {"preserve-context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
131 {"strip", no_argument, NULL, 's'},
132 {"strip-program", required_argument, NULL, STRIP_PROGRAM_OPTION},
133 {"suffix", required_argument, NULL, 'S'},
134 {"target-directory", required_argument, NULL, 't'},
135 {"verbose", no_argument, NULL, 'v'},
136 {GETOPT_HELP_OPTION_DECL},
137 {GETOPT_VERSION_OPTION_DECL},
138 {NULL, 0, NULL, 0}
141 /* Compare content of opened files using file descriptors A_FD and B_FD. Return
142 true if files are equal. */
143 static bool
144 have_same_content (int a_fd, int b_fd)
146 enum { CMP_BLOCK_SIZE = 4096 };
147 static char a_buff[CMP_BLOCK_SIZE];
148 static char b_buff[CMP_BLOCK_SIZE];
150 size_t size;
151 while (0 < (size = full_read (a_fd, a_buff, sizeof a_buff))) {
152 if (size != full_read (b_fd, b_buff, sizeof b_buff))
153 return false;
155 if (memcmp (a_buff, b_buff, size) != 0)
156 return false;
159 return size == 0;
162 /* Return true for mode with non-permission bits. */
163 static bool
164 extra_mode (mode_t input)
166 mode_t mask = S_IRWXUGO | S_IFMT;
167 return !! (input & ~ mask);
170 /* Return true if copy of file SRC_NAME to file DEST_NAME is necessary. */
171 static bool
172 need_copy (const char *src_name, const char *dest_name,
173 const struct cp_options *x)
175 struct stat src_sb, dest_sb;
176 int src_fd, dest_fd;
177 bool content_match;
179 if (extra_mode (mode))
180 return true;
182 /* compare files using stat */
183 if (lstat (src_name, &src_sb) != 0)
184 return true;
186 if (lstat (dest_name, &dest_sb) != 0)
187 return true;
189 if (!S_ISREG (src_sb.st_mode) || !S_ISREG (dest_sb.st_mode)
190 || extra_mode (src_sb.st_mode) || extra_mode (dest_sb.st_mode))
191 return true;
193 if (src_sb.st_size != dest_sb.st_size
194 || (dest_sb.st_mode & CHMOD_MODE_BITS) != mode)
195 return true;
197 if (owner_id == (uid_t) -1)
199 errno = 0;
200 uid_t ruid = getuid ();
201 if ((ruid == (uid_t) -1 && errno) || dest_sb.st_uid != ruid)
202 return true;
204 else if (dest_sb.st_uid != owner_id)
205 return true;
207 if (group_id == (uid_t) -1)
209 errno = 0;
210 gid_t rgid = getgid ();
211 if ((rgid == (uid_t) -1 && errno) || dest_sb.st_gid != rgid)
212 return true;
214 else if (dest_sb.st_gid != group_id)
215 return true;
217 /* compare SELinux context if preserving */
218 if (selinux_enabled && x->preserve_security_context)
220 char *file_scontext = NULL;
221 char *to_scontext = NULL;
222 bool scontext_match;
224 if (getfilecon (src_name, &file_scontext) == -1)
225 return true;
227 if (getfilecon (dest_name, &to_scontext) == -1)
229 freecon (file_scontext);
230 return true;
233 scontext_match = STREQ (file_scontext, to_scontext);
235 freecon (file_scontext);
236 freecon (to_scontext);
237 if (!scontext_match)
238 return true;
241 /* compare files content */
242 src_fd = open (src_name, O_RDONLY | O_BINARY);
243 if (src_fd < 0)
244 return true;
246 dest_fd = open (dest_name, O_RDONLY | O_BINARY);
247 if (dest_fd < 0)
249 close (src_fd);
250 return true;
253 content_match = have_same_content (src_fd, dest_fd);
255 close (src_fd);
256 close (dest_fd);
257 return !content_match;
260 static void
261 cp_option_init (struct cp_options *x)
263 cp_options_default (x);
264 x->copy_as_regular = true;
265 x->reflink_mode = REFLINK_NEVER;
266 x->dereference = DEREF_ALWAYS;
267 x->unlink_dest_before_opening = true;
268 x->unlink_dest_after_failed_open = false;
269 x->hard_link = false;
270 x->interactive = I_UNSPECIFIED;
271 x->move_mode = false;
272 x->one_file_system = false;
273 x->preserve_ownership = false;
274 x->preserve_links = false;
275 x->preserve_mode = false;
276 x->preserve_timestamps = false;
277 x->explicit_no_preserve_mode = false;
278 x->reduce_diagnostics=false;
279 x->data_copy_required = true;
280 x->require_preserve = false;
281 x->require_preserve_xattr = false;
282 x->recursive = false;
283 x->sparse_mode = SPARSE_AUTO;
284 x->symbolic_link = false;
285 x->backup_type = no_backups;
287 /* Create destination files initially writable so we can run strip on them.
288 Although GNU strip works fine on read-only files, some others
289 would fail. */
290 x->set_mode = true;
291 x->mode = S_IRUSR | S_IWUSR;
292 x->stdin_tty = false;
294 x->open_dangling_dest_symlink = false;
295 x->update = false;
296 x->require_preserve_context = false; /* Not used by install currently. */
297 x->preserve_security_context = false; /* Whether to copy context from src. */
298 x->set_security_context = false; /* Whether to set sys default context. */
299 x->preserve_xattr = false;
300 x->verbose = false;
301 x->dest_info = NULL;
302 x->src_info = NULL;
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. Note this sets the context to that returned by matchpathcon,
309 and thus discards MLS levels and user identity of the FILE. */
310 static void
311 setdefaultfilecon (char const *file)
313 struct stat st;
314 char *scontext = NULL;
315 static bool first_call = true;
317 if (selinux_enabled != 1)
319 /* Indicate no context found. */
320 return;
322 if (lstat (file, &st) != 0)
323 return;
325 if (first_call && IS_ABSOLUTE_FILE_NAME (file))
327 /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
328 is an optimization to minimize the expense of the following
329 matchpathcon call. Do it only once, just before the first
330 matchpathcon call. We *could* call matchpathcon_fini after
331 the final matchpathcon call, but that's not necessary, since
332 by then we're about to exit, and besides, the buffers it
333 would free are still reachable. */
334 char const *p0;
335 char const *p = file + 1;
336 while (ISSLASH (*p))
337 ++p;
339 /* Record final leading slash, for when FILE starts with two or more. */
340 p0 = p - 1;
342 if (*p)
344 char *prefix;
347 ++p;
349 while (*p && !ISSLASH (*p));
351 prefix = malloc (p - p0 + 2);
352 if (prefix)
354 stpcpy (stpncpy (prefix, p0, p - p0), "/");
355 matchpathcon_init_prefix (NULL, prefix);
356 free (prefix);
360 first_call = false;
362 /* If there's an error determining the context, or it has none,
363 return to allow default context. Note the "<<none>>" check
364 is only needed for libselinux < 1.20 (2005-01-04). */
365 if ((matchpathcon (file, st.st_mode, &scontext) != 0)
366 || STREQ (scontext, "<<none>>"))
368 if (scontext != NULL)
369 freecon (scontext);
370 return;
373 if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
374 error (0, errno,
375 _("warning: %s: failed to change context to %s"),
376 quote_n (0, file), quote_n (1, scontext));
378 freecon (scontext);
379 return;
381 #else
382 static void
383 setdefaultfilecon (char const *file)
385 (void) file;
387 #endif
389 /* FILE is the last operand of this command. Return true if FILE is a
390 directory. But report an error there is a problem accessing FILE,
391 or if FILE does not exist but would have to refer to an existing
392 directory if it referred to anything at all. */
394 static bool
395 target_directory_operand (char const *file)
397 char const *b = last_component (file);
398 size_t blen = strlen (b);
399 bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
400 struct stat st;
401 int err = (stat (file, &st) == 0 ? 0 : errno);
402 bool is_a_dir = !err && S_ISDIR (st.st_mode);
403 if (err && err != ENOENT)
404 error (EXIT_FAILURE, err, _("failed to access %s"), quote (file));
405 if (is_a_dir < looks_like_a_dir)
406 error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
407 return is_a_dir;
410 /* Report that directory DIR was made, if OPTIONS requests this. */
411 static void
412 announce_mkdir (char const *dir, void *options)
414 struct cp_options const *x = options;
415 if (x->verbose)
416 prog_fprintf (stdout, _("creating directory %s"), quote (dir));
419 /* Make ancestor directory DIR, whose last file name component is
420 COMPONENT, with options OPTIONS. Assume the working directory is
421 COMPONENT's parent. */
422 static int
423 make_ancestor (char const *dir, char const *component, void *options)
425 int r = mkdir (component, DEFAULT_MODE);
426 if (r == 0)
427 announce_mkdir (dir, options);
428 return r;
431 /* Process a command-line file name, for the -d option. */
432 static int
433 process_dir (char *dir, struct savewd *wd, void *options)
435 return (make_dir_parents (dir, wd,
436 make_ancestor, options,
437 dir_mode, announce_mkdir,
438 dir_mode_bits, owner_id, group_id, false)
439 ? EXIT_SUCCESS
440 : EXIT_FAILURE);
443 /* Copy file FROM onto file TO, creating TO if necessary.
444 Return true if successful. */
446 static bool
447 copy_file (const char *from, const char *to, const struct cp_options *x)
449 bool copy_into_self;
451 if (copy_only_if_needed && !need_copy (from, to, x))
452 return true;
454 /* Allow installing from non-regular files like /dev/null.
455 Charles Karney reported that some Sun version of install allows that
456 and that sendmail's installation process relies on the behavior.
457 However, since !x->recursive, the call to "copy" will fail if FROM
458 is a directory. */
460 return copy (from, to, false, x, &copy_into_self, NULL);
463 /* Set the attributes of file or directory NAME.
464 Return true if successful. */
466 static bool
467 change_attributes (char const *name)
469 bool ok = false;
470 /* chown must precede chmod because on some systems,
471 chown clears the set[ug]id bits for non-superusers,
472 resulting in incorrect permissions.
473 On System V, users can give away files with chown and then not
474 be able to chmod them. So don't give files away.
476 We don't normally ignore errors from chown because the idea of
477 the install command is that the file is supposed to end up with
478 precisely the attributes that the user specified (or defaulted).
479 If the file doesn't end up with the group they asked for, they'll
480 want to know. */
482 if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
483 && lchown (name, owner_id, group_id) != 0)
484 error (0, errno, _("cannot change ownership of %s"), quote (name));
485 else if (chmod (name, mode) != 0)
486 error (0, errno, _("cannot change permissions of %s"), quote (name));
487 else
488 ok = true;
490 if (use_default_selinux_context)
491 setdefaultfilecon (name);
493 return ok;
496 /* Set the timestamps of file DEST to match those of SRC_SB.
497 Return true if successful. */
499 static bool
500 change_timestamps (struct stat const *src_sb, char const *dest)
502 struct timespec timespec[2];
503 timespec[0] = get_stat_atime (src_sb);
504 timespec[1] = get_stat_mtime (src_sb);
506 if (utimens (dest, timespec))
508 error (0, errno, _("cannot set time stamps for %s"), quote (dest));
509 return false;
511 return true;
514 /* Strip the symbol table from the file NAME.
515 We could dig the magic number out of the file first to
516 determine whether to strip it, but the header files and
517 magic numbers vary so much from system to system that making
518 it portable would be very difficult. Not worth the effort. */
520 static bool
521 strip (char const *name)
523 int status;
524 bool ok = false;
525 pid_t pid = fork ();
527 switch (pid)
529 case -1:
530 error (0, errno, _("fork system call failed"));
531 break;
532 case 0: /* Child. */
533 execlp (strip_program, strip_program, name, NULL);
534 error (EXIT_FAILURE, errno, _("cannot run %s"), quote (strip_program));
535 break;
536 default: /* Parent. */
537 if (waitpid (pid, &status, 0) < 0)
538 error (0, errno, _("waiting for strip"));
539 else if (! WIFEXITED (status) || WEXITSTATUS (status))
540 error (0, 0, _("strip process terminated abnormally"));
541 else
542 ok = true; /* strip succeeded */
543 break;
545 return ok;
548 /* Initialize the user and group ownership of the files to install. */
550 static void
551 get_ids (void)
553 struct passwd *pw;
554 struct group *gr;
556 if (owner_name)
558 pw = getpwnam (owner_name);
559 if (pw == NULL)
561 unsigned long int tmp;
562 if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
563 || UID_T_MAX < tmp)
564 error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
565 owner_id = tmp;
567 else
568 owner_id = pw->pw_uid;
569 endpwent ();
571 else
572 owner_id = (uid_t) -1;
574 if (group_name)
576 gr = getgrnam (group_name);
577 if (gr == NULL)
579 unsigned long int tmp;
580 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
581 || GID_T_MAX < tmp)
582 error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
583 group_id = tmp;
585 else
586 group_id = gr->gr_gid;
587 endgrent ();
589 else
590 group_id = (gid_t) -1;
593 void
594 usage (int status)
596 if (status != EXIT_SUCCESS)
597 emit_try_help ();
598 else
600 printf (_("\
601 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
602 or: %s [OPTION]... SOURCE... DIRECTORY\n\
603 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
604 or: %s [OPTION]... -d DIRECTORY...\n\
606 program_name, program_name, program_name, program_name);
607 fputs (_("\
609 This install program copies files (often just compiled) into destination\n\
610 locations you choose. If you want to download and install a ready-to-use\n\
611 package on a GNU/Linux system, you should instead be using a package manager\n\
612 like yum(1) or apt-get(1).\n\
614 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
615 the existing DIRECTORY, while setting permission modes and owner/group.\n\
616 In the 4th form, create all components of the given DIRECTORY(ies).\n\
617 "), stdout);
619 emit_mandatory_arg_note ();
621 fputs (_("\
622 --backup[=CONTROL] make a backup of each existing destination file\n\
623 -b like --backup but does not accept an argument\n\
624 -c (ignored)\n\
625 -C, --compare compare each pair of source and destination files, and\n\
626 in some cases, do not modify the destination at all\n\
627 -d, --directory treat all arguments as directory names; create all\n\
628 components of the specified directories\n\
629 "), stdout);
630 fputs (_("\
631 -D create all leading components of DEST except the last,\n\
632 then copy SOURCE to DEST\n\
633 -g, --group=GROUP set group ownership, instead of process' current group\n\
634 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
635 -o, --owner=OWNER set ownership (super-user only)\n\
636 "), stdout);
637 fputs (_("\
638 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
639 to corresponding destination files\n\
640 -s, --strip strip symbol tables\n\
641 --strip-program=PROGRAM program used to strip binaries\n\
642 -S, --suffix=SUFFIX override the usual backup suffix\n\
643 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
644 -T, --no-target-directory treat DEST as a normal file\n\
645 -v, --verbose print the name of each directory as it is created\n\
646 "), stdout);
647 fputs (_("\
648 --preserve-context preserve SELinux security context\n\
649 -Z set SELinux security context of destination\n\
650 file to default type\n\
651 --context[=CTX] like -Z, or if CTX is specified then set the\n\
652 SELinux or SMACK security context to CTX\n\
653 "), stdout);
655 fputs (HELP_OPTION_DESCRIPTION, stdout);
656 fputs (VERSION_OPTION_DESCRIPTION, stdout);
657 fputs (_("\
659 The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
660 The version control method may be selected via the --backup option or through\n\
661 the VERSION_CONTROL environment variable. Here are the values:\n\
663 "), stdout);
664 fputs (_("\
665 none, off never make backups (even if --backup is given)\n\
666 numbered, t make numbered backups\n\
667 existing, nil numbered if numbered backups exist, simple otherwise\n\
668 simple, never always make simple backups\n\
669 "), stdout);
670 emit_ancillary_info (PROGRAM_NAME);
672 exit (status);
675 /* Copy file FROM onto file TO and give TO the appropriate
676 attributes.
677 Return true if successful. */
679 static bool
680 install_file_in_file (const char *from, const char *to,
681 const struct cp_options *x)
683 struct stat from_sb;
684 if (x->preserve_timestamps && stat (from, &from_sb) != 0)
686 error (0, errno, _("cannot stat %s"), quote (from));
687 return false;
689 if (! copy_file (from, to, x))
690 return false;
691 if (strip_files)
692 if (! strip (to))
694 if (unlink (to) != 0) /* Cleanup. */
695 error (EXIT_FAILURE, errno, _("cannot unlink %s"), quote (to));
696 return false;
698 if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
699 && ! change_timestamps (&from_sb, to))
700 return false;
701 return change_attributes (to);
704 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
705 Return true if successful. */
707 static bool
708 mkancesdirs_safe_wd (char const *from, char *to, struct cp_options *x)
710 bool save_working_directory =
711 ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
712 int status = EXIT_SUCCESS;
714 struct savewd wd;
715 savewd_init (&wd);
716 if (! save_working_directory)
717 savewd_finish (&wd);
719 if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
721 error (0, errno, _("cannot create directory %s"), quote (to));
722 status = EXIT_FAILURE;
725 if (save_working_directory)
727 int restore_result = savewd_restore (&wd, status);
728 int restore_errno = errno;
729 savewd_finish (&wd);
730 if (EXIT_SUCCESS < restore_result)
731 return false;
732 if (restore_result < 0 && status == EXIT_SUCCESS)
734 error (0, restore_errno, _("cannot create directory %s"), quote (to));
735 return false;
738 return status == EXIT_SUCCESS;
741 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
742 Return true if successful. */
744 static bool
745 install_file_in_file_parents (char const *from, char *to,
746 const struct cp_options *x)
748 return (mkancesdirs_safe_wd (from, to, (struct cp_options *)x)
749 && install_file_in_file (from, to, x));
752 /* Copy file FROM into directory TO_DIR, keeping its same name,
753 and give the copy the appropriate attributes.
754 Return true if successful. */
756 static bool
757 install_file_in_dir (const char *from, const char *to_dir,
758 const struct cp_options *x, bool mkdir_and_install)
760 const char *from_base = last_component (from);
761 char *to = file_name_concat (to_dir, from_base, NULL);
762 bool ret = true;
764 if (mkdir_and_install)
765 ret = mkancesdirs_safe_wd (from, to, (struct cp_options *)x);
767 ret = ret && install_file_in_file (from, to, x);
768 free (to);
769 return ret;
773 main (int argc, char **argv)
775 int optc;
776 int exit_status = EXIT_SUCCESS;
777 const char *specified_mode = NULL;
778 bool make_backups = false;
779 char *backup_suffix_string;
780 char *version_control_string = NULL;
781 bool mkdir_and_install = false;
782 struct cp_options x;
783 char const *target_directory = NULL;
784 bool no_target_directory = false;
785 int n_files;
786 char **file;
787 bool strip_program_specified = false;
788 char const *scontext = NULL;
789 /* set iff kernel has extra selinux system calls */
790 selinux_enabled = (0 < is_selinux_enabled ());
792 initialize_main (&argc, &argv);
793 set_program_name (argv[0]);
794 setlocale (LC_ALL, "");
795 bindtextdomain (PACKAGE, LOCALEDIR);
796 textdomain (PACKAGE);
798 atexit (close_stdin);
800 cp_option_init (&x);
802 owner_name = NULL;
803 group_name = NULL;
804 strip_files = false;
805 dir_arg = false;
806 umask (0);
808 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
809 we'll actually use backup_suffix_string. */
810 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
812 while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z", long_options,
813 NULL)) != -1)
815 switch (optc)
817 case 'b':
818 make_backups = true;
819 if (optarg)
820 version_control_string = optarg;
821 break;
822 case 'c':
823 break;
824 case 'C':
825 copy_only_if_needed = true;
826 break;
827 case 's':
828 strip_files = true;
829 #ifdef SIGCHLD
830 /* System V fork+wait does not work if SIGCHLD is ignored. */
831 signal (SIGCHLD, SIG_DFL);
832 #endif
833 break;
834 case STRIP_PROGRAM_OPTION:
835 strip_program = xstrdup (optarg);
836 strip_program_specified = true;
837 break;
838 case 'd':
839 dir_arg = true;
840 break;
841 case 'D':
842 mkdir_and_install = true;
843 break;
844 case 'v':
845 x.verbose = true;
846 break;
847 case 'g':
848 group_name = optarg;
849 break;
850 case 'm':
851 specified_mode = optarg;
852 break;
853 case 'o':
854 owner_name = optarg;
855 break;
856 case 'p':
857 x.preserve_timestamps = true;
858 break;
859 case 'S':
860 make_backups = true;
861 backup_suffix_string = optarg;
862 break;
863 case 't':
864 if (target_directory)
865 error (EXIT_FAILURE, 0,
866 _("multiple target directories specified"));
867 target_directory = optarg;
868 break;
869 case 'T':
870 no_target_directory = true;
871 break;
873 case PRESERVE_CONTEXT_OPTION:
874 if (! selinux_enabled)
876 error (0, 0, _("WARNING: ignoring --preserve-context; "
877 "this kernel is not SELinux-enabled"));
878 break;
880 x.preserve_security_context = true;
881 use_default_selinux_context = false;
882 break;
883 case 'Z':
884 if (selinux_enabled)
886 /* Disable use of the install(1) specific setdefaultfilecon().
887 Note setdefaultfilecon() is different from the newer and more
888 generic restorecon() in that the former sets the context of
889 the dest files to that returned by matchpathcon directly,
890 thus discarding MLS level and user identity of the file.
891 TODO: consider removing setdefaultfilecon() in future. */
892 use_default_selinux_context = false;
894 if (optarg)
895 scontext = optarg;
896 else
897 x.set_security_context = true;
899 else if (optarg)
901 error (0, 0,
902 _("warning: ignoring --context; "
903 "it requires an SELinux-enabled kernel"));
905 break;
906 case_GETOPT_HELP_CHAR;
907 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
908 default:
909 usage (EXIT_FAILURE);
913 /* Check for invalid combinations of arguments. */
914 if (dir_arg && strip_files)
915 error (EXIT_FAILURE, 0,
916 _("the strip option may not be used when installing a directory"));
917 if (dir_arg && target_directory)
918 error (EXIT_FAILURE, 0,
919 _("target directory not allowed when installing a directory"));
921 if (target_directory)
923 struct stat st;
924 bool stat_success = stat (target_directory, &st) == 0 ? true : false;
925 if (! mkdir_and_install && ! stat_success)
926 error (EXIT_FAILURE, errno, _("failed to access %s"),
927 quote (target_directory));
928 if (stat_success && ! S_ISDIR (st.st_mode))
929 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
930 quote (target_directory));
933 if (backup_suffix_string)
934 simple_backup_suffix = xstrdup (backup_suffix_string);
936 x.backup_type = (make_backups
937 ? xget_version (_("backup type"),
938 version_control_string)
939 : no_backups);
941 if (x.preserve_security_context && (x.set_security_context || scontext))
942 error (EXIT_FAILURE, 0,
943 _("cannot set target context and preserve it"));
945 if (scontext && setfscreatecon (se_const (scontext)) < 0)
946 error (EXIT_FAILURE, errno,
947 _("failed to set default file creation context to %s"),
948 quote (scontext));
950 n_files = argc - optind;
951 file = argv + optind;
953 if (n_files <= ! (dir_arg || target_directory))
955 if (n_files <= 0)
956 error (0, 0, _("missing file operand"));
957 else
958 error (0, 0, _("missing destination file operand after %s"),
959 quote (file[0]));
960 usage (EXIT_FAILURE);
963 if (no_target_directory)
965 if (target_directory)
966 error (EXIT_FAILURE, 0,
967 _("cannot combine --target-directory (-t) "
968 "and --no-target-directory (-T)"));
969 if (2 < n_files)
971 error (0, 0, _("extra operand %s"), quote (file[2]));
972 usage (EXIT_FAILURE);
975 else if (! (dir_arg || target_directory))
977 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
978 target_directory = file[--n_files];
979 else if (2 < n_files)
980 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
981 quote (file[n_files - 1]));
984 if (specified_mode)
986 struct mode_change *change = mode_compile (specified_mode);
987 if (!change)
988 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
989 mode = mode_adjust (0, false, 0, change, NULL);
990 dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
991 free (change);
994 if (strip_program_specified && !strip_files)
995 error (0, 0, _("WARNING: ignoring --strip-program option as -s option was "
996 "not specified"));
998 if (copy_only_if_needed && x.preserve_timestamps)
1000 error (0, 0, _("options --compare (-C) and --preserve-timestamps are "
1001 "mutually exclusive"));
1002 usage (EXIT_FAILURE);
1005 if (copy_only_if_needed && strip_files)
1007 error (0, 0, _("options --compare (-C) and --strip are mutually "
1008 "exclusive"));
1009 usage (EXIT_FAILURE);
1012 if (copy_only_if_needed && extra_mode (mode))
1013 error (0, 0, _("the --compare (-C) option is ignored when you"
1014 " specify a mode with non-permission bits"));
1016 get_ids ();
1018 if (dir_arg)
1019 exit_status = savewd_process_files (n_files, file, process_dir, &x);
1020 else
1022 /* FIXME: it's a little gross that this initialization is
1023 required by copy.c::copy. */
1024 hash_init ();
1026 if (!target_directory)
1028 if (! (mkdir_and_install
1029 ? install_file_in_file_parents (file[0], file[1], &x)
1030 : install_file_in_file (file[0], file[1], &x)))
1031 exit_status = EXIT_FAILURE;
1033 else
1035 int i;
1036 dest_info_init (&x);
1037 for (i = 0; i < n_files; i++)
1038 if (! install_file_in_dir (file[i], target_directory, &x,
1039 mkdir_and_install))
1040 exit_status = EXIT_FAILURE;
1044 return exit_status;