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