reindent a little
[platform/upstream/coreutils.git] / src / install.c
1 /* install - copy files and set attributes
2    Copyright (C) 89, 90, 91, 95, 96, 97, 1998 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 /* Copy files and set their permission modes and, if possible,
19    their owner and group.  Used similarly to `cp'; typically
20    used in Makefiles to copy programs into their destination
21    directories.  It can also be used to create the destination
22    directories and any leading directories, and to set the final
23    directory's modes.  It refuses to copy files onto themselves.
24
25    Options:
26    -g, --group=GROUP
27         Set the group ownership of the installed file or directory
28         to the group ID of GROUP (default is process's current
29         group).  GROUP may also be a numeric group ID.
30
31    -m, --mode=MODE
32         Set the permission mode for the installed file or directory
33         to MODE, which is an octal number (default is 0755).
34
35    -o, --owner=OWNER
36         If run as root, set the ownership of the installed file to
37         the user ID of OWNER (default is root).  OWNER may also be
38         a numeric user ID.
39
40    -c   No effect.  For compatibility with old Unix versions of install.
41
42    -s, --strip
43         Strip the symbol tables from installed files.
44
45    -p, --preserve-timestamps
46         Retain creation and modification timestamps when installing files.
47
48    -d, --directory
49         Create a directory and its leading directories, if they
50         do not already exist.  Set the owner, group and mode
51         as given on the command line.  Any leading directories
52         that are created are also given those attributes.
53         This is different from the SunOS 4.0 install, which gives
54         directories that it creates the default attributes.
55
56   -D
57         Like the -d option, but a file is installed, along with the directory.
58         Useful when installing into a new directory, and the install
59         process doesn't properly comprehend making directories.
60
61    David MacKenzie <djm@gnu.ai.mit.edu> */
62
63 #ifdef _AIX
64  #pragma alloca
65 #endif
66
67 #include <config.h>
68 #include <stdio.h>
69 #include <getopt.h>
70 #include <sys/types.h>
71 #include <pwd.h>
72 #include <grp.h>
73
74 #include "system.h"
75 #include "backupfile.h"
76 #include "modechange.h"
77 #include "makepath.h"
78 #include "closeout.h"
79 #include "error.h"
80 #include "xstrtol.h"
81
82 #if HAVE_SYS_WAIT_H
83 # include <sys/wait.h>
84 #endif
85
86 #if HAVE_VALUES_H
87 # include <values.h>
88 #endif
89
90 struct passwd *getpwnam ();
91 struct group *getgrnam ();
92
93 #ifndef _POSIX_VERSION
94 uid_t getuid ();
95 gid_t getgid ();
96 #endif
97
98 #ifndef HAVE_ENDGRENT
99 # define endgrent() ((void) 0)
100 #endif
101
102 #ifndef HAVE_ENDPWENT
103 # define endpwent() ((void) 0)
104 #endif
105
106 /* True if C is an ASCII octal digit. */
107 #define isodigit(c) ((c) >= '0' && c <= '7')
108
109 /* Number of bytes of a file to copy at a time. */
110 #define READ_SIZE (32 * 1024)
111
112 #ifndef UID_T_MAX
113 # define UID_T_MAX TYPE_MAXIMUM (uid_t)
114 #endif
115
116 #ifndef GID_T_MAX
117 # define GID_T_MAX TYPE_MAXIMUM (gid_t)
118 #endif
119
120 char *base_name ();
121 char *dirname ();
122 int safe_read ();
123 int full_write ();
124 int isdir ();
125 enum backup_type get_version ();
126
127 static int change_timestamps PARAMS ((const char *from, const char *to));
128 static int change_attributes PARAMS ((const char *path, int no_need_to_chown));
129 static int copy_file PARAMS ((const char *from, const char *to,
130                               int *to_created));
131 static int install_file_to_path PARAMS ((const char *from, const char *to));
132 static int install_file_in_dir PARAMS ((const char *from, const char *to_dir));
133 static int install_file_in_file PARAMS ((const char *from, const char *to));
134 static void get_ids PARAMS ((void));
135 static void strip PARAMS ((const char *path));
136 static void usage PARAMS ((int status));
137
138 /* The name this program was run with, for error messages. */
139 char *program_name;
140
141 /* The user name that will own the files, or NULL to make the owner
142    the current user ID. */
143 static char *owner_name;
144
145 /* The user ID corresponding to `owner_name'. */
146 static uid_t owner_id;
147
148 /* The group name that will own the files, or NULL to make the group
149    the current group ID. */
150 static char *group_name;
151
152 /* The group ID corresponding to `group_name'. */
153 static gid_t group_id;
154
155 /* The permissions to which the files will be set.  The umask has
156    no effect. */
157 static int mode;
158
159 /* If nonzero, strip executable files after copying them. */
160 static int strip_files;
161
162 /* If nonzero, preserve timestamps when installing files. */
163 static int preserve_timestamps;
164
165 /* If nonzero, install a directory instead of a regular file. */
166 static int dir_arg;
167
168 /* If nonzero, show what we are doing.  */
169 static int verbose;
170
171 /* If nonzero, display usage information and exit.  */
172 static int show_help;
173
174 /* If nonzero, print the version on standard output and exit.  */
175 static int show_version;
176
177 static struct option const long_options[] =
178 {
179   {"strip", no_argument, NULL, 's'},
180   {"directory", no_argument, NULL, 'd'},
181   {"group", required_argument, NULL, 'g'},
182   {"mode", required_argument, NULL, 'm'},
183   {"owner", required_argument, NULL, 'o'},
184   {"preserve-timestamps", no_argument, NULL, 'p'},
185   {"backup", no_argument, NULL, 'b'},
186   {"version-control", required_argument, NULL, 'V'},
187   {"verbose", no_argument, NULL, 'v'},
188   {"help", no_argument, &show_help, 1},
189   {"version", no_argument, &show_version, 1},
190   {NULL, 0, NULL, 0}
191 };
192
193 int
194 main (int argc, char **argv)
195 {
196   int optc;
197   int errors = 0;
198   char *symbolic_mode = NULL;
199   int make_backups = 0;
200   char *version;
201   int mkdir_and_install = 0;
202
203   program_name = argv[0];
204   setlocale (LC_ALL, "");
205   bindtextdomain (PACKAGE, LOCALEDIR);
206   textdomain (PACKAGE);
207
208   owner_name = NULL;
209   group_name = NULL;
210   mode = 0755;
211   strip_files = 0;
212   preserve_timestamps = 0;
213   dir_arg = 0;
214   verbose = 0;
215   umask (0);
216
217   version = getenv ("SIMPLE_BACKUP_SUFFIX");
218   if (version)
219     simple_backup_suffix = version;
220   version = getenv ("VERSION_CONTROL");
221
222   while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pvV:S:", long_options,
223                               NULL)) != -1)
224     {
225       switch (optc)
226         {
227         case 0:
228           break;
229         case 'b':
230           make_backups = 1;
231           break;
232         case 'c':
233           break;
234         case 's':
235           strip_files = 1;
236           break;
237         case 'd':
238           dir_arg = 1;
239           break;
240         case 'D':
241           mkdir_and_install = 1;
242           break;
243         case 'v':
244           verbose = 1;
245           break;
246         case 'g':
247           group_name = optarg;
248           break;
249         case 'm':
250           symbolic_mode = optarg;
251           break;
252         case 'o':
253           owner_name = optarg;
254           break;
255         case 'p':
256           preserve_timestamps = 1;
257           break;
258         case 'S':
259           simple_backup_suffix = optarg;
260           break;
261         case 'V':
262           version = optarg;
263           break;
264         default:
265           usage (1);
266         }
267     }
268
269   if (show_version)
270     {
271       printf ("install (%s) %s\n", GNU_PACKAGE, VERSION);
272       close_stdout ();
273       exit (0);
274     }
275
276   if (show_help)
277     usage (0);
278
279   /* Check for invalid combinations of arguments. */
280   if (dir_arg && strip_files)
281     error (1, 0,
282            _("the strip option may not be used when installing a directory"));
283
284   if (make_backups)
285     backup_type = get_version (version);
286
287   if (optind == argc || (optind == argc - 1 && !dir_arg))
288     {
289       error (0, 0, _("too few arguments"));
290       usage (1);
291     }
292
293   if (symbolic_mode)
294     {
295       struct mode_change *change = mode_compile (symbolic_mode, 0);
296       if (change == MODE_INVALID)
297         error (1, 0, _("invalid mode `%s'"), symbolic_mode);
298       else if (change == MODE_MEMORY_EXHAUSTED)
299         error (1, 0, _("virtual memory exhausted"));
300       mode = mode_adjust (0, change);
301     }
302
303   get_ids ();
304
305   if (dir_arg)
306     {
307       for (; optind < argc; ++optind)
308         {
309           errors |=
310             make_path (argv[optind], mode, mode, owner_id, group_id, 0,
311                        (verbose ? "creating directory `%s'" : NULL));
312         }
313     }
314   else
315     {
316       if (optind == argc - 2)
317         {
318           if (mkdir_and_install)
319             errors = install_file_to_path (argv[argc - 2], argv[argc - 1]);
320           else if (!isdir (argv[argc - 1]))
321             errors = install_file_in_file (argv[argc - 2], argv[argc - 1]);
322           else
323             errors = install_file_in_dir (argv[argc - 2], argv[argc - 1]);
324         }
325       else
326         {
327           if (!isdir (argv[argc - 1]))
328             usage (1);
329           for (; optind < argc - 1; ++optind)
330             {
331               errors |= install_file_in_dir (argv[optind], argv[argc - 1]);
332             }
333         }
334     }
335
336   if (verbose)
337     close_stdout ();
338   exit (errors);
339 }
340
341 /* Copy file FROM onto file TO, creating any missing parent directories of TO.
342    Return 0 if successful, 1 if an error occurs */
343
344 static int
345 install_file_to_path (const char *from, const char *to)
346 {
347   char *dest_dir;
348   int fail;
349
350   dest_dir = dirname (to);
351
352   /* check to make sure this is a path (not install a b ) */
353   if (!STREQ (dest_dir, ".")
354       && !isdir (dest_dir))
355     {
356       /* FIXME: Note that it's a little kludgey (even dangerous) that we
357          derive the permissions for parent directories from the permissions
358          specfied for the file, but since this option is intended mainly to
359          help installers when the distribution doesn't provide proper install
360          rules, it's not so bad.  Maybe use something like this instead:
361          int parent_dir_mode = (mode | (S_IRUGO | S_IXUGO)) & (~SPECIAL_BITS);
362          */
363       fail = make_path (dest_dir, mode, mode, owner_id, group_id, 0,
364                         (verbose ? _("creating directory `%s'") : NULL));
365     }
366   else
367     {
368       fail = install_file_in_file (from, to);
369     }
370
371   free (dest_dir);
372
373   return fail;
374 }
375
376 /* Copy file FROM onto file TO and give TO the appropriate
377    attributes.
378    Return 0 if successful, 1 if an error occurs. */
379
380 static int
381 install_file_in_file (const char *from, const char *to)
382 {
383   int to_created;
384   int no_need_to_chown;
385
386   if (copy_file (from, to, &to_created))
387     return 1;
388   if (strip_files)
389     strip (to);
390   no_need_to_chown = (to_created
391                       && owner_name == NULL
392                       && group_name == NULL);
393   if (change_attributes (to, no_need_to_chown))
394     return 1;
395   if (preserve_timestamps)
396     return change_timestamps (from, to);
397   return 0;
398 }
399
400 /* Copy file FROM into directory TO_DIR, keeping its same name,
401    and give the copy the appropriate attributes.
402    Return 0 if successful, 1 if not. */
403
404 static int
405 install_file_in_dir (const char *from, const char *to_dir)
406 {
407   char *from_base;
408   char *to;
409   int ret;
410
411   from_base = base_name (from);
412   to = xmalloc ((unsigned) (strlen (to_dir) + strlen (from_base) + 2));
413   stpcpy (stpcpy (stpcpy (to, to_dir), "/"), from_base);
414   ret = install_file_in_file (from, to);
415   free (to);
416   return ret;
417 }
418
419 /* A chunk of a file being copied. */
420 static char buffer[READ_SIZE];
421
422 /* Copy file FROM onto file TO, creating TO if necessary.
423    Return 0 if the copy is successful, 1 if not.  If the copy is
424    successful, set *TO_CREATED to nonzero if TO was created (if it did
425    not exist or did, but was unlinked) and to zero otherwise.  If the
426    copy fails, don't modify *TO_CREATED.  */
427
428 static int
429 copy_file (const char *from, const char *to, int *to_created)
430 {
431   int fromfd, tofd;
432   int bytes;
433   int ret = 0;
434   struct stat from_stats, to_stats;
435   int target_created = 1;
436
437   if (stat (from, &from_stats))
438     {
439       error (0, errno, "%s", from);
440       return 1;
441     }
442
443   /* Allow installing from non-regular files like /dev/null.
444      Charles Karney reported that some Sun version of install allows that
445      and that sendmail's installation process relies on the behavior.  */
446   if (S_ISDIR (from_stats.st_mode))
447     {
448       error (0, 0, _("`%s' is a directory"), from);
449       return 1;
450     }
451   if (stat (to, &to_stats) == 0)
452     {
453       if (!S_ISREG (to_stats.st_mode))
454         {
455           error (0, 0, _("`%s' is not a regular file"), to);
456           return 1;
457         }
458       if (from_stats.st_dev == to_stats.st_dev
459           && from_stats.st_ino == to_stats.st_ino)
460         {
461           error (0, 0, _("`%s' and `%s' are the same file"), from, to);
462           return 1;
463         }
464
465       /* The destination file exists.  Try to back it up if required.  */
466       if (backup_type != none)
467         {
468           char *tmp_backup = find_backup_file_name (to);
469           char *dst_backup;
470
471           if (tmp_backup == NULL)
472             error (1, 0, "virtual memory exhausted");
473           dst_backup = (char *) alloca (strlen (tmp_backup) + 1);
474           strcpy (dst_backup, tmp_backup);
475           free (tmp_backup);
476           if (rename (to, dst_backup))
477             {
478               if (errno != ENOENT)
479                 {
480                   error (0, errno, "cannot backup `%s'", to);
481                   return 1;
482                 }
483             }
484         }
485
486       /* If unlink fails, try to proceed anyway.  */
487       if (unlink (to))
488         target_created = 0;
489     }
490
491   /* Now it's the time to give some feedback if requested.  */
492   if (verbose)
493     printf ("copying `%s' to `%s'\n", from, to);
494
495   fromfd = open (from, O_RDONLY, 0);
496   if (fromfd == -1)
497     {
498       error (0, errno, "%s", from);
499       return 1;
500     }
501
502   /* Make sure to open the file in a mode that allows writing. */
503   tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC, 0600);
504   if (tofd == -1)
505     {
506       error (0, errno, "%s", to);
507       close (fromfd);
508       return 1;
509     }
510
511   while ((bytes = safe_read (fromfd, buffer, READ_SIZE)) > 0)
512     if (full_write (tofd, buffer, bytes) < 0)
513       {
514         error (0, errno, "%s", to);
515         goto copy_error;
516       }
517
518   if (bytes == -1)
519     {
520       error (0, errno, "%s", from);
521       goto copy_error;
522     }
523
524   if (close (fromfd) < 0)
525     {
526       error (0, errno, "%s", from);
527       ret = 1;
528     }
529   if (close (tofd) < 0)
530     {
531       error (0, errno, "%s", to);
532       ret = 1;
533     }
534   if (ret == 0)
535     *to_created = target_created;
536   return ret;
537
538  copy_error:
539   close (fromfd);
540   close (tofd);
541   return 1;
542 }
543
544 /* Set the attributes of file or directory PATH.
545    If NO_NEED_TO_CHOWN is nonzero, don't call chown.
546    Return 0 if successful, 1 if not. */
547
548 static int
549 change_attributes (const char *path, int no_need_to_chown)
550 {
551   int err = 0;
552
553   /* chown must precede chmod because on some systems,
554      chown clears the set[ug]id bits for non-superusers,
555      resulting in incorrect permissions.
556      On System V, users can give away files with chown and then not
557      be able to chmod them.  So don't give files away.
558
559      We don't pass -1 to chown to mean "don't change the value"
560      because SVR3 and earlier non-BSD systems don't support that.
561
562      We don't normally ignore errors from chown because the idea of
563      the install command is that the file is supposed to end up with
564      precisely the attributes that the user specified (or defaulted).
565      If the file doesn't end up with the group they asked for, they'll
566      want to know.  But AFS returns EPERM when you try to change a
567      file's group; thus the kludge.  */
568
569   if (!no_need_to_chown && chown (path, owner_id, group_id)
570 #ifdef AFS
571       && errno != EPERM
572 #endif
573       )
574     err = errno;
575   if (chmod (path, mode))
576     err = errno;
577   if (err)
578     {
579       error (0, err, "%s", path);
580       return 1;
581     }
582   return 0;
583 }
584
585 /* Set the timestamps of file TO to match those of file FROM.
586    Return 0 if successful, 1 if not. */
587
588 static int
589 change_timestamps (const char *from, const char *to)
590 {
591   struct stat stb;
592   struct utimbuf utb;
593
594   if (stat (from, &stb))
595     {
596       error (0, errno, "%s", from);
597       return 1;
598     }
599   utb.actime = stb.st_atime;
600   utb.modtime = stb.st_mtime;
601   if (utime (to, &utb))
602     {
603       error (0, errno, "%s", to);
604       return 1;
605     }
606   return 0;
607 }
608
609 /* Strip the symbol table from the file PATH.
610    We could dig the magic number out of the file first to
611    determine whether to strip it, but the header files and
612    magic numbers vary so much from system to system that making
613    it portable would be very difficult.  Not worth the effort. */
614
615 static void
616 strip (const char *path)
617 {
618   int pid, status;
619
620   pid = fork ();
621   switch (pid)
622     {
623     case -1:
624       error (1, errno, _("fork system call failed"));
625       break;
626     case 0:                     /* Child. */
627       execlp ("strip", "strip", path, NULL);
628       error (1, errno, _("cannot run strip"));
629       break;
630     default:                    /* Parent. */
631       /* Parent process. */
632       while (pid != wait (&status))     /* Wait for kid to finish. */
633         /* Do nothing. */ ;
634       break;
635     }
636 }
637
638 /* Initialize the user and group ownership of the files to install. */
639
640 static void
641 get_ids (void)
642 {
643   struct passwd *pw;
644   struct group *gr;
645
646   if (owner_name)
647     {
648       pw = getpwnam (owner_name);
649       if (pw == NULL)
650         {
651           long int tmp_long;
652           if (xstrtol (owner_name, NULL, 0, &tmp_long, NULL) != LONGINT_OK
653               || tmp_long < 0 || tmp_long > UID_T_MAX)
654             error (1, 0, _("invalid user `%s'"), owner_name);
655           owner_id = (uid_t) tmp_long;
656         }
657       else
658         owner_id = pw->pw_uid;
659       endpwent ();
660     }
661   else
662     owner_id = (uid_t) -1;
663
664   if (group_name)
665     {
666       gr = getgrnam (group_name);
667       if (gr == NULL)
668         {
669           long int tmp_long;
670           if (xstrtol (group_name, NULL, 0, &tmp_long, NULL) != LONGINT_OK
671               || tmp_long < 0 || tmp_long > GID_T_MAX)
672             error (1, 0, _("invalid group `%s'"), group_name);
673           group_id = (gid_t) tmp_long;
674         }
675       else
676         group_id = gr->gr_gid;
677       endgrent ();
678     }
679   else
680     group_id = (gid_t) -1;
681 }
682
683 static void
684 usage (int status)
685 {
686   if (status != 0)
687     fprintf (stderr, _("Try `%s --help' for more information.\n"),
688              program_name);
689   else
690     {
691       printf (_("\
692 Usage: %s [OPTION]... SOURCE DEST           (1st format)\n\
693   or:  %s [OPTION]... SOURCE... DIRECTORY   (2nd format)\n\
694   or:  %s -d [OPTION]... DIRECTORY...       (3rd format)\n\
695 "),
696               program_name, program_name, program_name);
697       printf (_("\
698 In first two formats, copy SOURCE to DEST or multiple SOURCE(s) to\n\
699 DIRECTORY, while setting permission modes and owner/group.  In third\n\
700 format, make all components of the given DIRECTORY(ies).\n\
701 \n\
702   -b, --backup        make backup before removal\n\
703   -c                  (ignored)\n\
704   -d, --directory     create [leading] directories, mandatory for 3rd format\n\
705   -g, --group=GROUP   set group ownership, instead of process' current group\n\
706   -m, --mode=MODE     set permission mode (as in chmod), instead of rwxr-xr-x\n\
707   -o, --owner=OWNER   set ownership (super-user only)\n\
708   -p, --preserve-timestamps   apply access/modification times of SOURCE files\n\
709                         to corresponding destination files\n\
710   -s, --strip         strip symbol tables, only for 1st and 2nd formats\n\
711   -S, --suffix=SUFFIX override the usual backup suffix\n\
712       --verbose       print the name of each directory as it is created\n\
713   -V, --version-control=WORD   override the usual version control\n\
714       --help          display this help and exit\n\
715       --version       output version information and exit\n\
716 \n\
717 "));
718       printf (_("\
719 The backup suffix is ~, unless set with SIMPLE_BACKUP_SUFFIX.  The\n\
720 version control may be set with VERSION_CONTROL, values are:\n\
721 \n\
722   t, numbered     make numbered backups\n\
723   nil, existing   numbered if numbered backups exist, simple otherwise\n\
724   never, simple   always make simple backups\n\
725 "));
726       puts (_("\nReport bugs to <fileutils-bugs@gnu.org>."));
727       close_stdout ();
728     }
729   exit (status);
730 }