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