1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <strings.h> 29 #include <sys/param.h> 30 #include <fcntl.h> 31 #include <sys/errno.h> 32 #include <sys/types.h> 33 #include <sys/uio.h> 34 #include <unistd.h> 35 #include <sys/stat.h> 36 #include <errno.h> 37 #include <libgen.h> 38 #include "stdusers.h" 39 40 41 #define FILE_BUFF 40960 42 43 static int suppress = 0; 44 45 static void usage(void); 46 static void file_copy(char *src_file, char *dest_file); 47 static void chown_file(const char *file, const char *group, const char *owner); 48 static void formclosed(char *root, char *closedroot); 49 static char *find_basename(const char *str); 50 static int creatdir(char *fn); 51 52 53 void 54 usage(void) 55 { 56 (void) fprintf(stderr, 57 "usage: install [-sdO][-m mode][-g group][-u owner] " 58 "-f dir file ...\n"); 59 } 60 61 void 62 file_copy(char *src_file, char *dest_file) 63 { 64 int src_fd; 65 int dest_fd; 66 int count; 67 static char file_buff[FILE_BUFF]; 68 69 if ((src_fd = open(src_file, O_RDONLY)) == -1) { 70 (void) fprintf(stderr, "install:file_copy: %s failed " 71 "(%d): %s\n", src_file, errno, strerror(errno)); 72 exit(1); 73 } 74 75 if ((dest_fd = open(dest_file, O_CREAT|O_WRONLY|O_TRUNC, 0755)) == -1) { 76 (void) fprintf(stderr, "install:file_copy: %s failed " 77 "(%d): %s\n", dest_file, errno, strerror(errno)); 78 exit(1); 79 } 80 81 while ((count = read(src_fd, file_buff, FILE_BUFF)) > 0) { 82 (void) write(dest_fd, file_buff, count); 83 } 84 85 if (count == -1) { 86 (void) fprintf(stderr, "install:file_copy:read failed " 87 "(%d): %s\n", errno, strerror(errno)); 88 exit(1); 89 } 90 91 if (!suppress) 92 (void) printf("%s installed as %s\n", src_file, dest_file); 93 94 (void) close(src_fd); 95 (void) close(dest_fd); 96 } 97 98 99 void 100 chown_file(const char *file, const char *group, const char *owner) 101 { 102 gid_t grp = (gid_t)-1; 103 uid_t own = (uid_t)-1; 104 105 if (group) { 106 grp = stdfind(group, groupnames); 107 if (grp < 0) 108 (void) fprintf(stderr, "unknown group(%s)\n", group); 109 } 110 111 if (owner) { 112 own = stdfind(owner, usernames); 113 if (own < 0) { 114 (void) fprintf(stderr, "unknown owner(%s)\n", owner); 115 exit(1); 116 } 117 118 } 119 120 if (chown(file, own, grp) == -1) { 121 (void) fprintf(stderr, "install:chown_file: failed " 122 "(%d): %s\n", errno, strerror(errno)); 123 exit(1); 124 } 125 } 126 127 128 void 129 formclosed(char *root, char *closedroot) 130 { 131 int wholelen, residlen; 132 char *temp; 133 134 wholelen = strlen(root); 135 temp = strstr(strstr(root, "proto/root_"), "/"); 136 temp++; 137 temp = strstr(temp, "/"); 138 residlen = strlen(temp); 139 (void) strlcpy(closedroot, root, wholelen - residlen + 1); 140 (void) strlcat(closedroot, "-closed", MAXPATHLEN); 141 (void) strlcat(closedroot, temp, MAXPATHLEN); 142 } 143 144 145 char * 146 find_basename(const char *str) 147 { 148 int i; 149 int len; 150 151 len = strlen(str); 152 153 for (i = len-1; i >= 0; i--) 154 if (str[i] == '/') 155 return ((char *)(str + i + 1)); 156 return ((char *)str); 157 } 158 159 int 160 creatdir(char *fn) { 161 162 errno = 0; 163 164 if (mkdirp(fn, 0755) == -1) { 165 if (errno != EEXIST) 166 return (errno); 167 } else if (!suppress) { 168 (void) printf("directory %s created\n", fn); 169 } 170 return (0); 171 } 172 173 174 int 175 main(int argc, char **argv) 176 { 177 int c; 178 int errflg = 0; 179 int dirflg = 0; 180 char *group = NULL; 181 char *owner = NULL; 182 char *dirb = NULL; 183 char *ins_file = NULL; 184 int mode = -1; 185 char dest_file[MAXPATHLEN]; 186 char shadow_dest[MAXPATHLEN]; 187 char shadow_dirb[MAXPATHLEN]; 188 int tonic = 0; 189 int rv = 0; 190 191 while ((c = getopt(argc, argv, "f:sm:du:g:O")) != EOF) { 192 switch (c) { 193 case 'f': 194 dirb = optarg; 195 break; 196 case 'g': 197 group = optarg; 198 break; 199 case 'u': 200 owner = optarg; 201 break; 202 case 'd': 203 dirflg = 1; 204 break; 205 case 'm': 206 mode = strtol(optarg, NULL, 8); 207 break; 208 case 's': 209 suppress = 1; 210 break; 211 case 'O': 212 tonic = 1; 213 break; 214 case '?': 215 errflg++; 216 break; 217 } 218 } 219 220 if (errflg) { 221 usage(); 222 return (1); 223 } 224 225 if (argc == optind) { 226 usage(); 227 return (1); 228 } 229 230 if (!dirflg && (dirb == NULL)) { 231 (void) fprintf(stderr, 232 "install: no destination directory specified.\n"); 233 return (1); 234 } 235 236 for (c = optind; c < argc; c++) { 237 ins_file = argv[c]; 238 239 if (dirflg) { 240 if (tonic) { 241 formclosed(ins_file, shadow_dest); 242 rv = creatdir(shadow_dest); 243 if (rv) { 244 (void) fprintf(stderr, 245 "install: tonic creatdir " 246 "%s (%d): (%s)\n", 247 shadow_dest, errno, 248 strerror(errno)); 249 return (rv); 250 } 251 } 252 rv = creatdir(ins_file); 253 if (rv) { 254 (void) fprintf(stderr, 255 "install: creatdir %s (%d): %s\n", 256 ins_file, errno, strerror(errno)); 257 return (rv); 258 } 259 (void) strlcpy(dest_file, ins_file, MAXPATHLEN); 260 261 } else { 262 (void) strcat(strcat(strcpy(dest_file, dirb), "/"), 263 find_basename(ins_file)); 264 file_copy(ins_file, dest_file); 265 266 if (tonic) { 267 formclosed(dirb, shadow_dirb); 268 /* 269 * The standard directories in the proto 270 * area are created as part of "make setup", 271 * but that doesn't create them in the 272 * closed proto area. So if the target 273 * directory doesn't exist, we need to 274 * create it now. 275 */ 276 rv = creatdir(shadow_dirb); 277 if (rv) { 278 (void) fprintf(stderr, 279 "install: tonic creatdir(f) " 280 "%s (%d): %s\n", 281 shadow_dirb, errno, 282 strerror(errno)); 283 return (rv); 284 } 285 (void) strcat(strcat(strcpy(shadow_dest, 286 shadow_dirb), "/"), 287 find_basename(ins_file)); 288 file_copy(ins_file, shadow_dest); 289 } 290 } 291 292 if (group || owner) { 293 chown_file(dest_file, group, owner); 294 if (tonic) 295 chown_file(shadow_dest, group, owner); 296 } 297 if (mode != -1) { 298 (void) umask(0); 299 if (chmod(dest_file, mode) == -1) { 300 (void) fprintf(stderr, 301 "install: chmod of %s to mode %o failed " 302 "(%d): %s\n", 303 dest_file, mode, errno, strerror(errno)); 304 return (1); 305 } 306 if (tonic) { 307 if (chmod(shadow_dest, mode) == -1) { 308 (void) fprintf(stderr, 309 "install: tonic chmod of %s " 310 "to mode %o failed (%d): %s\n", 311 shadow_dest, mode, 312 errno, strerror(errno)); 313 return (1); 314 } 315 } 316 } 317 } 318 return (0); 319 } 320