Finally remove support for --version-control=S (-V).
[platform/upstream/coreutils.git] / src / install.c
1 /* install - copy files and set attributes
2    Copyright (C) 89, 90, 91, 1995-2005 Free Software Foundation, Inc.
3
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)
7    any later version.
8
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.
13
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.  */
17
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu> */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <getopt.h>
23 #include <sys/types.h>
24 #include <signal.h>
25 #include <pwd.h>
26 #include <grp.h>
27
28 #include "system.h"
29 #include "backupfile.h"
30 #include "error.h"
31 #include "cp-hash.h"
32 #include "copy.h"
33 #include "dirname.h"
34 #include "filenamecat.h"
35 #include "mkdir-p.h"
36 #include "modechange.h"
37 #include "quote.h"
38 #include "utimens.h"
39 #include "xstrtol.h"
40
41 /* The official name of this program (e.g., no `g' prefix).  */
42 #define PROGRAM_NAME "install"
43
44 #define AUTHORS "David MacKenzie"
45
46 #if HAVE_SYS_WAIT_H
47 # include <sys/wait.h>
48 #endif
49
50 #if ! HAVE_ENDGRENT
51 # define endgrent() ((void) 0)
52 #endif
53
54 #if ! HAVE_ENDPWENT
55 # define endpwent() ((void) 0)
56 #endif
57
58 /* Initial number of entries in each hash table entry's table of inodes.  */
59 #define INITIAL_HASH_MODULE 100
60
61 /* Initial number of entries in the inode hash table.  */
62 #define INITIAL_ENTRY_TAB_SIZE 70
63
64 /* Number of bytes of a file to copy at a time. */
65 #define READ_SIZE (32 * 1024)
66
67 static bool change_timestamps (const char *from, const char *to);
68 static bool change_attributes (char const *name);
69 static bool copy_file (const char *from, const char *to,
70                        const struct cp_options *x);
71 static bool install_file_in_file_parents (char const *from, char const *to,
72                                           struct cp_options const *x);
73 static bool install_file_in_dir (const char *from, const char *to_dir,
74                                  const struct cp_options *x);
75 static bool install_file_in_file (const char *from, const char *to,
76                                   const struct cp_options *x);
77 static void get_ids (void);
78 static void strip (char const *name);
79 void usage (int status);
80
81 /* The name this program was run with, for error messages. */
82 char *program_name;
83
84 /* The user name that will own the files, or NULL to make the owner
85    the current user ID. */
86 static char *owner_name;
87
88 /* The user ID corresponding to `owner_name'. */
89 static uid_t owner_id;
90
91 /* The group name that will own the files, or NULL to make the group
92    the current group ID. */
93 static char *group_name;
94
95 /* The group ID corresponding to `group_name'. */
96 static gid_t group_id;
97
98 /* The permissions to which the files will be set.  The umask has
99    no effect. */
100 static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
101
102 /* If true, strip executable files after copying them. */
103 static bool strip_files;
104
105 /* If true, install a directory instead of a regular file. */
106 static bool dir_arg;
107
108 static struct option const long_options[] =
109 {
110   {"backup", optional_argument, NULL, 'b'},
111   {"directory", no_argument, NULL, 'd'},
112   {"group", required_argument, NULL, 'g'},
113   {"mode", required_argument, NULL, 'm'},
114   {"no-target-directory", no_argument, NULL, 'T'},
115   {"owner", required_argument, NULL, 'o'},
116   {"preserve-timestamps", no_argument, NULL, 'p'},
117   {"strip", no_argument, NULL, 's'},
118   {"suffix", required_argument, NULL, 'S'},
119   {"target-directory", required_argument, NULL, 't'},
120   {"verbose", no_argument, NULL, 'v'},
121   {GETOPT_HELP_OPTION_DECL},
122   {GETOPT_VERSION_OPTION_DECL},
123   {NULL, 0, NULL, 0}
124 };
125
126 static void
127 cp_option_init (struct cp_options *x)
128 {
129   x->copy_as_regular = true;
130   x->dereference = DEREF_ALWAYS;
131   x->unlink_dest_before_opening = true;
132   x->unlink_dest_after_failed_open = false;
133   x->hard_link = false;
134   x->interactive = I_UNSPECIFIED;
135   x->move_mode = false;
136   x->chown_privileges = chown_privileges ();
137   x->one_file_system = false;
138   x->preserve_ownership = false;
139   x->preserve_links = false;
140   x->preserve_mode = false;
141   x->preserve_timestamps = false;
142   x->require_preserve = false;
143   x->recursive = false;
144   x->sparse_mode = SPARSE_AUTO;
145   x->symbolic_link = false;
146   x->backup_type = no_backups;
147
148   /* Create destination files initially writable so we can run strip on them.
149      Although GNU strip works fine on read-only files, some others
150      would fail.  */
151   x->set_mode = true;
152   x->mode = S_IRUSR | S_IWUSR;
153   x->stdin_tty = false;
154
155   x->umask_kill = 0;
156   x->update = false;
157   x->verbose = false;
158   x->dest_info = NULL;
159   x->src_info = NULL;
160 }
161
162 /* FILE is the last operand of this command.  Return true if FILE is a
163    directory.  But report an error there is a problem accessing FILE,
164    or if FILE does not exist but would have to refer to an existing
165    directory if it referred to anything at all.  */
166
167 static bool
168 target_directory_operand (char const *file)
169 {
170   char const *b = base_name (file);
171   size_t blen = strlen (b);
172   bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
173   struct stat st;
174   int err = (stat (file, &st) == 0 ? 0 : errno);
175   bool is_a_dir = !err && S_ISDIR (st.st_mode);
176   if (err && err != ENOENT)
177     error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
178   if (is_a_dir < looks_like_a_dir)
179     error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
180   return is_a_dir;
181 }
182
183 int
184 main (int argc, char **argv)
185 {
186   int optc;
187   bool ok = true;
188   const char *specified_mode = NULL;
189   bool make_backups = false;
190   char *backup_suffix_string;
191   char *version_control_string = NULL;
192   bool mkdir_and_install = false;
193   struct cp_options x;
194   char const *target_directory = NULL;
195   bool no_target_directory = false;
196   int n_files;
197   char **file;
198
199   initialize_main (&argc, &argv);
200   program_name = argv[0];
201   setlocale (LC_ALL, "");
202   bindtextdomain (PACKAGE, LOCALEDIR);
203   textdomain (PACKAGE);
204
205   atexit (close_stdout);
206
207   cp_option_init (&x);
208
209   owner_name = NULL;
210   group_name = NULL;
211   strip_files = false;
212   dir_arg = false;
213   umask (0);
214
215   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
216      we'll actually use backup_suffix_string.  */
217   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
218
219   while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:", long_options,
220                               NULL)) != -1)
221     {
222       switch (optc)
223         {
224         case 'b':
225           make_backups = true;
226           if (optarg)
227             version_control_string = optarg;
228           break;
229         case 'c':
230           break;
231         case 's':
232           strip_files = true;
233 #ifdef SIGCHLD
234           /* System V fork+wait does not work if SIGCHLD is ignored.  */
235           signal (SIGCHLD, SIG_DFL);
236 #endif
237           break;
238         case 'd':
239           dir_arg = true;
240           break;
241         case 'D':
242           mkdir_and_install = true;
243           break;
244         case 'v':
245           x.verbose = true;
246           break;
247         case 'g':
248           group_name = optarg;
249           break;
250         case 'm':
251           specified_mode = optarg;
252           break;
253         case 'o':
254           owner_name = optarg;
255           break;
256         case 'p':
257           x.preserve_timestamps = true;
258           break;
259         case 'S':
260           make_backups = true;
261           backup_suffix_string = optarg;
262           break;
263         case 't':
264           if (target_directory)
265             error (EXIT_FAILURE, 0,
266                    _("multiple target directories specified"));
267           else
268             {
269               struct stat st;
270               if (stat (optarg, &st) != 0)
271                 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
272               if (! S_ISDIR (st.st_mode))
273                 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
274                        quote (optarg));
275             }
276           target_directory = optarg;
277           break;
278         case 'T':
279           no_target_directory = true;
280           break;
281         case_GETOPT_HELP_CHAR;
282         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
283         default:
284           usage (EXIT_FAILURE);
285         }
286     }
287
288   /* Check for invalid combinations of arguments. */
289   if (dir_arg & strip_files)
290     error (EXIT_FAILURE, 0,
291            _("the strip option may not be used when installing a directory"));
292   if (dir_arg && target_directory)
293     error (EXIT_FAILURE, 0,
294            _("target directory not allowed when installing a directory"));
295
296   if (backup_suffix_string)
297     simple_backup_suffix = xstrdup (backup_suffix_string);
298
299   x.backup_type = (make_backups
300                    ? xget_version (_("backup type"),
301                                    version_control_string)
302                    : no_backups);
303
304   n_files = argc - optind;
305   file = argv + optind;
306
307   if (n_files <= ! (dir_arg || target_directory))
308     {
309       if (n_files <= 0)
310         error (0, 0, _("missing file operand"));
311       else
312         error (0, 0, _("missing destination file operand after %s"),
313                quote (file[0]));
314       usage (EXIT_FAILURE);
315     }
316
317   if (no_target_directory)
318     {
319       if (target_directory)
320         error (EXIT_FAILURE, 0,
321                _("Cannot combine --target-directory (-t) "
322                  "and --no-target-directory (-T)"));
323       if (2 < n_files)
324         {
325           error (0, 0, _("extra operand %s"), quote (file[2]));
326           usage (EXIT_FAILURE);
327         }
328     }
329   else if (! (dir_arg || target_directory))
330     {
331       if (2 <= n_files && target_directory_operand (file[n_files - 1]))
332         target_directory = file[--n_files];
333       else if (2 < n_files)
334         error (EXIT_FAILURE, 0, _("target %s is not a directory"),
335                quote (file[n_files - 1]));
336     }
337
338   if (specified_mode)
339     {
340       struct mode_change *change = mode_compile (specified_mode);
341       if (!change)
342         error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
343       mode = mode_adjust (0, change, 0);
344       free (change);
345     }
346
347   get_ids ();
348
349   if (dir_arg)
350     {
351       int i;
352       int cwd_errno = 0;
353       for (i = 0; i < n_files; i++)
354         {
355           if (cwd_errno != 0 && IS_RELATIVE_FILE_NAME (file[i]))
356             {
357               error (0, cwd_errno, _("cannot return to working directory"));
358               ok = false;
359             }
360           else
361             ok &=
362               make_dir_parents (file[i], mode, mode, owner_id, group_id, false,
363                                 (x.verbose ? _("creating directory %s") : NULL),
364                                 &cwd_errno);
365         }
366     }
367   else
368     {
369       /* FIXME: it's a little gross that this initialization is
370          required by copy.c::copy. */
371       hash_init ();
372
373       if (!target_directory)
374         {
375           if (mkdir_and_install)
376             ok = install_file_in_file_parents (file[0], file[1], &x);
377           else
378             ok = install_file_in_file (file[0], file[1], &x);
379         }
380       else
381         {
382           int i;
383           dest_info_init (&x);
384           for (i = 0; i < n_files; i++)
385             {
386               ok &= install_file_in_dir (file[i], target_directory, &x);
387             }
388         }
389     }
390
391   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
392 }
393
394 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
395    Return true if successful.  */
396
397 static bool
398 install_file_in_file_parents (char const *from, char const *to,
399                               struct cp_options const *x)
400 {
401   char *dest_dir = dir_name (to);
402   bool ok = true;
403
404   /* Make sure that the parent of the destination is a directory.  */
405   if (! STREQ (dest_dir, "."))
406     {
407       /* Someone will probably ask for a new option or three to specify
408          owner, group, and permissions for parent directories.  Remember
409          that this option is intended mainly to help installers when the
410          distribution doesn't provide proper install rules.  */
411       mode_t dir_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
412       int cwd_errno = 0;
413       ok = make_dir_parents (dest_dir, dir_mode, dir_mode,
414                              owner_id, group_id, true,
415                              (x->verbose ? _("creating directory %s") : NULL),
416                              &cwd_errno);
417       if (ok && cwd_errno != 0
418           && (IS_RELATIVE_FILE_NAME (from) || IS_RELATIVE_FILE_NAME (to)))
419         {
420           error (0, cwd_errno, _("cannot return to current directory"));
421           ok = false;
422         }
423     }
424
425   free (dest_dir);
426
427   if (ok)
428     ok = install_file_in_file (from, to, x);
429
430   return ok;
431 }
432
433 /* Copy file FROM onto file TO and give TO the appropriate
434    attributes.
435    Return true if successful.  */
436
437 static bool
438 install_file_in_file (const char *from, const char *to,
439                       const struct cp_options *x)
440 {
441   if (! copy_file (from, to, x))
442     return false;
443   if (strip_files)
444     strip (to);
445   if (! change_attributes (to))
446     return false;
447   if (x->preserve_timestamps)
448     return change_timestamps (from, to);
449   return true;
450 }
451
452 /* Copy file FROM into directory TO_DIR, keeping its same name,
453    and give the copy the appropriate attributes.
454    Return true if successful.  */
455
456 static bool
457 install_file_in_dir (const char *from, const char *to_dir,
458                      const struct cp_options *x)
459 {
460   const char *from_base = base_name (from);
461   char *to = file_name_concat (to_dir, from_base, NULL);
462   bool ret = install_file_in_file (from, to, x);
463   free (to);
464   return ret;
465 }
466
467 /* Copy file FROM onto file TO, creating TO if necessary.
468    Return true if successful.  */
469
470 static bool
471 copy_file (const char *from, const char *to, const struct cp_options *x)
472 {
473   bool copy_into_self;
474
475   /* Allow installing from non-regular files like /dev/null.
476      Charles Karney reported that some Sun version of install allows that
477      and that sendmail's installation process relies on the behavior.
478      However, since !x->recursive, the call to "copy" will fail if FROM
479      is a directory.  */
480
481   return copy (from, to, false, x, &copy_into_self, NULL);
482 }
483
484 /* Set the attributes of file or directory NAME.
485    Return true if successful.  */
486
487 static bool
488 change_attributes (char const *name)
489 {
490   bool ok = true;
491
492   /* chown must precede chmod because on some systems,
493      chown clears the set[ug]id bits for non-superusers,
494      resulting in incorrect permissions.
495      On System V, users can give away files with chown and then not
496      be able to chmod them.  So don't give files away.
497
498      We don't normally ignore errors from chown because the idea of
499      the install command is that the file is supposed to end up with
500      precisely the attributes that the user specified (or defaulted).
501      If the file doesn't end up with the group they asked for, they'll
502      want to know.  But AFS returns EPERM when you try to change a
503      file's group; thus the kludge.  */
504
505   if (chown (name, owner_id, group_id) != 0
506 #ifdef AFS
507       && errno != EPERM
508 #endif
509       )
510     {
511       error (0, errno, _("cannot change ownership of %s"), quote (name));
512       ok = false;
513     }
514
515   if (ok && chmod (name, mode) != 0)
516     {
517       error (0, errno, _("cannot change permissions of %s"), quote (name));
518       ok = false;
519     }
520
521   return ok;
522 }
523
524 /* Set the timestamps of file TO to match those of file FROM.
525    Return true if successful.  */
526
527 static bool
528 change_timestamps (const char *from, const char *to)
529 {
530   struct stat stb;
531   struct timespec timespec[2];
532
533   if (stat (from, &stb))
534     {
535       error (0, errno, _("cannot obtain time stamps for %s"), quote (from));
536       return false;
537     }
538
539   timespec[0].tv_sec = stb.st_atime;
540   timespec[0].tv_nsec = TIMESPEC_NS (stb.st_atim);
541   timespec[1].tv_sec = stb.st_mtime;
542   timespec[1].tv_nsec = TIMESPEC_NS (stb.st_mtim);
543   if (utimens (to, timespec))
544     {
545       error (0, errno, _("cannot set time stamps for %s"), quote (to));
546       return false;
547     }
548   return true;
549 }
550
551 /* Strip the symbol table from the file NAME.
552    We could dig the magic number out of the file first to
553    determine whether to strip it, but the header files and
554    magic numbers vary so much from system to system that making
555    it portable would be very difficult.  Not worth the effort. */
556
557 static void
558 strip (char const *name)
559 {
560   int status;
561   pid_t pid = fork ();
562
563   switch (pid)
564     {
565     case -1:
566       error (EXIT_FAILURE, errno, _("fork system call failed"));
567       break;
568     case 0:                     /* Child. */
569       execlp ("strip", "strip", name, NULL);
570       error (EXIT_FAILURE, errno, _("cannot run strip"));
571       break;
572     default:                    /* Parent. */
573       /* Parent process. */
574       while (pid != wait (&status))     /* Wait for kid to finish. */
575         /* Do nothing. */ ;
576       if (status)
577         error (EXIT_FAILURE, 0, _("strip failed"));
578       break;
579     }
580 }
581
582 /* Initialize the user and group ownership of the files to install. */
583
584 static void
585 get_ids (void)
586 {
587   struct passwd *pw;
588   struct group *gr;
589
590   if (owner_name)
591     {
592       pw = getpwnam (owner_name);
593       if (pw == NULL)
594         {
595           unsigned long int tmp;
596           if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
597               || UID_T_MAX < tmp)
598             error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
599           owner_id = tmp;
600         }
601       else
602         owner_id = pw->pw_uid;
603       endpwent ();
604     }
605   else
606     owner_id = (uid_t) -1;
607
608   if (group_name)
609     {
610       gr = getgrnam (group_name);
611       if (gr == NULL)
612         {
613           unsigned long int tmp;
614           if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
615               || GID_T_MAX < tmp)
616             error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
617           group_id = tmp;
618         }
619       else
620         group_id = gr->gr_gid;
621       endgrent ();
622     }
623   else
624     group_id = (gid_t) -1;
625 }
626
627 void
628 usage (int status)
629 {
630   if (status != EXIT_SUCCESS)
631     fprintf (stderr, _("Try `%s --help' for more information.\n"),
632              program_name);
633   else
634     {
635       printf (_("\
636 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
637   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
638   or:  %s [OPTION]... -t DIRECTORY SOURCE...\n\
639   or:  %s [OPTION]... -d DIRECTORY...\n\
640 "),
641               program_name, program_name, program_name, program_name);
642       fputs (_("\
643 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
644 the existing DIRECTORY, while setting permission modes and owner/group.\n\
645 In the 4th form, create all components of the given DIRECTORY(ies).\n\
646 \n\
647 "), stdout);
648       fputs (_("\
649 Mandatory arguments to long options are mandatory for short options too.\n\
650 "), stdout);
651       fputs (_("\
652       --backup[=CONTROL] make a backup of each existing destination file\n\
653   -b                  like --backup but does not accept an argument\n\
654   -c                  (ignored)\n\
655   -d, --directory     treat all arguments as directory names; create all\n\
656                         components of the specified directories\n\
657 "), stdout);
658       fputs (_("\
659   -D                  create all leading components of DEST except the last,\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\
664 "), stdout);
665       fputs (_("\
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   -S, --suffix=SUFFIX override the usual backup suffix\n\
670   -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY\n\
671   -T, --no-target-directory  treat DEST as a normal file\n\
672   -v, --verbose       print the name of each directory as it is created\n\
673 "), stdout);
674       fputs (HELP_OPTION_DESCRIPTION, stdout);
675       fputs (VERSION_OPTION_DESCRIPTION, stdout);
676       fputs (_("\
677 \n\
678 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
679 The version control method may be selected via the --backup option or through\n\
680 the VERSION_CONTROL environment variable.  Here are the values:\n\
681 \n\
682 "), stdout);
683       fputs (_("\
684   none, off       never make backups (even if --backup is given)\n\
685   numbered, t     make numbered backups\n\
686   existing, nil   numbered if numbered backups exist, simple otherwise\n\
687   simple, never   always make simple backups\n\
688 "), stdout);
689       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
690     }
691   exit (status);
692 }