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
usage(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
file_copy(char * src_file,char * dest_file)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
chown_file(const char * file,const char * group,const char * owner)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
formclosed(char * root,char * closedroot)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 *
find_basename(const char * str)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
creatdir(char * fn)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
main(int argc,char ** argv)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