(main): Fix -d regression introduced with
[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 = 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 = 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 0:
236           break;
237
238         case 'V':  /* FIXME: this is deprecated.  Remove it in 2001.  */
239           error (0, 0,
240                  _("warning: --version-control (-V) is obsolete;  support for\
241  it\nwill be removed in some future release.  Use --backup=%s instead."
242                    ), optarg);
243           /* Fall through.  */
244
245         case 'b':
246           make_backups = true;
247           if (optarg)
248             version_control_string = optarg;
249           break;
250         case 'c':
251           break;
252         case 's':
253           strip_files = true;
254 #ifdef SIGCHLD
255           /* System V fork+wait does not work if SIGCHLD is ignored.  */
256           signal (SIGCHLD, SIG_DFL);
257 #endif
258           break;
259         case 'd':
260           dir_arg = true;
261           break;
262         case 'D':
263           mkdir_and_install = true;
264           break;
265         case 'v':
266           x.verbose = true;
267           break;
268         case 'g':
269           group_name = optarg;
270           break;
271         case 'm':
272           specified_mode = optarg;
273           break;
274         case 'o':
275           owner_name = optarg;
276           break;
277         case 'p':
278           x.preserve_timestamps = true;
279           break;
280         case 'S':
281           make_backups = true;
282           backup_suffix_string = optarg;
283           break;
284         case 't':
285           if (target_directory)
286             error (EXIT_FAILURE, 0,
287                    _("multiple target directories specified"));
288           else
289             {
290               struct stat st;
291               if (stat (optarg, &st) != 0)
292                 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
293               if (! S_ISDIR (st.st_mode))
294                 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
295                        quote (optarg));
296             }
297           target_directory = optarg;
298           break;
299         case 'T':
300           no_target_directory = true;
301           break;
302         case_GETOPT_HELP_CHAR;
303         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
304         default:
305           usage (EXIT_FAILURE);
306         }
307     }
308
309   /* Check for invalid combinations of arguments. */
310   if (dir_arg & strip_files)
311     error (EXIT_FAILURE, 0,
312            _("the strip option may not be used when installing a directory"));
313   if (dir_arg && target_directory)
314     error (EXIT_FAILURE, 0,
315            _("target directory not allowed when installing a directory"));
316
317   if (backup_suffix_string)
318     simple_backup_suffix = xstrdup (backup_suffix_string);
319
320   x.backup_type = (make_backups
321                    ? xget_version (_("backup type"),
322                                    version_control_string)
323                    : none);
324
325   n_files = argc - optind;
326   file = argv + optind;
327
328   if (n_files <= !(dir_arg || target_directory))
329     {
330       if (n_files <= 0)
331         error (0, 0, _("missing file operand"));
332       else
333         error (0, 0, _("missing destination file operand after %s"),
334                quote (file[0]));
335       usage (EXIT_FAILURE);
336     }
337
338   if (no_target_directory)
339     {
340       if (target_directory)
341         error (EXIT_FAILURE, 0,
342                _("Cannot combine --target-directory (-t) "
343                  "and --no-target-directory (-T)"));
344       if (2 < n_files)
345         {
346           error (0, 0, _("extra operand %s"), quote (file[2]));
347           usage (EXIT_FAILURE);
348         }
349     }
350   else if (!target_directory)
351     {
352       if (2 <= n_files && target_directory_operand (file[n_files - 1]))
353         target_directory = file[--n_files];
354       else if (2 < n_files)
355         error (EXIT_FAILURE, 0, _("target %s is not a directory"),
356                quote (file[n_files - 1]));
357     }
358
359   if (specified_mode)
360     {
361       struct mode_change *change = mode_compile (specified_mode, 0);
362       if (change == MODE_INVALID)
363         error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
364       else if (change == MODE_MEMORY_EXHAUSTED)
365         xalloc_die ();
366       mode = mode_adjust (0, change);
367     }
368
369   get_ids ();
370
371   if (dir_arg)
372     {
373       int i;
374       for (i = 0; i < n_files; i++)
375         {
376           ok &=
377             make_path (file[i], mode, mode, owner_id, group_id, false,
378                        (x.verbose ? _("creating directory %s") : NULL));
379         }
380     }
381   else
382     {
383       /* FIXME: it's a little gross that this initialization is
384          required by copy.c::copy. */
385       hash_init ();
386
387       if (!target_directory)
388         {
389           if (mkdir_and_install)
390             ok = install_file_to_path (file[0], file[1], &x);
391           else
392             ok = install_file_in_file (file[0], file[1], &x);
393         }
394       else
395         {
396           int i;
397           dest_info_init (&x);
398           for (i = 0; i < n_files; i++)
399             {
400               ok &= install_file_in_dir (file[i], target_directory, &x);
401             }
402         }
403     }
404
405   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
406 }
407
408 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
409    Return true if successful.  */
410
411 static bool
412 install_file_to_path (const char *from, const char *to,
413                       const struct cp_options *x)
414 {
415   char *dest_dir = dir_name (to);
416   bool ok = true;
417
418   /* Make sure that the parent of the destination is a directory.  */
419   if (! STREQ (dest_dir, "."))
420     {
421       /* Someone will probably ask for a new option or three to specify
422          owner, group, and permissions for parent directories.  Remember
423          that this option is intended mainly to help installers when the
424          distribution doesn't provide proper install rules.  */
425 #define DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
426       ok = make_path (dest_dir, DIR_MODE, DIR_MODE, owner_id, group_id, true,
427                       (x->verbose ? _("creating directory %s") : NULL));
428     }
429
430   free (dest_dir);
431
432   if (ok)
433     ok = install_file_in_file (from, to, x);
434
435   return ok;
436 }
437
438 /* Copy file FROM onto file TO and give TO the appropriate
439    attributes.
440    Return true if successful.  */
441
442 static bool
443 install_file_in_file (const char *from, const char *to,
444                       const struct cp_options *x)
445 {
446   if (! copy_file (from, to, x))
447     return false;
448   if (strip_files)
449     strip (to);
450   if (! change_attributes (to))
451     return false;
452   if (x->preserve_timestamps)
453     return change_timestamps (from, to);
454   return true;
455 }
456
457 /* Copy file FROM into directory TO_DIR, keeping its same name,
458    and give the copy the appropriate attributes.
459    Return true if successful.  */
460
461 static bool
462 install_file_in_dir (const char *from, const char *to_dir,
463                      const struct cp_options *x)
464 {
465   const char *from_base = base_name (from);
466   char *to = path_concat (to_dir, from_base, NULL);
467   bool ret = install_file_in_file (from, to, x);
468   free (to);
469   return ret;
470 }
471
472 /* Copy file FROM onto file TO, creating TO if necessary.
473    Return true if successful.  */
474
475 static bool
476 copy_file (const char *from, const char *to, const struct cp_options *x)
477 {
478   bool copy_into_self;
479
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
484      is a directory.  */
485
486   return copy (from, to, false, x, &copy_into_self, NULL);
487 }
488
489 /* Set the attributes of file or directory PATH.
490    Return true if successful.  */
491
492 static bool
493 change_attributes (const char *path)
494 {
495   bool ok = true;
496
497   /* chown must precede chmod because on some systems,
498      chown clears the set[ug]id bits for non-superusers,
499      resulting in incorrect permissions.
500      On System V, users can give away files with chown and then not
501      be able to chmod them.  So don't give files away.
502
503      We don't normally ignore errors from chown because the idea of
504      the install command is that the file is supposed to end up with
505      precisely the attributes that the user specified (or defaulted).
506      If the file doesn't end up with the group they asked for, they'll
507      want to know.  But AFS returns EPERM when you try to change a
508      file's group; thus the kludge.  */
509
510   if (chown (path, owner_id, group_id)
511 #ifdef AFS
512       && errno != EPERM
513 #endif
514       )
515     {
516       error (0, errno, _("cannot change ownership of %s"), quote (path));
517       ok = false;
518     }
519
520   if (ok && chmod (path, mode))
521     {
522       error (0, errno, _("cannot change permissions of %s"), quote (path));
523       ok = false;
524     }
525
526   return ok;
527 }
528
529 /* Set the timestamps of file TO to match those of file FROM.
530    Return true if successful.  */
531
532 static bool
533 change_timestamps (const char *from, const char *to)
534 {
535   struct stat stb;
536   struct timespec timespec[2];
537
538   if (stat (from, &stb))
539     {
540       error (0, errno, _("cannot obtain time stamps for %s"), quote (from));
541       return false;
542     }
543
544   timespec[0].tv_sec = stb.st_atime;
545   timespec[0].tv_nsec = TIMESPEC_NS (stb.st_atim);
546   timespec[1].tv_sec = stb.st_mtime;
547   timespec[1].tv_nsec = TIMESPEC_NS (stb.st_mtim);
548   if (utimens (to, timespec))
549     {
550       error (0, errno, _("cannot set time stamps for %s"), quote (to));
551       return false;
552     }
553   return true;
554 }
555
556 /* Strip the symbol table from the file PATH.
557    We could dig the magic number out of the file first to
558    determine whether to strip it, but the header files and
559    magic numbers vary so much from system to system that making
560    it portable would be very difficult.  Not worth the effort. */
561
562 static void
563 strip (const char *path)
564 {
565   int status;
566   pid_t pid = fork ();
567
568   switch (pid)
569     {
570     case -1:
571       error (EXIT_FAILURE, errno, _("fork system call failed"));
572       break;
573     case 0:                     /* Child. */
574       execlp ("strip", "strip", path, NULL);
575       error (EXIT_FAILURE, errno, _("cannot run strip"));
576       break;
577     default:                    /* Parent. */
578       /* Parent process. */
579       while (pid != wait (&status))     /* Wait for kid to finish. */
580         /* Do nothing. */ ;
581       if (status)
582         error (EXIT_FAILURE, 0, _("strip failed"));
583       break;
584     }
585 }
586
587 /* Initialize the user and group ownership of the files to install. */
588
589 static void
590 get_ids (void)
591 {
592   struct passwd *pw;
593   struct group *gr;
594
595   if (owner_name)
596     {
597       pw = getpwnam (owner_name);
598       if (pw == NULL)
599         {
600           unsigned long int tmp;
601           if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
602               || UID_T_MAX < tmp)
603             error (EXIT_FAILURE, 0, _("invalid user %s"), quote (owner_name));
604           owner_id = tmp;
605         }
606       else
607         owner_id = pw->pw_uid;
608       endpwent ();
609     }
610   else
611     owner_id = (uid_t) -1;
612
613   if (group_name)
614     {
615       gr = getgrnam (group_name);
616       if (gr == NULL)
617         {
618           unsigned long int tmp;
619           if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
620               || GID_T_MAX < tmp)
621             error (EXIT_FAILURE, 0, _("invalid group %s"), quote (group_name));
622           group_id = tmp;
623         }
624       else
625         group_id = gr->gr_gid;
626       endgrent ();
627     }
628   else
629     group_id = (gid_t) -1;
630 }
631
632 void
633 usage (int status)
634 {
635   if (status != EXIT_SUCCESS)
636     fprintf (stderr, _("Try `%s --help' for more information.\n"),
637              program_name);
638   else
639     {
640       printf (_("\
641 Usage: %s [OPTION]... [-T] SOURCE DEST        (1st form)\n\
642   or:  %s [OPTION]... SOURCE... DIRECTORY     (2nd form)\n\
643   or:  %s [OPTION]... -t DIRECTORY SOURCE...  (3rd form)\n\
644   or:  %s [OPTION]... -d DIRECTORY...         (4th form)\n\
645 "),
646               program_name, program_name, program_name, program_name);
647       fputs (_("\
648 In the first three forms, copy SOURCE to DEST or multiple SOURCE(s) to\n\
649 the existing DIRECTORY, while setting permission modes and owner/group.\n\
650 In the 4th form, create all components of the given DIRECTORY(ies).\n\
651 \n\
652 "), stdout);
653       fputs (_("\
654 Mandatory arguments to long options are mandatory for short options too.\n\
655 "), stdout);
656       fputs (_("\
657       --backup[=CONTROL] make a backup of each existing destination file\n\
658   -b                  like --backup but does not accept an argument\n\
659   -c                  (ignored)\n\
660   -d, --directory     treat all arguments as directory names; create all\n\
661                         components of the specified directories\n\
662 "), stdout);
663       fputs (_("\
664   -D                  create all leading components of DEST except the last,\n\
665                         then copy SOURCE to DEST;  useful in the 1st format\n\
666   -g, --group=GROUP   set group ownership, instead of process' current group\n\
667   -m, --mode=MODE     set permission mode (as in chmod), instead of rwxr-xr-x\n\
668   -o, --owner=OWNER   set ownership (super-user only)\n\
669 "), stdout);
670       fputs (_("\
671   -p, --preserve-timestamps   apply access/modification times of SOURCE files\n\
672                         to corresponding destination files\n\
673   -s, --strip         strip symbol tables, only for 1st and 2nd formats\n\
674   -S, --suffix=SUFFIX override the usual backup suffix\n\
675   -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY\n\
676   -T, --no-target-directory  treat DEST as a normal file\n\
677   -v, --verbose       print the name of each directory as it is created\n\
678 "), stdout);
679       fputs (HELP_OPTION_DESCRIPTION, stdout);
680       fputs (VERSION_OPTION_DESCRIPTION, stdout);
681       fputs (_("\
682 \n\
683 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
684 The version control method may be selected via the --backup option or through\n\
685 the VERSION_CONTROL environment variable.  Here are the values:\n\
686 \n\
687 "), stdout);
688       fputs (_("\
689   none, off       never make backups (even if --backup is given)\n\
690   numbered, t     make numbered backups\n\
691   existing, nil   numbered if numbered backups exist, simple otherwise\n\
692   simple, never   always make simple backups\n\
693 "), stdout);
694       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
695     }
696   exit (status);
697 }