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