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