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