blob: f6d84c15f6e3d0ad765d0a5799e6fc461931a319 [file] [log] [blame]
"Robert P. J. Day"63fc1a92006-07-02 19:47:05 +00001/* vi: set sw=4 ts=4: */
Glenn L McGratheebcc1d2003-09-24 03:22:57 +00002/*
Glenn L McGrathc6992fe2004-04-25 05:11:19 +00003 * Copyright (C) 2003 by Glenn McGrath <bug1@iinet.net.au>
Glenn L McGratheebcc1d2003-09-24 03:22:57 +00004 *
"Robert P. J. Day"801ab142006-07-12 07:56:04 +00005 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Glenn L McGratheebcc1d2003-09-24 03:22:57 +00006 *
7 * TODO: -d option, need a way of recursively making directories and changing
8 * owner/group, will probably modify bb_make_directory(...)
Glenn L McGratheebcc1d2003-09-24 03:22:57 +00009 */
10
11#include <sys/stat.h>
12#include <sys/types.h>
13#include <errno.h>
Glenn L McGratheebcc1d2003-09-24 03:22:57 +000014#include <stdlib.h>
Glenn L McGratha406a9c2003-09-24 05:00:29 +000015#include <string.h>
Glenn L McGratheebcc1d2003-09-24 03:22:57 +000016#include <unistd.h>
Rob Landleyb7128c62005-09-11 01:05:30 +000017#include <getopt.h> /* struct option */
Glenn L McGratheebcc1d2003-09-24 03:22:57 +000018
Glenn L McGrath11e69472003-11-27 22:40:08 +000019#include "busybox.h"
20#include "libcoreutils/coreutils.h"
21
22#define INSTALL_OPT_CMD 1
23#define INSTALL_OPT_DIRECTORY 2
24#define INSTALL_OPT_PRESERVE_TIME 4
25#define INSTALL_OPT_STRIP 8
26#define INSTALL_OPT_GROUP 16
27#define INSTALL_OPT_MODE 32
28#define INSTALL_OPT_OWNER 64
Glenn L McGratheebcc1d2003-09-24 03:22:57 +000029
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +000030#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
Glenn L McGrathca43b482004-01-23 21:57:16 +000031static const struct option install_long_options[] = {
32 { "directory", 0, NULL, 'd' },
33 { "preserve-timestamps", 0, NULL, 'p' },
34 { "strip", 0, NULL, 's' },
35 { "group", 0, NULL, 'g' },
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000036 { "mode", 0, NULL, 'm' },
Glenn L McGrathca43b482004-01-23 21:57:16 +000037 { "owner", 0, NULL, 'o' },
38 { 0, 0, 0, 0 }
39};
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +000040#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +000041
Rob Landleydfba7412006-03-06 20:47:33 +000042int install_main(int argc, char **argv)
Glenn L McGratheebcc1d2003-09-24 03:22:57 +000043{
Glenn L McGrath578eff52004-01-23 10:57:00 +000044 mode_t mode;
45 uid_t uid;
46 gid_t gid;
47 char *gid_str = "-1";
48 char *uid_str = "-1";
49 char *mode_str = "0755";
Glenn L McGrath11e69472003-11-27 22:40:08 +000050 int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
Rob Landleyae907f32005-10-09 11:16:01 +000051 int ret = EXIT_SUCCESS, flags, i, isdir;
Glenn L McGratheebcc1d2003-09-24 03:22:57 +000052
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +000053#if ENABLE_FEATURE_INSTALL_LONG_OPTIONS
Glenn L McGrathca43b482004-01-23 21:57:16 +000054 bb_applet_long_options = install_long_options;
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +000055#endif
"Vladimir N. Oleynik"f704b272005-10-14 09:56:52 +000056 bb_opt_complementally = "?:s--d:d--s";
Bernhard Reutner-Fischera1bccc02006-04-02 20:17:55 +000057 /* -c exists for backwards compatibility, its needed */
Glenn L McGrath11e69472003-11-27 22:40:08 +000058 flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */
59
60 /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
61 if (flags & INSTALL_OPT_PRESERVE_TIME) {
62 copy_flags |= FILEUTILS_PRESERVE_STATUS;
63 }
Glenn L McGrath578eff52004-01-23 10:57:00 +000064 bb_parse_mode(mode_str, &mode);
Bernhard Reutner-Fischerd5bd1372005-09-20 21:06:17 +000065 gid = get_ug_id(gid_str, bb_xgetgrnam);
66 uid = get_ug_id(uid_str, bb_xgetpwnam);
Glenn L McGrath578eff52004-01-23 10:57:00 +000067 umask(0);
Glenn L McGratheebcc1d2003-09-24 03:22:57 +000068
Glenn L McGrath578eff52004-01-23 10:57:00 +000069 /* Create directories
70 * dont use bb_make_directory() as it cant change uid or gid
71 * perhaps bb_make_directory() should be improved.
72 */
Glenn L McGrath11e69472003-11-27 22:40:08 +000073 if (flags & INSTALL_OPT_DIRECTORY) {
Glenn L McGratha406a9c2003-09-24 05:00:29 +000074 for (argv += optind; *argv; argv++) {
Glenn L McGrath578eff52004-01-23 10:57:00 +000075 char *old_argv_ptr = *argv + 1;
76 char *argv_ptr;
Glenn L McGratha406a9c2003-09-24 05:00:29 +000077 do {
Glenn L McGrath578eff52004-01-23 10:57:00 +000078 argv_ptr = strchr(old_argv_ptr, '/');
79 old_argv_ptr = argv_ptr;
Glenn L McGratha406a9c2003-09-24 05:00:29 +000080 if (argv_ptr) {
81 *argv_ptr = '\0';
Glenn L McGrath578eff52004-01-23 10:57:00 +000082 old_argv_ptr++;
Glenn L McGratha406a9c2003-09-24 05:00:29 +000083 }
Glenn L McGrath711bb922004-01-23 20:28:53 +000084 if (mkdir(*argv, mode) == -1) {
85 if (errno != EEXIST) {
86 bb_perror_msg("coulnt create %s", *argv);
87 ret = EXIT_FAILURE;
88 break;
89 }
Glenn L McGrath578eff52004-01-23 10:57:00 +000090 }
91 else if (lchown(*argv, uid, gid) == -1) {
92 bb_perror_msg("cannot change ownership of %s", *argv);
93 ret = EXIT_FAILURE;
94 break;
95 }
96 if (argv_ptr) {
97 *argv_ptr = '/';
98 }
99 } while (old_argv_ptr);
Glenn L McGratha406a9c2003-09-24 05:00:29 +0000100 }
101 return(ret);
102 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000103
Rob Landleyae907f32005-10-09 11:16:01 +0000104 {
105 struct stat statbuf;
106 isdir = lstat(argv[argc - 1], &statbuf)<0
107 ? 0 : S_ISDIR(statbuf.st_mode);
108 }
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000109 for (i = optind; i < argc - 1; i++) {
Eric Andersen5e678872006-01-30 19:48:23 +0000110 char *dest;
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000111
Rob Landleyae907f32005-10-09 11:16:01 +0000112 dest = argv[argc - 1];
113 if (isdir) dest = concat_path_file(argv[argc - 1], basename(argv[i]));
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000114 ret |= copy_file(argv[i], dest, copy_flags);
115
116 /* Set the file mode */
117 if (chmod(dest, mode) == -1) {
118 bb_perror_msg("cannot change permissions of %s", dest);
Glenn L McGrath578eff52004-01-23 10:57:00 +0000119 ret = EXIT_FAILURE;
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000120 }
121
122 /* Set the user and group id */
Glenn L McGrath11e69472003-11-27 22:40:08 +0000123 if (lchown(dest, uid, gid) == -1) {
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000124 bb_perror_msg("cannot change ownership of %s", dest);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000125 ret = EXIT_FAILURE;
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000126 }
Glenn L McGrath11e69472003-11-27 22:40:08 +0000127 if (flags & INSTALL_OPT_STRIP) {
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000128 if (execlp("strip", "strip", dest, NULL) == -1) {
129 bb_error_msg("strip failed");
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000130 ret = EXIT_FAILURE;
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000131 }
132 }
Rob Landleyae907f32005-10-09 11:16:01 +0000133 if(ENABLE_FEATURE_CLEAN_UP && isdir) free(dest);
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000134 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000135
Glenn L McGratheebcc1d2003-09-24 03:22:57 +0000136 return(ret);
137}