test: use consistent quoting
[coreutils.git] / src / install.c
blob66e2ea53d6b8c8adb68c075a00ab016a69dae89f
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 quotef_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"), quoteaf (file));
405 if (is_a_dir < looks_like_a_dir)
406 error (EXIT_FAILURE, err, _("target %s is not a directory"),
407 quoteaf (file));
408 return is_a_dir;
411 /* Report that directory DIR was made, if OPTIONS requests this. */
412 static void
413 announce_mkdir (char const *dir, void *options)
415 struct cp_options const *x = options;
416 if (x->verbose)
417 prog_fprintf (stdout, _("creating directory %s"), quoteaf (dir));
420 /* Make ancestor directory DIR, whose last file name component is
421 COMPONENT, with options OPTIONS. Assume the working directory is
422 COMPONENT's parent. */
423 static int
424 make_ancestor (char const *dir, char const *component, void *options)
426 int r = mkdir (component, DEFAULT_MODE);
427 if (r == 0)
428 announce_mkdir (dir, options);
429 return r;
432 /* Process a command-line file name, for the -d option. */
433 static int
434 process_dir (char *dir, struct savewd *wd, void *options)
436 return (make_dir_parents (dir, wd,
437 make_ancestor, options,
438 dir_mode, announce_mkdir,
439 dir_mode_bits, owner_id, group_id, false)
440 ? EXIT_SUCCESS
441 : EXIT_FAILURE);
444 /* Copy file FROM onto file TO, creating TO if necessary.
445 Return true if successful. */
447 static bool
448 copy_file (const char *from, const char *to, const struct cp_options *x)
450 bool copy_into_self;
452 if (copy_only_if_needed && !need_copy (from, to, x))
453 return true;
455 /* Allow installing from non-regular files like /dev/null.
456 Charles Karney reported that some Sun version of install allows that
457 and that sendmail's installation process relies on the behavior.
458 However, since !x->recursive, the call to "copy" will fail if FROM
459 is a directory. */
461 return copy (from, to, false, x, &copy_into_self, NULL);
464 /* Set the attributes of file or directory NAME.
465 Return true if successful. */
467 static bool
468 change_attributes (char const *name)
470 bool ok = false;
471 /* chown must precede chmod because on some systems,
472 chown clears the set[ug]id bits for non-superusers,
473 resulting in incorrect permissions.
474 On System V, users can give away files with chown and then not
475 be able to chmod them. So don't give files away.
477 We don't normally ignore errors from chown because the idea of
478 the install command is that the file is supposed to end up with
479 precisely the attributes that the user specified (or defaulted).
480 If the file doesn't end up with the group they asked for, they'll
481 want to know. */
483 if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
484 && lchown (name, owner_id, group_id) != 0)
485 error (0, errno, _("cannot change ownership of %s"), quoteaf (name));
486 else if (chmod (name, mode) != 0)
487 error (0, errno, _("cannot change permissions of %s"), quoteaf (name));
488 else
489 ok = true;
491 if (use_default_selinux_context)
492 setdefaultfilecon (name);
494 return ok;
497 /* Set the timestamps of file DEST to match those of SRC_SB.
498 Return true if successful. */
500 static bool
501 change_timestamps (struct stat const *src_sb, char const *dest)
503 struct timespec timespec[2];
504 timespec[0] = get_stat_atime (src_sb);
505 timespec[1] = get_stat_mtime (src_sb);
507 if (utimens (dest, timespec))
509 error (0, errno, _("cannot set time stamps for %s"), quoteaf (dest));
510 return false;
512 return true;
515 /* Strip the symbol table from the file NAME.
516 We could dig the magic number out of the file first to
517 determine whether to strip it, but the header files and
518 magic numbers vary so much from system to system that making
519 it portable would be very difficult. Not worth the effort. */
521 static bool
522 strip (char const *name)
524 int status;
525 bool ok = false;
526 pid_t pid = fork ();
528 switch (pid)
530 case -1:
531 error (0, errno, _("fork system call failed"));
532 break;
533 case 0: /* Child. */
534 execlp (strip_program, strip_program, name, NULL);
535 error (EXIT_FAILURE, errno, _("cannot run %s"), quoteaf (strip_program));
536 break;
537 default: /* Parent. */
538 if (waitpid (pid, &status, 0) < 0)
539 error (0, errno, _("waiting for strip"));
540 else if (! WIFEXITED (status) || WEXITSTATUS (status))
541 error (0, 0, _("strip process terminated abnormally"));
542 else
543 ok = true; /* strip succeeded */
544 break;
546 return ok;
549 /* Initialize the user and group ownership of the files to install. */
551 static void
552 get_ids (void)
554 struct passwd *pw;
555 struct group *gr;
557 if (owner_name)
559 pw = getpwnam (owner_name);
560 if (pw == NULL)
562 unsigned long int tmp;
563 if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
564 || UID_T_MAX < tmp)
565 error (EXIT_FAILURE, 0, _("invalid user %s"),
566 quote (owner_name));
567 owner_id = tmp;
569 else
570 owner_id = pw->pw_uid;
571 endpwent ();
573 else
574 owner_id = (uid_t) -1;
576 if (group_name)
578 gr = getgrnam (group_name);
579 if (gr == NULL)
581 unsigned long int tmp;
582 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
583 || GID_T_MAX < tmp)
584 error (EXIT_FAILURE, 0, _("invalid group %s"),
585 quote (group_name));
586 group_id = tmp;
588 else
589 group_id = gr->gr_gid;
590 endgrent ();
592 else
593 group_id = (gid_t) -1;
596 void
597 usage (int status)
599 if (status != EXIT_SUCCESS)
600 emit_try_help ();
601 else
603 printf (_("\
604 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
605 or: %s [OPTION]... SOURCE... DIRECTORY\n\
606 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
607 or: %s [OPTION]... -d DIRECTORY...\n\
609 program_name, program_name, program_name, program_name);
610 fputs (_("\
612 This install program copies files (often just compiled) into destination\n\
613 locations you choose. If you want to download and install a ready-to-use\n\
614 package on a GNU/Linux system, you should instead be using a package manager\n\
615 like yum(1) or apt-get(1).\n\
617 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
618 the existing DIRECTORY, while setting permission modes and owner/group.\n\
619 In the 4th form, create all components of the given DIRECTORY(ies).\n\
620 "), stdout);
622 emit_mandatory_arg_note ();
624 fputs (_("\
625 --backup[=CONTROL] make a backup of each existing destination file\n\
626 -b like --backup but does not accept an argument\n\
627 -c (ignored)\n\
628 -C, --compare compare each pair of source and destination files, and\n\
629 in some cases, do not modify the destination at all\n\
630 -d, --directory treat all arguments as directory names; create all\n\
631 components of the specified directories\n\
632 "), stdout);
633 fputs (_("\
634 -D create all leading components of DEST except the last,\n\
635 then copy SOURCE to DEST\n\
636 -g, --group=GROUP set group ownership, instead of process' current group\n\
637 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
638 -o, --owner=OWNER set ownership (super-user only)\n\
639 "), stdout);
640 fputs (_("\
641 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
642 to corresponding destination files\n\
643 -s, --strip strip symbol tables\n\
644 --strip-program=PROGRAM program used to strip binaries\n\
645 -S, --suffix=SUFFIX override the usual backup suffix\n\
646 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
647 -T, --no-target-directory treat DEST as a normal file\n\
648 -v, --verbose print the name of each directory as it is created\n\
649 "), stdout);
650 fputs (_("\
651 --preserve-context preserve SELinux security context\n\
652 -Z set SELinux security context of destination\n\
653 file to default type\n\
654 --context[=CTX] like -Z, or if CTX is specified then set the\n\
655 SELinux or SMACK security context to CTX\n\
656 "), stdout);
658 fputs (HELP_OPTION_DESCRIPTION, stdout);
659 fputs (VERSION_OPTION_DESCRIPTION, stdout);
660 fputs (_("\
662 The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
663 The version control method may be selected via the --backup option or through\n\
664 the VERSION_CONTROL environment variable. Here are the values:\n\
666 "), stdout);
667 fputs (_("\
668 none, off never make backups (even if --backup is given)\n\
669 numbered, t make numbered backups\n\
670 existing, nil numbered if numbered backups exist, simple otherwise\n\
671 simple, never always make simple backups\n\
672 "), stdout);
673 emit_ancillary_info (PROGRAM_NAME);
675 exit (status);
678 /* Copy file FROM onto file TO and give TO the appropriate
679 attributes.
680 Return true if successful. */
682 static bool
683 install_file_in_file (const char *from, const char *to,
684 const struct cp_options *x)
686 struct stat from_sb;
687 if (x->preserve_timestamps && stat (from, &from_sb) != 0)
689 error (0, errno, _("cannot stat %s"), quoteaf (from));
690 return false;
692 if (! copy_file (from, to, x))
693 return false;
694 if (strip_files)
695 if (! strip (to))
697 if (unlink (to) != 0) /* Cleanup. */
698 error (EXIT_FAILURE, errno, _("cannot unlink %s"), quoteaf (to));
699 return false;
701 if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
702 && ! change_timestamps (&from_sb, to))
703 return false;
704 return change_attributes (to);
707 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
708 Return true if successful. */
710 static bool
711 mkancesdirs_safe_wd (char const *from, char *to, struct cp_options *x)
713 bool save_working_directory =
714 ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
715 int status = EXIT_SUCCESS;
717 struct savewd wd;
718 savewd_init (&wd);
719 if (! save_working_directory)
720 savewd_finish (&wd);
722 if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
724 error (0, errno, _("cannot create directory %s"), quoteaf (to));
725 status = EXIT_FAILURE;
728 if (save_working_directory)
730 int restore_result = savewd_restore (&wd, status);
731 int restore_errno = errno;
732 savewd_finish (&wd);
733 if (EXIT_SUCCESS < restore_result)
734 return false;
735 if (restore_result < 0 && status == EXIT_SUCCESS)
737 error (0, restore_errno, _("cannot create directory %s"),
738 quoteaf (to));
739 return false;
742 return status == EXIT_SUCCESS;
745 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
746 Return true if successful. */
748 static bool
749 install_file_in_file_parents (char const *from, char *to,
750 const struct cp_options *x)
752 return (mkancesdirs_safe_wd (from, to, (struct cp_options *)x)
753 && install_file_in_file (from, to, x));
756 /* Copy file FROM into directory TO_DIR, keeping its same name,
757 and give the copy the appropriate attributes.
758 Return true if successful. */
760 static bool
761 install_file_in_dir (const char *from, const char *to_dir,
762 const struct cp_options *x, bool mkdir_and_install)
764 const char *from_base = last_component (from);
765 char *to = file_name_concat (to_dir, from_base, NULL);
766 bool ret = true;
768 if (mkdir_and_install)
769 ret = mkancesdirs_safe_wd (from, to, (struct cp_options *)x);
771 ret = ret && install_file_in_file (from, to, x);
772 free (to);
773 return ret;
777 main (int argc, char **argv)
779 int optc;
780 int exit_status = EXIT_SUCCESS;
781 const char *specified_mode = NULL;
782 bool make_backups = false;
783 char *backup_suffix_string;
784 char *version_control_string = NULL;
785 bool mkdir_and_install = false;
786 struct cp_options x;
787 char const *target_directory = NULL;
788 bool no_target_directory = false;
789 int n_files;
790 char **file;
791 bool strip_program_specified = false;
792 char const *scontext = NULL;
793 /* set iff kernel has extra selinux system calls */
794 selinux_enabled = (0 < is_selinux_enabled ());
796 initialize_main (&argc, &argv);
797 set_program_name (argv[0]);
798 setlocale (LC_ALL, "");
799 bindtextdomain (PACKAGE, LOCALEDIR);
800 textdomain (PACKAGE);
802 atexit (close_stdin);
804 cp_option_init (&x);
806 owner_name = NULL;
807 group_name = NULL;
808 strip_files = false;
809 dir_arg = false;
810 umask (0);
812 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
813 we'll actually use backup_suffix_string. */
814 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
816 while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z", long_options,
817 NULL)) != -1)
819 switch (optc)
821 case 'b':
822 make_backups = true;
823 if (optarg)
824 version_control_string = optarg;
825 break;
826 case 'c':
827 break;
828 case 'C':
829 copy_only_if_needed = true;
830 break;
831 case 's':
832 strip_files = true;
833 #ifdef SIGCHLD
834 /* System V fork+wait does not work if SIGCHLD is ignored. */
835 signal (SIGCHLD, SIG_DFL);
836 #endif
837 break;
838 case STRIP_PROGRAM_OPTION:
839 strip_program = xstrdup (optarg);
840 strip_program_specified = true;
841 break;
842 case 'd':
843 dir_arg = true;
844 break;
845 case 'D':
846 mkdir_and_install = true;
847 break;
848 case 'v':
849 x.verbose = true;
850 break;
851 case 'g':
852 group_name = optarg;
853 break;
854 case 'm':
855 specified_mode = optarg;
856 break;
857 case 'o':
858 owner_name = optarg;
859 break;
860 case 'p':
861 x.preserve_timestamps = true;
862 break;
863 case 'S':
864 make_backups = true;
865 backup_suffix_string = optarg;
866 break;
867 case 't':
868 if (target_directory)
869 error (EXIT_FAILURE, 0,
870 _("multiple target directories specified"));
871 target_directory = optarg;
872 break;
873 case 'T':
874 no_target_directory = true;
875 break;
877 case PRESERVE_CONTEXT_OPTION:
878 if (! selinux_enabled)
880 error (0, 0, _("WARNING: ignoring --preserve-context; "
881 "this kernel is not SELinux-enabled"));
882 break;
884 x.preserve_security_context = true;
885 use_default_selinux_context = false;
886 break;
887 case 'Z':
888 if (selinux_enabled)
890 /* Disable use of the install(1) specific setdefaultfilecon().
891 Note setdefaultfilecon() is different from the newer and more
892 generic restorecon() in that the former sets the context of
893 the dest files to that returned by matchpathcon directly,
894 thus discarding MLS level and user identity of the file.
895 TODO: consider removing setdefaultfilecon() in future. */
896 use_default_selinux_context = false;
898 if (optarg)
899 scontext = optarg;
900 else
901 x.set_security_context = true;
903 else if (optarg)
905 error (0, 0,
906 _("warning: ignoring --context; "
907 "it requires an SELinux-enabled kernel"));
909 break;
910 case_GETOPT_HELP_CHAR;
911 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
912 default:
913 usage (EXIT_FAILURE);
917 /* Check for invalid combinations of arguments. */
918 if (dir_arg && strip_files)
919 error (EXIT_FAILURE, 0,
920 _("the strip option may not be used when installing a directory"));
921 if (dir_arg && target_directory)
922 error (EXIT_FAILURE, 0,
923 _("target directory not allowed when installing a directory"));
925 if (target_directory)
927 struct stat st;
928 bool stat_success = stat (target_directory, &st) == 0 ? true : false;
929 if (! mkdir_and_install && ! stat_success)
930 error (EXIT_FAILURE, errno, _("failed to access %s"),
931 quoteaf (target_directory));
932 if (stat_success && ! S_ISDIR (st.st_mode))
933 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
934 quoteaf (target_directory));
937 if (backup_suffix_string)
938 simple_backup_suffix = xstrdup (backup_suffix_string);
940 x.backup_type = (make_backups
941 ? xget_version (_("backup type"),
942 version_control_string)
943 : no_backups);
945 if (x.preserve_security_context && (x.set_security_context || scontext))
946 error (EXIT_FAILURE, 0,
947 _("cannot set target context and preserve it"));
949 if (scontext && setfscreatecon (se_const (scontext)) < 0)
950 error (EXIT_FAILURE, errno,
951 _("failed to set default file creation context to %s"),
952 quote (scontext));
954 n_files = argc - optind;
955 file = argv + optind;
957 if (n_files <= ! (dir_arg || target_directory))
959 if (n_files <= 0)
960 error (0, 0, _("missing file operand"));
961 else
962 error (0, 0, _("missing destination file operand after %s"),
963 quoteaf (file[0]));
964 usage (EXIT_FAILURE);
967 if (no_target_directory)
969 if (target_directory)
970 error (EXIT_FAILURE, 0,
971 _("cannot combine --target-directory (-t) "
972 "and --no-target-directory (-T)"));
973 if (2 < n_files)
975 error (0, 0, _("extra operand %s"), quoteaf (file[2]));
976 usage (EXIT_FAILURE);
979 else if (! (dir_arg || target_directory))
981 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
982 target_directory = file[--n_files];
983 else if (2 < n_files)
984 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
985 quoteaf (file[n_files - 1]));
988 if (specified_mode)
990 struct mode_change *change = mode_compile (specified_mode);
991 if (!change)
992 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
993 mode = mode_adjust (0, false, 0, change, NULL);
994 dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
995 free (change);
998 if (strip_program_specified && !strip_files)
999 error (0, 0, _("WARNING: ignoring --strip-program option as -s option was "
1000 "not specified"));
1002 if (copy_only_if_needed && x.preserve_timestamps)
1004 error (0, 0, _("options --compare (-C) and --preserve-timestamps are "
1005 "mutually exclusive"));
1006 usage (EXIT_FAILURE);
1009 if (copy_only_if_needed && strip_files)
1011 error (0, 0, _("options --compare (-C) and --strip are mutually "
1012 "exclusive"));
1013 usage (EXIT_FAILURE);
1016 if (copy_only_if_needed && extra_mode (mode))
1017 error (0, 0, _("the --compare (-C) option is ignored when you"
1018 " specify a mode with non-permission bits"));
1020 get_ids ();
1022 if (dir_arg)
1023 exit_status = savewd_process_files (n_files, file, process_dir, &x);
1024 else
1026 /* FIXME: it's a little gross that this initialization is
1027 required by copy.c::copy. */
1028 hash_init ();
1030 if (!target_directory)
1032 if (! (mkdir_and_install
1033 ? install_file_in_file_parents (file[0], file[1], &x)
1034 : install_file_in_file (file[0], file[1], &x)))
1035 exit_status = EXIT_FAILURE;
1037 else
1039 int i;
1040 dest_info_init (&x);
1041 for (i = 0; i < n_files; i++)
1042 if (! install_file_in_dir (file[i], target_directory, &x,
1043 mkdir_and_install))
1044 exit_status = EXIT_FAILURE;
1048 return exit_status;