diff options
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/install.c | 122 |
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 |
36 | static bool use_default_selinux_context = 1; | ||
37 | |||
38 | static void setdefaultfilecon(const char *path) | 38 | static 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; |