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