Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/coreutils/install.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/coreutils/install.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 * 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> 3 5 * 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 of the License, or 7 * (at your option) 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 Library 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 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * 6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 18 7 * 19 8 * TODO: -d option, need a way of recursively making directories and changing … … 21 10 */ 22 11 23 #include <sys/stat.h> 24 #include <sys/types.h> 25 #include <errno.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 12 #include <libgen.h> 29 13 #include <getopt.h> /* struct option */ 30 14 31 #include " busybox.h"15 #include "libbb.h" 32 16 #include "libcoreutils/coreutils.h" 33 17 34 #define INSTALL_OPT_CMD 135 #define INSTALL_OPT_DIRECTORY 236 #define INSTALL_OPT_PRESERVE_TIME 437 #define INSTALL_OPT_STRIP 838 #define INSTALL_OPT_GROUP 1639 #define INSTALL_OPT_MODE 3240 #define INSTALL_OPT_OWNER 6441 42 18 #if ENABLE_FEATURE_INSTALL_LONG_OPTIONS 43 static const struct option install_long_options[] = { 44 { "directory", 0, NULL, 'd' }, 45 { "preserve-timestamps", 0, NULL, 'p' }, 46 { "strip", 0, NULL, 's' }, 47 { "group", 0, NULL, 'g' }, 48 { "mode", 0, NULL, 'm' }, 49 { "owner", 0, NULL, 'o' }, 50 { 0, 0, 0, 0 } 51 }; 52 #endif 53 19 static const char install_longopts[] ALIGN1 = 20 "directory\0" No_argument "d" 21 "preserve-timestamps\0" No_argument "p" 22 "strip\0" No_argument "s" 23 "group\0" No_argument "g" 24 "mode\0" No_argument "m" 25 "owner\0" No_argument "o" 26 /* autofs build insists of using -b --suffix=.orig */ 27 /* TODO? (short option for --suffix is -S) */ 28 #if ENABLE_SELINUX 29 "context\0" Required_argument "Z" 30 "preserve_context\0" No_argument "\xff" 31 "preserve-context\0" No_argument "\xff" 32 #endif 33 ; 34 #endif 35 36 37 #if ENABLE_SELINUX 38 static void setdefaultfilecon(const char *path) 39 { 40 struct stat s; 41 security_context_t scontext = NULL; 42 43 if (!is_selinux_enabled()) { 44 return; 45 } 46 if (lstat(path, &s) != 0) { 47 return; 48 } 49 50 if (matchpathcon(path, s.st_mode, &scontext) < 0) { 51 goto out; 52 } 53 if (strcmp(scontext, "<<none>>") == 0) { 54 goto out; 55 } 56 57 if (lsetfilecon(path, scontext) < 0) { 58 if (errno != ENOTSUP) { 59 bb_perror_msg("warning: failed to change context of %s to %s", path, scontext); 60 } 61 } 62 63 out: 64 freecon(scontext); 65 } 66 67 #endif 68 69 int install_main(int argc, char **argv); 54 70 int install_main(int argc, char **argv) 55 71 { 72 struct stat statbuf; 56 73 mode_t mode; 57 74 uid_t uid; 58 75 gid_t gid; 59 char *gid_str = "-1"; 60 char *uid_str = "-1"; 61 char *mode_str = "0755"; 76 char *arg, *last; 77 const char *gid_str; 78 const char *uid_str; 79 const char *mode_str; 62 80 int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE; 63 int ret = EXIT_SUCCESS, flags, i, isdir; 81 int flags; 82 int ret = EXIT_SUCCESS; 83 int isdir; 84 #if ENABLE_SELINUX 85 security_context_t scontext; 86 bool use_default_selinux_context = 1; 87 #endif 88 enum { 89 OPT_c = 1 << 0, 90 OPT_v = 1 << 1, 91 OPT_b = 1 << 2, 92 OPT_DIRECTORY = 1 << 3, 93 OPT_PRESERVE_TIME = 1 << 4, 94 OPT_STRIP = 1 << 5, 95 OPT_GROUP = 1 << 6, 96 OPT_MODE = 1 << 7, 97 OPT_OWNER = 1 << 8, 98 #if ENABLE_SELINUX 99 OPT_SET_SECURITY_CONTEXT = 1 << 9, 100 OPT_PRESERVE_SECURITY_CONTEXT = 1 << 10, 101 #endif 102 }; 64 103 65 104 #if ENABLE_FEATURE_INSTALL_LONG_OPTIONS 66 bb_applet_long_options = install_long_options; 67 #endif 68 bb_opt_complementally = "?:s--d:d--s"; 69 /* -c exists for backwards compatibility, its needed */ 70 flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */ 105 applet_long_options = install_longopts; 106 #endif 107 opt_complementary = "s--d:d--s" USE_SELINUX(":Z--\xff:\xff--Z"); 108 /* -c exists for backwards compatibility, it's needed */ 109 /* -v is ignored ("print name of each created directory") */ 110 /* -b is ignored ("make a backup of each existing destination file") */ 111 flags = getopt32(argv, "cvb" "dpsg:m:o:" USE_SELINUX("Z:"), 112 &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext)); 113 argc -= optind; 114 argv += optind; 115 116 #if ENABLE_SELINUX 117 if (flags & (OPT_PRESERVE_SECURITY_CONTEXT|OPT_SET_SECURITY_CONTEXT)) { 118 selinux_or_die(); 119 use_default_selinux_context = 0; 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 } 127 } 128 #endif 71 129 72 130 /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */ 73 if (flags & INSTALL_OPT_PRESERVE_TIME) {131 if (flags & OPT_PRESERVE_TIME) { 74 132 copy_flags |= FILEUTILS_PRESERVE_STATUS; 75 133 } 76 bb_parse_mode(mode_str, &mode); 77 gid = get_ug_id(gid_str, bb_xgetgrnam); 78 uid = get_ug_id(uid_str, bb_xgetpwnam); 79 umask(0); 134 mode = 0666; 135 if (flags & OPT_MODE) 136 bb_parse_mode(mode_str, &mode); 137 uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid(); 138 gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid(); 139 if (flags & (OPT_OWNER|OPT_GROUP)) 140 umask(0); 80 141 81 142 /* Create directories 82 * don t use bb_make_directory() as it cant change uid or gid143 * don't use bb_make_directory() as it can't change uid or gid 83 144 * perhaps bb_make_directory() should be improved. 84 145 */ 85 if (flags & INSTALL_OPT_DIRECTORY) { 86 for (argv += optind; *argv; argv++) { 87 char *old_argv_ptr = *argv + 1; 88 char *argv_ptr; 89 do { 90 argv_ptr = strchr(old_argv_ptr, '/'); 91 old_argv_ptr = argv_ptr; 92 if (argv_ptr) { 93 *argv_ptr = '\0'; 94 old_argv_ptr++; 95 } 96 if (mkdir(*argv, mode) == -1) { 146 if (flags & OPT_DIRECTORY) { 147 while ((arg = *argv++) != NULL) { 148 char *slash = arg; 149 while (1) { 150 slash = strchr(slash + 1, '/'); 151 if (slash) 152 *slash = '\0'; 153 if (mkdir(arg, mode | 0111) == -1) { 97 154 if (errno != EEXIST) { 98 bb_perror_msg("c oulnt create %s", *argv);155 bb_perror_msg("cannot create %s", arg); 99 156 ret = EXIT_FAILURE; 100 157 break; 101 158 } 102 } 103 else if (lchown(*argv, uid, gid) == -1) { 104 bb_perror_msg("cannot change ownership of %s", *argv); 159 } /* dir was created, chown? */ 160 else if ((flags & (OPT_OWNER|OPT_GROUP)) 161 && lchown(arg, uid, gid) == -1 162 ) { 163 bb_perror_msg("cannot change ownership of %s", arg); 105 164 ret = EXIT_FAILURE; 106 165 break; 107 166 } 108 if (argv_ptr) { 109 *argv_ptr = '/'; 110 } 111 } while (old_argv_ptr); 112 } 113 return(ret); 114 } 115 116 { 117 struct stat statbuf; 118 isdir = lstat(argv[argc - 1], &statbuf)<0 119 ? 0 : S_ISDIR(statbuf.st_mode); 120 } 121 for (i = optind; i < argc - 1; i++) { 122 char *dest; 123 124 dest = argv[argc - 1]; 125 if (isdir) dest = concat_path_file(argv[argc - 1], basename(argv[i])); 126 ret |= copy_file(argv[i], dest, copy_flags); 167 if (!slash) 168 break; 169 *slash = '/'; 170 } 171 } 172 return ret; 173 } 174 175 if (argc < 2) 176 bb_show_usage(); 177 178 last = argv[argc - 1]; 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); 182 183 while ((arg = *argv++) != NULL) { 184 char *dest = last; 185 if (isdir) 186 dest = concat_path_file(last, basename(arg)); 187 if (copy_file(arg, dest, copy_flags)) { 188 /* copy is not made */ 189 ret = EXIT_FAILURE; 190 goto next; 191 } 127 192 128 193 /* Set the file mode */ 129 if ( chmod(dest, mode) == -1) {194 if ((flags & OPT_MODE) && chmod(dest, mode) == -1) { 130 195 bb_perror_msg("cannot change permissions of %s", dest); 131 196 ret = EXIT_FAILURE; 132 197 } 133 198 #if ENABLE_SELINUX 199 if (use_default_selinux_context) 200 setdefaultfilecon(dest); 201 #endif 134 202 /* Set the user and group id */ 135 if (lchown(dest, uid, gid) == -1) { 203 if ((flags & (OPT_OWNER|OPT_GROUP)) 204 && lchown(dest, uid, gid) == -1 205 ) { 136 206 bb_perror_msg("cannot change ownership of %s", dest); 137 207 ret = EXIT_FAILURE; 138 208 } 139 if (flags & INSTALL_OPT_STRIP) { 140 if (execlp("strip", "strip", dest, NULL) == -1) { 141 bb_error_msg("strip failed"); 209 if (flags & OPT_STRIP) { 210 char *args[3]; 211 args[0] = (char*)"strip"; 212 args[1] = dest; 213 args[2] = NULL; 214 if (spawn_and_wait(args)) { 215 bb_perror_msg("strip"); 142 216 ret = EXIT_FAILURE; 143 217 } 144 218 } 145 if(ENABLE_FEATURE_CLEAN_UP && isdir) free(dest); 146 } 147 148 return(ret); 219 next: 220 if (ENABLE_FEATURE_CLEAN_UP && isdir) 221 free(dest); 222 } 223 224 return ret; 149 225 }
Note:
See TracChangeset
for help on using the changeset viewer.