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