1 /* install - copy files and set attributes
2 Copyright (C) 1989-2017 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>
30 #include "backupfile.h"
35 #include "filenamecat.h"
36 #include "full-read.h"
37 #include "mkancesdirs.h"
39 #include "modechange.h"
40 #include "prog-fprintf.h"
44 #include "stat-time.h"
48 /* The official name of this program (e.g., no 'g' prefix). */
49 #define PROGRAM_NAME "install"
51 #define AUTHORS proper_name ("David MacKenzie")
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 #if ! HAVE_MATCHPATHCON_INIT_PREFIX
69 # define matchpathcon_init_prefix(a, p) /* empty */
72 /* The user name that will own the files, or NULL to make the owner
73 the current user ID. */
74 static char *owner_name
;
76 /* The user ID corresponding to 'owner_name'. */
77 static uid_t owner_id
;
79 /* The group name that will own the files, or NULL to make the group
80 the current group ID. */
81 static char *group_name
;
83 /* The group ID corresponding to 'group_name'. */
84 static gid_t group_id
;
86 #define DEFAULT_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
88 /* The file mode bits to which non-directory files will be set. The umask has
90 static mode_t mode
= DEFAULT_MODE
;
92 /* Similar, but for directories. */
93 static mode_t dir_mode
= DEFAULT_MODE
;
95 /* The file mode bits that the user cares about. This should be a
96 superset of DIR_MODE and a subset of CHMOD_MODE_BITS. This matters
97 for directories, since otherwise directories may keep their S_ISUID
99 static mode_t dir_mode_bits
= CHMOD_MODE_BITS
;
101 /* Compare files before installing (-C) */
102 static bool copy_only_if_needed
;
104 /* If true, strip executable files after copying them. */
105 static bool strip_files
;
107 /* If true, install a directory instead of a regular file. */
110 /* Program used to strip binaries, "strip" is default */
111 static char const *strip_program
= "strip";
113 /* For long options that have no equivalent short option, use a
114 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
117 PRESERVE_CONTEXT_OPTION
= CHAR_MAX
+ 1,
121 static struct option
const long_options
[] =
123 {"backup", optional_argument
, NULL
, 'b'},
124 {"compare", no_argument
, NULL
, 'C'},
125 {GETOPT_SELINUX_CONTEXT_OPTION_DECL
},
126 {"directory", no_argument
, NULL
, 'd'},
127 {"group", required_argument
, NULL
, 'g'},
128 {"mode", required_argument
, NULL
, 'm'},
129 {"no-target-directory", no_argument
, NULL
, 'T'},
130 {"owner", required_argument
, NULL
, 'o'},
131 {"preserve-timestamps", no_argument
, NULL
, 'p'},
132 {"preserve-context", no_argument
, NULL
, PRESERVE_CONTEXT_OPTION
},
133 {"strip", no_argument
, NULL
, 's'},
134 {"strip-program", required_argument
, NULL
, STRIP_PROGRAM_OPTION
},
135 {"suffix", required_argument
, NULL
, 'S'},
136 {"target-directory", required_argument
, NULL
, 't'},
137 {"verbose", no_argument
, NULL
, 'v'},
138 {GETOPT_HELP_OPTION_DECL
},
139 {GETOPT_VERSION_OPTION_DECL
},
143 /* Compare content of opened files using file descriptors A_FD and B_FD. Return
144 true if files are equal. */
146 have_same_content (int a_fd
, int b_fd
)
148 enum { CMP_BLOCK_SIZE
= 4096 };
149 static char a_buff
[CMP_BLOCK_SIZE
];
150 static char b_buff
[CMP_BLOCK_SIZE
];
153 while (0 < (size
= full_read (a_fd
, a_buff
, sizeof a_buff
))) {
154 if (size
!= full_read (b_fd
, b_buff
, sizeof b_buff
))
157 if (memcmp (a_buff
, b_buff
, size
) != 0)
164 /* Return true for mode with non-permission bits. */
166 extra_mode (mode_t input
)
168 mode_t mask
= S_IRWXUGO
| S_IFMT
;
169 return !! (input
& ~ mask
);
172 /* Return true if copy of file SRC_NAME to file DEST_NAME is necessary. */
174 need_copy (const char *src_name
, const char *dest_name
,
175 const struct cp_options
*x
)
177 struct stat src_sb
, dest_sb
;
181 if (extra_mode (mode
))
184 /* compare files using stat */
185 if (lstat (src_name
, &src_sb
) != 0)
188 if (lstat (dest_name
, &dest_sb
) != 0)
191 if (!S_ISREG (src_sb
.st_mode
) || !S_ISREG (dest_sb
.st_mode
)
192 || extra_mode (src_sb
.st_mode
) || extra_mode (dest_sb
.st_mode
))
195 if (src_sb
.st_size
!= dest_sb
.st_size
196 || (dest_sb
.st_mode
& CHMOD_MODE_BITS
) != mode
)
199 if (owner_id
== (uid_t
) -1)
202 uid_t ruid
= getuid ();
203 if ((ruid
== (uid_t
) -1 && errno
) || dest_sb
.st_uid
!= ruid
)
206 else if (dest_sb
.st_uid
!= owner_id
)
209 if (group_id
== (uid_t
) -1)
212 gid_t rgid
= getgid ();
213 if ((rgid
== (uid_t
) -1 && errno
) || dest_sb
.st_gid
!= rgid
)
216 else if (dest_sb
.st_gid
!= group_id
)
219 /* compare SELinux context if preserving */
220 if (selinux_enabled
&& x
->preserve_security_context
)
222 char *file_scontext
= NULL
;
223 char *to_scontext
= NULL
;
226 if (getfilecon (src_name
, &file_scontext
) == -1)
229 if (getfilecon (dest_name
, &to_scontext
) == -1)
231 freecon (file_scontext
);
235 scontext_match
= STREQ (file_scontext
, to_scontext
);
237 freecon (file_scontext
);
238 freecon (to_scontext
);
243 /* compare files content */
244 src_fd
= open (src_name
, O_RDONLY
| O_BINARY
);
248 dest_fd
= open (dest_name
, O_RDONLY
| O_BINARY
);
255 content_match
= have_same_content (src_fd
, dest_fd
);
259 return !content_match
;
263 cp_option_init (struct cp_options
*x
)
265 cp_options_default (x
);
266 x
->copy_as_regular
= true;
267 x
->reflink_mode
= REFLINK_NEVER
;
268 x
->dereference
= DEREF_ALWAYS
;
269 x
->unlink_dest_before_opening
= true;
270 x
->unlink_dest_after_failed_open
= false;
271 x
->hard_link
= false;
272 x
->interactive
= I_UNSPECIFIED
;
273 x
->move_mode
= false;
274 x
->install_mode
= true;
275 x
->one_file_system
= false;
276 x
->preserve_ownership
= false;
277 x
->preserve_links
= false;
278 x
->preserve_mode
= false;
279 x
->preserve_timestamps
= false;
280 x
->explicit_no_preserve_mode
= false;
281 x
->reduce_diagnostics
=false;
282 x
->data_copy_required
= true;
283 x
->require_preserve
= false;
284 x
->require_preserve_xattr
= false;
285 x
->recursive
= false;
286 x
->sparse_mode
= SPARSE_AUTO
;
287 x
->symbolic_link
= false;
288 x
->backup_type
= no_backups
;
290 /* Create destination files initially writable so we can run strip on them.
291 Although GNU strip works fine on read-only files, some others
294 x
->mode
= S_IRUSR
| S_IWUSR
;
295 x
->stdin_tty
= false;
297 x
->open_dangling_dest_symlink
= false;
299 x
->require_preserve_context
= false; /* Not used by install currently. */
300 x
->preserve_security_context
= false; /* Whether to copy context from src. */
301 x
->set_security_context
= false; /* Whether to set sys default context. */
302 x
->preserve_xattr
= false;
308 #ifdef ENABLE_MATCHPATHCON
309 /* Modify file context to match the specified policy.
310 If an error occurs the file will remain with the default directory
311 context. Note this sets the context to that returned by matchpathcon,
312 and thus discards MLS levels and user identity of the FILE. */
314 setdefaultfilecon (char const *file
)
317 char *scontext
= NULL
;
318 static bool first_call
= true;
320 if (selinux_enabled
!= 1)
322 /* Indicate no context found. */
325 if (lstat (file
, &st
) != 0)
328 if (first_call
&& IS_ABSOLUTE_FILE_NAME (file
))
330 /* Calling matchpathcon_init_prefix (NULL, "/first_component/")
331 is an optimization to minimize the expense of the following
332 matchpathcon call. Do it only once, just before the first
333 matchpathcon call. We *could* call matchpathcon_fini after
334 the final matchpathcon call, but that's not necessary, since
335 by then we're about to exit, and besides, the buffers it
336 would free are still reachable. */
338 char const *p
= file
+ 1;
342 /* Record final leading slash, for when FILE starts with two or more. */
352 while (*p
&& !ISSLASH (*p
));
354 prefix
= malloc (p
- p0
+ 2);
357 stpcpy (stpncpy (prefix
, p0
, p
- p0
), "/");
358 matchpathcon_init_prefix (NULL
, prefix
);
365 /* If there's an error determining the context, or it has none,
366 return to allow default context. Note the "<<none>>" check
367 is only needed for libselinux < 1.20 (2005-01-04). */
368 if ((matchpathcon (file
, st
.st_mode
, &scontext
) != 0)
369 || STREQ (scontext
, "<<none>>"))
371 if (scontext
!= NULL
)
376 if (lsetfilecon (file
, scontext
) < 0 && errno
!= ENOTSUP
)
378 _("warning: %s: failed to change context to %s"),
379 quotef_n (0, file
), quote_n (1, scontext
));
386 setdefaultfilecon (char const *file
)
392 /* FILE is the last operand of this command. Return true if FILE is a
393 directory. But report an error there is a problem accessing FILE,
394 or if FILE does not exist but would have to refer to an existing
395 directory if it referred to anything at all. */
398 target_directory_operand (char const *file
)
400 char const *b
= last_component (file
);
401 size_t blen
= strlen (b
);
402 bool looks_like_a_dir
= (blen
== 0 || ISSLASH (b
[blen
- 1]));
404 int err
= (stat (file
, &st
) == 0 ? 0 : errno
);
405 bool is_a_dir
= !err
&& S_ISDIR (st
.st_mode
);
406 if (err
&& err
!= ENOENT
)
407 die (EXIT_FAILURE
, err
, _("failed to access %s"), quoteaf (file
));
408 if (is_a_dir
< looks_like_a_dir
)
409 die (EXIT_FAILURE
, err
, _("target %s is not a directory"),
414 /* Report that directory DIR was made, if OPTIONS requests this. */
416 announce_mkdir (char const *dir
, void *options
)
418 struct cp_options
const *x
= options
;
420 prog_fprintf (stdout
, _("creating directory %s"), quoteaf (dir
));
423 /* Make ancestor directory DIR, whose last file name component is
424 COMPONENT, with options OPTIONS. Assume the working directory is
425 COMPONENT's parent. */
427 make_ancestor (char const *dir
, char const *component
, void *options
)
429 struct cp_options
const *x
= options
;
430 if (x
->set_security_context
&& defaultcon (component
, S_IFDIR
) < 0
431 && ! ignorable_ctx_err (errno
))
432 error (0, errno
, _("failed to set default creation context for %s"),
435 int r
= mkdir (component
, DEFAULT_MODE
);
437 announce_mkdir (dir
, options
);
441 /* Process a command-line file name, for the -d option. */
443 process_dir (char *dir
, struct savewd
*wd
, void *options
)
445 struct cp_options
const *x
= options
;
447 int ret
= (make_dir_parents (dir
, wd
, make_ancestor
, options
,
448 dir_mode
, announce_mkdir
,
449 dir_mode_bits
, owner_id
, group_id
, false)
453 /* FIXME: Due to the current structure of make_dir_parents()
454 we don't have the facility to call defaultcon() before the
455 final component of DIR is created. So for now, create the
456 final component with the context from previous component
457 and here we set the context for the final component. */
458 if (ret
== EXIT_SUCCESS
&& x
->set_security_context
)
460 if (! restorecon (last_component (dir
), false, false)
461 && ! ignorable_ctx_err (errno
))
462 error (0, errno
, _("failed to restore context for %s"),
469 /* Copy file FROM onto file TO, creating TO if necessary.
470 Return true if successful. */
473 copy_file (const char *from
, const char *to
, const struct cp_options
*x
)
477 if (copy_only_if_needed
&& !need_copy (from
, to
, x
))
480 /* Allow installing from non-regular files like /dev/null.
481 Charles Karney reported that some Sun version of install allows that
482 and that sendmail's installation process relies on the behavior.
483 However, since !x->recursive, the call to "copy" will fail if FROM
486 return copy (from
, to
, false, x
, ©_into_self
, NULL
);
489 /* Set the attributes of file or directory NAME.
490 Return true if successful. */
493 change_attributes (char const *name
)
496 /* chown must precede chmod because on some systems,
497 chown clears the set[ug]id bits for non-superusers,
498 resulting in incorrect permissions.
499 On System V, users can give away files with chown and then not
500 be able to chmod them. So don't give files away.
502 We don't normally ignore errors from chown because the idea of
503 the install command is that the file is supposed to end up with
504 precisely the attributes that the user specified (or defaulted).
505 If the file doesn't end up with the group they asked for, they'll
508 if (! (owner_id
== (uid_t
) -1 && group_id
== (gid_t
) -1)
509 && lchown (name
, owner_id
, group_id
) != 0)
510 error (0, errno
, _("cannot change ownership of %s"), quoteaf (name
));
511 else if (chmod (name
, mode
) != 0)
512 error (0, errno
, _("cannot change permissions of %s"), quoteaf (name
));
516 if (use_default_selinux_context
)
517 setdefaultfilecon (name
);
522 /* Set the timestamps of file DEST to match those of SRC_SB.
523 Return true if successful. */
526 change_timestamps (struct stat
const *src_sb
, char const *dest
)
528 struct timespec timespec
[2];
529 timespec
[0] = get_stat_atime (src_sb
);
530 timespec
[1] = get_stat_mtime (src_sb
);
532 if (utimens (dest
, timespec
))
534 error (0, errno
, _("cannot set time stamps for %s"), quoteaf (dest
));
540 /* Strip the symbol table from the file NAME.
541 We could dig the magic number out of the file first to
542 determine whether to strip it, but the header files and
543 magic numbers vary so much from system to system that making
544 it portable would be very difficult. Not worth the effort. */
547 strip (char const *name
)
556 error (0, errno
, _("fork system call failed"));
559 execlp (strip_program
, strip_program
, name
, NULL
);
560 die (EXIT_FAILURE
, errno
, _("cannot run %s"), quoteaf (strip_program
));
561 default: /* Parent. */
562 if (waitpid (pid
, &status
, 0) < 0)
563 error (0, errno
, _("waiting for strip"));
564 else if (! WIFEXITED (status
) || WEXITSTATUS (status
))
565 error (0, 0, _("strip process terminated abnormally"));
567 ok
= true; /* strip succeeded */
573 /* Initialize the user and group ownership of the files to install. */
583 pw
= getpwnam (owner_name
);
586 unsigned long int tmp
;
587 if (xstrtoul (owner_name
, NULL
, 0, &tmp
, NULL
) != LONGINT_OK
589 die (EXIT_FAILURE
, 0, _("invalid user %s"),
594 owner_id
= pw
->pw_uid
;
598 owner_id
= (uid_t
) -1;
602 gr
= getgrnam (group_name
);
605 unsigned long int tmp
;
606 if (xstrtoul (group_name
, NULL
, 0, &tmp
, NULL
) != LONGINT_OK
608 die (EXIT_FAILURE
, 0, _("invalid group %s"),
613 group_id
= gr
->gr_gid
;
617 group_id
= (gid_t
) -1;
623 if (status
!= EXIT_SUCCESS
)
628 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
629 or: %s [OPTION]... SOURCE... DIRECTORY\n\
630 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
631 or: %s [OPTION]... -d DIRECTORY...\n\
633 program_name
, program_name
, program_name
, program_name
);
636 This install program copies files (often just compiled) into destination\n\
637 locations you choose. If you want to download and install a ready-to-use\n\
638 package on a GNU/Linux system, you should instead be using a package manager\n\
639 like yum(1) or apt-get(1).\n\
641 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
642 the existing DIRECTORY, while setting permission modes and owner/group.\n\
643 In the 4th form, create all components of the given DIRECTORY(ies).\n\
646 emit_mandatory_arg_note ();
649 --backup[=CONTROL] make a backup of each existing destination file\n\
650 -b like --backup but does not accept an argument\n\
652 -C, --compare compare each pair of source and destination files, and\n\
653 in some cases, do not modify the destination at all\n\
654 -d, --directory treat all arguments as directory names; create all\n\
655 components of the specified directories\n\
658 -D create all leading components of DEST except the last,\n\
659 or all components of --target-directory,\n\
660 then copy SOURCE to DEST\n\
661 -g, --group=GROUP set group ownership, instead of process' current group\n\
662 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
663 -o, --owner=OWNER set ownership (super-user only)\n\
666 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
667 to corresponding destination files\n\
668 -s, --strip strip symbol tables\n\
669 --strip-program=PROGRAM program used to strip binaries\n\
670 -S, --suffix=SUFFIX override the usual backup suffix\n\
671 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
672 -T, --no-target-directory treat DEST as a normal file\n\
673 -v, --verbose print the name of each directory as it is created\n\
676 --preserve-context preserve SELinux security context\n\
677 -Z set SELinux security context of destination\n\
678 file and each created directory to default type\n\
679 --context[=CTX] like -Z, or if CTX is specified then set the\n\
680 SELinux or SMACK security context to CTX\n\
683 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
684 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
685 emit_backup_suffix_note ();
686 emit_ancillary_info (PROGRAM_NAME
);
691 /* Copy file FROM onto file TO and give TO the appropriate
693 Return true if successful. */
696 install_file_in_file (const char *from
, const char *to
,
697 const struct cp_options
*x
)
700 if (x
->preserve_timestamps
&& stat (from
, &from_sb
) != 0)
702 error (0, errno
, _("cannot stat %s"), quoteaf (from
));
705 if (! copy_file (from
, to
, x
))
710 if (unlink (to
) != 0) /* Cleanup. */
711 die (EXIT_FAILURE
, errno
, _("cannot unlink %s"), quoteaf (to
));
714 if (x
->preserve_timestamps
&& (strip_files
|| ! S_ISREG (from_sb
.st_mode
))
715 && ! change_timestamps (&from_sb
, to
))
717 return change_attributes (to
);
720 /* Create any missing parent directories of TO,
721 while maintaining the current Working Directory.
722 Return true if successful. */
725 mkancesdirs_safe_wd (char const *from
, char *to
, struct cp_options
*x
,
728 bool save_working_directory
=
730 || ! (IS_ABSOLUTE_FILE_NAME (from
) && IS_ABSOLUTE_FILE_NAME (to
));
731 int status
= EXIT_SUCCESS
;
735 if (! save_working_directory
)
738 if (mkancesdirs (to
, &wd
, make_ancestor
, x
) == -1)
740 error (0, errno
, _("cannot create directory %s"), quoteaf (to
));
741 status
= EXIT_FAILURE
;
744 if (save_working_directory
)
746 int restore_result
= savewd_restore (&wd
, status
);
747 int restore_errno
= errno
;
749 if (EXIT_SUCCESS
< restore_result
)
751 if (restore_result
< 0 && status
== EXIT_SUCCESS
)
753 error (0, restore_errno
, _("cannot create directory %s"),
758 return status
== EXIT_SUCCESS
;
761 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
762 Return true if successful. */
765 install_file_in_file_parents (char const *from
, char *to
,
766 const struct cp_options
*x
)
768 return (mkancesdirs_safe_wd (from
, to
, (struct cp_options
*)x
, false)
769 && install_file_in_file (from
, to
, x
));
772 /* Copy file FROM into directory TO_DIR, keeping its same name,
773 and give the copy the appropriate attributes.
774 Return true if successful. */
777 install_file_in_dir (const char *from
, const char *to_dir
,
778 const struct cp_options
*x
, bool mkdir_and_install
)
780 const char *from_base
= last_component (from
);
781 char *to
= file_name_concat (to_dir
, from_base
, NULL
);
784 if (mkdir_and_install
)
785 ret
= mkancesdirs_safe_wd (from
, to
, (struct cp_options
*)x
, true);
787 ret
= ret
&& install_file_in_file (from
, to
, x
);
793 main (int argc
, char **argv
)
796 int exit_status
= EXIT_SUCCESS
;
797 const char *specified_mode
= NULL
;
798 bool make_backups
= false;
799 char *version_control_string
= NULL
;
800 bool mkdir_and_install
= false;
802 char const *target_directory
= NULL
;
803 bool no_target_directory
= false;
806 bool strip_program_specified
= false;
807 char const *scontext
= NULL
;
808 /* set iff kernel has extra selinux system calls */
809 selinux_enabled
= (0 < is_selinux_enabled ());
811 initialize_main (&argc
, &argv
);
812 set_program_name (argv
[0]);
813 setlocale (LC_ALL
, "");
814 bindtextdomain (PACKAGE
, LOCALEDIR
);
815 textdomain (PACKAGE
);
817 atexit (close_stdin
);
827 while ((optc
= getopt_long (argc
, argv
, "bcCsDdg:m:o:pt:TvS:Z", long_options
,
835 version_control_string
= optarg
;
840 copy_only_if_needed
= true;
845 /* System V fork+wait does not work if SIGCHLD is ignored. */
846 signal (SIGCHLD
, SIG_DFL
);
849 case STRIP_PROGRAM_OPTION
:
850 strip_program
= xstrdup (optarg
);
851 strip_program_specified
= true;
857 mkdir_and_install
= true;
866 specified_mode
= optarg
;
872 x
.preserve_timestamps
= true;
876 simple_backup_suffix
= optarg
;
879 if (target_directory
)
880 die (EXIT_FAILURE
, 0,
881 _("multiple target directories specified"));
882 target_directory
= optarg
;
885 no_target_directory
= true;
888 case PRESERVE_CONTEXT_OPTION
:
889 if (! selinux_enabled
)
891 error (0, 0, _("WARNING: ignoring --preserve-context; "
892 "this kernel is not SELinux-enabled"));
895 x
.preserve_security_context
= true;
896 use_default_selinux_context
= false;
901 /* Disable use of the install(1) specific setdefaultfilecon().
902 Note setdefaultfilecon() is different from the newer and more
903 generic restorecon() in that the former sets the context of
904 the dest files to that returned by matchpathcon directly,
905 thus discarding MLS level and user identity of the file.
906 TODO: consider removing setdefaultfilecon() in future. */
907 use_default_selinux_context
= false;
912 x
.set_security_context
= true;
917 _("warning: ignoring --context; "
918 "it requires an SELinux-enabled kernel"));
921 case_GETOPT_HELP_CHAR
;
922 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
924 usage (EXIT_FAILURE
);
928 /* Check for invalid combinations of arguments. */
929 if (dir_arg
&& strip_files
)
930 die (EXIT_FAILURE
, 0,
931 _("the strip option may not be used when installing a directory"));
932 if (dir_arg
&& target_directory
)
933 die (EXIT_FAILURE
, 0,
934 _("target directory not allowed when installing a directory"));
936 if (target_directory
)
939 bool stat_success
= stat (target_directory
, &st
) == 0 ? true : false;
940 if (! mkdir_and_install
&& ! stat_success
)
941 die (EXIT_FAILURE
, errno
, _("failed to access %s"),
942 quoteaf (target_directory
));
943 if (stat_success
&& ! S_ISDIR (st
.st_mode
))
944 die (EXIT_FAILURE
, 0, _("target %s is not a directory"),
945 quoteaf (target_directory
));
948 x
.backup_type
= (make_backups
949 ? xget_version (_("backup type"),
950 version_control_string
)
953 if (x
.preserve_security_context
&& (x
.set_security_context
|| scontext
))
954 die (EXIT_FAILURE
, 0,
955 _("cannot set target context and preserve it"));
957 if (scontext
&& setfscreatecon (se_const (scontext
)) < 0)
958 die (EXIT_FAILURE
, errno
,
959 _("failed to set default file creation context to %s"),
962 n_files
= argc
- optind
;
963 file
= argv
+ optind
;
965 if (n_files
<= ! (dir_arg
|| target_directory
))
968 error (0, 0, _("missing file operand"));
970 error (0, 0, _("missing destination file operand after %s"),
972 usage (EXIT_FAILURE
);
975 if (no_target_directory
)
977 if (target_directory
)
978 die (EXIT_FAILURE
, 0,
979 _("cannot combine --target-directory (-t) "
980 "and --no-target-directory (-T)"));
983 error (0, 0, _("extra operand %s"), quoteaf (file
[2]));
984 usage (EXIT_FAILURE
);
987 else if (! (dir_arg
|| target_directory
))
989 if (2 <= n_files
&& target_directory_operand (file
[n_files
- 1]))
990 target_directory
= file
[--n_files
];
991 else if (2 < n_files
)
992 die (EXIT_FAILURE
, 0, _("target %s is not a directory"),
993 quoteaf (file
[n_files
- 1]));
998 struct mode_change
*change
= mode_compile (specified_mode
);
1000 die (EXIT_FAILURE
, 0, _("invalid mode %s"), quote (specified_mode
));
1001 mode
= mode_adjust (0, false, 0, change
, NULL
);
1002 dir_mode
= mode_adjust (0, true, 0, change
, &dir_mode_bits
);
1006 if (strip_program_specified
&& !strip_files
)
1007 error (0, 0, _("WARNING: ignoring --strip-program option as -s option was "
1010 if (copy_only_if_needed
&& x
.preserve_timestamps
)
1012 error (0, 0, _("options --compare (-C) and --preserve-timestamps are "
1013 "mutually exclusive"));
1014 usage (EXIT_FAILURE
);
1017 if (copy_only_if_needed
&& strip_files
)
1019 error (0, 0, _("options --compare (-C) and --strip are mutually "
1021 usage (EXIT_FAILURE
);
1024 if (copy_only_if_needed
&& extra_mode (mode
))
1025 error (0, 0, _("the --compare (-C) option is ignored when you"
1026 " specify a mode with non-permission bits"));
1031 exit_status
= savewd_process_files (n_files
, file
, process_dir
, &x
);
1034 /* FIXME: it's a little gross that this initialization is
1035 required by copy.c::copy. */
1038 if (!target_directory
)
1040 if (! (mkdir_and_install
1041 ? install_file_in_file_parents (file
[0], file
[1], &x
)
1042 : install_file_in_file (file
[0], file
[1], &x
)))
1043 exit_status
= EXIT_FAILURE
;
1048 dest_info_init (&x
);
1049 for (i
= 0; i
< n_files
; i
++)
1050 if (! install_file_in_dir (file
[i
], target_directory
, &x
,
1051 i
== 0 && mkdir_and_install
))
1052 exit_status
= EXIT_FAILURE
;