1 /* install - copy files and set attributes
2 Copyright (C) 89, 90, 91, 1995-2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu> */
23 #include <sys/types.h>
29 #include "backupfile.h"
35 #include "modechange.h"
36 #include "path-concat.h"
41 /* The official name of this program (e.g., no `g' prefix). */
42 #define PROGRAM_NAME "install"
44 #define AUTHORS "David MacKenzie"
47 # include <sys/wait.h>
50 struct passwd *getpwnam ();
51 struct group *getgrnam ();
53 #ifndef _POSIX_VERSION
59 # define endgrent() ((void) 0)
63 # define endpwent() ((void) 0)
66 /* Initial number of entries in each hash table entry's table of inodes. */
67 #define INITIAL_HASH_MODULE 100
69 /* Initial number of entries in the inode hash table. */
70 #define INITIAL_ENTRY_TAB_SIZE 70
72 /* Number of bytes of a file to copy at a time. */
73 #define READ_SIZE (32 * 1024)
79 static int change_timestamps (const char *from, const char *to);
80 static int change_attributes (const char *path);
81 static int copy_file (const char *from, const char *to,
82 const struct cp_options *x);
83 static int install_file_to_path (const char *from, const char *to,
84 const struct cp_options *x);
85 static int install_file_in_dir (const char *from, const char *to_dir,
86 const struct cp_options *x);
87 static int install_file_in_file (const char *from, const char *to,
88 const struct cp_options *x);
89 static void get_ids (void);
90 static void strip (const char *path);
91 void usage (int status);
93 /* The name this program was run with, for error messages. */
96 /* The user name that will own the files, or NULL to make the owner
97 the current user ID. */
98 static char *owner_name;
100 /* The user ID corresponding to `owner_name'. */
101 static uid_t owner_id;
103 /* The group name that will own the files, or NULL to make the group
104 the current group ID. */
105 static char *group_name;
107 /* The group ID corresponding to `group_name'. */
108 static gid_t group_id;
110 /* The permissions to which the files will be set. The umask has
112 static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
114 /* If nonzero, strip executable files after copying them. */
115 static int strip_files;
117 /* If nonzero, install a directory instead of a regular file. */
120 static struct option const long_options[] =
122 {"backup", optional_argument, NULL, 'b'},
123 {"directory", no_argument, NULL, 'd'},
124 {"group", required_argument, NULL, 'g'},
125 {"mode", required_argument, NULL, 'm'},
126 {"no-target-directory", no_argument, NULL, 'T'},
127 {"owner", required_argument, NULL, 'o'},
128 {"preserve-timestamps", no_argument, NULL, 'p'},
129 {"strip", no_argument, NULL, 's'},
130 {"suffix", required_argument, NULL, 'S'},
131 {"target-directory", required_argument, NULL, 't'},
132 {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */
133 {"verbose", no_argument, NULL, 'v'},
134 {GETOPT_HELP_OPTION_DECL},
135 {GETOPT_VERSION_OPTION_DECL},
140 cp_option_init (struct cp_options *x)
142 x->copy_as_regular = 1;
143 x->dereference = DEREF_ALWAYS;
144 x->unlink_dest_before_opening = 1;
145 x->unlink_dest_after_failed_open = 0;
147 x->interactive = I_UNSPECIFIED;
149 x->myeuid = geteuid ();
150 x->one_file_system = 0;
151 x->preserve_ownership = 0;
152 x->preserve_links = 0;
153 x->preserve_mode = 0;
154 x->preserve_timestamps = 0;
155 x->require_preserve = 0;
157 x->sparse_mode = SPARSE_AUTO;
158 x->symbolic_link = 0;
159 x->backup_type = none;
161 /* Create destination files initially writable so we can run strip on them.
162 Although GNU strip works fine on read-only files, some others
165 x->mode = S_IRUSR | S_IWUSR;
175 /* FILE is the last operand of this command. Return true if FILE is a
176 directory. But report an error there is a problem accessing FILE,
177 or if FILE does not exist but would have to refer to an existing
178 directory if it referred to anything at all. */
181 target_directory_operand (char const *file)
183 char const *b = base_name (file);
184 size_t blen = strlen (b);
185 bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
187 int err = (stat (file, &st) == 0 ? 0 : errno);
188 bool is_a_dir = !err && S_ISDIR (st.st_mode);
189 if (err && err != ENOENT)
190 error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
191 if (is_a_dir < looks_like_a_dir)
192 error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
197 main (int argc, char **argv)
201 const char *specified_mode = NULL;
202 int make_backups = 0;
203 char *backup_suffix_string;
204 char *version_control_string = NULL;
205 int mkdir_and_install = 0;
207 char const *target_directory = NULL;
208 bool no_target_directory = false;
212 initialize_main (&argc, &argv);
213 program_name = argv[0];
214 setlocale (LC_ALL, "");
215 bindtextdomain (PACKAGE, LOCALEDIR);
216 textdomain (PACKAGE);
218 atexit (close_stdout);
228 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
229 we'll actually use backup_suffix_string. */
230 backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
232 while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvV:S:", long_options,
240 case 'V': /* FIXME: this is deprecated. Remove it in 2001. */
242 _("warning: --version-control (-V) is obsolete; support for\
243 it\nwill be removed in some future release. Use --backup=%s instead."
250 version_control_string = optarg;
257 /* System V fork+wait does not work if SIGCHLD is ignored. */
258 signal (SIGCHLD, SIG_DFL);
265 mkdir_and_install = 1;
274 specified_mode = optarg;
280 x.preserve_timestamps = 1;
284 backup_suffix_string = optarg;
287 if (target_directory)
288 error (EXIT_FAILURE, 0,
289 _("multiple target directories specified"));
293 if (stat (optarg, &st) != 0)
294 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
295 if (! S_ISDIR (st.st_mode))
296 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
299 target_directory = optarg;
302 no_target_directory = true;
304 case_GETOPT_HELP_CHAR;
305 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
307 usage (EXIT_FAILURE);
311 /* Check for invalid combinations of arguments. */
312 if (dir_arg && strip_files)
313 error (EXIT_FAILURE, 0,
314 _("the strip option may not be used when installing a directory"));
315 if (dir_arg && target_directory)
316 error (EXIT_FAILURE, 0,
317 _("target directory not allowed when installing a directory"));
319 if (backup_suffix_string)
320 simple_backup_suffix = xstrdup (backup_suffix_string);
322 x.backup_type = (make_backups
323 ? xget_version (_("backup type"),
324 version_control_string)
327 n_files = argc - optind;
328 file = argv + optind;
330 if (n_files <= !target_directory)
333 error (0, 0, _("missing file operand"));
335 error (0, 0, _("missing destination file operand after %s"),
337 usage (EXIT_FAILURE);
340 if (no_target_directory)
342 if (target_directory)
343 error (EXIT_FAILURE, 0,
344 _("Cannot combine --target-directory (-t) "
345 "and --no-target-directory (-T)"));
348 error (0, 0, _("extra operand %s"), quote (file[2]));
349 usage (EXIT_FAILURE);
352 else if (!target_directory)
354 if (2 <= n_files && target_directory_operand (file[n_files - 1]))
355 target_directory = file[--n_files];
356 else if (2 < n_files)
357 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
358 quote (file[n_files - 1]));
363 struct mode_change *change = mode_compile (specified_mode, 0);
364 if (change == MODE_INVALID)
365 error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
366 else if (change == MODE_MEMORY_EXHAUSTED)
368 mode = mode_adjust (0, change);
376 for (i = 0; i < n_files; i++)
379 make_path (file[i], mode, mode, owner_id, group_id, 0,
380 (x.verbose ? _("creating directory %s") : NULL));
385 /* FIXME: it's a little gross that this initialization is
386 required by copy.c::copy. */
389 if (!target_directory)
391 if (mkdir_and_install)
392 errors = install_file_to_path (file[0], file[1], &x);
394 errors = install_file_in_file (file[0], file[1], &x);
400 for (i = 0; i < n_files; i++)
402 errors |= install_file_in_dir (file[i], target_directory, &x);
407 exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
410 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
411 Return 0 if successful, 1 if an error occurs */
414 install_file_to_path (const char *from, const char *to,
415 const struct cp_options *x)
420 dest_dir = dir_name (to);
422 /* check to make sure this is a path (not install a b ) */
423 if (!STREQ (dest_dir, ".")
424 && !isdir (dest_dir))
426 /* Someone will probably ask for a new option or three to specify
427 owner, group, and permissions for parent directories. Remember
428 that this option is intended mainly to help installers when the
429 distribution doesn't provide proper install rules. */
430 #define DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
431 fail = make_path (dest_dir, DIR_MODE, DIR_MODE, owner_id, group_id, 0,
432 (x->verbose ? _("creating directory %s") : NULL));
436 fail = install_file_in_file (from, to, x);
443 /* Copy file FROM onto file TO and give TO the appropriate
445 Return 0 if successful, 1 if an error occurs. */
448 install_file_in_file (const char *from, const char *to,
449 const struct cp_options *x)
451 if (copy_file (from, to, x))
455 if (change_attributes (to))
457 if (x->preserve_timestamps)
458 return change_timestamps (from, to);
462 /* Copy file FROM into directory TO_DIR, keeping its same name,
463 and give the copy the appropriate attributes.
464 Return 0 if successful, 1 if not. */
467 install_file_in_dir (const char *from, const char *to_dir,
468 const struct cp_options *x)
470 const char *from_base;
474 from_base = base_name (from);
475 to = path_concat (to_dir, from_base, NULL);
476 ret = install_file_in_file (from, to, x);
481 /* Copy file FROM onto file TO, creating TO if necessary.
482 Return 0 if the copy is successful, 1 if not. */
485 copy_file (const char *from, const char *to, const struct cp_options *x)
488 int nonexistent_dst = 0;
491 /* Allow installing from non-regular files like /dev/null.
492 Charles Karney reported that some Sun version of install allows that
493 and that sendmail's installation process relies on the behavior. */
496 error (0, 0, _("%s is a directory"), quote (from));
500 fail = copy (from, to, nonexistent_dst, x, ©_into_self, NULL);
505 /* Set the attributes of file or directory PATH.
506 Return 0 if successful, 1 if not. */
509 change_attributes (const char *path)
513 /* chown must precede chmod because on some systems,
514 chown clears the set[ug]id bits for non-superusers,
515 resulting in incorrect permissions.
516 On System V, users can give away files with chown and then not
517 be able to chmod them. So don't give files away.
519 We don't normally ignore errors from chown because the idea of
520 the install command is that the file is supposed to end up with
521 precisely the attributes that the user specified (or defaulted).
522 If the file doesn't end up with the group they asked for, they'll
523 want to know. But AFS returns EPERM when you try to change a
524 file's group; thus the kludge. */
526 if (chown (path, owner_id, group_id)
532 error (0, errno, _("cannot change ownership of %s"), quote (path));
536 if (!err && chmod (path, mode))
538 error (0, errno, _("cannot change permissions of %s"), quote (path));
545 /* Set the timestamps of file TO to match those of file FROM.
546 Return 0 if successful, 1 if not. */
549 change_timestamps (const char *from, const char *to)
552 struct timespec timespec[2];
554 if (stat (from, &stb))
556 error (0, errno, _("cannot obtain time stamps for %s"), quote (from));
560 timespec[0].tv_sec = stb.st_atime;
561 timespec[0].tv_nsec = TIMESPEC_NS (stb.st_atim);
562 timespec[1].tv_sec = stb.st_mtime;
563 timespec[1].tv_nsec = TIMESPEC_NS (stb.st_mtim);
564 if (utimens (to, timespec))
566 error (0, errno, _("cannot set time stamps for %s"), quote (to));
572 /* Strip the symbol table from the file PATH.
573 We could dig the magic number out of the file first to
574 determine whether to strip it, but the header files and
575 magic numbers vary so much from system to system that making
576 it portable would be very difficult. Not worth the effort. */
579 strip (const char *path)
587 error (EXIT_FAILURE, errno, _("fork system call failed"));
590 execlp ("strip", "strip", path, NULL);
591 error (EXIT_FAILURE, errno, _("cannot run strip"));
593 default: /* Parent. */
594 /* Parent process. */
595 while (pid != wait (&status)) /* Wait for kid to finish. */
598 error (EXIT_FAILURE, 0, _("strip failed"));
603 /* Initialize the user and group ownership of the files to install. */
613 pw = getpwnam (owner_name);
616 unsigned long int tmp;
617 if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
619 error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
623 owner_id = pw->pw_uid;
627 owner_id = (uid_t) -1;
631 gr = getgrnam (group_name);
634 unsigned long int tmp;
635 if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
637 error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
641 group_id = gr->gr_gid;
645 group_id = (gid_t) -1;
651 if (status != EXIT_SUCCESS)
652 fprintf (stderr, _("Try `%s --help' for more information.\n"),
657 Usage: %s [OPTION]... [-T] SOURCE DEST (1st form)\n\
658 or: %s [OPTION]... SOURCE... DIRECTORY (2nd form)\n\
659 or: %s [OPTION]... -t DIRECTORY SOURCE... (3rd form)\n\
660 or: %s [OPTION]... -d DIRECTORY... (4th form)\n\
662 program_name, program_name, program_name, program_name);
664 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
665 the existing DIRECTORY, while setting permission modes and owner/group.\n\
666 In the 4th form, create all components of the given DIRECTORY(ies).\n\
670 Mandatory arguments to long options are mandatory for short options too.\n\
673 --backup[=CONTROL] make a backup of each existing destination file\n\
674 -b like --backup but does not accept an argument\n\
676 -d, --directory treat all arguments as directory names; create all\n\
677 components of the specified directories\n\
680 -D create all leading components of DEST except the last,\n\
681 then copy SOURCE to DEST; useful in the 1st format\n\
682 -g, --group=GROUP set group ownership, instead of process' current group\n\
683 -m, --mode=MODE set permission mode (as in chmod), instead of rwxr-xr-x\n\
684 -o, --owner=OWNER set ownership (super-user only)\n\
687 -p, --preserve-timestamps apply access/modification times of SOURCE files\n\
688 to corresponding destination files\n\
689 -s, --strip strip symbol tables, only for 1st and 2nd formats\n\
690 -S, --suffix=SUFFIX override the usual backup suffix\n\
691 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
692 -T, --no-target-directory treat DEST as a normal file\n\
693 -v, --verbose print the name of each directory as it is created\n\
695 fputs (HELP_OPTION_DESCRIPTION, stdout);
696 fputs (VERSION_OPTION_DESCRIPTION, stdout);
699 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
700 The version control method may be selected via the --backup option or through\n\
701 the VERSION_CONTROL environment variable. Here are the values:\n\
705 none, off never make backups (even if --backup is given)\n\
706 numbered, t make numbered backups\n\
707 existing, nil numbered if numbered backups exist, simple otherwise\n\
708 simple, never always make simple backups\n\
710 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);