1 /* install - copy files and set attributes
2 Copyright (C) 89, 90, 91, 1995-2008 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> */
22 #include <sys/types.h>
26 #include <selinux/selinux.h>
29 #include "backupfile.h"
33 #include "filenamecat.h"
34 #include "mkancesdirs.h"
36 #include "modechange.h"
37 #include "prog-fprintf.h"
41 #include "stat-time.h"
45 /* The official name of this program (e.g., no `g' prefix). */
46 #define PROGRAM_NAME "install"
48 #define AUTHORS "David MacKenzie"
51 # include <sys/wait.h>
54 static int selinux_enabled = 0;
55 static bool use_default_selinux_context = true;
58 # define endgrent() ((void) 0)
62 # define endpwent() ((void) 0)
66 # define lchown(name, uid, gid) chown (name, uid, gid)
69 /* Initial number of entries in each hash table entry's table of inodes. */
70 #define INITIAL_HASH_MODULE 100
72 /* Initial number of entries in the inode hash table. */
73 #define INITIAL_ENTRY_TAB_SIZE 70
75 /* Number of bytes of a file to copy at a time. */
76 #define READ_SIZE (32 * 1024)
78 static bool change_timestamps (struct stat const *from_sb, char const *to);
79 static bool change_attributes (char const *name);
80 static bool copy_file (const char *from, const char *to,
81 const struct cp_options *x);
82 static bool install_file_in_file_parents (char const *from, char *to,
83 struct cp_options *x);
84 static bool install_file_in_dir (const char *from, const char *to_dir,
85 const struct cp_options *x);
86 static bool install_file_in_file (const char *from, const char *to,
87 const struct cp_options *x);
88 static void get_ids (void);
89 static void strip (char const *name);
90 static void announce_mkdir (char const *dir, void *options);
91 static int make_ancestor (char const *dir, char const *component,
93 void usage (int status);
95 /* The name this program was run with, for error messages. */
98 /* The user name that will own the files, or NULL to make the owner
99 the current user ID. */
100 static char *owner_name;
102 /* The user ID corresponding to `owner_name'. */
103 static uid_t owner_id;
105 /* The group name that will own the files, or NULL to make the group
106 the current group ID. */
107 static char *group_name;
109 /* The group ID corresponding to `group_name'. */
110 static gid_t group_id;
112 #define DEFAULT_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
114 /* The file mode bits to which non-directory files will be set. The umask has
116 static mode_t mode = DEFAULT_MODE;
118 /* Similar, but for directories. */
119 static mode_t dir_mode = DEFAULT_MODE;
121 /* The file mode bits that the user cares about. This should be a
122 superset of DIR_MODE and a subset of CHMOD_MODE_BITS. This matters
123 for directories, since otherwise directories may keep their S_ISUID
125 static mode_t dir_mode_bits = CHMOD_MODE_BITS;
127 /* If true, strip executable files after copying them. */
128 static bool strip_files;
130 /* If true, install a directory instead of a regular file. */
133 /* For long options that have no equivalent short option, use a
134 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
137 PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1
140 static struct option const long_options[] =
142 {"backup", optional_argument, NULL, 'b'},
143 {GETOPT_SELINUX_CONTEXT_OPTION_DECL},
144 {"directory", no_argument, NULL, 'd'},
145 {"group", required_argument, NULL, 'g'},
146 {"mode", required_argument, NULL, 'm'},
147 {"no-target-directory", no_argument, NULL, 'T'},
148 {"owner", required_argument, NULL, 'o'},
149 {"preserve-timestamps", no_argument, NULL, 'p'},
150 {"preserve-context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
151 /* Continue silent support for --preserve_context until Jan 2008. FIXME-obs
152 After that, FIXME-obs: warn in, say, late 2008, and disable altogether
153 a year or two later. */
154 {"preserve_context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
155 {"strip", no_argument, NULL, 's'},
156 {"suffix", required_argument, NULL, 'S'},
157 {"target-directory", required_argument, NULL, 't'},
158 {"verbose", no_argument, NULL, 'v'},
159 {GETOPT_HELP_OPTION_DECL},
160 {GETOPT_VERSION_OPTION_DECL},
165 cp_option_init (struct cp_options *x)
167 cp_options_default (x);
168 x->copy_as_regular = true;
169 x->dereference = DEREF_ALWAYS;
170 x->unlink_dest_before_opening = true;
171 x->unlink_dest_after_failed_open = false;
172 x->hard_link = false;
173 x->interactive = I_UNSPECIFIED;
174 x->move_mode = false;
175 x->one_file_system = false;
176 x->preserve_ownership = false;
177 x->preserve_links = false;
178 x->preserve_mode = false;
179 x->preserve_timestamps = false;
180 x->require_preserve = false;
181 x->require_preserve_context = false;
182 x->recursive = false;
183 x->sparse_mode = SPARSE_AUTO;
184 x->symbolic_link = false;
185 x->backup_type = no_backups;
187 /* Create destination files initially writable so we can run strip on them.
188 Although GNU strip works fine on read-only files, some others
191 x->mode = S_IRUSR | S_IWUSR;
192 x->stdin_tty = false;
194 x->open_dangling_dest_symlink = false;
196 x->preserve_security_context = false;
202 #ifdef ENABLE_WHEN_MATCHPATHCON_IS_MORE_EFFICIENT
203 /* Modify file context to match the specified policy.
204 If an error occurs the file will remain with the default directory
207 setdefaultfilecon (char const *file)
210 security_context_t scontext = NULL;
211 if (selinux_enabled != 1)
213 /* Indicate no context found. */
216 if (lstat (file, &st) != 0)
219 if (IS_ABSOLUTE_FILE_NAME (file))
221 /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
222 is an optimization to minimize the expense of the following
223 matchpathcon call. */
225 char const *p = file + 1;
229 /* Record final leading slash, for when FILE starts with two or more. */
239 while (*p && !ISSLASH (*p));
241 prefix = malloc (p - p0 + 2);
244 stpcpy (stpncpy (prefix, p0, p - p0), "/");
245 matchpathcon_init_prefix (NULL, prefix);
251 /* If there's an error determining the context, or it has none,
252 return to allow default context */
253 if ((matchpathcon (file, st.st_mode, &scontext) != 0) ||
254 STREQ (scontext, "<<none>>"))
256 if (scontext != NULL)
261 if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
263 _("warning: %s: failed to change context to %s"),
264 quotearg_colon (file), scontext);
271 setdefaultfilecon (char const *file)
277 /* FILE is the last operand of this command. Return true if FILE is a
278 directory. But report an error there is a problem accessing FILE,
279 or if FILE does not exist but would have to refer to an existing
280 directory if it referred to anything at all. */
283 target_directory_operand (char const *file)
285 char const *b = last_component (file);
286 size_t blen = strlen (b);
287 bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
289 int err = (stat (file, &st) == 0 ? 0 : errno);
290 bool is_a_dir = !err && S_ISDIR (st.st_mode);
291 if (err && err != ENOENT)
292 error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
293 if (is_a_dir < looks_like_a_dir)
294 error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
298 /* Process a command-line file name, for the -d option. */
300 process_dir (char *dir, struct savewd *wd, void *options)
302 return (make_dir_parents (dir, wd,
303 make_ancestor, options,
304 dir_mode, announce_mkdir,
305 dir_mode_bits, owner_id, group_id, false)
311 main (int argc, char **argv)
314 int exit_status = EXIT_SUCCESS;
315 const char *specified_mode = NULL;
316 bool make_backups = false;
317 char *backup_suffix_string;
318 char *version_control_string = NULL;
319 bool mkdir_and_install = false;
321 char const *target_directory = NULL;
322 bool no_target_directory = false;
325 security_context_t scontext = NULL;
326 /* set iff kernel has extra selinux system calls */
327 selinux_enabled = (0 < is_selinux_enabled ());
329 initialize_main (&argc, &argv);
330 program_name = argv[0];
331 setlocale (LC_ALL, "");
332 bindtextdomain (PACKAGE, LOCALEDIR);
333 textdomain (PACKAGE);
335 atexit (close_stdin);
345 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
346 we'll actually use backup_suffix_string. */
347 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
349 while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:Z:", long_options,
357 version_control_string = optarg;
364 /* System V fork+wait does not work if SIGCHLD is ignored. */
365 signal (SIGCHLD, SIG_DFL);
372 mkdir_and_install = true;
381 specified_mode = optarg;
387 x.preserve_timestamps = true;
391 backup_suffix_string = optarg;
394 if (target_directory)
395 error (EXIT_FAILURE, 0,
396 _("multiple target directories specified"));
400 if (stat (optarg, &st) != 0)
401 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
402 if (! S_ISDIR (st.st_mode))
403 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
406 target_directory = optarg;
409 no_target_directory = true;
412 case PRESERVE_CONTEXT_OPTION:
413 if ( ! selinux_enabled)
415 error (0, 0, _("Warning: ignoring --preserve-context; "
416 "this kernel is not SELinux-enabled."));
419 x.preserve_security_context = true;
420 use_default_selinux_context = false;
423 if ( ! selinux_enabled)
425 error (0, 0, _("Warning: ignoring --context (-Z); "
426 "this kernel is not SELinux-enabled."));
430 use_default_selinux_context = false;
432 case_GETOPT_HELP_CHAR;
433 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
435 usage (EXIT_FAILURE);
439 /* Check for invalid combinations of arguments. */
440 if (dir_arg & strip_files)
441 error (EXIT_FAILURE, 0,
442 _("the strip option may not be used when installing a directory"));
443 if (dir_arg && target_directory)
444 error (EXIT_FAILURE, 0,
445 _("target directory not allowed when installing a directory"));
447 if (x.preserve_security_context && scontext != NULL)
448 error (EXIT_FAILURE, 0,
449 _("cannot force target context to %s and preserve it"),
452 if (backup_suffix_string)
453 simple_backup_suffix = xstrdup (backup_suffix_string);
455 x.backup_type = (make_backups
456 ? xget_version (_("backup type"),
457 version_control_string)
460 if (scontext && setfscreatecon (scontext) < 0)
461 error (EXIT_FAILURE, errno,
462 _("failed to set default file creation context to %s"),
465 n_files = argc - optind;
466 file = argv + optind;
468 if (n_files <= ! (dir_arg || target_directory))
471 error (0, 0, _("missing file operand"));
473 error (0, 0, _("missing destination file operand after %s"),
475 usage (EXIT_FAILURE);
478 if (no_target_directory)
480 if (target_directory)
481 error (EXIT_FAILURE, 0,
482 _("Cannot combine --target-directory (-t) "
483 "and --no-target-directory (-T)"));
486 error (0, 0, _("extra operand %s"), quote (file[2]));
487 usage (EXIT_FAILURE);
490 else if (! (dir_arg || target_directory))
492 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
493 target_directory = file[--n_files];
494 else if (2 < n_files)
495 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
496 quote (file[n_files - 1]));
501 struct mode_change *change = mode_compile (specified_mode);
503 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
504 mode = mode_adjust (0, false, 0, change, NULL);
505 dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
512 exit_status = savewd_process_files (n_files, file, process_dir, &x);
515 /* FIXME: it's a little gross that this initialization is
516 required by copy.c::copy. */
519 if (!target_directory)
521 if (! (mkdir_and_install
522 ? install_file_in_file_parents (file[0], file[1], &x)
523 : install_file_in_file (file[0], file[1], &x)))
524 exit_status = EXIT_FAILURE;
530 for (i = 0; i < n_files; i++)
531 if (! install_file_in_dir (file[i], target_directory, &x))
532 exit_status = EXIT_FAILURE;
539 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
540 Return true if successful. */
543 install_file_in_file_parents (char const *from, char *to,
544 struct cp_options *x)
546 bool save_working_directory =
547 ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
548 int status = EXIT_SUCCESS;
552 if (! save_working_directory)
555 if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
557 error (0, errno, _("cannot create directory %s"), to);
558 status = EXIT_FAILURE;
561 if (save_working_directory)
563 int restore_result = savewd_restore (&wd, status);
564 int restore_errno = errno;
566 if (EXIT_SUCCESS < restore_result)
568 if (restore_result < 0 && status == EXIT_SUCCESS)
570 error (0, restore_errno, _("cannot create directory %s"), to);
575 return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
578 /* Copy file FROM onto file TO and give TO the appropriate
580 Return true if successful. */
583 install_file_in_file (const char *from, const char *to,
584 const struct cp_options *x)
587 if (x->preserve_timestamps && stat (from, &from_sb) != 0)
589 error (0, errno, _("cannot stat %s"), quote (from));
592 if (! copy_file (from, to, x))
596 if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
597 && ! change_timestamps (&from_sb, to))
599 return change_attributes (to);
602 /* Copy file FROM into directory TO_DIR, keeping its same name,
603 and give the copy the appropriate attributes.
604 Return true if successful. */
607 install_file_in_dir (const char *from, const char *to_dir,
608 const struct cp_options *x)
610 const char *from_base = last_component (from);
611 char *to = file_name_concat (to_dir, from_base, NULL);
612 bool ret = install_file_in_file (from, to, x);
617 /* Copy file FROM onto file TO, creating TO if necessary.
618 Return true if successful. */
621 copy_file (const char *from, const char *to, const struct cp_options *x)
625 /* Allow installing from non-regular files like /dev/null.
626 Charles Karney reported that some Sun version of install allows that
627 and that sendmail's installation process relies on the behavior.
628 However, since !x->recursive, the call to "copy" will fail if FROM
631 return copy (from, to, false, x, ©_into_self, NULL);
634 /* Set the attributes of file or directory NAME.
635 Return true if successful. */
638 change_attributes (char const *name)
641 /* chown must precede chmod because on some systems,
642 chown clears the set[ug]id bits for non-superusers,
643 resulting in incorrect permissions.
644 On System V, users can give away files with chown and then not
645 be able to chmod them. So don't give files away.
647 We don't normally ignore errors from chown because the idea of
648 the install command is that the file is supposed to end up with
649 precisely the attributes that the user specified (or defaulted).
650 If the file doesn't end up with the group they asked for, they'll
653 if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
654 && lchown (name, owner_id, group_id) != 0)
655 error (0, errno, _("cannot change ownership of %s"), quote (name));
656 else if (chmod (name, mode) != 0)
657 error (0, errno, _("cannot change permissions of %s"), quote (name));
661 if (use_default_selinux_context)
662 setdefaultfilecon (name);
667 /* Set the timestamps of file TO to match those of file FROM.
668 Return true if successful. */
671 change_timestamps (struct stat const *from_sb, char const *to)
673 struct timespec timespec[2];
674 timespec[0] = get_stat_atime (from_sb);
675 timespec[1] = get_stat_mtime (from_sb);
677 if (utimens (to, timespec))
679 error (0, errno, _("cannot set time stamps for %s"), quote (to));
685 /* Strip the symbol table from the file NAME.
686 We could dig the magic number out of the file first to
687 determine whether to strip it, but the header files and
688 magic numbers vary so much from system to system that making
689 it portable would be very difficult. Not worth the effort. */
692 strip (char const *name)
700 error (EXIT_FAILURE, errno, _("fork system call failed"));
703 execlp ("strip", "strip", name, NULL);
704 error (EXIT_FAILURE, errno, _("cannot run strip"));
706 default: /* Parent. */
707 if (waitpid (pid, &status, 0) < 0)
708 error (EXIT_FAILURE, errno, _("waiting for strip"));
709 else if (! WIFEXITED (status) || WEXITSTATUS (status))
710 error (EXIT_FAILURE, 0, _("strip process terminated abnormally"));
715 /* Initialize the user and group ownership of the files to install. */
725 pw = getpwnam (owner_name);
728 unsigned long int tmp;
729 if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
731 error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
735 owner_id = pw->pw_uid;
739 owner_id = (uid_t) -1;
743 gr = getgrnam (group_name);
746 unsigned long int tmp;
747 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
749 error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
753 group_id = gr->gr_gid;
757 group_id = (gid_t) -1;
760 /* Report that directory DIR was made, if OPTIONS requests this. */
762 announce_mkdir (char const *dir, void *options)
764 struct cp_options const *x = options;
766 prog_fprintf (stdout, _("creating directory %s"), quote (dir));
769 /* Make ancestor directory DIR, whose last file name component is
770 COMPONENT, with options OPTIONS. Assume the working directory is
771 COMPONENT's parent. */
773 make_ancestor (char const *dir, char const *component, void *options)
775 int r = mkdir (component, DEFAULT_MODE);
777 announce_mkdir (dir, options);
784 if (status != EXIT_SUCCESS)
785 fprintf (stderr, _("Try `%s --help' for more information.\n"),
790 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
791 or: %s [OPTION]... SOURCE... DIRECTORY\n\
792 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
793 or: %s [OPTION]... -d DIRECTORY...\n\
795 program_name, program_name, program_name, program_name);
797 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
798 the existing DIRECTORY, while setting permission modes and owner/group.\n\
799 In the 4th form, create all components of the given DIRECTORY(ies).\n\
803 Mandatory arguments to long options are mandatory for short options too.\n\
806 --backup[=CONTROL] make a backup of each existing destination file\n\
807 -b like --backup but does not accept an argument\n\
809 -d, --directory treat all arguments as directory names; create all\n\
810 components of the specified directories\n\
813 -D create all leading components of DEST except the last,\n\
814 then copy SOURCE to DEST\n\
815 -g, --group=GROUP set group ownership, instead of process' current group\n\
816 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
817 -o, --owner=OWNER set ownership (super-user only)\n\
820 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
821 to corresponding destination files\n\
822 -s, --strip strip symbol tables\n\
823 -S, --suffix=SUFFIX override the usual backup suffix\n\
824 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
825 -T, --no-target-directory treat DEST as a normal file\n\
826 -v, --verbose print the name of each directory as it is created\n\
829 --preserve-context preserve SELinux security context\n\
830 -Z, --context=CONTEXT set SELinux security context of files and directories\n\
833 fputs (HELP_OPTION_DESCRIPTION, stdout);
834 fputs (VERSION_OPTION_DESCRIPTION, stdout);
837 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
838 The version control method may be selected via the --backup option or through\n\
839 the VERSION_CONTROL environment variable. Here are the values:\n\
843 none, off never make backups (even if --backup is given)\n\
844 numbered, t make numbered backups\n\
845 existing, nil numbered if numbered backups exist, simple otherwise\n\
846 simple, never always make simple backups\n\
848 emit_bug_reporting_address ();