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