doc: clarify the operation of wc -L
[coreutils.git] / src / install.c
blobbfde21d63b358faf915757a28fe45249613f94a9
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 "quotearg.h"
42 #include "savewd.h"
43 #include "stat-time.h"
44 #include "utimens.h"
45 #include "xstrtol.h"
47 /* The official name of this program (e.g., no 'g' prefix). */
48 #define PROGRAM_NAME "install"
50 #define AUTHORS proper_name ("David MacKenzie")
52 static int selinux_enabled = 0;
53 static bool use_default_selinux_context = true;
55 #if ! HAVE_ENDGRENT
56 # define endgrent() ((void) 0)
57 #endif
59 #if ! HAVE_ENDPWENT
60 # define endpwent() ((void) 0)
61 #endif
63 #if ! HAVE_LCHOWN
64 # define lchown(name, uid, gid) chown (name, uid, gid)
65 #endif
67 #if ! HAVE_MATCHPATHCON_INIT_PREFIX
68 # define matchpathcon_init_prefix(a, p) /* empty */
69 #endif
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;
75 /* The user ID corresponding to 'owner_name'. */
76 static uid_t owner_id;
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;
82 /* The group ID corresponding to 'group_name'. */
83 static gid_t group_id;
85 #define DEFAULT_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
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;
91 /* Similar, but for directories. */
92 static mode_t dir_mode = DEFAULT_MODE;
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;
100 /* Compare files before installing (-C) */
101 static bool copy_only_if_needed;
103 /* If true, strip executable files after copying them. */
104 static bool strip_files;
106 /* If true, install a directory instead of a regular file. */
107 static bool dir_arg;
109 /* Program used to strip binaries, "strip" is default */
110 static char const *strip_program = "strip";
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
116 PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1,
117 STRIP_PROGRAM_OPTION
120 static struct option const long_options[] =
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}
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)
147 enum { CMP_BLOCK_SIZE = 4096 };
148 static char a_buff[CMP_BLOCK_SIZE];
149 static char b_buff[CMP_BLOCK_SIZE];
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;
156 if (memcmp (a_buff, b_buff, size) != 0)
157 return false;
160 return size == 0;
163 /* Return true for mode with non-permission bits. */
164 static bool
165 extra_mode (mode_t input)
167 mode_t mask = S_IRWXUGO | S_IFMT;
168 return !! (input & ~ mask);
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)
176 struct stat src_sb, dest_sb;
177 int src_fd, dest_fd;
178 bool content_match;
180 if (extra_mode (mode))
181 return true;
183 /* compare files using stat */
184 if (lstat (src_name, &src_sb) != 0)
185 return true;
187 if (lstat (dest_name, &dest_sb) != 0)
188 return true;
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;
194 if (src_sb.st_size != dest_sb.st_size
195 || (dest_sb.st_mode & CHMOD_MODE_BITS) != mode)
196 return true;
198 if (owner_id == (uid_t) -1)
200 errno = 0;
201 uid_t ruid = getuid ();
202 if ((ruid == (uid_t) -1 && errno) || dest_sb.st_uid != ruid)
203 return true;
205 else if (dest_sb.st_uid != owner_id)
206 return true;
208 if (group_id == (uid_t) -1)
210 errno = 0;
211 gid_t rgid = getgid ();
212 if ((rgid == (uid_t) -1 && errno) || dest_sb.st_gid != rgid)
213 return true;
215 else if (dest_sb.st_gid != group_id)
216 return true;
218 /* compare SELinux context if preserving */
219 if (selinux_enabled && x->preserve_security_context)
221 char *file_scontext = NULL;
222 char *to_scontext = NULL;
223 bool scontext_match;
225 if (getfilecon (src_name, &file_scontext) == -1)
226 return true;
228 if (getfilecon (dest_name, &to_scontext) == -1)
230 freecon (file_scontext);
231 return true;
234 scontext_match = STREQ (file_scontext, to_scontext);
236 freecon (file_scontext);
237 freecon (to_scontext);
238 if (!scontext_match)
239 return true;
242 /* compare files content */
243 src_fd = open (src_name, O_RDONLY | O_BINARY);
244 if (src_fd < 0)
245 return true;
247 dest_fd = open (dest_name, O_RDONLY | O_BINARY);
248 if (dest_fd < 0)
250 close (src_fd);
251 return true;
254 content_match = have_same_content (src_fd, dest_fd);
256 close (src_fd);
257 close (dest_fd);
258 return !content_match;
261 static void
262 cp_option_init (struct cp_options *x)
264 cp_options_default (x);
265 x->copy_as_regular = true;
266 x->reflink_mode = REFLINK_NEVER;
267 x->dereference = DEREF_ALWAYS;
268 x->unlink_dest_before_opening = true;
269 x->unlink_dest_after_failed_open = false;
270 x->hard_link = false;
271 x->interactive = I_UNSPECIFIED;
272 x->move_mode = false;
273 x->one_file_system = false;
274 x->preserve_ownership = false;
275 x->preserve_links = false;
276 x->preserve_mode = false;
277 x->preserve_timestamps = false;
278 x->explicit_no_preserve_mode = false;
279 x->reduce_diagnostics=false;
280 x->data_copy_required = true;
281 x->require_preserve = false;
282 x->require_preserve_xattr = false;
283 x->recursive = false;
284 x->sparse_mode = SPARSE_AUTO;
285 x->symbolic_link = false;
286 x->backup_type = no_backups;
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;
295 x->open_dangling_dest_symlink = false;
296 x->update = false;
297 x->require_preserve_context = false; /* Not used by install currently. */
298 x->preserve_security_context = false; /* Whether to copy context from src. */
299 x->set_security_context = false; /* Whether to set sys default context. */
300 x->preserve_xattr = false;
301 x->verbose = false;
302 x->dest_info = NULL;
303 x->src_info = NULL;
306 #ifdef ENABLE_MATCHPATHCON
307 /* Modify file context to match the specified policy.
308 If an error occurs the file will remain with the default directory
309 context. Note this sets the context to that returned by matchpathcon,
310 and thus discards MLS levels and user identity of the FILE. */
311 static void
312 setdefaultfilecon (char const *file)
314 struct stat st;
315 char *scontext = NULL;
316 static bool first_call = true;
318 if (selinux_enabled != 1)
320 /* Indicate no context found. */
321 return;
323 if (lstat (file, &st) != 0)
324 return;
326 if (first_call && IS_ABSOLUTE_FILE_NAME (file))
328 /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
329 is an optimization to minimize the expense of the following
330 matchpathcon call. Do it only once, just before the first
331 matchpathcon call. We *could* call matchpathcon_fini after
332 the final matchpathcon call, but that's not necessary, since
333 by then we're about to exit, and besides, the buffers it
334 would free are still reachable. */
335 char const *p0;
336 char const *p = file + 1;
337 while (ISSLASH (*p))
338 ++p;
340 /* Record final leading slash, for when FILE starts with two or more. */
341 p0 = p - 1;
343 if (*p)
345 char *prefix;
348 ++p;
350 while (*p && !ISSLASH (*p));
352 prefix = malloc (p - p0 + 2);
353 if (prefix)
355 stpcpy (stpncpy (prefix, p0, p - p0), "/");
356 matchpathcon_init_prefix (NULL, prefix);
357 free (prefix);
361 first_call = false;
363 /* If there's an error determining the context, or it has none,
364 return to allow default context. Note the "<<none>>" check
365 is only needed for libselinux < 1.20 (2005-01-04). */
366 if ((matchpathcon (file, st.st_mode, &scontext) != 0)
367 || STREQ (scontext, "<<none>>"))
369 if (scontext != NULL)
370 freecon (scontext);
371 return;
374 if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
375 error (0, errno,
376 _("warning: %s: failed to change context to %s"),
377 quotearg_colon (file), scontext);
379 freecon (scontext);
380 return;
382 #else
383 static void
384 setdefaultfilecon (char const *file)
386 (void) file;
388 #endif
390 /* FILE is the last operand of this command. Return true if FILE is a
391 directory. But report an error there is a problem accessing FILE,
392 or if FILE does not exist but would have to refer to an existing
393 directory if it referred to anything at all. */
395 static bool
396 target_directory_operand (char const *file)
398 char const *b = last_component (file);
399 size_t blen = strlen (b);
400 bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
401 struct stat st;
402 int err = (stat (file, &st) == 0 ? 0 : errno);
403 bool is_a_dir = !err && S_ISDIR (st.st_mode);
404 if (err && err != ENOENT)
405 error (EXIT_FAILURE, err, _("failed to access %s"), quote (file));
406 if (is_a_dir < looks_like_a_dir)
407 error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (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"), quote (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"), quote (name));
486 else if (chmod (name, mode) != 0)
487 error (0, errno, _("cannot change permissions of %s"), quote (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"), quote (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"), 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"), quote (owner_name));
566 owner_id = tmp;
568 else
569 owner_id = pw->pw_uid;
570 endpwent ();
572 else
573 owner_id = (uid_t) -1;
575 if (group_name)
577 gr = getgrnam (group_name);
578 if (gr == NULL)
580 unsigned long int tmp;
581 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
582 || GID_T_MAX < tmp)
583 error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
584 group_id = tmp;
586 else
587 group_id = gr->gr_gid;
588 endgrent ();
590 else
591 group_id = (gid_t) -1;
594 void
595 usage (int status)
597 if (status != EXIT_SUCCESS)
598 emit_try_help ();
599 else
601 printf (_("\
602 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
603 or: %s [OPTION]... SOURCE... DIRECTORY\n\
604 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
605 or: %s [OPTION]... -d DIRECTORY...\n\
607 program_name, program_name, program_name, program_name);
608 fputs (_("\
610 This install program copies files (often just compiled) into destination\n\
611 locations you choose. If you want to download and install a ready-to-use\n\
612 package on a GNU/Linux system, you should instead be using a package manager\n\
613 like yum(1) or apt-get(1).\n\
615 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
616 the existing DIRECTORY, while setting permission modes and owner/group.\n\
617 In the 4th form, create all components of the given DIRECTORY(ies).\n\
618 "), stdout);
620 emit_mandatory_arg_note ();
622 fputs (_("\
623 --backup[=CONTROL] make a backup of each existing destination file\n\
624 -b like --backup but does not accept an argument\n\
625 -c (ignored)\n\
626 -C, --compare compare each pair of source and destination files, and\n\
627 in some cases, do not modify the destination at all\n\
628 -d, --directory treat all arguments as directory names; create all\n\
629 components of the specified directories\n\
630 "), stdout);
631 fputs (_("\
632 -D create all leading components of DEST except the last,\n\
633 then copy SOURCE to DEST\n\
634 -g, --group=GROUP set group ownership, instead of process' current group\n\
635 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
636 -o, --owner=OWNER set ownership (super-user only)\n\
637 "), stdout);
638 fputs (_("\
639 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
640 to corresponding destination files\n\
641 -s, --strip strip symbol tables\n\
642 --strip-program=PROGRAM program used to strip binaries\n\
643 -S, --suffix=SUFFIX override the usual backup suffix\n\
644 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
645 -T, --no-target-directory treat DEST as a normal file\n\
646 -v, --verbose print the name of each directory as it is created\n\
647 "), stdout);
648 fputs (_("\
649 --preserve-context preserve SELinux security context\n\
650 -Z set SELinux security context of destination\n\
651 file to default type\n\
652 --context[=CTX] like -Z, or if CTX is specified then set the\n\
653 SELinux or SMACK security context to CTX\n\
654 "), stdout);
656 fputs (HELP_OPTION_DESCRIPTION, stdout);
657 fputs (VERSION_OPTION_DESCRIPTION, stdout);
658 fputs (_("\
660 The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
661 The version control method may be selected via the --backup option or through\n\
662 the VERSION_CONTROL environment variable. Here are the values:\n\
664 "), stdout);
665 fputs (_("\
666 none, off never make backups (even if --backup is given)\n\
667 numbered, t make numbered backups\n\
668 existing, nil numbered if numbered backups exist, simple otherwise\n\
669 simple, never always make simple backups\n\
670 "), stdout);
671 emit_ancillary_info (PROGRAM_NAME);
673 exit (status);
676 /* Copy file FROM onto file TO and give TO the appropriate
677 attributes.
678 Return true if successful. */
680 static bool
681 install_file_in_file (const char *from, const char *to,
682 const struct cp_options *x)
684 struct stat from_sb;
685 if (x->preserve_timestamps && stat (from, &from_sb) != 0)
687 error (0, errno, _("cannot stat %s"), quote (from));
688 return false;
690 if (! copy_file (from, to, x))
691 return false;
692 if (strip_files)
693 if (! strip (to))
695 if (unlink (to) != 0) /* Cleanup. */
696 error (EXIT_FAILURE, errno, _("cannot unlink %s"), to);
697 return false;
699 if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
700 && ! change_timestamps (&from_sb, to))
701 return false;
702 return change_attributes (to);
705 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
706 Return true if successful. */
708 static bool
709 mkancesdirs_safe_wd (char const *from, char *to, struct cp_options *x)
711 bool save_working_directory =
712 ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
713 int status = EXIT_SUCCESS;
715 struct savewd wd;
716 savewd_init (&wd);
717 if (! save_working_directory)
718 savewd_finish (&wd);
720 if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
722 error (0, errno, _("cannot create directory %s"), to);
723 status = EXIT_FAILURE;
726 if (save_working_directory)
728 int restore_result = savewd_restore (&wd, status);
729 int restore_errno = errno;
730 savewd_finish (&wd);
731 if (EXIT_SUCCESS < restore_result)
732 return false;
733 if (restore_result < 0 && status == EXIT_SUCCESS)
735 error (0, restore_errno, _("cannot create directory %s"), to);
736 return false;
739 return status == EXIT_SUCCESS;
742 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
743 Return true if successful. */
745 static bool
746 install_file_in_file_parents (char const *from, char *to,
747 const struct cp_options *x)
749 return (mkancesdirs_safe_wd (from, to, (struct cp_options *)x)
750 && install_file_in_file (from, to, x));
753 /* Copy file FROM into directory TO_DIR, keeping its same name,
754 and give the copy the appropriate attributes.
755 Return true if successful. */
757 static bool
758 install_file_in_dir (const char *from, const char *to_dir,
759 const struct cp_options *x, bool mkdir_and_install)
761 const char *from_base = last_component (from);
762 char *to = file_name_concat (to_dir, from_base, NULL);
763 bool ret = true;
765 if (mkdir_and_install)
766 ret = mkancesdirs_safe_wd (from, to, (struct cp_options *)x);
768 ret = ret && install_file_in_file (from, to, x);
769 free (to);
770 return ret;
774 main (int argc, char **argv)
776 int optc;
777 int exit_status = EXIT_SUCCESS;
778 const char *specified_mode = NULL;
779 bool make_backups = false;
780 char *backup_suffix_string;
781 char *version_control_string = NULL;
782 bool mkdir_and_install = false;
783 struct cp_options x;
784 char const *target_directory = NULL;
785 bool no_target_directory = false;
786 int n_files;
787 char **file;
788 bool strip_program_specified = false;
789 char const *scontext = NULL;
790 /* set iff kernel has extra selinux system calls */
791 selinux_enabled = (0 < is_selinux_enabled ());
793 initialize_main (&argc, &argv);
794 set_program_name (argv[0]);
795 setlocale (LC_ALL, "");
796 bindtextdomain (PACKAGE, LOCALEDIR);
797 textdomain (PACKAGE);
799 atexit (close_stdin);
801 cp_option_init (&x);
803 owner_name = NULL;
804 group_name = NULL;
805 strip_files = false;
806 dir_arg = false;
807 umask (0);
809 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
810 we'll actually use backup_suffix_string. */
811 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
813 while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z", long_options,
814 NULL)) != -1)
816 switch (optc)
818 case 'b':
819 make_backups = true;
820 if (optarg)
821 version_control_string = optarg;
822 break;
823 case 'c':
824 break;
825 case 'C':
826 copy_only_if_needed = true;
827 break;
828 case 's':
829 strip_files = true;
830 #ifdef SIGCHLD
831 /* System V fork+wait does not work if SIGCHLD is ignored. */
832 signal (SIGCHLD, SIG_DFL);
833 #endif
834 break;
835 case STRIP_PROGRAM_OPTION:
836 strip_program = xstrdup (optarg);
837 strip_program_specified = true;
838 break;
839 case 'd':
840 dir_arg = true;
841 break;
842 case 'D':
843 mkdir_and_install = true;
844 break;
845 case 'v':
846 x.verbose = true;
847 break;
848 case 'g':
849 group_name = optarg;
850 break;
851 case 'm':
852 specified_mode = optarg;
853 break;
854 case 'o':
855 owner_name = optarg;
856 break;
857 case 'p':
858 x.preserve_timestamps = true;
859 break;
860 case 'S':
861 make_backups = true;
862 backup_suffix_string = optarg;
863 break;
864 case 't':
865 if (target_directory)
866 error (EXIT_FAILURE, 0,
867 _("multiple target directories specified"));
868 target_directory = optarg;
869 break;
870 case 'T':
871 no_target_directory = true;
872 break;
874 case PRESERVE_CONTEXT_OPTION:
875 if (! selinux_enabled)
877 error (0, 0, _("WARNING: ignoring --preserve-context; "
878 "this kernel is not SELinux-enabled"));
879 break;
881 x.preserve_security_context = true;
882 use_default_selinux_context = false;
883 break;
884 case 'Z':
885 if (selinux_enabled)
887 /* Disable use of the install(1) specific setdefaultfilecon().
888 Note setdefaultfilecon() is different from the newer and more
889 generic restorecon() in that the former sets the context of
890 the dest files to that returned by matchpathcon directly,
891 thus discarding MLS level and user identity of the file.
892 TODO: consider removing setdefaultfilecon() in future. */
893 use_default_selinux_context = false;
895 if (optarg)
896 scontext = optarg;
897 else
898 x.set_security_context = true;
900 else if (optarg)
902 error (0, 0,
903 _("warning: ignoring --context; "
904 "it requires an SELinux-enabled kernel"));
906 break;
907 case_GETOPT_HELP_CHAR;
908 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
909 default:
910 usage (EXIT_FAILURE);
914 /* Check for invalid combinations of arguments. */
915 if (dir_arg && strip_files)
916 error (EXIT_FAILURE, 0,
917 _("the strip option may not be used when installing a directory"));
918 if (dir_arg && target_directory)
919 error (EXIT_FAILURE, 0,
920 _("target directory not allowed when installing a directory"));
922 if (target_directory)
924 struct stat st;
925 bool stat_success = stat (target_directory, &st) == 0 ? true : false;
926 if (! mkdir_and_install && ! stat_success)
927 error (EXIT_FAILURE, errno, _("failed to access %s"),
928 quote (target_directory));
929 if (stat_success && ! S_ISDIR (st.st_mode))
930 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
931 quote (target_directory));
934 if (backup_suffix_string)
935 simple_backup_suffix = xstrdup (backup_suffix_string);
937 x.backup_type = (make_backups
938 ? xget_version (_("backup type"),
939 version_control_string)
940 : no_backups);
942 if (x.preserve_security_context && (x.set_security_context || scontext))
943 error (EXIT_FAILURE, 0,
944 _("cannot set target context and preserve it"));
946 if (scontext && setfscreatecon (se_const (scontext)) < 0)
947 error (EXIT_FAILURE, errno,
948 _("failed to set default file creation context to %s"),
949 quote (scontext));
951 n_files = argc - optind;
952 file = argv + optind;
954 if (n_files <= ! (dir_arg || target_directory))
956 if (n_files <= 0)
957 error (0, 0, _("missing file operand"));
958 else
959 error (0, 0, _("missing destination file operand after %s"),
960 quote (file[0]));
961 usage (EXIT_FAILURE);
964 if (no_target_directory)
966 if (target_directory)
967 error (EXIT_FAILURE, 0,
968 _("cannot combine --target-directory (-t) "
969 "and --no-target-directory (-T)"));
970 if (2 < n_files)
972 error (0, 0, _("extra operand %s"), quote (file[2]));
973 usage (EXIT_FAILURE);
976 else if (! (dir_arg || target_directory))
978 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
979 target_directory = file[--n_files];
980 else if (2 < n_files)
981 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
982 quote (file[n_files - 1]));
985 if (specified_mode)
987 struct mode_change *change = mode_compile (specified_mode);
988 if (!change)
989 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
990 mode = mode_adjust (0, false, 0, change, NULL);
991 dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
992 free (change);
995 if (strip_program_specified && !strip_files)
996 error (0, 0, _("WARNING: ignoring --strip-program option as -s option was "
997 "not specified"));
999 if (copy_only_if_needed && x.preserve_timestamps)
1001 error (0, 0, _("options --compare (-C) and --preserve-timestamps are "
1002 "mutually exclusive"));
1003 usage (EXIT_FAILURE);
1006 if (copy_only_if_needed && strip_files)
1008 error (0, 0, _("options --compare (-C) and --strip are mutually "
1009 "exclusive"));
1010 usage (EXIT_FAILURE);
1013 if (copy_only_if_needed && extra_mode (mode))
1014 error (0, 0, _("the --compare (-C) option is ignored when you"
1015 " specify a mode with non-permission bits"));
1017 get_ids ();
1019 if (dir_arg)
1020 exit_status = savewd_process_files (n_files, file, process_dir, &x);
1021 else
1023 /* FIXME: it's a little gross that this initialization is
1024 required by copy.c::copy. */
1025 hash_init ();
1027 if (!target_directory)
1029 if (! (mkdir_and_install
1030 ? install_file_in_file_parents (file[0], file[1], &x)
1031 : install_file_in_file (file[0], file[1], &x)))
1032 exit_status = EXIT_FAILURE;
1034 else
1036 int i;
1037 dest_info_init (&x);
1038 for (i = 0; i < n_files; i++)
1039 if (! install_file_in_dir (file[i], target_directory, &x,
1040 mkdir_and_install))
1041 exit_status = EXIT_FAILURE;
1045 return exit_status;