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