1 /* install - copy files and set attributes
2 Copyright (C) 89, 90, 91, 1995-2007 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"
40 #include "stat-time.h"
44 /* The official name of this program (e.g., no `g' prefix). */
45 #define PROGRAM_NAME "install"
47 #define AUTHORS "David MacKenzie"
50 # include <sys/wait.h>
53 static int selinux_enabled = 0;
54 static bool use_default_selinux_context = true;
57 # define endgrent() ((void) 0)
61 # define endpwent() ((void) 0)
65 # define lchown(name, uid, gid) chown (name, uid, gid)
68 /* Initial number of entries in each hash table entry's table of inodes. */
69 #define INITIAL_HASH_MODULE 100
71 /* Initial number of entries in the inode hash table. */
72 #define INITIAL_ENTRY_TAB_SIZE 70
74 /* Number of bytes of a file to copy at a time. */
75 #define READ_SIZE (32 * 1024)
77 static bool change_timestamps (struct stat const *from_sb, char const *to);
78 static bool change_attributes (char const *name);
79 static bool copy_file (const char *from, const char *to,
80 const struct cp_options *x);
81 static bool install_file_in_file_parents (char const *from, char *to,
82 struct cp_options *x);
83 static bool install_file_in_dir (const char *from, const char *to_dir,
84 const struct cp_options *x);
85 static bool install_file_in_file (const char *from, const char *to,
86 const struct cp_options *x);
87 static void get_ids (void);
88 static void strip (char const *name);
89 static void announce_mkdir (char const *dir, void *options);
90 static int make_ancestor (char const *dir, char const *component,
92 void usage (int status);
94 /* The name this program was run with, for error messages. */
97 /* The user name that will own the files, or NULL to make the owner
98 the current user ID. */
99 static char *owner_name;
101 /* The user ID corresponding to `owner_name'. */
102 static uid_t owner_id;
104 /* The group name that will own the files, or NULL to make the group
105 the current group ID. */
106 static char *group_name;
108 /* The group ID corresponding to `group_name'. */
109 static gid_t group_id;
111 #define DEFAULT_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
113 /* The file mode bits to which non-directory files will be set. The umask has
115 static mode_t mode = DEFAULT_MODE;
117 /* Similar, but for directories. */
118 static mode_t dir_mode = DEFAULT_MODE;
120 /* The file mode bits that the user cares about. This should be a
121 superset of DIR_MODE and a subset of CHMOD_MODE_BITS. This matters
122 for directories, since otherwise directories may keep their S_ISUID
124 static mode_t dir_mode_bits = CHMOD_MODE_BITS;
126 /* If true, strip executable files after copying them. */
127 static bool strip_files;
129 /* If true, install a directory instead of a regular file. */
132 /* For long options that have no equivalent short option, use a
133 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
136 PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1
139 static struct option const long_options[] =
141 {"backup", optional_argument, NULL, 'b'},
142 {GETOPT_SELINUX_CONTEXT_OPTION_DECL},
143 {"directory", no_argument, NULL, 'd'},
144 {"group", required_argument, NULL, 'g'},
145 {"mode", required_argument, NULL, 'm'},
146 {"no-target-directory", no_argument, NULL, 'T'},
147 {"owner", required_argument, NULL, 'o'},
148 {"preserve-timestamps", no_argument, NULL, 'p'},
149 {"preserve-context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
150 /* Continue silent support for --preserve_context until Jan 2008. FIXME-obs
151 After that, FIXME-obs: warn in, say, late 2008, and disable altogether
152 a year or two later. */
153 {"preserve_context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
154 {"strip", no_argument, NULL, 's'},
155 {"suffix", required_argument, NULL, 'S'},
156 {"target-directory", required_argument, NULL, 't'},
157 {"verbose", no_argument, NULL, 'v'},
158 {GETOPT_HELP_OPTION_DECL},
159 {GETOPT_VERSION_OPTION_DECL},
164 cp_option_init (struct cp_options *x)
166 x->copy_as_regular = true;
167 x->dereference = DEREF_ALWAYS;
168 x->unlink_dest_before_opening = true;
169 x->unlink_dest_after_failed_open = false;
170 x->hard_link = false;
171 x->interactive = I_UNSPECIFIED;
172 x->move_mode = false;
173 x->chown_privileges = chown_privileges ();
174 x->one_file_system = false;
175 x->preserve_ownership = false;
176 x->preserve_links = false;
177 x->preserve_mode = false;
178 x->preserve_timestamps = false;
179 x->require_preserve = false;
180 x->require_preserve_context = false;
181 x->recursive = false;
182 x->sparse_mode = SPARSE_AUTO;
183 x->symbolic_link = false;
184 x->backup_type = no_backups;
186 /* Create destination files initially writable so we can run strip on them.
187 Although GNU strip works fine on read-only files, some others
190 x->mode = S_IRUSR | S_IWUSR;
191 x->stdin_tty = false;
194 x->preserve_security_context = false;
200 /* Modify file context to match the specified policy.
201 If an error occurs the file will remain with the default directory
204 setdefaultfilecon (char const *file)
207 security_context_t scontext = NULL;
208 if (selinux_enabled != 1)
210 /* Indicate no context found. */
213 if (lstat (file, &st) != 0)
216 #ifdef ENABLE_WHEN_MATCHPATHCON_IS_MORE_EFFICIENT
217 if (IS_ABSOLUTE_FILE_NAME (file))
219 /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
220 is an optimization to minimize the expense of the following
221 matchpathcon call. */
223 char const *p = file + 1;
227 /* Record final leading slash, for when FILE starts with two or more. */
237 while (*p && !ISSLASH (*p));
239 prefix = malloc (p - p0 + 2);
242 stpcpy (stpncpy (prefix, p0, p - p0), "/");
243 matchpathcon_init_prefix (NULL, prefix);
249 /* If there's an error determining the context, or it has none,
250 return to allow default context */
251 if ((matchpathcon (file, st.st_mode, &scontext) != 0) ||
252 STREQ (scontext, "<<none>>"))
254 if (scontext != NULL)
260 if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
262 _("warning: %s: failed to change context to %s"),
263 quotearg_colon (file), scontext);
269 /* FILE is the last operand of this command. Return true if FILE is a
270 directory. But report an error there is a problem accessing FILE,
271 or if FILE does not exist but would have to refer to an existing
272 directory if it referred to anything at all. */
275 target_directory_operand (char const *file)
277 char const *b = last_component (file);
278 size_t blen = strlen (b);
279 bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
281 int err = (stat (file, &st) == 0 ? 0 : errno);
282 bool is_a_dir = !err && S_ISDIR (st.st_mode);
283 if (err && err != ENOENT)
284 error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
285 if (is_a_dir < looks_like_a_dir)
286 error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
290 /* Process a command-line file name, for the -d option. */
292 process_dir (char *dir, struct savewd *wd, void *options)
294 return (make_dir_parents (dir, wd,
295 make_ancestor, options,
296 dir_mode, announce_mkdir,
297 dir_mode_bits, owner_id, group_id, false)
303 main (int argc, char **argv)
306 int exit_status = EXIT_SUCCESS;
307 const char *specified_mode = NULL;
308 bool make_backups = false;
309 char *backup_suffix_string;
310 char *version_control_string = NULL;
311 bool mkdir_and_install = false;
313 char const *target_directory = NULL;
314 bool no_target_directory = false;
317 security_context_t scontext = NULL;
318 /* set iff kernel has extra selinux system calls */
319 selinux_enabled = (0 < is_selinux_enabled ());
321 initialize_main (&argc, &argv);
322 program_name = argv[0];
323 setlocale (LC_ALL, "");
324 bindtextdomain (PACKAGE, LOCALEDIR);
325 textdomain (PACKAGE);
327 atexit (close_stdin);
337 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
338 we'll actually use backup_suffix_string. */
339 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
341 while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:Z:", long_options,
349 version_control_string = optarg;
356 /* System V fork+wait does not work if SIGCHLD is ignored. */
357 signal (SIGCHLD, SIG_DFL);
364 mkdir_and_install = true;
373 specified_mode = optarg;
379 x.preserve_timestamps = true;
383 backup_suffix_string = optarg;
386 if (target_directory)
387 error (EXIT_FAILURE, 0,
388 _("multiple target directories specified"));
392 if (stat (optarg, &st) != 0)
393 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
394 if (! S_ISDIR (st.st_mode))
395 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
398 target_directory = optarg;
401 no_target_directory = true;
404 case PRESERVE_CONTEXT_OPTION:
405 if ( ! selinux_enabled)
407 error (0, 0, _("Warning: ignoring --preserve-context; "
408 "this kernel is not SELinux-enabled."));
411 x.preserve_security_context = true;
412 use_default_selinux_context = false;
415 if ( ! selinux_enabled)
417 error (0, 0, _("Warning: ignoring --context (-Z); "
418 "this kernel is not SELinux-enabled."));
422 use_default_selinux_context = false;
424 case_GETOPT_HELP_CHAR;
425 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
427 usage (EXIT_FAILURE);
431 /* Check for invalid combinations of arguments. */
432 if (dir_arg & strip_files)
433 error (EXIT_FAILURE, 0,
434 _("the strip option may not be used when installing a directory"));
435 if (dir_arg && target_directory)
436 error (EXIT_FAILURE, 0,
437 _("target directory not allowed when installing a directory"));
439 if (x.preserve_security_context && scontext != NULL)
440 error (EXIT_FAILURE, 0,
441 _("cannot force target context to %s and preserve it"),
444 if (backup_suffix_string)
445 simple_backup_suffix = xstrdup (backup_suffix_string);
447 x.backup_type = (make_backups
448 ? xget_version (_("backup type"),
449 version_control_string)
452 if (scontext && setfscreatecon (scontext) < 0)
453 error (EXIT_FAILURE, errno,
454 _("failed to set default file creation context to %s"),
457 n_files = argc - optind;
458 file = argv + optind;
460 if (n_files <= ! (dir_arg || target_directory))
463 error (0, 0, _("missing file operand"));
465 error (0, 0, _("missing destination file operand after %s"),
467 usage (EXIT_FAILURE);
470 if (no_target_directory)
472 if (target_directory)
473 error (EXIT_FAILURE, 0,
474 _("Cannot combine --target-directory (-t) "
475 "and --no-target-directory (-T)"));
478 error (0, 0, _("extra operand %s"), quote (file[2]));
479 usage (EXIT_FAILURE);
482 else if (! (dir_arg || target_directory))
484 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
485 target_directory = file[--n_files];
486 else if (2 < n_files)
487 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
488 quote (file[n_files - 1]));
493 struct mode_change *change = mode_compile (specified_mode);
495 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
496 mode = mode_adjust (0, false, 0, change, NULL);
497 dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
504 exit_status = savewd_process_files (n_files, file, process_dir, &x);
507 /* FIXME: it's a little gross that this initialization is
508 required by copy.c::copy. */
511 if (!target_directory)
513 if (! (mkdir_and_install
514 ? install_file_in_file_parents (file[0], file[1], &x)
515 : install_file_in_file (file[0], file[1], &x)))
516 exit_status = EXIT_FAILURE;
522 for (i = 0; i < n_files; i++)
523 if (! install_file_in_dir (file[i], target_directory, &x))
524 exit_status = EXIT_FAILURE;
531 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
532 Return true if successful. */
535 install_file_in_file_parents (char const *from, char *to,
536 struct cp_options *x)
538 bool save_working_directory =
539 ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
540 int status = EXIT_SUCCESS;
544 if (! save_working_directory)
547 if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
549 error (0, errno, _("cannot create directory %s"), to);
550 status = EXIT_FAILURE;
553 if (save_working_directory)
555 int restore_result = savewd_restore (&wd, status);
556 int restore_errno = errno;
558 if (EXIT_SUCCESS < restore_result)
560 if (restore_result < 0 && status == EXIT_SUCCESS)
562 error (0, restore_errno, _("cannot create directory %s"), to);
567 return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
570 /* Copy file FROM onto file TO and give TO the appropriate
572 Return true if successful. */
575 install_file_in_file (const char *from, const char *to,
576 const struct cp_options *x)
579 if (x->preserve_timestamps && stat (from, &from_sb) != 0)
581 error (0, errno, _("cannot stat %s"), quote (from));
584 if (! copy_file (from, to, x))
588 if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
589 && ! change_timestamps (&from_sb, to))
591 return change_attributes (to);
594 /* Copy file FROM into directory TO_DIR, keeping its same name,
595 and give the copy the appropriate attributes.
596 Return true if successful. */
599 install_file_in_dir (const char *from, const char *to_dir,
600 const struct cp_options *x)
602 const char *from_base = last_component (from);
603 char *to = file_name_concat (to_dir, from_base, NULL);
604 bool ret = install_file_in_file (from, to, x);
609 /* Copy file FROM onto file TO, creating TO if necessary.
610 Return true if successful. */
613 copy_file (const char *from, const char *to, const struct cp_options *x)
617 /* Allow installing from non-regular files like /dev/null.
618 Charles Karney reported that some Sun version of install allows that
619 and that sendmail's installation process relies on the behavior.
620 However, since !x->recursive, the call to "copy" will fail if FROM
623 return copy (from, to, false, x, ©_into_self, NULL);
626 /* Set the attributes of file or directory NAME.
627 Return true if successful. */
630 change_attributes (char const *name)
633 /* chown must precede chmod because on some systems,
634 chown clears the set[ug]id bits for non-superusers,
635 resulting in incorrect permissions.
636 On System V, users can give away files with chown and then not
637 be able to chmod them. So don't give files away.
639 We don't normally ignore errors from chown because the idea of
640 the install command is that the file is supposed to end up with
641 precisely the attributes that the user specified (or defaulted).
642 If the file doesn't end up with the group they asked for, they'll
645 if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
646 && lchown (name, owner_id, group_id) != 0)
647 error (0, errno, _("cannot change ownership of %s"), quote (name));
648 else if (chmod (name, mode) != 0)
649 error (0, errno, _("cannot change permissions of %s"), quote (name));
653 if (use_default_selinux_context)
654 setdefaultfilecon (name);
659 /* Set the timestamps of file TO to match those of file FROM.
660 Return true if successful. */
663 change_timestamps (struct stat const *from_sb, char const *to)
665 struct timespec timespec[2];
666 timespec[0] = get_stat_atime (from_sb);
667 timespec[1] = get_stat_mtime (from_sb);
669 if (utimens (to, timespec))
671 error (0, errno, _("cannot set time stamps for %s"), quote (to));
677 /* Strip the symbol table from the file NAME.
678 We could dig the magic number out of the file first to
679 determine whether to strip it, but the header files and
680 magic numbers vary so much from system to system that making
681 it portable would be very difficult. Not worth the effort. */
684 strip (char const *name)
692 error (EXIT_FAILURE, errno, _("fork system call failed"));
695 execlp ("strip", "strip", name, NULL);
696 error (EXIT_FAILURE, errno, _("cannot run strip"));
698 default: /* Parent. */
699 if (waitpid (pid, &status, 0) < 0)
700 error (EXIT_FAILURE, errno, _("waiting for strip"));
701 else if (! WIFEXITED (status) || WEXITSTATUS (status))
702 error (EXIT_FAILURE, 0, _("strip process terminated abnormally"));
707 /* Initialize the user and group ownership of the files to install. */
717 pw = getpwnam (owner_name);
720 unsigned long int tmp;
721 if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
723 error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
727 owner_id = pw->pw_uid;
731 owner_id = (uid_t) -1;
735 gr = getgrnam (group_name);
738 unsigned long int tmp;
739 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
741 error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
745 group_id = gr->gr_gid;
749 group_id = (gid_t) -1;
752 /* Report that directory DIR was made, if OPTIONS requests this. */
754 announce_mkdir (char const *dir, void *options)
756 struct cp_options const *x = options;
758 error (0, 0, _("creating directory %s"), quote (dir));
761 /* Make ancestor directory DIR, whose last file name component is
762 COMPONENT, with options OPTIONS. Assume the working directory is
763 COMPONENT's parent. */
765 make_ancestor (char const *dir, char const *component, void *options)
767 int r = mkdir (component, DEFAULT_MODE);
769 announce_mkdir (dir, options);
776 if (status != EXIT_SUCCESS)
777 fprintf (stderr, _("Try `%s --help' for more information.\n"),
782 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
783 or: %s [OPTION]... SOURCE... DIRECTORY\n\
784 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
785 or: %s [OPTION]... -d DIRECTORY...\n\
787 program_name, program_name, program_name, program_name);
789 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
790 the existing DIRECTORY, while setting permission modes and owner/group.\n\
791 In the 4th form, create all components of the given DIRECTORY(ies).\n\
795 Mandatory arguments to long options are mandatory for short options too.\n\
798 --backup[=CONTROL] make a backup of each existing destination file\n\
799 -b like --backup but does not accept an argument\n\
801 -d, --directory treat all arguments as directory names; create all\n\
802 components of the specified directories\n\
805 -D create all leading components of DEST except the last,\n\
806 then copy SOURCE to DEST\n\
807 -g, --group=GROUP set group ownership, instead of process' current group\n\
808 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
809 -o, --owner=OWNER set ownership (super-user only)\n\
812 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
813 to corresponding destination files\n\
814 -s, --strip strip symbol tables\n\
815 -S, --suffix=SUFFIX override the usual backup suffix\n\
816 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
817 -T, --no-target-directory treat DEST as a normal file\n\
818 -v, --verbose print the name of each directory as it is created\n\
821 --preserve-context preserve SELinux security context\n\
822 -Z, --context=CONTEXT set SELinux security context of files and directories\n\
825 fputs (HELP_OPTION_DESCRIPTION, stdout);
826 fputs (VERSION_OPTION_DESCRIPTION, stdout);
829 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
830 The version control method may be selected via the --backup option or through\n\
831 the VERSION_CONTROL environment variable. Here are the values:\n\
835 none, off never make backups (even if --backup is given)\n\
836 numbered, t make numbered backups\n\
837 existing, nil numbered if numbered backups exist, simple otherwise\n\
838 simple, never always make simple backups\n\
840 emit_bug_reporting_address ();