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