summaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/install.c122
1 files changed, 69 insertions, 53 deletions
diff --git a/coreutils/install.c b/coreutils/install.c
index cf62a0022..516208474 100644
--- a/coreutils/install.c
+++ b/coreutils/install.c
@@ -1,6 +1,6 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Copyright (C) 2003 by Glenn McGrath <bug1@iinet.net.au> 3 * Copyright (C) 2003 by Glenn McGrath
4 * SELinux support: by Yuichi Nakamura <ynakam@hitachisoft.jp> 4 * SELinux support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
5 * 5 *
6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
@@ -23,6 +23,8 @@ static const char install_longopts[] ALIGN1 =
23 "group\0" No_argument "g" 23 "group\0" No_argument "g"
24 "mode\0" No_argument "m" 24 "mode\0" No_argument "m"
25 "owner\0" No_argument "o" 25 "owner\0" No_argument "o"
26/* autofs build insists of using -b --suffix=.orig */
27/* TODO? (short option for --suffix is -S) */
26#if ENABLE_SELINUX 28#if ENABLE_SELINUX
27 "context\0" Required_argument "Z" 29 "context\0" Required_argument "Z"
28 "preserve_context\0" No_argument "\xff" 30 "preserve_context\0" No_argument "\xff"
@@ -33,8 +35,6 @@ static const char install_longopts[] ALIGN1 =
33 35
34 36
35#if ENABLE_SELINUX 37#if ENABLE_SELINUX
36static bool use_default_selinux_context = 1;
37
38static void setdefaultfilecon(const char *path) 38static void setdefaultfilecon(const char *path)
39{ 39{
40 struct stat s; 40 struct stat s;
@@ -73,25 +73,31 @@ int install_main(int argc, char **argv)
73 mode_t mode; 73 mode_t mode;
74 uid_t uid; 74 uid_t uid;
75 gid_t gid; 75 gid_t gid;
76 char *arg, *last;
76 const char *gid_str; 77 const char *gid_str;
77 const char *uid_str; 78 const char *uid_str;
78 const char *mode_str; 79 const char *mode_str;
79 int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE; 80 int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
80 int ret = EXIT_SUCCESS, flags, i, isdir; 81 int flags;
82 int ret = EXIT_SUCCESS;
83 int isdir;
81#if ENABLE_SELINUX 84#if ENABLE_SELINUX
82 security_context_t scontext; 85 security_context_t scontext;
86 bool use_default_selinux_context = 1;
83#endif 87#endif
84 enum { 88 enum {
85 OPT_CMD = 0x1, 89 OPT_c = 1 << 0,
86 OPT_DIRECTORY = 0x2, 90 OPT_v = 1 << 1,
87 OPT_PRESERVE_TIME = 0x4, 91 OPT_b = 1 << 2,
88 OPT_STRIP = 0x8, 92 OPT_DIRECTORY = 1 << 3,
89 OPT_GROUP = 0x10, 93 OPT_PRESERVE_TIME = 1 << 4,
90 OPT_MODE = 0x20, 94 OPT_STRIP = 1 << 5,
91 OPT_OWNER = 0x40, 95 OPT_GROUP = 1 << 6,
96 OPT_MODE = 1 << 7,
97 OPT_OWNER = 1 << 8,
92#if ENABLE_SELINUX 98#if ENABLE_SELINUX
93 OPT_SET_SECURITY_CONTEXT = 0x80, 99 OPT_SET_SECURITY_CONTEXT = 1 << 9,
94 OPT_PRESERVE_SECURITY_CONTEXT = 0x100, 100 OPT_PRESERVE_SECURITY_CONTEXT = 1 << 10,
95#endif 101#endif
96 }; 102 };
97 103
@@ -100,21 +106,24 @@ int install_main(int argc, char **argv)
100#endif 106#endif
101 opt_complementary = "s--d:d--s" USE_SELINUX(":Z--\xff:\xff--Z"); 107 opt_complementary = "s--d:d--s" USE_SELINUX(":Z--\xff:\xff--Z");
102 /* -c exists for backwards compatibility, it's needed */ 108 /* -c exists for backwards compatibility, it's needed */
103 109 /* -v is ignored ("print name of each created directory") */
104 flags = getopt32(argv, "cdpsg:m:o:" USE_SELINUX("Z:"), 110 /* -b is ignored ("make a backup of each existing destination file") */
111 flags = getopt32(argv, "cvb" "dpsg:m:o:" USE_SELINUX("Z:"),
105 &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext)); 112 &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext));
113 argc -= optind;
114 argv += optind;
106 115
107#if ENABLE_SELINUX 116#if ENABLE_SELINUX
108 if (flags & OPT_PRESERVE_SECURITY_CONTEXT) { 117 if (flags & (OPT_PRESERVE_SECURITY_CONTEXT|OPT_SET_SECURITY_CONTEXT)) {
109 use_default_selinux_context = 0;
110 copy_flags |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
111 selinux_or_die();
112 }
113 if (flags & OPT_SET_SECURITY_CONTEXT) {
114 selinux_or_die(); 118 selinux_or_die();
115 setfscreatecon_or_die(scontext);
116 use_default_selinux_context = 0; 119 use_default_selinux_context = 0;
117 copy_flags |= FILEUTILS_SET_SECURITY_CONTEXT; 120 if (flags & OPT_PRESERVE_SECURITY_CONTEXT) {
121 copy_flags |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
122 }
123 if (flags & OPT_SET_SECURITY_CONTEXT) {
124 setfscreatecon_or_die(scontext);
125 copy_flags |= FILEUTILS_SET_SECURITY_CONTEXT;
126 }
118 } 127 }
119#endif 128#endif
120 129
@@ -123,58 +132,63 @@ int install_main(int argc, char **argv)
123 copy_flags |= FILEUTILS_PRESERVE_STATUS; 132 copy_flags |= FILEUTILS_PRESERVE_STATUS;
124 } 133 }
125 mode = 0666; 134 mode = 0666;
126 if (flags & OPT_MODE) bb_parse_mode(mode_str, &mode); 135 if (flags & OPT_MODE)
136 bb_parse_mode(mode_str, &mode);
127 uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid(); 137 uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
128 gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid(); 138 gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
129 if (flags & (OPT_OWNER|OPT_GROUP)) umask(0); 139 if (flags & (OPT_OWNER|OPT_GROUP))
140 umask(0);
130 141
131 /* Create directories 142 /* Create directories
132 * don't use bb_make_directory() as it can't change uid or gid 143 * don't use bb_make_directory() as it can't change uid or gid
133 * perhaps bb_make_directory() should be improved. 144 * perhaps bb_make_directory() should be improved.
134 */ 145 */
135 if (flags & OPT_DIRECTORY) { 146 if (flags & OPT_DIRECTORY) {
136 for (argv += optind; *argv; argv++) { 147 while ((arg = *argv++) != NULL) {
137 char *old_argv_ptr = *argv + 1; 148 char *slash = arg;
138 char *argv_ptr; 149 while (1) {
139 do { 150 slash = strchr(slash + 1, '/');
140 argv_ptr = strchr(old_argv_ptr, '/'); 151 if (slash)
141 old_argv_ptr = argv_ptr; 152 *slash = '\0';
142 if (argv_ptr) { 153 if (mkdir(arg, mode | 0111) == -1) {
143 *argv_ptr = '\0';
144 old_argv_ptr++;
145 }
146 if (mkdir(*argv, mode | 0111) == -1) {
147 if (errno != EEXIST) { 154 if (errno != EEXIST) {
148 bb_perror_msg("cannot create %s", *argv); 155 bb_perror_msg("cannot create %s", arg);
149 ret = EXIT_FAILURE; 156 ret = EXIT_FAILURE;
150 break; 157 break;
151 } 158 }
152 } 159 } /* dir was created, chown? */
153 if ((flags & (OPT_OWNER|OPT_GROUP)) 160 else if ((flags & (OPT_OWNER|OPT_GROUP))
154 && lchown(*argv, uid, gid) == -1 161 && lchown(arg, uid, gid) == -1
155 ) { 162 ) {
156 bb_perror_msg("cannot change ownership of %s", *argv); 163 bb_perror_msg("cannot change ownership of %s", arg);
157 ret = EXIT_FAILURE; 164 ret = EXIT_FAILURE;
158 break; 165 break;
159 } 166 }
160 if (argv_ptr) { 167 if (!slash)
161 *argv_ptr = '/'; 168 break;
162 } 169 *slash = '/';
163 } while (old_argv_ptr); 170 }
164 } 171 }
165 return ret; 172 return ret;
166 } 173 }
167 174
168 /* coreutils install resolves link in this case, don't use lstat */ 175 if (argc < 2)
169 isdir = stat(argv[argc - 1], &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode); 176 bb_show_usage();
170 177
171 for (i = optind; i < argc - 1; i++) { 178 last = argv[argc - 1];
172 char *dest; 179 argv[argc - 1] = NULL;
180 /* coreutils install resolves link in this case, don't use lstat */
181 isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode);
173 182
174 dest = argv[argc - 1]; 183 while ((arg = *argv++) != NULL) {
184 char *dest = last;
175 if (isdir) 185 if (isdir)
176 dest = concat_path_file(argv[argc - 1], basename(argv[i])); 186 dest = concat_path_file(last, basename(arg));
177 ret |= copy_file(argv[i], dest, copy_flags); 187 if (copy_file(arg, dest, copy_flags)) {
188 /* copy is not made */
189 ret = EXIT_FAILURE;
190 goto next;
191 }
178 192
179 /* Set the file mode */ 193 /* Set the file mode */
180 if ((flags & OPT_MODE) && chmod(dest, mode) == -1) { 194 if ((flags & OPT_MODE) && chmod(dest, mode) == -1) {
@@ -202,7 +216,9 @@ int install_main(int argc, char **argv)
202 ret = EXIT_FAILURE; 216 ret = EXIT_FAILURE;
203 } 217 }
204 } 218 }
205 if (ENABLE_FEATURE_CLEAN_UP && isdir) free(dest); 219 next:
220 if (ENABLE_FEATURE_CLEAN_UP && isdir)
221 free(dest);
206 } 222 }
207 223
208 return ret; 224 return ret;