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