xref: /onnv-gate/usr/src/tools/install.bin/install.bin.c (revision 12210:436b06ce515d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54335Scasper  * Common Development and Distribution License (the "License").
64335Scasper  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12210SJames.McPherson@Sun.COM  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <strings.h>
290Sstevel@tonic-gate #include <sys/param.h>
300Sstevel@tonic-gate #include <fcntl.h>
310Sstevel@tonic-gate #include <sys/errno.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/uio.h>
340Sstevel@tonic-gate #include <unistd.h>
350Sstevel@tonic-gate #include <sys/stat.h>
360Sstevel@tonic-gate #include <errno.h>
370Sstevel@tonic-gate #include <libgen.h>
381384Smike_s #include "stdusers.h"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #define	FILE_BUFF	40960
420Sstevel@tonic-gate 
43*12210SJames.McPherson@Sun.COM static int suppress = 0;
44*12210SJames.McPherson@Sun.COM 
45*12210SJames.McPherson@Sun.COM static void usage(void);
46*12210SJames.McPherson@Sun.COM static void file_copy(char *src_file, char *dest_file);
47*12210SJames.McPherson@Sun.COM static void chown_file(const char *file, const char *group, const char *owner);
48*12210SJames.McPherson@Sun.COM static void formclosed(char *root, char *closedroot);
49*12210SJames.McPherson@Sun.COM static char *find_basename(const char *str);
50*12210SJames.McPherson@Sun.COM static int creatdir(char *fn);
510Sstevel@tonic-gate 
520Sstevel@tonic-gate 
530Sstevel@tonic-gate void
usage(void)540Sstevel@tonic-gate usage(void)
550Sstevel@tonic-gate {
560Sstevel@tonic-gate 	(void) fprintf(stderr,
57*12210SJames.McPherson@Sun.COM 	    "usage: install [-sdO][-m mode][-g group][-u owner] "
580Sstevel@tonic-gate 	    "-f dir file ...\n");
590Sstevel@tonic-gate }
600Sstevel@tonic-gate 
610Sstevel@tonic-gate void
file_copy(char * src_file,char * dest_file)620Sstevel@tonic-gate file_copy(char *src_file, char *dest_file)
630Sstevel@tonic-gate {
640Sstevel@tonic-gate 	int	src_fd;
650Sstevel@tonic-gate 	int	dest_fd;
660Sstevel@tonic-gate 	int	count;
670Sstevel@tonic-gate 	static char file_buff[FILE_BUFF];
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	if ((src_fd = open(src_file, O_RDONLY))  == -1) {
70*12210SJames.McPherson@Sun.COM 		(void) fprintf(stderr, "install:file_copy: %s failed "
71*12210SJames.McPherson@Sun.COM 		    "(%d): %s\n", src_file, errno, strerror(errno));
720Sstevel@tonic-gate 		exit(1);
730Sstevel@tonic-gate 	}
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	if ((dest_fd = open(dest_file, O_CREAT|O_WRONLY|O_TRUNC, 0755)) == -1) {
76*12210SJames.McPherson@Sun.COM 		(void) fprintf(stderr, "install:file_copy: %s failed "
77*12210SJames.McPherson@Sun.COM 		    "(%d): %s\n", dest_file, errno, strerror(errno));
780Sstevel@tonic-gate 		exit(1);
790Sstevel@tonic-gate 	}
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	while ((count = read(src_fd, file_buff, FILE_BUFF)) > 0) {
82*12210SJames.McPherson@Sun.COM 		(void) write(dest_fd, file_buff, count);
830Sstevel@tonic-gate 	}
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	if (count == -1) {
86*12210SJames.McPherson@Sun.COM 		(void) fprintf(stderr, "install:file_copy:read failed "
87*12210SJames.McPherson@Sun.COM 		    "(%d): %s\n", errno, strerror(errno));
880Sstevel@tonic-gate 		exit(1);
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 
91*12210SJames.McPherson@Sun.COM 	if (!suppress)
920Sstevel@tonic-gate 		(void) printf("%s installed as %s\n", src_file, dest_file);
930Sstevel@tonic-gate 
94*12210SJames.McPherson@Sun.COM 	(void) close(src_fd);
95*12210SJames.McPherson@Sun.COM 	(void) close(dest_fd);
960Sstevel@tonic-gate }
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 
990Sstevel@tonic-gate void
chown_file(const char * file,const char * group,const char * owner)1000Sstevel@tonic-gate chown_file(const char *file, const char *group, const char *owner)
1010Sstevel@tonic-gate {
1024335Scasper 	gid_t	grp = (gid_t)-1;
1034335Scasper 	uid_t	own = (uid_t)-1;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	if (group) {
1061384Smike_s 		grp = stdfind(group, groupnames);
1071384Smike_s 		if (grp < 0)
1080Sstevel@tonic-gate 			(void) fprintf(stderr, "unknown group(%s)\n", group);
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	if (owner) {
1121384Smike_s 		own = stdfind(owner, usernames);
1131384Smike_s 		if (own < 0) {
1140Sstevel@tonic-gate 			(void) fprintf(stderr, "unknown owner(%s)\n", owner);
1150Sstevel@tonic-gate 			exit(1);
1160Sstevel@tonic-gate 		}
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	if (chown(file, own, grp) == -1) {
121*12210SJames.McPherson@Sun.COM 		(void) fprintf(stderr, "install:chown_file: failed "
122*12210SJames.McPherson@Sun.COM 		    "(%d): %s\n", errno, strerror(errno));
1230Sstevel@tonic-gate 		exit(1);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate 
127*12210SJames.McPherson@Sun.COM 
128*12210SJames.McPherson@Sun.COM void
formclosed(char * root,char * closedroot)129*12210SJames.McPherson@Sun.COM formclosed(char *root, char *closedroot)
130*12210SJames.McPherson@Sun.COM {
131*12210SJames.McPherson@Sun.COM 	int wholelen, residlen;
132*12210SJames.McPherson@Sun.COM 	char *temp;
133*12210SJames.McPherson@Sun.COM 
134*12210SJames.McPherson@Sun.COM 	wholelen = strlen(root);
135*12210SJames.McPherson@Sun.COM 	temp = strstr(strstr(root, "proto/root_"), "/");
136*12210SJames.McPherson@Sun.COM 	temp++;
137*12210SJames.McPherson@Sun.COM 	temp = strstr(temp, "/");
138*12210SJames.McPherson@Sun.COM 	residlen = strlen(temp);
139*12210SJames.McPherson@Sun.COM 	(void) strlcpy(closedroot, root, wholelen - residlen + 1);
140*12210SJames.McPherson@Sun.COM 	(void) strlcat(closedroot, "-closed", MAXPATHLEN);
141*12210SJames.McPherson@Sun.COM 	(void) strlcat(closedroot, temp, MAXPATHLEN);
142*12210SJames.McPherson@Sun.COM }
143*12210SJames.McPherson@Sun.COM 
144*12210SJames.McPherson@Sun.COM 
1450Sstevel@tonic-gate char *
find_basename(const char * str)1460Sstevel@tonic-gate find_basename(const char *str)
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate 	int	i;
1490Sstevel@tonic-gate 	int	len;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	len = strlen(str);
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	for (i = len-1; i >= 0; i--)
1540Sstevel@tonic-gate 		if (str[i] == '/')
1550Sstevel@tonic-gate 			return ((char *)(str + i + 1));
1560Sstevel@tonic-gate 	return ((char *)str);
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate 
159*12210SJames.McPherson@Sun.COM int
creatdir(char * fn)160*12210SJames.McPherson@Sun.COM creatdir(char *fn) {
161*12210SJames.McPherson@Sun.COM 
162*12210SJames.McPherson@Sun.COM 	errno = 0;
163*12210SJames.McPherson@Sun.COM 
164*12210SJames.McPherson@Sun.COM 	if (mkdirp(fn, 0755) == -1) {
165*12210SJames.McPherson@Sun.COM 		if (errno != EEXIST)
166*12210SJames.McPherson@Sun.COM 			return (errno);
167*12210SJames.McPherson@Sun.COM 	} else if (!suppress) {
168*12210SJames.McPherson@Sun.COM 		(void) printf("directory %s created\n", fn);
169*12210SJames.McPherson@Sun.COM 	}
170*12210SJames.McPherson@Sun.COM 	return (0);
171*12210SJames.McPherson@Sun.COM }
172*12210SJames.McPherson@Sun.COM 
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate int
main(int argc,char ** argv)1750Sstevel@tonic-gate main(int argc, char **argv)
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate 	int	c;
1780Sstevel@tonic-gate 	int	errflg = 0;
1790Sstevel@tonic-gate 	int	dirflg = 0;
1800Sstevel@tonic-gate 	char	*group = NULL;
1810Sstevel@tonic-gate 	char	*owner = NULL;
1820Sstevel@tonic-gate 	char	*dirb = NULL;
1830Sstevel@tonic-gate 	char	*ins_file = NULL;
1840Sstevel@tonic-gate 	int	mode = -1;
1850Sstevel@tonic-gate 	char	dest_file[MAXPATHLEN];
186*12210SJames.McPherson@Sun.COM 	char    shadow_dest[MAXPATHLEN];
187*12210SJames.McPherson@Sun.COM 	char	shadow_dirb[MAXPATHLEN];
188*12210SJames.McPherson@Sun.COM 	int	tonic = 0;
189*12210SJames.McPherson@Sun.COM 	int	rv = 0;
1900Sstevel@tonic-gate 
191*12210SJames.McPherson@Sun.COM 	while ((c = getopt(argc, argv, "f:sm:du:g:O")) != EOF) {
1920Sstevel@tonic-gate 		switch (c) {
1930Sstevel@tonic-gate 		case 'f':
1940Sstevel@tonic-gate 			dirb = optarg;
1950Sstevel@tonic-gate 			break;
1960Sstevel@tonic-gate 		case 'g':
1970Sstevel@tonic-gate 			group = optarg;
1980Sstevel@tonic-gate 			break;
1990Sstevel@tonic-gate 		case 'u':
2000Sstevel@tonic-gate 			owner = optarg;
2010Sstevel@tonic-gate 			break;
2020Sstevel@tonic-gate 		case 'd':
2030Sstevel@tonic-gate 			dirflg = 1;
2040Sstevel@tonic-gate 			break;
2050Sstevel@tonic-gate 		case 'm':
2060Sstevel@tonic-gate 			mode = strtol(optarg, NULL, 8);
2070Sstevel@tonic-gate 			break;
2080Sstevel@tonic-gate 		case 's':
209*12210SJames.McPherson@Sun.COM 			suppress = 1;
210*12210SJames.McPherson@Sun.COM 			break;
211*12210SJames.McPherson@Sun.COM 		case 'O':
212*12210SJames.McPherson@Sun.COM 			tonic = 1;
2130Sstevel@tonic-gate 			break;
2140Sstevel@tonic-gate 		case '?':
2150Sstevel@tonic-gate 			errflg++;
2160Sstevel@tonic-gate 			break;
2170Sstevel@tonic-gate 		}
2180Sstevel@tonic-gate 	}
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	if (errflg) {
2210Sstevel@tonic-gate 		usage();
2220Sstevel@tonic-gate 		return (1);
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	if (argc == optind) {
2260Sstevel@tonic-gate 		usage();
2270Sstevel@tonic-gate 		return (1);
2280Sstevel@tonic-gate 	}
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	if (!dirflg && (dirb == NULL)) {
2310Sstevel@tonic-gate 		(void) fprintf(stderr,
2320Sstevel@tonic-gate 		    "install: no destination directory specified.\n");
2330Sstevel@tonic-gate 		return (1);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	for (c = optind; c < argc; c++) {
2370Sstevel@tonic-gate 		ins_file = argv[c];
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 		if (dirflg) {
240*12210SJames.McPherson@Sun.COM 			if (tonic) {
241*12210SJames.McPherson@Sun.COM 				formclosed(ins_file, shadow_dest);
242*12210SJames.McPherson@Sun.COM 				rv = creatdir(shadow_dest);
243*12210SJames.McPherson@Sun.COM 				if (rv) {
244*12210SJames.McPherson@Sun.COM 					(void) fprintf(stderr,
245*12210SJames.McPherson@Sun.COM 					    "install: tonic creatdir "
246*12210SJames.McPherson@Sun.COM 					    "%s (%d): (%s)\n",
247*12210SJames.McPherson@Sun.COM 					    shadow_dest, errno,
248*12210SJames.McPherson@Sun.COM 					    strerror(errno));
249*12210SJames.McPherson@Sun.COM 					return (rv);
2500Sstevel@tonic-gate 				}
2510Sstevel@tonic-gate 			}
252*12210SJames.McPherson@Sun.COM 			rv = creatdir(ins_file);
253*12210SJames.McPherson@Sun.COM 			if (rv) {
254*12210SJames.McPherson@Sun.COM 				(void) fprintf(stderr,
255*12210SJames.McPherson@Sun.COM 				    "install: creatdir %s (%d): %s\n",
256*12210SJames.McPherson@Sun.COM 				    ins_file, errno, strerror(errno));
257*12210SJames.McPherson@Sun.COM 				return (rv);
258*12210SJames.McPherson@Sun.COM 			}
259*12210SJames.McPherson@Sun.COM 			(void) strlcpy(dest_file, ins_file, MAXPATHLEN);
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 		} else {
2620Sstevel@tonic-gate 			(void) strcat(strcat(strcpy(dest_file, dirb), "/"),
2630Sstevel@tonic-gate 			    find_basename(ins_file));
2640Sstevel@tonic-gate 			file_copy(ins_file, dest_file);
265*12210SJames.McPherson@Sun.COM 
266*12210SJames.McPherson@Sun.COM 			if (tonic) {
267*12210SJames.McPherson@Sun.COM 				formclosed(dirb, shadow_dirb);
268*12210SJames.McPherson@Sun.COM 				/*
269*12210SJames.McPherson@Sun.COM 				 * The standard directories in the proto
270*12210SJames.McPherson@Sun.COM 				 * area are created as part of "make setup",
271*12210SJames.McPherson@Sun.COM 				 * but that doesn't create them in the
272*12210SJames.McPherson@Sun.COM 				 * closed proto area. So if the target
273*12210SJames.McPherson@Sun.COM 				 * directory doesn't exist, we need to
274*12210SJames.McPherson@Sun.COM 				 * create it now.
275*12210SJames.McPherson@Sun.COM 				 */
276*12210SJames.McPherson@Sun.COM 				rv = creatdir(shadow_dirb);
277*12210SJames.McPherson@Sun.COM 				if (rv) {
278*12210SJames.McPherson@Sun.COM 					(void) fprintf(stderr,
279*12210SJames.McPherson@Sun.COM 					    "install: tonic creatdir(f) "
280*12210SJames.McPherson@Sun.COM 					    "%s (%d): %s\n",
281*12210SJames.McPherson@Sun.COM 					    shadow_dirb, errno,
282*12210SJames.McPherson@Sun.COM 					    strerror(errno));
283*12210SJames.McPherson@Sun.COM 					return (rv);
284*12210SJames.McPherson@Sun.COM 				}
285*12210SJames.McPherson@Sun.COM 				(void) strcat(strcat(strcpy(shadow_dest,
286*12210SJames.McPherson@Sun.COM 				    shadow_dirb), "/"),
287*12210SJames.McPherson@Sun.COM 				    find_basename(ins_file));
288*12210SJames.McPherson@Sun.COM 				file_copy(ins_file, shadow_dest);
289*12210SJames.McPherson@Sun.COM 			}
2900Sstevel@tonic-gate 		}
2910Sstevel@tonic-gate 
292*12210SJames.McPherson@Sun.COM 		if (group || owner) {
2930Sstevel@tonic-gate 			chown_file(dest_file, group, owner);
294*12210SJames.McPherson@Sun.COM 			if (tonic)
295*12210SJames.McPherson@Sun.COM 				chown_file(shadow_dest, group, owner);
296*12210SJames.McPherson@Sun.COM 		}
2970Sstevel@tonic-gate 		if (mode != -1) {
298*12210SJames.McPherson@Sun.COM 			(void) umask(0);
2990Sstevel@tonic-gate 			if (chmod(dest_file, mode) == -1) {
300*12210SJames.McPherson@Sun.COM 				(void) fprintf(stderr,
301*12210SJames.McPherson@Sun.COM 				    "install: chmod of %s to mode %o failed "
302*12210SJames.McPherson@Sun.COM 				    "(%d): %s\n",
303*12210SJames.McPherson@Sun.COM 				    dest_file, mode, errno, strerror(errno));
3040Sstevel@tonic-gate 				return (1);
3050Sstevel@tonic-gate 			}
306*12210SJames.McPherson@Sun.COM 			if (tonic) {
307*12210SJames.McPherson@Sun.COM 				if (chmod(shadow_dest, mode) == -1) {
308*12210SJames.McPherson@Sun.COM 					(void) fprintf(stderr,
309*12210SJames.McPherson@Sun.COM 					    "install: tonic chmod of %s "
310*12210SJames.McPherson@Sun.COM 					    "to mode %o failed (%d): %s\n",
311*12210SJames.McPherson@Sun.COM 					    shadow_dest, mode,
312*12210SJames.McPherson@Sun.COM 					    errno, strerror(errno));
313*12210SJames.McPherson@Sun.COM 					return (1);
314*12210SJames.McPherson@Sun.COM 				}
315*12210SJames.McPherson@Sun.COM 			}
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate 	return (0);
3190Sstevel@tonic-gate }
320