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 * Copyright (c) 2018, Joyent, Inc. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <strings.h> 32 #include <sys/param.h> 33 #include <fcntl.h> 34 #include <sys/errno.h> 35 #include <sys/types.h> 36 #include <sys/uio.h> 37 #include <unistd.h> 38 #include <sys/stat.h> 39 #include <errno.h> 40 #include <libgen.h> 41 #include "stdusers.h" 42 43 44 #define FILE_BUFF 40960 45 46 static int suppress = 0; 47 48 static void usage(void); 49 static void file_copy(char *src_file, char *dest_file); 50 static void chown_file(const char *file, const char *group, const char *owner); 51 static char *find_basename(const char *str); 52 static int creatdir(char *fn); 53 54 55 void 56 usage(void) 57 { 58 (void) fprintf(stderr, 59 "usage: install [-sd][-m mode][-g group][-u owner] " 60 "-f dir file ...\n"); 61 } 62 63 void 64 file_copy(char *src_file, char *dest_file) 65 { 66 int src_fd; 67 int dest_fd; 68 int count; 69 static char file_buff[FILE_BUFF]; 70 71 if ((src_fd = open(src_file, O_RDONLY)) == -1) { 72 (void) fprintf(stderr, "install:file_copy: %s failed " 73 "(%d): %s\n", src_file, errno, strerror(errno)); 74 exit(1); 75 } 76 77 if ((dest_fd = open(dest_file, O_CREAT|O_WRONLY|O_TRUNC, 0755)) == -1) { 78 (void) fprintf(stderr, "install:file_copy: %s failed " 79 "(%d): %s\n", dest_file, errno, strerror(errno)); 80 exit(1); 81 } 82 83 while ((count = read(src_fd, file_buff, FILE_BUFF)) > 0) { 84 (void) write(dest_fd, file_buff, count); 85 } 86 87 if (count == -1) { 88 (void) fprintf(stderr, "install:file_copy:read failed " 89 "(%d): %s\n", errno, strerror(errno)); 90 exit(1); 91 } 92 93 if (!suppress) 94 (void) printf("%s installed as %s\n", src_file, dest_file); 95 96 (void) close(src_fd); 97 (void) close(dest_fd); 98 } 99 100 101 void 102 chown_file(const char *file, const char *group, const char *owner) 103 { 104 gid_t grp = (gid_t)-1; 105 uid_t own = (uid_t)-1; 106 107 if (group) { 108 grp = stdfind(group, groupnames); 109 if (grp == (gid_t)-1) 110 (void) fprintf(stderr, "unknown group(%s)\n", group); 111 } 112 113 if (owner) { 114 own = stdfind(owner, usernames); 115 if (own == (uid_t)-1) { 116 (void) fprintf(stderr, "unknown owner(%s)\n", owner); 117 exit(1); 118 } 119 120 } 121 122 if (chown(file, own, grp) == -1) { 123 (void) fprintf(stderr, "install:chown_file: failed " 124 "(%d): %s\n", errno, strerror(errno)); 125 exit(1); 126 } 127 } 128 129 130 char * 131 find_basename(const char *str) 132 { 133 int i; 134 int len; 135 136 len = strlen(str); 137 138 for (i = len-1; i >= 0; i--) 139 if (str[i] == '/') 140 return ((char *)(str + i + 1)); 141 return ((char *)str); 142 } 143 144 int 145 creatdir(char *fn) { 146 147 errno = 0; 148 149 if (mkdirp(fn, 0755) == -1) { 150 if (errno != EEXIST) 151 return (errno); 152 } else if (!suppress) { 153 (void) printf("directory %s created\n", fn); 154 } 155 return (0); 156 } 157 158 159 int 160 main(int argc, char **argv) 161 { 162 int c; 163 int errflg = 0; 164 int dirflg = 0; 165 char *group = NULL; 166 char *owner = NULL; 167 char *dirb = NULL; 168 char *ins_file = NULL; 169 int mode = -1; 170 char dest_file[MAXPATHLEN]; 171 int rv = 0; 172 173 while ((c = getopt(argc, argv, "f:sm:du:g:")) != EOF) { 174 switch (c) { 175 case 'f': 176 dirb = optarg; 177 break; 178 case 'g': 179 group = optarg; 180 break; 181 case 'u': 182 owner = optarg; 183 break; 184 case 'd': 185 dirflg = 1; 186 break; 187 case 'm': 188 mode = strtol(optarg, NULL, 8); 189 break; 190 case 's': 191 suppress = 1; 192 break; 193 case '?': 194 errflg++; 195 break; 196 } 197 } 198 199 if (errflg) { 200 usage(); 201 return (1); 202 } 203 204 if (argc == optind) { 205 usage(); 206 return (1); 207 } 208 209 if (!dirflg && (dirb == NULL)) { 210 (void) fprintf(stderr, 211 "install: no destination directory specified.\n"); 212 return (1); 213 } 214 215 for (c = optind; c < argc; c++) { 216 ins_file = argv[c]; 217 218 if (dirflg) { 219 rv = creatdir(ins_file); 220 if (rv) { 221 (void) fprintf(stderr, 222 "install: creatdir %s (%d): %s\n", 223 ins_file, errno, strerror(errno)); 224 return (rv); 225 } 226 (void) strlcpy(dest_file, ins_file, MAXPATHLEN); 227 228 } else { 229 (void) strcat(strcat(strcpy(dest_file, dirb), "/"), 230 find_basename(ins_file)); 231 file_copy(ins_file, dest_file); 232 } 233 234 if (group || owner) 235 chown_file(dest_file, group, owner); 236 237 if (mode != -1) { 238 (void) umask(0); 239 if (chmod(dest_file, mode) == -1) { 240 (void) fprintf(stderr, 241 "install: chmod of %s to mode %o failed " 242 "(%d): %s\n", 243 dest_file, mode, errno, strerror(errno)); 244 return (1); 245 } 246 } 247 } 248 return (0); 249 } 250