1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*5c51f124SMoriah Waterland /* All Rights Reserved */ 29*5c51f124SMoriah Waterland 30*5c51f124SMoriah Waterland 31*5c51f124SMoriah Waterland /* 32*5c51f124SMoriah Waterland * System includes 33*5c51f124SMoriah Waterland */ 34*5c51f124SMoriah Waterland 35*5c51f124SMoriah Waterland #include <stdio.h> 36*5c51f124SMoriah Waterland #include <string.h> 37*5c51f124SMoriah Waterland #include <stdlib.h> 38*5c51f124SMoriah Waterland #include <unistd.h> 39*5c51f124SMoriah Waterland #include <utime.h> 40*5c51f124SMoriah Waterland #include <locale.h> 41*5c51f124SMoriah Waterland #include <libintl.h> 42*5c51f124SMoriah Waterland #include <pkglocs.h> 43*5c51f124SMoriah Waterland #include <errno.h> 44*5c51f124SMoriah Waterland #include <fcntl.h> 45*5c51f124SMoriah Waterland #include <sys/types.h> 46*5c51f124SMoriah Waterland #include <sys/stat.h> 47*5c51f124SMoriah Waterland 48*5c51f124SMoriah Waterland /* 49*5c51f124SMoriah Waterland * consolidation pkg command library includes 50*5c51f124SMoriah Waterland */ 51*5c51f124SMoriah Waterland 52*5c51f124SMoriah Waterland #include <pkglib.h> 53*5c51f124SMoriah Waterland 54*5c51f124SMoriah Waterland /* 55*5c51f124SMoriah Waterland * local pkg command library includes 56*5c51f124SMoriah Waterland */ 57*5c51f124SMoriah Waterland 58*5c51f124SMoriah Waterland #include "libadm.h" 59*5c51f124SMoriah Waterland #include "libinst.h" 60*5c51f124SMoriah Waterland #include "install.h" 61*5c51f124SMoriah Waterland #include "messages.h" 62*5c51f124SMoriah Waterland #include "pkginstall.h" 63*5c51f124SMoriah Waterland 64*5c51f124SMoriah Waterland /* 65*5c51f124SMoriah Waterland * forward declarations 66*5c51f124SMoriah Waterland */ 67*5c51f124SMoriah Waterland 68*5c51f124SMoriah Waterland static int write_file(char **r_linknam, int a_ctrl, mode_t a_mode, 69*5c51f124SMoriah Waterland char *a_file); 70*5c51f124SMoriah Waterland static int create_path(int a_ctrl, char *a_file); 71*5c51f124SMoriah Waterland 72*5c51f124SMoriah Waterland /* 73*5c51f124SMoriah Waterland * Name: cppath 74*5c51f124SMoriah Waterland * Description: copy a path object (install new file on system) 75*5c51f124SMoriah Waterland * Arguments: 76*5c51f124SMoriah Waterland * - a_cntrl - determine how the destination file mode is set: 77*5c51f124SMoriah Waterland * |= MODE_0666 - force mode to 0666 78*5c51f124SMoriah Waterland * |= MODE_SET - mode is a_mode (no mask SET?ID bits) 79*5c51f124SMoriah Waterland * |= MODE_SRC - mode from source file (mask SET?ID bits) 80*5c51f124SMoriah Waterland * |= DIR_DISPLAY - display "%s <implied directory>" if directory created 81*5c51f124SMoriah Waterland * - a_srcPath - path to source to copy 82*5c51f124SMoriah Waterland * - a_dstPath - path to copy source to 83*5c51f124SMoriah Waterland * - a_mode - mode to set a_dstpath to (mode controlled by a_ctrl) 84*5c51f124SMoriah Waterland * Returns: int 85*5c51f124SMoriah Waterland * == 0 - success 86*5c51f124SMoriah Waterland * != 0 - failure 87*5c51f124SMoriah Waterland */ 88*5c51f124SMoriah Waterland 89*5c51f124SMoriah Waterland int 90*5c51f124SMoriah Waterland cppath(int a_ctrl, char *a_srcPath, char *a_dstPath, mode_t a_mode) 91*5c51f124SMoriah Waterland { 92*5c51f124SMoriah Waterland char *linknam = (char *)NULL; 93*5c51f124SMoriah Waterland int dstFd; 94*5c51f124SMoriah Waterland int len; 95*5c51f124SMoriah Waterland int srcFd; 96*5c51f124SMoriah Waterland long status; 97*5c51f124SMoriah Waterland struct stat srcStatbuf; 98*5c51f124SMoriah Waterland struct utimbuf times; 99*5c51f124SMoriah Waterland 100*5c51f124SMoriah Waterland /* entry debugging info */ 101*5c51f124SMoriah Waterland 102*5c51f124SMoriah Waterland echoDebug(DBG_CPPATH_ENTRY, a_ctrl, a_mode, a_srcPath, a_dstPath); 103*5c51f124SMoriah Waterland 104*5c51f124SMoriah Waterland /* open source file for reading */ 105*5c51f124SMoriah Waterland 106*5c51f124SMoriah Waterland srcFd = open(a_srcPath, O_RDONLY); 107*5c51f124SMoriah Waterland if (srcFd < 0) { 108*5c51f124SMoriah Waterland progerr(ERR_OPEN_READ, a_srcPath, 109*5c51f124SMoriah Waterland errno, strerror(errno)); 110*5c51f124SMoriah Waterland return (1); 111*5c51f124SMoriah Waterland } 112*5c51f124SMoriah Waterland 113*5c51f124SMoriah Waterland /* obtain file status of source file */ 114*5c51f124SMoriah Waterland 115*5c51f124SMoriah Waterland if (fstat(srcFd, &srcStatbuf) != 0) { 116*5c51f124SMoriah Waterland progerr(ERR_FSTAT, srcFd, a_srcPath, errno, strerror(errno)); 117*5c51f124SMoriah Waterland (void) close(srcFd); 118*5c51f124SMoriah Waterland return (1); 119*5c51f124SMoriah Waterland } 120*5c51f124SMoriah Waterland 121*5c51f124SMoriah Waterland /* 122*5c51f124SMoriah Waterland * Determine the permissions mode for the destination: 123*5c51f124SMoriah Waterland * - if MODE_SET is specified: 124*5c51f124SMoriah Waterland * --> use a_mode (do not mask off any portion) 125*5c51f124SMoriah Waterland * --> If a_mode is unknown (? in the pkgmap), then the file gets 126*5c51f124SMoriah Waterland * --> installed with the default 0644 mode 127*5c51f124SMoriah Waterland * - if MODE_SRC is specified: 128*5c51f124SMoriah Waterland * --> use the mode of the source (srcStatbuf.st_mode) but mask off all 129*5c51f124SMoriah Waterland * --> non-access mode bits (remove SET?UID bits) 130*5c51f124SMoriah Waterland * - otherwise: 131*5c51f124SMoriah Waterland * --> use 0666 132*5c51f124SMoriah Waterland */ 133*5c51f124SMoriah Waterland 134*5c51f124SMoriah Waterland if (a_ctrl & MODE_SET) { 135*5c51f124SMoriah Waterland mode_t usemode; 136*5c51f124SMoriah Waterland 137*5c51f124SMoriah Waterland usemode = (a_mode ^ BADMODE) ? a_mode : 0644; 138*5c51f124SMoriah Waterland if (a_mode != usemode && usemode == 0644) { 139*5c51f124SMoriah Waterland logerr(WRN_DEF_MODE, a_dstPath); 140*5c51f124SMoriah Waterland a_mode = usemode; 141*5c51f124SMoriah Waterland } 142*5c51f124SMoriah Waterland } else if (a_ctrl & MODE_SRC) { 143*5c51f124SMoriah Waterland a_mode = (srcStatbuf.st_mode & S_IAMB); 144*5c51f124SMoriah Waterland } else { 145*5c51f124SMoriah Waterland a_mode = 0666; 146*5c51f124SMoriah Waterland } 147*5c51f124SMoriah Waterland 148*5c51f124SMoriah Waterland /* 149*5c51f124SMoriah Waterland * Get fd of newly created destination file or, if this 150*5c51f124SMoriah Waterland * is an overwrite, a temporary file (linknam). 151*5c51f124SMoriah Waterland */ 152*5c51f124SMoriah Waterland 153*5c51f124SMoriah Waterland dstFd = write_file(&linknam, a_ctrl, a_mode, a_dstPath); 154*5c51f124SMoriah Waterland if (dstFd < 0) { 155*5c51f124SMoriah Waterland (void) close(srcFd); 156*5c51f124SMoriah Waterland return (1); 157*5c51f124SMoriah Waterland } 158*5c51f124SMoriah Waterland 159*5c51f124SMoriah Waterland /* 160*5c51f124SMoriah Waterland * source and target files are open: copy data 161*5c51f124SMoriah Waterland */ 162*5c51f124SMoriah Waterland 163*5c51f124SMoriah Waterland status = copyFile(srcFd, dstFd, a_srcPath, a_dstPath, &srcStatbuf, 0); 164*5c51f124SMoriah Waterland 165*5c51f124SMoriah Waterland (void) close(srcFd); 166*5c51f124SMoriah Waterland (void) close(dstFd); 167*5c51f124SMoriah Waterland 168*5c51f124SMoriah Waterland if (status != 0) { 169*5c51f124SMoriah Waterland progerr(ERR_INPUT, a_srcPath, errno, strerror(errno)); 170*5c51f124SMoriah Waterland if (linknam) { 171*5c51f124SMoriah Waterland (void) remove(linknam); 172*5c51f124SMoriah Waterland } 173*5c51f124SMoriah Waterland return (1); 174*5c51f124SMoriah Waterland } 175*5c51f124SMoriah Waterland 176*5c51f124SMoriah Waterland /* 177*5c51f124SMoriah Waterland * If this is an overwrite, rename temp over original 178*5c51f124SMoriah Waterland */ 179*5c51f124SMoriah Waterland 180*5c51f124SMoriah Waterland if ((linknam != (char *)NULL) && (rename(linknam, a_dstPath) != 0)) { 181*5c51f124SMoriah Waterland FILE *logfp = (FILE *)NULL; 182*5c51f124SMoriah Waterland char busylog[PATH_MAX]; 183*5c51f124SMoriah Waterland 184*5c51f124SMoriah Waterland /* output log message if busy else program error */ 185*5c51f124SMoriah Waterland 186*5c51f124SMoriah Waterland if (errno == ETXTBSY) { 187*5c51f124SMoriah Waterland logerr(MSG_PROCMV, linknam); 188*5c51f124SMoriah Waterland } else { 189*5c51f124SMoriah Waterland progerr(ERR_OUTPUT_WRITING, a_dstPath, errno, 190*5c51f124SMoriah Waterland strerror(errno)); 191*5c51f124SMoriah Waterland } 192*5c51f124SMoriah Waterland 193*5c51f124SMoriah Waterland (void) remove(linknam); 194*5c51f124SMoriah Waterland 195*5c51f124SMoriah Waterland /* open the log file and append log entry */ 196*5c51f124SMoriah Waterland 197*5c51f124SMoriah Waterland len = snprintf(busylog, sizeof (busylog), 198*5c51f124SMoriah Waterland "%s/textbusy", get_PKGADM()); 199*5c51f124SMoriah Waterland if (len > sizeof (busylog)) { 200*5c51f124SMoriah Waterland progerr(ERR_CREATE_PATH_2, get_PKGADM(), 201*5c51f124SMoriah Waterland "textbusy"); 202*5c51f124SMoriah Waterland } else { 203*5c51f124SMoriah Waterland logfp = fopen(busylog, "a"); 204*5c51f124SMoriah Waterland if (logfp == NULL) { 205*5c51f124SMoriah Waterland progerr(ERR_LOG, busylog, errno, 206*5c51f124SMoriah Waterland strerror(errno)); 207*5c51f124SMoriah Waterland } else { 208*5c51f124SMoriah Waterland (void) fprintf(logfp, "%s\n", linknam); 209*5c51f124SMoriah Waterland (void) fclose(logfp); 210*5c51f124SMoriah Waterland } 211*5c51f124SMoriah Waterland } 212*5c51f124SMoriah Waterland } 213*5c51f124SMoriah Waterland 214*5c51f124SMoriah Waterland /* set access/modification times for target */ 215*5c51f124SMoriah Waterland 216*5c51f124SMoriah Waterland times.actime = srcStatbuf.st_atime; 217*5c51f124SMoriah Waterland times.modtime = srcStatbuf.st_mtime; 218*5c51f124SMoriah Waterland 219*5c51f124SMoriah Waterland if (utime(a_dstPath, ×) != 0) { 220*5c51f124SMoriah Waterland progerr(ERR_MODTIM, a_dstPath, errno, strerror(errno)); 221*5c51f124SMoriah Waterland return (1); 222*5c51f124SMoriah Waterland } 223*5c51f124SMoriah Waterland 224*5c51f124SMoriah Waterland /* success! */ 225*5c51f124SMoriah Waterland 226*5c51f124SMoriah Waterland return (0); 227*5c51f124SMoriah Waterland } 228*5c51f124SMoriah Waterland 229*5c51f124SMoriah Waterland /* 230*5c51f124SMoriah Waterland * This function creates all of the directory components of the specified path. 231*5c51f124SMoriah Waterland */ 232*5c51f124SMoriah Waterland static int 233*5c51f124SMoriah Waterland create_path(int a_ctrl, char *a_file) 234*5c51f124SMoriah Waterland { 235*5c51f124SMoriah Waterland char *pt; 236*5c51f124SMoriah Waterland int found = 0; 237*5c51f124SMoriah Waterland 238*5c51f124SMoriah Waterland for (pt = a_file; *pt; pt++) { 239*5c51f124SMoriah Waterland /* continue if not at path separator or at start of path */ 240*5c51f124SMoriah Waterland 241*5c51f124SMoriah Waterland if ((*pt != '/') || (pt == a_file)) { 242*5c51f124SMoriah Waterland continue; 243*5c51f124SMoriah Waterland } 244*5c51f124SMoriah Waterland 245*5c51f124SMoriah Waterland /* at '/' - terminate path at current entry */ 246*5c51f124SMoriah Waterland 247*5c51f124SMoriah Waterland *pt = '\0'; 248*5c51f124SMoriah Waterland 249*5c51f124SMoriah Waterland /* continue if path element exists */ 250*5c51f124SMoriah Waterland 251*5c51f124SMoriah Waterland if (access(a_file, F_OK) == 0) { 252*5c51f124SMoriah Waterland *pt = '/'; 253*5c51f124SMoriah Waterland continue; 254*5c51f124SMoriah Waterland } 255*5c51f124SMoriah Waterland 256*5c51f124SMoriah Waterland /* create directory in path */ 257*5c51f124SMoriah Waterland 258*5c51f124SMoriah Waterland if (mkdir(a_file, 0755)) { 259*5c51f124SMoriah Waterland progerr(ERR_MAKE_DIR, a_file, errno, strerror(errno)); 260*5c51f124SMoriah Waterland *pt = '/'; 261*5c51f124SMoriah Waterland return (1); 262*5c51f124SMoriah Waterland } 263*5c51f124SMoriah Waterland 264*5c51f124SMoriah Waterland /* display 'implied directory created' message */ 265*5c51f124SMoriah Waterland 266*5c51f124SMoriah Waterland if (a_ctrl & DIR_DISPLAY) { 267*5c51f124SMoriah Waterland echo(MSG_IMPDIR, a_file); 268*5c51f124SMoriah Waterland } 269*5c51f124SMoriah Waterland 270*5c51f124SMoriah Waterland found++; 271*5c51f124SMoriah Waterland 272*5c51f124SMoriah Waterland *pt = '/'; 273*5c51f124SMoriah Waterland } 274*5c51f124SMoriah Waterland 275*5c51f124SMoriah Waterland return (!found); 276*5c51f124SMoriah Waterland } 277*5c51f124SMoriah Waterland 278*5c51f124SMoriah Waterland /* 279*5c51f124SMoriah Waterland * Name: write_file 280*5c51f124SMoriah Waterland * Description: creates a new destination file if the file does not already 281*5c51f124SMoriah Waterland * exist; otherwise, creates a temporary file and places a 282*5c51f124SMoriah Waterland * pointer to the temporary file name in 'r_linknam'. 283*5c51f124SMoriah Waterland * Arguments: r_linknam - pointer to (char*) where name of temporary file 284*5c51f124SMoriah Waterland * created is returned 285*5c51f124SMoriah Waterland * a_ctrl - determine if the destination file name is displayed: 286*5c51f124SMoriah Waterland * |= DIR_DISPLAY - display "%s <implied directory>" 287*5c51f124SMoriah Waterland * if directory created 288*5c51f124SMoriah Waterland * a_mode - permissions mode to set a_file to 289*5c51f124SMoriah Waterland * a_file - name of destination file to open 290*5c51f124SMoriah Waterland * Returns: int 291*5c51f124SMoriah Waterland * success - file descriptor of the file it opened. 292*5c51f124SMoriah Waterland * failure - returns -1 293*5c51f124SMoriah Waterland */ 294*5c51f124SMoriah Waterland 295*5c51f124SMoriah Waterland static int 296*5c51f124SMoriah Waterland write_file(char **r_linknam, int a_ctrl, mode_t a_mode, char *a_file) 297*5c51f124SMoriah Waterland { 298*5c51f124SMoriah Waterland int len; 299*5c51f124SMoriah Waterland int fd = -1; 300*5c51f124SMoriah Waterland static char loc_link[PATH_MAX]; 301*5c51f124SMoriah Waterland 302*5c51f124SMoriah Waterland /* entry debugging */ 303*5c51f124SMoriah Waterland 304*5c51f124SMoriah Waterland echoDebug(DBG_WRITEFILE_ENTRY, a_ctrl, a_mode, a_file); 305*5c51f124SMoriah Waterland 306*5c51f124SMoriah Waterland /* reset pointer to returned 'temporary file name' */ 307*5c51f124SMoriah Waterland 308*5c51f124SMoriah Waterland *r_linknam = (char *)NULL; 309*5c51f124SMoriah Waterland 310*5c51f124SMoriah Waterland /* 311*5c51f124SMoriah Waterland * If we are overwriting an existing file, arrange to replace 312*5c51f124SMoriah Waterland * it transparently. 313*5c51f124SMoriah Waterland */ 314*5c51f124SMoriah Waterland 315*5c51f124SMoriah Waterland if (access(a_file, F_OK) == 0) { 316*5c51f124SMoriah Waterland /* 317*5c51f124SMoriah Waterland * link the file to be copied to a temporary name in case 318*5c51f124SMoriah Waterland * it is executing or it is being written/used (e.g., a shell 319*5c51f124SMoriah Waterland * script currently being executed 320*5c51f124SMoriah Waterland */ 321*5c51f124SMoriah Waterland 322*5c51f124SMoriah Waterland if (!RELATIVE(a_file)) { 323*5c51f124SMoriah Waterland len = snprintf(loc_link, sizeof (loc_link), 324*5c51f124SMoriah Waterland "%sXXXXXX", a_file); 325*5c51f124SMoriah Waterland if (len > sizeof (loc_link)) { 326*5c51f124SMoriah Waterland progerr(ERR_CREATE_PATH_2, a_file, "XXXXXX"); 327*5c51f124SMoriah Waterland } 328*5c51f124SMoriah Waterland } else { 329*5c51f124SMoriah Waterland logerr(WRN_RELATIVE, a_file); 330*5c51f124SMoriah Waterland len = snprintf(loc_link, sizeof (loc_link), 331*5c51f124SMoriah Waterland "./%sXXXXXX", a_file); 332*5c51f124SMoriah Waterland if (len > sizeof (loc_link)) { 333*5c51f124SMoriah Waterland progerr(ERR_CREATE_PATH_3, "./", a_file, 334*5c51f124SMoriah Waterland "XXXXXX"); 335*5c51f124SMoriah Waterland } 336*5c51f124SMoriah Waterland } 337*5c51f124SMoriah Waterland 338*5c51f124SMoriah Waterland /* create and open temporary file */ 339*5c51f124SMoriah Waterland 340*5c51f124SMoriah Waterland fd = mkstemp(loc_link); 341*5c51f124SMoriah Waterland if (fd == -1) { 342*5c51f124SMoriah Waterland progerr(ERR_MKTEMP, loc_link, errno, strerror(errno)); 343*5c51f124SMoriah Waterland return (-1); 344*5c51f124SMoriah Waterland } 345*5c51f124SMoriah Waterland 346*5c51f124SMoriah Waterland /* remember name of temporary file */ 347*5c51f124SMoriah Waterland 348*5c51f124SMoriah Waterland *r_linknam = loc_link; 349*5c51f124SMoriah Waterland 350*5c51f124SMoriah Waterland /* make sure temporary file has correct mode */ 351*5c51f124SMoriah Waterland 352*5c51f124SMoriah Waterland if (fchmod(fd, a_mode) < 0) { 353*5c51f124SMoriah Waterland progerr(ERR_FCHMOD, loc_link, a_mode, errno, 354*5c51f124SMoriah Waterland strerror(errno)); 355*5c51f124SMoriah Waterland } 356*5c51f124SMoriah Waterland 357*5c51f124SMoriah Waterland return (fd); 358*5c51f124SMoriah Waterland } 359*5c51f124SMoriah Waterland 360*5c51f124SMoriah Waterland /* 361*5c51f124SMoriah Waterland * We are not overwriting an existing file, create a new one directly. 362*5c51f124SMoriah Waterland */ 363*5c51f124SMoriah Waterland 364*5c51f124SMoriah Waterland fd = open(a_file, O_WRONLY | O_CREAT | O_TRUNC, a_mode); 365*5c51f124SMoriah Waterland if (fd == -1) { 366*5c51f124SMoriah Waterland if (create_path(a_ctrl, a_file) == 0) { 367*5c51f124SMoriah Waterland fd = open(a_file, O_WRONLY | O_CREAT | O_TRUNC, a_mode); 368*5c51f124SMoriah Waterland } 369*5c51f124SMoriah Waterland } 370*5c51f124SMoriah Waterland 371*5c51f124SMoriah Waterland if (fd == -1) { 372*5c51f124SMoriah Waterland progerr(ERR_OPEN_WRITE, a_file, errno, strerror(errno)); 373*5c51f124SMoriah Waterland } 374*5c51f124SMoriah Waterland 375*5c51f124SMoriah Waterland return (fd); 376*5c51f124SMoriah Waterland } 377