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