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 proper_name ("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 #if ! HAVE_MATCHPATHCON_INIT_PREFIX
70 # define matchpathcon_init_prefix(a, p) /* empty */
73 /* Initial number of entries in each hash table entry's table of inodes. */
74 #define INITIAL_HASH_MODULE 100
76 /* Initial number of entries in the inode hash table. */
77 #define INITIAL_ENTRY_TAB_SIZE 70
79 /* Number of bytes of a file to copy at a time. */
80 #define READ_SIZE (32 * 1024)
82 static bool change_timestamps (struct stat const *from_sb, char const *to);
83 static bool change_attributes (char const *name);
84 static bool copy_file (const char *from, const char *to,
85 const struct cp_options *x);
86 static bool install_file_in_file_parents (char const *from, char *to,
87 struct cp_options *x);
88 static bool install_file_in_dir (const char *from, const char *to_dir,
89 const struct cp_options *x);
90 static bool install_file_in_file (const char *from, const char *to,
91 const struct cp_options *x);
92 static void get_ids (void);
93 static void strip (char const *name);
94 static void announce_mkdir (char const *dir, void *options);
95 static int make_ancestor (char const *dir, char const *component,
97 void usage (int status);
99 /* The name this program was run with, for error messages. */
100 char const *program_name;
102 /* The user name that will own the files, or NULL to make the owner
103 the current user ID. */
104 static char *owner_name;
106 /* The user ID corresponding to `owner_name'. */
107 static uid_t owner_id;
109 /* The group name that will own the files, or NULL to make the group
110 the current group ID. */
111 static char *group_name;
113 /* The group ID corresponding to `group_name'. */
114 static gid_t group_id;
116 #define DEFAULT_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
118 /* The file mode bits to which non-directory files will be set. The umask has
120 static mode_t mode = DEFAULT_MODE;
122 /* Similar, but for directories. */
123 static mode_t dir_mode = DEFAULT_MODE;
125 /* The file mode bits that the user cares about. This should be a
126 superset of DIR_MODE and a subset of CHMOD_MODE_BITS. This matters
127 for directories, since otherwise directories may keep their S_ISUID
129 static mode_t dir_mode_bits = CHMOD_MODE_BITS;
131 /* If true, strip executable files after copying them. */
132 static bool strip_files;
134 /* If true, install a directory instead of a regular file. */
137 /* For long options that have no equivalent short option, use a
138 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
141 PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1
144 static struct option const long_options[] =
146 {"backup", optional_argument, NULL, 'b'},
147 {GETOPT_SELINUX_CONTEXT_OPTION_DECL},
148 {"directory", no_argument, NULL, 'd'},
149 {"group", required_argument, NULL, 'g'},
150 {"mode", required_argument, NULL, 'm'},
151 {"no-target-directory", no_argument, NULL, 'T'},
152 {"owner", required_argument, NULL, 'o'},
153 {"preserve-timestamps", no_argument, NULL, 'p'},
154 {"preserve-context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
155 /* Continue silent support for --preserve_context until Jan 2008. FIXME-obs
156 After that, FIXME-obs: warn in, say, late 2008, and disable altogether
157 a year or two later. */
158 {"preserve_context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
159 {"strip", no_argument, NULL, 's'},
160 {"suffix", required_argument, NULL, 'S'},
161 {"target-directory", required_argument, NULL, 't'},
162 {"verbose", no_argument, NULL, 'v'},
163 {GETOPT_HELP_OPTION_DECL},
164 {GETOPT_VERSION_OPTION_DECL},
169 cp_option_init (struct cp_options *x)
171 cp_options_default (x);
172 x->copy_as_regular = true;
173 x->dereference = DEREF_ALWAYS;
174 x->unlink_dest_before_opening = true;
175 x->unlink_dest_after_failed_open = false;
176 x->hard_link = false;
177 x->interactive = I_UNSPECIFIED;
178 x->move_mode = false;
179 x->one_file_system = false;
180 x->preserve_ownership = false;
181 x->preserve_links = false;
182 x->preserve_mode = false;
183 x->preserve_timestamps = false;
184 x->require_preserve = false;
185 x->require_preserve_context = false;
186 x->recursive = false;
187 x->sparse_mode = SPARSE_AUTO;
188 x->symbolic_link = false;
189 x->backup_type = no_backups;
191 /* Create destination files initially writable so we can run strip on them.
192 Although GNU strip works fine on read-only files, some others
195 x->mode = S_IRUSR | S_IWUSR;
196 x->stdin_tty = false;
198 x->open_dangling_dest_symlink = false;
200 x->preserve_security_context = false;
206 #ifdef ENABLE_MATCHPATHCON
207 /* Modify file context to match the specified policy.
208 If an error occurs the file will remain with the default directory
211 setdefaultfilecon (char const *file)
214 security_context_t scontext = NULL;
215 static bool first_call = true;
217 if (selinux_enabled != 1)
219 /* Indicate no context found. */
222 if (lstat (file, &st) != 0)
225 if (first_call && IS_ABSOLUTE_FILE_NAME (file))
227 /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
228 is an optimization to minimize the expense of the following
229 matchpathcon call. Do it only once, just before the first
230 matchpathcon call. We *could* call matchpathcon_fini after
231 the final matchpathcon call, but that's not necessary, since
232 by then we're about to exit, and besides, the buffers it
233 would free are still reachable. */
235 char const *p = file + 1;
239 /* Record final leading slash, for when FILE starts with two or more. */
249 while (*p && !ISSLASH (*p));
251 prefix = malloc (p - p0 + 2);
254 stpcpy (stpncpy (prefix, p0, p - p0), "/");
255 matchpathcon_init_prefix (NULL, prefix);
262 /* If there's an error determining the context, or it has none,
263 return to allow default context */
264 if ((matchpathcon (file, st.st_mode, &scontext) != 0) ||
265 STREQ (scontext, "<<none>>"))
267 if (scontext != NULL)
272 if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
274 _("warning: %s: failed to change context to %s"),
275 quotearg_colon (file), scontext);
282 setdefaultfilecon (char const *file)
288 /* FILE is the last operand of this command. Return true if FILE is a
289 directory. But report an error there is a problem accessing FILE,
290 or if FILE does not exist but would have to refer to an existing
291 directory if it referred to anything at all. */
294 target_directory_operand (char const *file)
296 char const *b = last_component (file);
297 size_t blen = strlen (b);
298 bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
300 int err = (stat (file, &st) == 0 ? 0 : errno);
301 bool is_a_dir = !err && S_ISDIR (st.st_mode);
302 if (err && err != ENOENT)
303 error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
304 if (is_a_dir < looks_like_a_dir)
305 error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
309 /* Process a command-line file name, for the -d option. */
311 process_dir (char *dir, struct savewd *wd, void *options)
313 return (make_dir_parents (dir, wd,
314 make_ancestor, options,
315 dir_mode, announce_mkdir,
316 dir_mode_bits, owner_id, group_id, false)
322 main (int argc, char **argv)
325 int exit_status = EXIT_SUCCESS;
326 const char *specified_mode = NULL;
327 bool make_backups = false;
328 char *backup_suffix_string;
329 char *version_control_string = NULL;
330 bool mkdir_and_install = false;
332 char const *target_directory = NULL;
333 bool no_target_directory = false;
336 security_context_t scontext = NULL;
337 /* set iff kernel has extra selinux system calls */
338 selinux_enabled = (0 < is_selinux_enabled ());
340 initialize_main (&argc, &argv);
341 program_name = argv[0];
342 setlocale (LC_ALL, "");
343 bindtextdomain (PACKAGE, LOCALEDIR);
344 textdomain (PACKAGE);
346 atexit (close_stdin);
356 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
357 we'll actually use backup_suffix_string. */
358 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
360 while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:Z:", long_options,
368 version_control_string = optarg;
375 /* System V fork+wait does not work if SIGCHLD is ignored. */
376 signal (SIGCHLD, SIG_DFL);
383 mkdir_and_install = true;
392 specified_mode = optarg;
398 x.preserve_timestamps = true;
402 backup_suffix_string = optarg;
405 if (target_directory)
406 error (EXIT_FAILURE, 0,
407 _("multiple target directories specified"));
411 if (stat (optarg, &st) != 0)
412 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
413 if (! S_ISDIR (st.st_mode))
414 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
417 target_directory = optarg;
420 no_target_directory = true;
423 case PRESERVE_CONTEXT_OPTION:
424 if ( ! selinux_enabled)
426 error (0, 0, _("Warning: ignoring --preserve-context; "
427 "this kernel is not SELinux-enabled."));
430 x.preserve_security_context = true;
431 use_default_selinux_context = false;
434 if ( ! selinux_enabled)
436 error (0, 0, _("Warning: ignoring --context (-Z); "
437 "this kernel is not SELinux-enabled."));
441 use_default_selinux_context = false;
443 case_GETOPT_HELP_CHAR;
444 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
446 usage (EXIT_FAILURE);
450 /* Check for invalid combinations of arguments. */
451 if (dir_arg & strip_files)
452 error (EXIT_FAILURE, 0,
453 _("the strip option may not be used when installing a directory"));
454 if (dir_arg && target_directory)
455 error (EXIT_FAILURE, 0,
456 _("target directory not allowed when installing a directory"));
458 if (x.preserve_security_context && scontext != NULL)
459 error (EXIT_FAILURE, 0,
460 _("cannot force target context to %s and preserve it"),
463 if (backup_suffix_string)
464 simple_backup_suffix = xstrdup (backup_suffix_string);
466 x.backup_type = (make_backups
467 ? xget_version (_("backup type"),
468 version_control_string)
471 if (scontext && setfscreatecon (scontext) < 0)
472 error (EXIT_FAILURE, errno,
473 _("failed to set default file creation context to %s"),
476 n_files = argc - optind;
477 file = argv + optind;
479 if (n_files <= ! (dir_arg || target_directory))
482 error (0, 0, _("missing file operand"));
484 error (0, 0, _("missing destination file operand after %s"),
486 usage (EXIT_FAILURE);
489 if (no_target_directory)
491 if (target_directory)
492 error (EXIT_FAILURE, 0,
493 _("Cannot combine --target-directory (-t) "
494 "and --no-target-directory (-T)"));
497 error (0, 0, _("extra operand %s"), quote (file[2]));
498 usage (EXIT_FAILURE);
501 else if (! (dir_arg || target_directory))
503 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
504 target_directory = file[--n_files];
505 else if (2 < n_files)
506 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
507 quote (file[n_files - 1]));
512 struct mode_change *change = mode_compile (specified_mode);
514 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
515 mode = mode_adjust (0, false, 0, change, NULL);
516 dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
523 exit_status = savewd_process_files (n_files, file, process_dir, &x);
526 /* FIXME: it's a little gross that this initialization is
527 required by copy.c::copy. */
530 if (!target_directory)
532 if (! (mkdir_and_install
533 ? install_file_in_file_parents (file[0], file[1], &x)
534 : install_file_in_file (file[0], file[1], &x)))
535 exit_status = EXIT_FAILURE;
541 for (i = 0; i < n_files; i++)
542 if (! install_file_in_dir (file[i], target_directory, &x))
543 exit_status = EXIT_FAILURE;
550 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
551 Return true if successful. */
554 install_file_in_file_parents (char const *from, char *to,
555 struct cp_options *x)
557 bool save_working_directory =
558 ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
559 int status = EXIT_SUCCESS;
563 if (! save_working_directory)
566 if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
568 error (0, errno, _("cannot create directory %s"), to);
569 status = EXIT_FAILURE;
572 if (save_working_directory)
574 int restore_result = savewd_restore (&wd, status);
575 int restore_errno = errno;
577 if (EXIT_SUCCESS < restore_result)
579 if (restore_result < 0 && status == EXIT_SUCCESS)
581 error (0, restore_errno, _("cannot create directory %s"), to);
586 return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
589 /* Copy file FROM onto file TO and give TO the appropriate
591 Return true if successful. */
594 install_file_in_file (const char *from, const char *to,
595 const struct cp_options *x)
598 if (x->preserve_timestamps && stat (from, &from_sb) != 0)
600 error (0, errno, _("cannot stat %s"), quote (from));
603 if (! copy_file (from, to, x))
607 if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
608 && ! change_timestamps (&from_sb, to))
610 return change_attributes (to);
613 /* Copy file FROM into directory TO_DIR, keeping its same name,
614 and give the copy the appropriate attributes.
615 Return true if successful. */
618 install_file_in_dir (const char *from, const char *to_dir,
619 const struct cp_options *x)
621 const char *from_base = last_component (from);
622 char *to = file_name_concat (to_dir, from_base, NULL);
623 bool ret = install_file_in_file (from, to, x);
628 /* Copy file FROM onto file TO, creating TO if necessary.
629 Return true if successful. */
632 copy_file (const char *from, const char *to, const struct cp_options *x)
636 /* Allow installing from non-regular files like /dev/null.
637 Charles Karney reported that some Sun version of install allows that
638 and that sendmail's installation process relies on the behavior.
639 However, since !x->recursive, the call to "copy" will fail if FROM
642 return copy (from, to, false, x, ©_into_self, NULL);
645 /* Set the attributes of file or directory NAME.
646 Return true if successful. */
649 change_attributes (char const *name)
652 /* chown must precede chmod because on some systems,
653 chown clears the set[ug]id bits for non-superusers,
654 resulting in incorrect permissions.
655 On System V, users can give away files with chown and then not
656 be able to chmod them. So don't give files away.
658 We don't normally ignore errors from chown because the idea of
659 the install command is that the file is supposed to end up with
660 precisely the attributes that the user specified (or defaulted).
661 If the file doesn't end up with the group they asked for, they'll
664 if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
665 && lchown (name, owner_id, group_id) != 0)
666 error (0, errno, _("cannot change ownership of %s"), quote (name));
667 else if (chmod (name, mode) != 0)
668 error (0, errno, _("cannot change permissions of %s"), quote (name));
672 if (use_default_selinux_context)
673 setdefaultfilecon (name);
678 /* Set the timestamps of file TO to match those of file FROM.
679 Return true if successful. */
682 change_timestamps (struct stat const *from_sb, char const *to)
684 struct timespec timespec[2];
685 timespec[0] = get_stat_atime (from_sb);
686 timespec[1] = get_stat_mtime (from_sb);
688 if (utimens (to, timespec))
690 error (0, errno, _("cannot set time stamps for %s"), quote (to));
696 /* Strip the symbol table from the file NAME.
697 We could dig the magic number out of the file first to
698 determine whether to strip it, but the header files and
699 magic numbers vary so much from system to system that making
700 it portable would be very difficult. Not worth the effort. */
703 strip (char const *name)
711 error (EXIT_FAILURE, errno, _("fork system call failed"));
714 execlp ("strip", "strip", name, NULL);
715 error (EXIT_FAILURE, errno, _("cannot run strip"));
717 default: /* Parent. */
718 if (waitpid (pid, &status, 0) < 0)
719 error (EXIT_FAILURE, errno, _("waiting for strip"));
720 else if (! WIFEXITED (status) || WEXITSTATUS (status))
721 error (EXIT_FAILURE, 0, _("strip process terminated abnormally"));
726 /* Initialize the user and group ownership of the files to install. */
736 pw = getpwnam (owner_name);
739 unsigned long int tmp;
740 if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
742 error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
746 owner_id = pw->pw_uid;
750 owner_id = (uid_t) -1;
754 gr = getgrnam (group_name);
757 unsigned long int tmp;
758 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
760 error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
764 group_id = gr->gr_gid;
768 group_id = (gid_t) -1;
771 /* Report that directory DIR was made, if OPTIONS requests this. */
773 announce_mkdir (char const *dir, void *options)
775 struct cp_options const *x = options;
777 prog_fprintf (stdout, _("creating directory %s"), quote (dir));
780 /* Make ancestor directory DIR, whose last file name component is
781 COMPONENT, with options OPTIONS. Assume the working directory is
782 COMPONENT's parent. */
784 make_ancestor (char const *dir, char const *component, void *options)
786 int r = mkdir (component, DEFAULT_MODE);
788 announce_mkdir (dir, options);
795 if (status != EXIT_SUCCESS)
796 fprintf (stderr, _("Try `%s --help' for more information.\n"),
801 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
802 or: %s [OPTION]... SOURCE... DIRECTORY\n\
803 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
804 or: %s [OPTION]... -d DIRECTORY...\n\
806 program_name, program_name, program_name, program_name);
808 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
809 the existing DIRECTORY, while setting permission modes and owner/group.\n\
810 In the 4th form, create all components of the given DIRECTORY(ies).\n\
814 Mandatory arguments to long options are mandatory for short options too.\n\
817 --backup[=CONTROL] make a backup of each existing destination file\n\
818 -b like --backup but does not accept an argument\n\
820 -d, --directory treat all arguments as directory names; create all\n\
821 components of the specified directories\n\
824 -D create all leading components of DEST except the last,\n\
825 then copy SOURCE to DEST\n\
826 -g, --group=GROUP set group ownership, instead of process' current group\n\
827 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
828 -o, --owner=OWNER set ownership (super-user only)\n\
831 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
832 to corresponding destination files\n\
833 -s, --strip strip symbol tables\n\
834 -S, --suffix=SUFFIX override the usual backup suffix\n\
835 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
836 -T, --no-target-directory treat DEST as a normal file\n\
837 -v, --verbose print the name of each directory as it is created\n\
840 --preserve-context preserve SELinux security context\n\
841 -Z, --context=CONTEXT set SELinux security context of files and directories\n\
844 fputs (HELP_OPTION_DESCRIPTION, stdout);
845 fputs (VERSION_OPTION_DESCRIPTION, stdout);
848 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
849 The version control method may be selected via the --backup option or through\n\
850 the VERSION_CONTROL environment variable. Here are the values:\n\
854 none, off never make backups (even if --backup is given)\n\
855 numbered, t make numbered backups\n\
856 existing, nil numbered if numbered backups exist, simple otherwise\n\
857 simple, never always make simple backups\n\
859 emit_bug_reporting_address ();