17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 519ca6462Scasper * Common Development and Distribution License (the "License"). 619ca6462Scasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*b83ec4edSjmcp * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <stdio.h> 277c478bd9Sstevel@tonic-gate #include <stdlib.h> 287c478bd9Sstevel@tonic-gate #include <strings.h> 297c478bd9Sstevel@tonic-gate #include <sys/param.h> 307c478bd9Sstevel@tonic-gate #include <fcntl.h> 317c478bd9Sstevel@tonic-gate #include <sys/errno.h> 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/uio.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <libgen.h> 380adc1619Smike_s #include "stdusers.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #define FILE_BUFF 40960 427c478bd9Sstevel@tonic-gate 43*b83ec4edSjmcp static int suppress = 0; 44*b83ec4edSjmcp 45*b83ec4edSjmcp static void usage(void); 46*b83ec4edSjmcp static void file_copy(char *src_file, char *dest_file); 47*b83ec4edSjmcp static void chown_file(const char *file, const char *group, const char *owner); 48*b83ec4edSjmcp static void formclosed(char *root, char *closedroot); 49*b83ec4edSjmcp static char *find_basename(const char *str); 50*b83ec4edSjmcp static int creatdir(char *fn); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate void 547c478bd9Sstevel@tonic-gate usage(void) 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 57*b83ec4edSjmcp "usage: install [-sdO][-m mode][-g group][-u owner] " 587c478bd9Sstevel@tonic-gate "-f dir file ...\n"); 597c478bd9Sstevel@tonic-gate } 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate void 627c478bd9Sstevel@tonic-gate file_copy(char *src_file, char *dest_file) 637c478bd9Sstevel@tonic-gate { 647c478bd9Sstevel@tonic-gate int src_fd; 657c478bd9Sstevel@tonic-gate int dest_fd; 667c478bd9Sstevel@tonic-gate int count; 677c478bd9Sstevel@tonic-gate static char file_buff[FILE_BUFF]; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if ((src_fd = open(src_file, O_RDONLY)) == -1) { 70*b83ec4edSjmcp (void) fprintf(stderr, "install:file_copy: %s failed " 71*b83ec4edSjmcp "(%d): %s\n", src_file, errno, strerror(errno)); 727c478bd9Sstevel@tonic-gate exit(1); 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate if ((dest_fd = open(dest_file, O_CREAT|O_WRONLY|O_TRUNC, 0755)) == -1) { 76*b83ec4edSjmcp (void) fprintf(stderr, "install:file_copy: %s failed " 77*b83ec4edSjmcp "(%d): %s\n", dest_file, errno, strerror(errno)); 787c478bd9Sstevel@tonic-gate exit(1); 797c478bd9Sstevel@tonic-gate } 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate while ((count = read(src_fd, file_buff, FILE_BUFF)) > 0) { 82*b83ec4edSjmcp (void) write(dest_fd, file_buff, count); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate if (count == -1) { 86*b83ec4edSjmcp (void) fprintf(stderr, "install:file_copy:read failed " 87*b83ec4edSjmcp "(%d): %s\n", errno, strerror(errno)); 887c478bd9Sstevel@tonic-gate exit(1); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 91*b83ec4edSjmcp if (!suppress) 927c478bd9Sstevel@tonic-gate (void) printf("%s installed as %s\n", src_file, dest_file); 937c478bd9Sstevel@tonic-gate 94*b83ec4edSjmcp (void) close(src_fd); 95*b83ec4edSjmcp (void) close(dest_fd); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate void 1007c478bd9Sstevel@tonic-gate chown_file(const char *file, const char *group, const char *owner) 1017c478bd9Sstevel@tonic-gate { 10219ca6462Scasper gid_t grp = (gid_t)-1; 10319ca6462Scasper uid_t own = (uid_t)-1; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if (group) { 1060adc1619Smike_s grp = stdfind(group, groupnames); 1070adc1619Smike_s if (grp < 0) 1087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unknown group(%s)\n", group); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate if (owner) { 1120adc1619Smike_s own = stdfind(owner, usernames); 1130adc1619Smike_s if (own < 0) { 1147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unknown owner(%s)\n", owner); 1157c478bd9Sstevel@tonic-gate exit(1); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if (chown(file, own, grp) == -1) { 121*b83ec4edSjmcp (void) fprintf(stderr, "install:chown_file: failed " 122*b83ec4edSjmcp "(%d): %s\n", errno, strerror(errno)); 1237c478bd9Sstevel@tonic-gate exit(1); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 127*b83ec4edSjmcp 128*b83ec4edSjmcp void 129*b83ec4edSjmcp formclosed(char *root, char *closedroot) 130*b83ec4edSjmcp { 131*b83ec4edSjmcp int wholelen, residlen; 132*b83ec4edSjmcp char *temp; 133*b83ec4edSjmcp 134*b83ec4edSjmcp wholelen = strlen(root); 135*b83ec4edSjmcp temp = strstr(strstr(root, "proto/root_"), "/"); 136*b83ec4edSjmcp temp++; 137*b83ec4edSjmcp temp = strstr(temp, "/"); 138*b83ec4edSjmcp residlen = strlen(temp); 139*b83ec4edSjmcp (void) strlcpy(closedroot, root, wholelen - residlen + 1); 140*b83ec4edSjmcp (void) strlcat(closedroot, "-closed", MAXPATHLEN); 141*b83ec4edSjmcp (void) strlcat(closedroot, temp, MAXPATHLEN); 142*b83ec4edSjmcp } 143*b83ec4edSjmcp 144*b83ec4edSjmcp 1457c478bd9Sstevel@tonic-gate char * 1467c478bd9Sstevel@tonic-gate find_basename(const char *str) 1477c478bd9Sstevel@tonic-gate { 1487c478bd9Sstevel@tonic-gate int i; 1497c478bd9Sstevel@tonic-gate int len; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate len = strlen(str); 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate for (i = len-1; i >= 0; i--) 1547c478bd9Sstevel@tonic-gate if (str[i] == '/') 1557c478bd9Sstevel@tonic-gate return ((char *)(str + i + 1)); 1567c478bd9Sstevel@tonic-gate return ((char *)str); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 159*b83ec4edSjmcp int 160*b83ec4edSjmcp creatdir(char *fn) { 161*b83ec4edSjmcp 162*b83ec4edSjmcp errno = 0; 163*b83ec4edSjmcp 164*b83ec4edSjmcp if (mkdirp(fn, 0755) == -1) { 165*b83ec4edSjmcp if (errno != EEXIST) 166*b83ec4edSjmcp return (errno); 167*b83ec4edSjmcp } else if (!suppress) { 168*b83ec4edSjmcp (void) printf("directory %s created\n", fn); 169*b83ec4edSjmcp } 170*b83ec4edSjmcp return (0); 171*b83ec4edSjmcp } 172*b83ec4edSjmcp 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate int 1757c478bd9Sstevel@tonic-gate main(int argc, char **argv) 1767c478bd9Sstevel@tonic-gate { 1777c478bd9Sstevel@tonic-gate int c; 1787c478bd9Sstevel@tonic-gate int errflg = 0; 1797c478bd9Sstevel@tonic-gate int dirflg = 0; 1807c478bd9Sstevel@tonic-gate char *group = NULL; 1817c478bd9Sstevel@tonic-gate char *owner = NULL; 1827c478bd9Sstevel@tonic-gate char *dirb = NULL; 1837c478bd9Sstevel@tonic-gate char *ins_file = NULL; 1847c478bd9Sstevel@tonic-gate int mode = -1; 1857c478bd9Sstevel@tonic-gate char dest_file[MAXPATHLEN]; 186*b83ec4edSjmcp char shadow_dest[MAXPATHLEN]; 187*b83ec4edSjmcp char shadow_dirb[MAXPATHLEN]; 188*b83ec4edSjmcp int tonic = 0; 189*b83ec4edSjmcp int rv = 0; 1907c478bd9Sstevel@tonic-gate 191*b83ec4edSjmcp while ((c = getopt(argc, argv, "f:sm:du:g:O")) != EOF) { 1927c478bd9Sstevel@tonic-gate switch (c) { 1937c478bd9Sstevel@tonic-gate case 'f': 1947c478bd9Sstevel@tonic-gate dirb = optarg; 1957c478bd9Sstevel@tonic-gate break; 1967c478bd9Sstevel@tonic-gate case 'g': 1977c478bd9Sstevel@tonic-gate group = optarg; 1987c478bd9Sstevel@tonic-gate break; 1997c478bd9Sstevel@tonic-gate case 'u': 2007c478bd9Sstevel@tonic-gate owner = optarg; 2017c478bd9Sstevel@tonic-gate break; 2027c478bd9Sstevel@tonic-gate case 'd': 2037c478bd9Sstevel@tonic-gate dirflg = 1; 2047c478bd9Sstevel@tonic-gate break; 2057c478bd9Sstevel@tonic-gate case 'm': 2067c478bd9Sstevel@tonic-gate mode = strtol(optarg, NULL, 8); 2077c478bd9Sstevel@tonic-gate break; 2087c478bd9Sstevel@tonic-gate case 's': 209*b83ec4edSjmcp suppress = 1; 210*b83ec4edSjmcp break; 211*b83ec4edSjmcp case 'O': 212*b83ec4edSjmcp tonic = 1; 2137c478bd9Sstevel@tonic-gate break; 2147c478bd9Sstevel@tonic-gate case '?': 2157c478bd9Sstevel@tonic-gate errflg++; 2167c478bd9Sstevel@tonic-gate break; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if (errflg) { 2217c478bd9Sstevel@tonic-gate usage(); 2227c478bd9Sstevel@tonic-gate return (1); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (argc == optind) { 2267c478bd9Sstevel@tonic-gate usage(); 2277c478bd9Sstevel@tonic-gate return (1); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate if (!dirflg && (dirb == NULL)) { 2317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2327c478bd9Sstevel@tonic-gate "install: no destination directory specified.\n"); 2337c478bd9Sstevel@tonic-gate return (1); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate for (c = optind; c < argc; c++) { 2377c478bd9Sstevel@tonic-gate ins_file = argv[c]; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate if (dirflg) { 240*b83ec4edSjmcp if (tonic) { 241*b83ec4edSjmcp formclosed(ins_file, shadow_dest); 242*b83ec4edSjmcp rv = creatdir(shadow_dest); 243*b83ec4edSjmcp if (rv) { 244*b83ec4edSjmcp (void) fprintf(stderr, 245*b83ec4edSjmcp "install: tonic creatdir " 246*b83ec4edSjmcp "%s (%d): (%s)\n", 247*b83ec4edSjmcp shadow_dest, errno, 248*b83ec4edSjmcp strerror(errno)); 249*b83ec4edSjmcp return (rv); 250*b83ec4edSjmcp } 251*b83ec4edSjmcp } 252*b83ec4edSjmcp rv = creatdir(ins_file); 253*b83ec4edSjmcp if (rv) { 254*b83ec4edSjmcp (void) fprintf(stderr, 255*b83ec4edSjmcp "install: creatdir %s (%d): %s\n", 256*b83ec4edSjmcp ins_file, errno, strerror(errno)); 257*b83ec4edSjmcp return (rv); 258*b83ec4edSjmcp } 259*b83ec4edSjmcp (void) strlcpy(dest_file, ins_file, MAXPATHLEN); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate } else { 2627c478bd9Sstevel@tonic-gate (void) strcat(strcat(strcpy(dest_file, dirb), "/"), 2637c478bd9Sstevel@tonic-gate find_basename(ins_file)); 2647c478bd9Sstevel@tonic-gate file_copy(ins_file, dest_file); 265*b83ec4edSjmcp 266*b83ec4edSjmcp if (tonic) { 267*b83ec4edSjmcp formclosed(dirb, shadow_dirb); 268*b83ec4edSjmcp /* 269*b83ec4edSjmcp * The standard directories in the proto 270*b83ec4edSjmcp * area are created as part of "make setup", 271*b83ec4edSjmcp * but that doesn't create them in the 272*b83ec4edSjmcp * closed proto area. So if the target 273*b83ec4edSjmcp * directory doesn't exist, we need to 274*b83ec4edSjmcp * create it now. 275*b83ec4edSjmcp */ 276*b83ec4edSjmcp rv = creatdir(shadow_dirb); 277*b83ec4edSjmcp if (rv) { 278*b83ec4edSjmcp (void) fprintf(stderr, 279*b83ec4edSjmcp "install: tonic creatdir(f) " 280*b83ec4edSjmcp "%s (%d): %s\n", 281*b83ec4edSjmcp shadow_dirb, errno, 282*b83ec4edSjmcp strerror(errno)); 283*b83ec4edSjmcp return (rv); 284*b83ec4edSjmcp } 285*b83ec4edSjmcp (void) strcat(strcat(strcpy(shadow_dest, 286*b83ec4edSjmcp shadow_dirb), "/"), 287*b83ec4edSjmcp find_basename(ins_file)); 288*b83ec4edSjmcp file_copy(ins_file, shadow_dest); 289*b83ec4edSjmcp } 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 292*b83ec4edSjmcp if (group || owner) { 2937c478bd9Sstevel@tonic-gate chown_file(dest_file, group, owner); 294*b83ec4edSjmcp if (tonic) 295*b83ec4edSjmcp chown_file(shadow_dest, group, owner); 296*b83ec4edSjmcp } 2977c478bd9Sstevel@tonic-gate if (mode != -1) { 298*b83ec4edSjmcp (void) umask(0); 2997c478bd9Sstevel@tonic-gate if (chmod(dest_file, mode) == -1) { 300*b83ec4edSjmcp (void) fprintf(stderr, 301*b83ec4edSjmcp "install: chmod of %s to mode %o failed " 302*b83ec4edSjmcp "(%d): %s\n", 303*b83ec4edSjmcp dest_file, mode, errno, strerror(errno)); 3047c478bd9Sstevel@tonic-gate return (1); 3057c478bd9Sstevel@tonic-gate } 306*b83ec4edSjmcp if (tonic) { 307*b83ec4edSjmcp if (chmod(shadow_dest, mode) == -1) { 308*b83ec4edSjmcp (void) fprintf(stderr, 309*b83ec4edSjmcp "install: tonic chmod of %s " 310*b83ec4edSjmcp "to mode %o failed (%d): %s\n", 311*b83ec4edSjmcp shadow_dest, mode, 312*b83ec4edSjmcp errno, strerror(errno)); 313*b83ec4edSjmcp return (1); 314*b83ec4edSjmcp } 315*b83ec4edSjmcp } 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate return (0); 3197c478bd9Sstevel@tonic-gate } 320