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