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 2, or (at your option)
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, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu> */
23 #include <sys/types.h>
27 #include <selinux/selinux.h>
30 #include "backupfile.h"
34 #include "filenamecat.h"
35 #include "mkancesdirs.h"
37 #include "modechange.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 x->copy_as_regular = true;
168 x->dereference = DEREF_ALWAYS;
169 x->unlink_dest_before_opening = true;
170 x->unlink_dest_after_failed_open = false;
171 x->hard_link = false;
172 x->interactive = I_UNSPECIFIED;
173 x->move_mode = false;
174 x->chown_privileges = chown_privileges ();
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;
195 x->preserve_security_context = false;
201 /* Modify file context to match the specified policy.
202 If an error occurs the file will remain with the default directory
205 setdefaultfilecon (char const *file)
208 security_context_t scontext = NULL;
209 if (selinux_enabled != 1)
211 /* Indicate no context found. */
214 if (lstat (file, &st) != 0)
217 /* If there's an error determining the context, or it has none,
218 return to allow default context */
219 if ((matchpathcon (file, st.st_mode, &scontext) != 0) ||
220 STREQ (scontext, "<<none>>"))
222 if (scontext != NULL)
227 if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
229 _("warning: %s: failed to change context to %s"),
230 quotearg_colon (file), scontext);
236 /* FILE is the last operand of this command. Return true if FILE is a
237 directory. But report an error there is a problem accessing FILE,
238 or if FILE does not exist but would have to refer to an existing
239 directory if it referred to anything at all. */
242 target_directory_operand (char const *file)
244 char const *b = last_component (file);
245 size_t blen = strlen (b);
246 bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
248 int err = (stat (file, &st) == 0 ? 0 : errno);
249 bool is_a_dir = !err && S_ISDIR (st.st_mode);
250 if (err && err != ENOENT)
251 error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
252 if (is_a_dir < looks_like_a_dir)
253 error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
257 /* Process a command-line file name, for the -d option. */
259 process_dir (char *dir, struct savewd *wd, void *options)
261 return (make_dir_parents (dir, wd,
262 make_ancestor, options,
263 dir_mode, announce_mkdir,
264 dir_mode_bits, owner_id, group_id, false)
270 main (int argc, char **argv)
273 int exit_status = EXIT_SUCCESS;
274 const char *specified_mode = NULL;
275 bool make_backups = false;
276 char *backup_suffix_string;
277 char *version_control_string = NULL;
278 bool mkdir_and_install = false;
280 char const *target_directory = NULL;
281 bool no_target_directory = false;
284 security_context_t scontext = NULL;
285 /* set iff kernel has extra selinux system calls */
286 selinux_enabled = (0 < is_selinux_enabled ());
288 initialize_main (&argc, &argv);
289 program_name = argv[0];
290 setlocale (LC_ALL, "");
291 bindtextdomain (PACKAGE, LOCALEDIR);
292 textdomain (PACKAGE);
294 atexit (close_stdout);
304 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
305 we'll actually use backup_suffix_string. */
306 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
308 while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:Z:", long_options,
316 version_control_string = optarg;
323 /* System V fork+wait does not work if SIGCHLD is ignored. */
324 signal (SIGCHLD, SIG_DFL);
331 mkdir_and_install = true;
340 specified_mode = optarg;
346 x.preserve_timestamps = true;
350 backup_suffix_string = optarg;
353 if (target_directory)
354 error (EXIT_FAILURE, 0,
355 _("multiple target directories specified"));
359 if (stat (optarg, &st) != 0)
360 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
361 if (! S_ISDIR (st.st_mode))
362 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
365 target_directory = optarg;
368 no_target_directory = true;
371 case PRESERVE_CONTEXT_OPTION:
372 if ( ! selinux_enabled)
374 error (0, 0, _("Warning: ignoring --preserve-context; "
375 "this kernel is not SELinux-enabled."));
378 x.preserve_security_context = true;
379 use_default_selinux_context = false;
382 if ( ! selinux_enabled)
384 error (0, 0, _("Warning: ignoring --context (-Z); "
385 "this kernel is not SELinux-enabled."));
389 use_default_selinux_context = false;
391 case_GETOPT_HELP_CHAR;
392 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
394 usage (EXIT_FAILURE);
398 /* Check for invalid combinations of arguments. */
399 if (dir_arg & strip_files)
400 error (EXIT_FAILURE, 0,
401 _("the strip option may not be used when installing a directory"));
402 if (dir_arg && target_directory)
403 error (EXIT_FAILURE, 0,
404 _("target directory not allowed when installing a directory"));
406 if (x.preserve_security_context && scontext != NULL)
407 error (EXIT_FAILURE, 0,
408 _("cannot force target context to %s and preserve it"),
411 if (backup_suffix_string)
412 simple_backup_suffix = xstrdup (backup_suffix_string);
414 x.backup_type = (make_backups
415 ? xget_version (_("backup type"),
416 version_control_string)
419 if (scontext && setfscreatecon (scontext) < 0)
420 error (EXIT_FAILURE, errno,
421 _("failed to set default file creation context to %s"),
424 n_files = argc - optind;
425 file = argv + optind;
427 if (n_files <= ! (dir_arg || target_directory))
430 error (0, 0, _("missing file operand"));
432 error (0, 0, _("missing destination file operand after %s"),
434 usage (EXIT_FAILURE);
437 if (no_target_directory)
439 if (target_directory)
440 error (EXIT_FAILURE, 0,
441 _("Cannot combine --target-directory (-t) "
442 "and --no-target-directory (-T)"));
445 error (0, 0, _("extra operand %s"), quote (file[2]));
446 usage (EXIT_FAILURE);
449 else if (! (dir_arg || target_directory))
451 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
452 target_directory = file[--n_files];
453 else if (2 < n_files)
454 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
455 quote (file[n_files - 1]));
460 struct mode_change *change = mode_compile (specified_mode);
462 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
463 mode = mode_adjust (0, false, 0, change, NULL);
464 dir_mode = mode_adjust (0, true, 0, change, &dir_mode_bits);
471 exit_status = savewd_process_files (n_files, file, process_dir, &x);
474 /* FIXME: it's a little gross that this initialization is
475 required by copy.c::copy. */
478 if (!target_directory)
480 if (! (mkdir_and_install
481 ? install_file_in_file_parents (file[0], file[1], &x)
482 : install_file_in_file (file[0], file[1], &x)))
483 exit_status = EXIT_FAILURE;
489 for (i = 0; i < n_files; i++)
490 if (! install_file_in_dir (file[i], target_directory, &x))
491 exit_status = EXIT_FAILURE;
498 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
499 Return true if successful. */
502 install_file_in_file_parents (char const *from, char *to,
503 struct cp_options *x)
505 bool save_working_directory =
506 ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
507 int status = EXIT_SUCCESS;
511 if (! save_working_directory)
514 if (mkancesdirs (to, &wd, make_ancestor, x) == -1)
516 error (0, errno, _("cannot create directory %s"), to);
517 status = EXIT_FAILURE;
520 if (save_working_directory)
522 int restore_result = savewd_restore (&wd, status);
523 int restore_errno = errno;
525 if (EXIT_SUCCESS < restore_result)
527 if (restore_result < 0 && status == EXIT_SUCCESS)
529 error (0, restore_errno, _("cannot create directory %s"), to);
534 return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
537 /* Copy file FROM onto file TO and give TO the appropriate
539 Return true if successful. */
542 install_file_in_file (const char *from, const char *to,
543 const struct cp_options *x)
546 if (x->preserve_timestamps && stat (from, &from_sb) != 0)
548 error (0, errno, _("cannot stat %s"), quote (from));
551 if (! copy_file (from, to, x))
555 if (x->preserve_timestamps && (strip_files || ! S_ISREG (from_sb.st_mode))
556 && ! change_timestamps (&from_sb, to))
558 return change_attributes (to);
561 /* Copy file FROM into directory TO_DIR, keeping its same name,
562 and give the copy the appropriate attributes.
563 Return true if successful. */
566 install_file_in_dir (const char *from, const char *to_dir,
567 const struct cp_options *x)
569 const char *from_base = last_component (from);
570 char *to = file_name_concat (to_dir, from_base, NULL);
571 bool ret = install_file_in_file (from, to, x);
576 /* Copy file FROM onto file TO, creating TO if necessary.
577 Return true if successful. */
580 copy_file (const char *from, const char *to, const struct cp_options *x)
584 /* Allow installing from non-regular files like /dev/null.
585 Charles Karney reported that some Sun version of install allows that
586 and that sendmail's installation process relies on the behavior.
587 However, since !x->recursive, the call to "copy" will fail if FROM
590 return copy (from, to, false, x, ©_into_self, NULL);
593 /* Set the attributes of file or directory NAME.
594 Return true if successful. */
597 change_attributes (char const *name)
600 /* chown must precede chmod because on some systems,
601 chown clears the set[ug]id bits for non-superusers,
602 resulting in incorrect permissions.
603 On System V, users can give away files with chown and then not
604 be able to chmod them. So don't give files away.
606 We don't normally ignore errors from chown because the idea of
607 the install command is that the file is supposed to end up with
608 precisely the attributes that the user specified (or defaulted).
609 If the file doesn't end up with the group they asked for, they'll
612 if (! (owner_id == (uid_t) -1 && group_id == (gid_t) -1)
613 && lchown (name, owner_id, group_id) != 0)
614 error (0, errno, _("cannot change ownership of %s"), quote (name));
615 else if (chmod (name, mode) != 0)
616 error (0, errno, _("cannot change permissions of %s"), quote (name));
620 if (use_default_selinux_context)
621 setdefaultfilecon (name);
626 /* Set the timestamps of file TO to match those of file FROM.
627 Return true if successful. */
630 change_timestamps (struct stat const *from_sb, char const *to)
632 struct timespec timespec[2];
633 timespec[0] = get_stat_atime (from_sb);
634 timespec[1] = get_stat_mtime (from_sb);
636 if (utimens (to, timespec))
638 error (0, errno, _("cannot set time stamps for %s"), quote (to));
644 /* Strip the symbol table from the file NAME.
645 We could dig the magic number out of the file first to
646 determine whether to strip it, but the header files and
647 magic numbers vary so much from system to system that making
648 it portable would be very difficult. Not worth the effort. */
651 strip (char const *name)
659 error (EXIT_FAILURE, errno, _("fork system call failed"));
662 execlp ("strip", "strip", name, NULL);
663 error (EXIT_FAILURE, errno, _("cannot run strip"));
665 default: /* Parent. */
666 if (waitpid (pid, &status, 0) < 0)
667 error (EXIT_FAILURE, errno, _("waiting for strip"));
668 else if (! WIFEXITED (status) || WEXITSTATUS (status))
669 error (EXIT_FAILURE, 0, _("strip process terminated abnormally"));
674 /* Initialize the user and group ownership of the files to install. */
684 pw = getpwnam (owner_name);
687 unsigned long int tmp;
688 if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
690 error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
694 owner_id = pw->pw_uid;
698 owner_id = (uid_t) -1;
702 gr = getgrnam (group_name);
705 unsigned long int tmp;
706 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
708 error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
712 group_id = gr->gr_gid;
716 group_id = (gid_t) -1;
719 /* Report that directory DIR was made, if OPTIONS requests this. */
721 announce_mkdir (char const *dir, void *options)
723 struct cp_options const *x = options;
725 error (0, 0, _("creating directory %s"), quote (dir));
728 /* Make ancestor directory DIR, whose last file name component is
729 COMPONENT, with options OPTIONS. Assume the working directory is
730 COMPONENT's parent. */
732 make_ancestor (char const *dir, char const *component, void *options)
734 int r = mkdir (component, DEFAULT_MODE);
736 announce_mkdir (dir, options);
743 if (status != EXIT_SUCCESS)
744 fprintf (stderr, _("Try `%s --help' for more information.\n"),
749 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
750 or: %s [OPTION]... SOURCE... DIRECTORY\n\
751 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
752 or: %s [OPTION]... -d DIRECTORY...\n\
754 program_name, program_name, program_name, program_name);
756 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
757 the existing DIRECTORY, while setting permission modes and owner/group.\n\
758 In the 4th form, create all components of the given DIRECTORY(ies).\n\
762 Mandatory arguments to long options are mandatory for short options too.\n\
765 --backup[=CONTROL] make a backup of each existing destination file\n\
766 -b like --backup but does not accept an argument\n\
768 -d, --directory treat all arguments as directory names; create all\n\
769 components of the specified directories\n\
772 -D create all leading components of DEST except the last,\n\
773 then copy SOURCE to DEST\n\
774 -g, --group=GROUP set group ownership, instead of process' current group\n\
775 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
776 -o, --owner=OWNER set ownership (super-user only)\n\
779 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
780 to corresponding destination files\n\
781 -s, --strip strip symbol tables\n\
782 -S, --suffix=SUFFIX override the usual backup suffix\n\
783 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
784 -T, --no-target-directory treat DEST as a normal file\n\
785 -v, --verbose print the name of each directory as it is created\n\
788 --preserve-context preserve SELinux security context\n\
789 -Z, --context=CONTEXT set SELinux security context of files and directories\n\
792 fputs (HELP_OPTION_DESCRIPTION, stdout);
793 fputs (VERSION_OPTION_DESCRIPTION, stdout);
796 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
797 The version control method may be selected via the --backup option or through\n\
798 the VERSION_CONTROL environment variable. Here are the values:\n\
802 none, off never make backups (even if --backup is given)\n\
803 numbered, t make numbered backups\n\
804 existing, nil numbered if numbered backups exist, simple otherwise\n\
805 simple, never always make simple backups\n\
807 emit_bug_reporting_address ();