19781SMoriah.Waterland@Sun.COM /* 29781SMoriah.Waterland@Sun.COM * CDDL HEADER START 39781SMoriah.Waterland@Sun.COM * 49781SMoriah.Waterland@Sun.COM * The contents of this file are subject to the terms of the 59781SMoriah.Waterland@Sun.COM * Common Development and Distribution License (the "License"). 69781SMoriah.Waterland@Sun.COM * You may not use this file except in compliance with the License. 79781SMoriah.Waterland@Sun.COM * 89781SMoriah.Waterland@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99781SMoriah.Waterland@Sun.COM * or http://www.opensolaris.org/os/licensing. 109781SMoriah.Waterland@Sun.COM * See the License for the specific language governing permissions 119781SMoriah.Waterland@Sun.COM * and limitations under the License. 129781SMoriah.Waterland@Sun.COM * 139781SMoriah.Waterland@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 149781SMoriah.Waterland@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159781SMoriah.Waterland@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 169781SMoriah.Waterland@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 179781SMoriah.Waterland@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 189781SMoriah.Waterland@Sun.COM * 199781SMoriah.Waterland@Sun.COM * CDDL HEADER END 209781SMoriah.Waterland@Sun.COM */ 219781SMoriah.Waterland@Sun.COM 229781SMoriah.Waterland@Sun.COM /* 239781SMoriah.Waterland@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 249781SMoriah.Waterland@Sun.COM * Use is subject to license terms. 259781SMoriah.Waterland@Sun.COM */ 269781SMoriah.Waterland@Sun.COM 279781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 289781SMoriah.Waterland@Sun.COM /* All Rights Reserved */ 299781SMoriah.Waterland@Sun.COM 309781SMoriah.Waterland@Sun.COM 319781SMoriah.Waterland@Sun.COM 329781SMoriah.Waterland@Sun.COM #include <stdio.h> 339781SMoriah.Waterland@Sun.COM #include <limits.h> 349781SMoriah.Waterland@Sun.COM #include <stdlib.h> 359781SMoriah.Waterland@Sun.COM #include <unistd.h> 369781SMoriah.Waterland@Sun.COM #include <utime.h> 379781SMoriah.Waterland@Sun.COM #include <sys/types.h> 389781SMoriah.Waterland@Sun.COM #include <sys/param.h> 399781SMoriah.Waterland@Sun.COM #include <sys/stat.h> 409781SMoriah.Waterland@Sun.COM #include <sys/statvfs.h> 419781SMoriah.Waterland@Sun.COM #include <grp.h> 429781SMoriah.Waterland@Sun.COM #include <pwd.h> 439781SMoriah.Waterland@Sun.COM #include <errno.h> 449781SMoriah.Waterland@Sun.COM #include <string.h> 459781SMoriah.Waterland@Sun.COM #include <stdarg.h> 469781SMoriah.Waterland@Sun.COM #include <fcntl.h> 479781SMoriah.Waterland@Sun.COM #include <sys/mkdev.h> 489781SMoriah.Waterland@Sun.COM #include "pkgstrct.h" 499781SMoriah.Waterland@Sun.COM #include "pkglib.h" 509781SMoriah.Waterland@Sun.COM #include "pkglibmsgs.h" 519781SMoriah.Waterland@Sun.COM #include "pkglocale.h" 529781SMoriah.Waterland@Sun.COM 539781SMoriah.Waterland@Sun.COM #define WDMSK 0xFFFF 549781SMoriah.Waterland@Sun.COM #define DATEFMT "%D %r" 559781SMoriah.Waterland@Sun.COM #define LONG_BOUNDARY ((sizeof (unsigned long))-1) 569781SMoriah.Waterland@Sun.COM #define CHUNK 1024*1024 579781SMoriah.Waterland@Sun.COM 589781SMoriah.Waterland@Sun.COM static char theErrBuf[PATH_MAX+512] = {'\0'}; 599781SMoriah.Waterland@Sun.COM static char *theErrStr = NULL; 609781SMoriah.Waterland@Sun.COM 619781SMoriah.Waterland@Sun.COM /* checksum disable switch */ 629781SMoriah.Waterland@Sun.COM static int enable_checksum = 1; 639781SMoriah.Waterland@Sun.COM 649781SMoriah.Waterland@Sun.COM /* attribute disable flag */ 659781SMoriah.Waterland@Sun.COM static int disable_attributes = 0; 669781SMoriah.Waterland@Sun.COM 679781SMoriah.Waterland@Sun.COM /* non-ABI symlinks supported */ 689781SMoriah.Waterland@Sun.COM static int nonabi_symlinks; 699781SMoriah.Waterland@Sun.COM 709781SMoriah.Waterland@Sun.COM /* 719781SMoriah.Waterland@Sun.COM * forward declarations 729781SMoriah.Waterland@Sun.COM */ 739781SMoriah.Waterland@Sun.COM 749781SMoriah.Waterland@Sun.COM static int clear_target(char *path, char *ftype, int is_a_dir); 759781SMoriah.Waterland@Sun.COM 769781SMoriah.Waterland@Sun.COM unsigned long compute_checksum(int *r_err, char *path); 779781SMoriah.Waterland@Sun.COM 789781SMoriah.Waterland@Sun.COM /* union used to generate checksum */ 799781SMoriah.Waterland@Sun.COM typedef union hilo { 809781SMoriah.Waterland@Sun.COM struct part { 819781SMoriah.Waterland@Sun.COM uint16_t hi; 829781SMoriah.Waterland@Sun.COM uint16_t lo; 839781SMoriah.Waterland@Sun.COM } hl; 849781SMoriah.Waterland@Sun.COM uint32_t lg; 859781SMoriah.Waterland@Sun.COM } CHECKSUM_T; 869781SMoriah.Waterland@Sun.COM 879781SMoriah.Waterland@Sun.COM /*PRINTFLIKE1*/ 88*10176Sok199659 static void 899781SMoriah.Waterland@Sun.COM reperr(char *fmt, ...) 909781SMoriah.Waterland@Sun.COM { 919781SMoriah.Waterland@Sun.COM char *pt; 929781SMoriah.Waterland@Sun.COM ssize_t ptln; 939781SMoriah.Waterland@Sun.COM va_list ap; 949781SMoriah.Waterland@Sun.COM int n; 959781SMoriah.Waterland@Sun.COM 969781SMoriah.Waterland@Sun.COM if (fmt == (char *)NULL) { 979781SMoriah.Waterland@Sun.COM theErrBuf[0] = '\0'; 989781SMoriah.Waterland@Sun.COM } else { 999781SMoriah.Waterland@Sun.COM if (n = strlen(theErrBuf)) { 1009781SMoriah.Waterland@Sun.COM pt = theErrBuf + n; 1019781SMoriah.Waterland@Sun.COM *pt++ = '\n'; 1029781SMoriah.Waterland@Sun.COM *pt = '\0'; 1039781SMoriah.Waterland@Sun.COM ptln = sizeof (theErrBuf)-n; 1049781SMoriah.Waterland@Sun.COM } else { 1059781SMoriah.Waterland@Sun.COM pt = theErrBuf; 1069781SMoriah.Waterland@Sun.COM ptln = sizeof (theErrBuf); 1079781SMoriah.Waterland@Sun.COM } 1089781SMoriah.Waterland@Sun.COM va_start(ap, fmt); 1099781SMoriah.Waterland@Sun.COM /* LINTED variable format specifier to vsnprintf() */ 1109781SMoriah.Waterland@Sun.COM (void) vsnprintf(pt, ptln, fmt, ap); 1119781SMoriah.Waterland@Sun.COM va_end(ap); 1129781SMoriah.Waterland@Sun.COM } 1139781SMoriah.Waterland@Sun.COM } 1149781SMoriah.Waterland@Sun.COM 1159781SMoriah.Waterland@Sun.COM /* 1169781SMoriah.Waterland@Sun.COM * Name: cverify 1179781SMoriah.Waterland@Sun.COM * Description: This function verifies and (if fix > 0) fixes the contents 1189781SMoriah.Waterland@Sun.COM * of the file at the path provided 1199781SMoriah.Waterland@Sun.COM * Arguments: fix - 0 - do not fix entries, 1 - fix entries 1209781SMoriah.Waterland@Sun.COM * ftype - single character "type" the entry is supposed to be 1219781SMoriah.Waterland@Sun.COM * path - path to file 1229781SMoriah.Waterland@Sun.COM * cinfo - content info structure representing the contents 1239781SMoriah.Waterland@Sun.COM * the entry is supposed to contain 1249781SMoriah.Waterland@Sun.COM * allow_checksum - determine if checksumming should be disabled: 1259781SMoriah.Waterland@Sun.COM * == 0 - do not perform checksum ever - override enable_checksum. 1269781SMoriah.Waterland@Sun.COM * != 0 - use the default checksum flag "enable_checksum" to 1279781SMoriah.Waterland@Sun.COM * determine if checksumming should be done. 1289781SMoriah.Waterland@Sun.COM * NOTE: modification and creation times can be repaired; the contents 1299781SMoriah.Waterland@Sun.COM * of the file cannot be corrected if the checksum indicates that 1309781SMoriah.Waterland@Sun.COM * the contents are not correct - VE_CONT will be returned in this 1319781SMoriah.Waterland@Sun.COM * case. 1329781SMoriah.Waterland@Sun.COM * Possible return values: 1339781SMoriah.Waterland@Sun.COM * - 0 = successful 1349781SMoriah.Waterland@Sun.COM * - VE_EXIST = path name does not exist 1359781SMoriah.Waterland@Sun.COM * - VE_FTYPE = path file type is not recognized, is not supported, 1369781SMoriah.Waterland@Sun.COM * or is not what was expected 1379781SMoriah.Waterland@Sun.COM * - VE_ATTR = path mode/group/user is not what was expected 1389781SMoriah.Waterland@Sun.COM * - VE_CONT = mod time/link target/major/minor/size/file system type/current 1399781SMoriah.Waterland@Sun.COM * directory is not what was expected 1409781SMoriah.Waterland@Sun.COM * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/ 1419781SMoriah.Waterland@Sun.COM * chown failed 1429781SMoriah.Waterland@Sun.COM */ 1439781SMoriah.Waterland@Sun.COM 1449781SMoriah.Waterland@Sun.COM int 1459781SMoriah.Waterland@Sun.COM cverify(int fix, char *ftype, char *path, struct cinfo *cinfo, 1469781SMoriah.Waterland@Sun.COM int allow_checksum) 1479781SMoriah.Waterland@Sun.COM { 1489781SMoriah.Waterland@Sun.COM struct stat status; /* file status buffer */ 1499781SMoriah.Waterland@Sun.COM struct utimbuf times; 1509781SMoriah.Waterland@Sun.COM unsigned long mycksum; 1519781SMoriah.Waterland@Sun.COM int setval, retcode; 1529781SMoriah.Waterland@Sun.COM char tbuf1[512]; 1539781SMoriah.Waterland@Sun.COM char tbuf2[512]; 1549781SMoriah.Waterland@Sun.COM int cksumerr; 1559781SMoriah.Waterland@Sun.COM 1569781SMoriah.Waterland@Sun.COM setval = (*ftype == '?'); 1579781SMoriah.Waterland@Sun.COM retcode = 0; 1589781SMoriah.Waterland@Sun.COM reperr(NULL); 1599781SMoriah.Waterland@Sun.COM 1609781SMoriah.Waterland@Sun.COM if (stat(path, &status) < 0) { 1619781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_EXIST)); 1629781SMoriah.Waterland@Sun.COM return (VE_EXIST); 1639781SMoriah.Waterland@Sun.COM } 1649781SMoriah.Waterland@Sun.COM 1659781SMoriah.Waterland@Sun.COM /* -1 requires modtimes to be the same */ 1669781SMoriah.Waterland@Sun.COM /* 0 reports modtime failure */ 1679781SMoriah.Waterland@Sun.COM /* 1 fixes modtimes */ 1689781SMoriah.Waterland@Sun.COM 1699781SMoriah.Waterland@Sun.COM if (setval || (cinfo->modtime == BADCONT)) { 1709781SMoriah.Waterland@Sun.COM cinfo->modtime = status.st_mtime; 1719781SMoriah.Waterland@Sun.COM } else if (status.st_mtime != cinfo->modtime) { 1729781SMoriah.Waterland@Sun.COM if (fix > 0) { 1739781SMoriah.Waterland@Sun.COM /* reset times on the file */ 1749781SMoriah.Waterland@Sun.COM times.actime = cinfo->modtime; 1759781SMoriah.Waterland@Sun.COM times.modtime = cinfo->modtime; 1769781SMoriah.Waterland@Sun.COM if (utime(path, ×)) { 1779781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_MODFAIL)); 1789781SMoriah.Waterland@Sun.COM retcode = VE_FAIL; 1799781SMoriah.Waterland@Sun.COM } 1809781SMoriah.Waterland@Sun.COM } else if (fix < 0) { 1819781SMoriah.Waterland@Sun.COM /* modtimes must be the same */ 1829781SMoriah.Waterland@Sun.COM if (strftime(tbuf1, sizeof (tbuf1), DATEFMT, 1839781SMoriah.Waterland@Sun.COM localtime(&cinfo->modtime)) == 0) { 1849781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_MEM)); 1859781SMoriah.Waterland@Sun.COM } 1869781SMoriah.Waterland@Sun.COM if (strftime(tbuf2, sizeof (tbuf2), DATEFMT, 1879781SMoriah.Waterland@Sun.COM localtime(&status.st_mtime)) == 0) { 1889781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_MEM)); 1899781SMoriah.Waterland@Sun.COM } 1909781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_MTIME), tbuf1, tbuf2); 1919781SMoriah.Waterland@Sun.COM retcode = VE_CONT; 1929781SMoriah.Waterland@Sun.COM } 1939781SMoriah.Waterland@Sun.COM } 1949781SMoriah.Waterland@Sun.COM 1959781SMoriah.Waterland@Sun.COM if (setval || (cinfo->size == (fsblkcnt_t)BADCONT)) { 1969781SMoriah.Waterland@Sun.COM cinfo->size = status.st_size; 1979781SMoriah.Waterland@Sun.COM } else if (status.st_size != cinfo->size) { 1989781SMoriah.Waterland@Sun.COM if (!retcode) { 1999781SMoriah.Waterland@Sun.COM retcode = VE_CONT; 2009781SMoriah.Waterland@Sun.COM } 2019781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_SIZE), cinfo->size, status.st_size); 2029781SMoriah.Waterland@Sun.COM } 2039781SMoriah.Waterland@Sun.COM 2049781SMoriah.Waterland@Sun.COM cksumerr = 0; 2059781SMoriah.Waterland@Sun.COM 2069781SMoriah.Waterland@Sun.COM /* 2079781SMoriah.Waterland@Sun.COM * see if checksumming should be done: if checksumming is allowed, 2089781SMoriah.Waterland@Sun.COM * and checksumming is enabled, then checksum the file. 2099781SMoriah.Waterland@Sun.COM */ 2109781SMoriah.Waterland@Sun.COM 2119781SMoriah.Waterland@Sun.COM /* return if no need to compute checksum */ 2129781SMoriah.Waterland@Sun.COM 2139781SMoriah.Waterland@Sun.COM if ((allow_checksum == 0) || (enable_checksum == 0)) { 2149781SMoriah.Waterland@Sun.COM return (retcode); 2159781SMoriah.Waterland@Sun.COM } 2169781SMoriah.Waterland@Sun.COM 2179781SMoriah.Waterland@Sun.COM /* compute checksum */ 2189781SMoriah.Waterland@Sun.COM 2199781SMoriah.Waterland@Sun.COM mycksum = compute_checksum(&cksumerr, path); 2209781SMoriah.Waterland@Sun.COM 2219781SMoriah.Waterland@Sun.COM /* set value if not set or if checksum cannot be computed */ 2229781SMoriah.Waterland@Sun.COM 2239781SMoriah.Waterland@Sun.COM if (setval || (cinfo->cksum == BADCONT)) { 2249781SMoriah.Waterland@Sun.COM cinfo->cksum = mycksum; 2259781SMoriah.Waterland@Sun.COM return (retcode); 2269781SMoriah.Waterland@Sun.COM } 2279781SMoriah.Waterland@Sun.COM 2289781SMoriah.Waterland@Sun.COM /* report / return error if checksums mismatch or there is an error */ 2299781SMoriah.Waterland@Sun.COM 2309781SMoriah.Waterland@Sun.COM if ((mycksum != cinfo->cksum) || cksumerr) { 2319781SMoriah.Waterland@Sun.COM if (!retcode) { 2329781SMoriah.Waterland@Sun.COM retcode = VE_CONT; 2339781SMoriah.Waterland@Sun.COM } 2349781SMoriah.Waterland@Sun.COM if (!cksumerr) { 2359781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_CKSUM), cinfo->cksum, mycksum); 2369781SMoriah.Waterland@Sun.COM } 2379781SMoriah.Waterland@Sun.COM } 2389781SMoriah.Waterland@Sun.COM 2399781SMoriah.Waterland@Sun.COM return (retcode); 2409781SMoriah.Waterland@Sun.COM } 2419781SMoriah.Waterland@Sun.COM 2429781SMoriah.Waterland@Sun.COM /* 2439781SMoriah.Waterland@Sun.COM * Name: compute_checksum 2449781SMoriah.Waterland@Sun.COM * Description: generate checksum for specified file 2459781SMoriah.Waterland@Sun.COM * Arguments: r_cksumerr (int *) [RO, *RW] 2469781SMoriah.Waterland@Sun.COM * - pointer to integer that is set on return to: 2479781SMoriah.Waterland@Sun.COM * == 0 - no error occurred 2489781SMoriah.Waterland@Sun.COM * != 0 - error occurred 2499781SMoriah.Waterland@Sun.COM * a_path (char *) [RO, *RO] 2509781SMoriah.Waterland@Sun.COM * - pointer to string representing path to file to 2519781SMoriah.Waterland@Sun.COM * generate checksum of 2529781SMoriah.Waterland@Sun.COM * Returns: unsigned long - results: 2539781SMoriah.Waterland@Sun.COM * - If *r_cksumerr == 0, checksum of specified file 2549781SMoriah.Waterland@Sun.COM * - If *r_cksumerr != 0, undefined 2559781SMoriah.Waterland@Sun.COM */ 2569781SMoriah.Waterland@Sun.COM unsigned long 2579781SMoriah.Waterland@Sun.COM compute_checksum(int *r_cksumerr, char *a_path) 2589781SMoriah.Waterland@Sun.COM { 2599781SMoriah.Waterland@Sun.COM CHECKSUM_T suma; /* to split four-bytes into 2 two-byte values */ 2609781SMoriah.Waterland@Sun.COM CHECKSUM_T tempa; 2619781SMoriah.Waterland@Sun.COM int fd; 2629781SMoriah.Waterland@Sun.COM uint32_t lg; /* running checksum value */ 2639781SMoriah.Waterland@Sun.COM uint32_t buf[CHUNK/4]; /* to read CHUNK bytes */ 2649781SMoriah.Waterland@Sun.COM uint32_t lsavhi; /* high order two-bytes of four-byte checksum */ 2659781SMoriah.Waterland@Sun.COM uint32_t lsavlo; /* low order two-bytes of four-byte checksum */ 2669781SMoriah.Waterland@Sun.COM int leap = sizeof (uint32_t); 2679781SMoriah.Waterland@Sun.COM int notyet = 0; 2689781SMoriah.Waterland@Sun.COM int nread; 2699781SMoriah.Waterland@Sun.COM struct stat64 sbuf; 2709781SMoriah.Waterland@Sun.COM 2719781SMoriah.Waterland@Sun.COM /* reset error flag */ 2729781SMoriah.Waterland@Sun.COM *r_cksumerr = 0; 2739781SMoriah.Waterland@Sun.COM 2749781SMoriah.Waterland@Sun.COM /* open file and obtain -> where file is mapped/read */ 2759781SMoriah.Waterland@Sun.COM if ((fd = open(a_path, O_RDONLY)) < 0) { 2769781SMoriah.Waterland@Sun.COM *r_cksumerr = 1; 2779781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_NO_CKSUM)); 2789781SMoriah.Waterland@Sun.COM perror(ERR_NO_CKSUM); 2799781SMoriah.Waterland@Sun.COM return (0); 2809781SMoriah.Waterland@Sun.COM } 2819781SMoriah.Waterland@Sun.COM 2829781SMoriah.Waterland@Sun.COM if (fstat64(fd, &sbuf) != 0) { 2839781SMoriah.Waterland@Sun.COM *r_cksumerr = 1; 2849781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_NO_CKSUM)); 2859781SMoriah.Waterland@Sun.COM perror(ERR_NO_CKSUM); 2869781SMoriah.Waterland@Sun.COM return (0); 2879781SMoriah.Waterland@Sun.COM } 2889781SMoriah.Waterland@Sun.COM 2899781SMoriah.Waterland@Sun.COM /* initialize checksum value */ 2909781SMoriah.Waterland@Sun.COM lg = 0; 2919781SMoriah.Waterland@Sun.COM 2929781SMoriah.Waterland@Sun.COM /* 2939781SMoriah.Waterland@Sun.COM * Read CHUNK bytes off the file at a time; Read size of long bytes 2949781SMoriah.Waterland@Sun.COM * from memory at a time and process them. 2959781SMoriah.Waterland@Sun.COM * If last read, then read remnant bytes and process individually. 2969781SMoriah.Waterland@Sun.COM */ 2979781SMoriah.Waterland@Sun.COM errno = 0; 2989781SMoriah.Waterland@Sun.COM while ((nread = read(fd, (void*)buf, 2999781SMoriah.Waterland@Sun.COM (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) { 3009781SMoriah.Waterland@Sun.COM uchar_t *s; 3019781SMoriah.Waterland@Sun.COM uint32_t *p = buf; 3029781SMoriah.Waterland@Sun.COM 3039781SMoriah.Waterland@Sun.COM notyet = nread % leap; 3049781SMoriah.Waterland@Sun.COM nread -= notyet; 3059781SMoriah.Waterland@Sun.COM 3069781SMoriah.Waterland@Sun.COM for (; nread > 0; nread -= leap) { 3079781SMoriah.Waterland@Sun.COM lg += ((((*p)>>24)&0xFF) & WDMSK); 3089781SMoriah.Waterland@Sun.COM lg += ((((*p)>>16)&0xFF) & WDMSK); 3099781SMoriah.Waterland@Sun.COM lg += ((((*p)>>8)&0xFF) & WDMSK); 3109781SMoriah.Waterland@Sun.COM lg += (((*p)&0xFF) & WDMSK); 3119781SMoriah.Waterland@Sun.COM p++; 3129781SMoriah.Waterland@Sun.COM } 3139781SMoriah.Waterland@Sun.COM s = (uchar_t *)p; 3149781SMoriah.Waterland@Sun.COM /* leftover bytes less than four in number */ 3159781SMoriah.Waterland@Sun.COM while (notyet--) 3169781SMoriah.Waterland@Sun.COM lg += (((uint32_t)(*s++)) & WDMSK); 3179781SMoriah.Waterland@Sun.COM } 3189781SMoriah.Waterland@Sun.COM 3199781SMoriah.Waterland@Sun.COM /* wind up */ 3209781SMoriah.Waterland@Sun.COM (void) close(fd); 3219781SMoriah.Waterland@Sun.COM 3229781SMoriah.Waterland@Sun.COM /* compute checksum components */ 3239781SMoriah.Waterland@Sun.COM suma.lg = lg; 3249781SMoriah.Waterland@Sun.COM tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK); 3259781SMoriah.Waterland@Sun.COM lsavhi = (uint32_t)tempa.hl.hi; 3269781SMoriah.Waterland@Sun.COM lsavlo = (uint32_t)tempa.hl.lo; 3279781SMoriah.Waterland@Sun.COM 3289781SMoriah.Waterland@Sun.COM /* return final checksum value */ 3299781SMoriah.Waterland@Sun.COM return (lsavhi+lsavlo); 3309781SMoriah.Waterland@Sun.COM } 3319781SMoriah.Waterland@Sun.COM 3329781SMoriah.Waterland@Sun.COM static struct stat status; /* file status buffer */ 3339781SMoriah.Waterland@Sun.COM static struct statvfs vfsstatus; /* filesystem status buffer */ 3349781SMoriah.Waterland@Sun.COM 3359781SMoriah.Waterland@Sun.COM /* 3369781SMoriah.Waterland@Sun.COM * Remove the thing that's currently in place so we can put down the package 3379781SMoriah.Waterland@Sun.COM * object. If we're replacing a directory with a directory, leave it alone. 3389781SMoriah.Waterland@Sun.COM * Returns 1 if all OK and 0 if failed. 3399781SMoriah.Waterland@Sun.COM */ 3409781SMoriah.Waterland@Sun.COM static int 3419781SMoriah.Waterland@Sun.COM clear_target(char *path, char *ftype, int is_a_dir) 3429781SMoriah.Waterland@Sun.COM { 3439781SMoriah.Waterland@Sun.COM int retcode = 1; 3449781SMoriah.Waterland@Sun.COM 3459781SMoriah.Waterland@Sun.COM if (is_a_dir) { /* if there's a directory there already ... */ 3469781SMoriah.Waterland@Sun.COM /* ... and this isn't, ... */ 3479781SMoriah.Waterland@Sun.COM if ((*ftype != 'd') && (*ftype != 'x')) { 3489781SMoriah.Waterland@Sun.COM if (rmdir(path)) { /* try to remove it. */ 3499781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_RMDIR), path); 3509781SMoriah.Waterland@Sun.COM retcode = 0; 3519781SMoriah.Waterland@Sun.COM } 3529781SMoriah.Waterland@Sun.COM } 3539781SMoriah.Waterland@Sun.COM } else { 3549781SMoriah.Waterland@Sun.COM if (remove(path)) { 3559781SMoriah.Waterland@Sun.COM if (errno != ENOENT) { 3569781SMoriah.Waterland@Sun.COM retcode = 0; /* It didn't work. */ 3579781SMoriah.Waterland@Sun.COM } 3589781SMoriah.Waterland@Sun.COM } 3599781SMoriah.Waterland@Sun.COM } 3609781SMoriah.Waterland@Sun.COM 3619781SMoriah.Waterland@Sun.COM return (retcode); 3629781SMoriah.Waterland@Sun.COM } 3639781SMoriah.Waterland@Sun.COM 3649781SMoriah.Waterland@Sun.COM /* 3659781SMoriah.Waterland@Sun.COM * Name: averify 3669781SMoriah.Waterland@Sun.COM * Description: This function verifies and (if fix > 0) fixes the attributes 3679781SMoriah.Waterland@Sun.COM * of the file at the path provided. 3689781SMoriah.Waterland@Sun.COM * Arguments: fix - 0 - do not fix entries, 1 - fix entries 3699781SMoriah.Waterland@Sun.COM * ftype - single character "type" the entry is supposed to be 3709781SMoriah.Waterland@Sun.COM * path - path to file 3719781SMoriah.Waterland@Sun.COM * ainfo - attribute info structure representing the attributes 3729781SMoriah.Waterland@Sun.COM * the entry is supposed to be 3739781SMoriah.Waterland@Sun.COM * NOTE: attributes are links and permissions 3749781SMoriah.Waterland@Sun.COM * Possible return values: 3759781SMoriah.Waterland@Sun.COM * - 0 = successful 3769781SMoriah.Waterland@Sun.COM * - VE_EXIST = path name does not exist 3779781SMoriah.Waterland@Sun.COM * - VE_FTYPE = path file type is not recognized, is not supported, 3789781SMoriah.Waterland@Sun.COM * or is not what was expected 3799781SMoriah.Waterland@Sun.COM * - VE_ATTR = path mode/group/user is not what was expected 3809781SMoriah.Waterland@Sun.COM * - VE_CONT = mod time/link target/major/minor/size/file system type/current 3819781SMoriah.Waterland@Sun.COM * directory is not what was expected 3829781SMoriah.Waterland@Sun.COM * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/ 3839781SMoriah.Waterland@Sun.COM * chown failed 3849781SMoriah.Waterland@Sun.COM */ 3859781SMoriah.Waterland@Sun.COM int 3869781SMoriah.Waterland@Sun.COM averify(int fix, char *ftype, char *path, struct ainfo *ainfo) 3879781SMoriah.Waterland@Sun.COM { 3889781SMoriah.Waterland@Sun.COM struct group *grp; /* group entry buffer */ 3899781SMoriah.Waterland@Sun.COM struct passwd *pwd; 3909781SMoriah.Waterland@Sun.COM int n; 3919781SMoriah.Waterland@Sun.COM int setval; 3929781SMoriah.Waterland@Sun.COM int uid, gid; 3939781SMoriah.Waterland@Sun.COM int dochown; 3949781SMoriah.Waterland@Sun.COM int retcode; 395*10176Sok199659 int statError = 0; 3969781SMoriah.Waterland@Sun.COM int targ_is_dir = 0; /* replacing a directory */ 3979781SMoriah.Waterland@Sun.COM char myftype; 3989781SMoriah.Waterland@Sun.COM char buf[PATH_MAX]; 3999781SMoriah.Waterland@Sun.COM ino_t my_ino; 4009781SMoriah.Waterland@Sun.COM dev_t my_dev; 4019781SMoriah.Waterland@Sun.COM char cwd[MAXPATHLEN]; 4029781SMoriah.Waterland@Sun.COM char *cd; 4039781SMoriah.Waterland@Sun.COM char *c; 4049781SMoriah.Waterland@Sun.COM 4059781SMoriah.Waterland@Sun.COM setval = (*ftype == '?'); 4069781SMoriah.Waterland@Sun.COM retcode = 0; 4079781SMoriah.Waterland@Sun.COM reperr(NULL); 4089781SMoriah.Waterland@Sun.COM 4099781SMoriah.Waterland@Sun.COM if (get_disable_attribute_check()) { 4109781SMoriah.Waterland@Sun.COM return (0); 4119781SMoriah.Waterland@Sun.COM } 4129781SMoriah.Waterland@Sun.COM 4139781SMoriah.Waterland@Sun.COM if (*ftype == 'l') { 4149781SMoriah.Waterland@Sun.COM if (stat(path, &status) < 0) { 4159781SMoriah.Waterland@Sun.COM retcode = VE_EXIST; 4169781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_EXIST)); 4179781SMoriah.Waterland@Sun.COM } 4189781SMoriah.Waterland@Sun.COM 4199781SMoriah.Waterland@Sun.COM my_ino = status.st_ino; 4209781SMoriah.Waterland@Sun.COM my_dev = status.st_dev; 4219781SMoriah.Waterland@Sun.COM 4229781SMoriah.Waterland@Sun.COM /* Get copy of the current working directory */ 4239781SMoriah.Waterland@Sun.COM if (getcwd(cwd, MAXPATHLEN) == NULL) { 4249781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_GETWD), ainfo->local); 4259781SMoriah.Waterland@Sun.COM return (VE_FAIL); 4269781SMoriah.Waterland@Sun.COM } 4279781SMoriah.Waterland@Sun.COM 4289781SMoriah.Waterland@Sun.COM /* 4299781SMoriah.Waterland@Sun.COM * Change to the directory in which the hard 4309781SMoriah.Waterland@Sun.COM * link is to be created. 4319781SMoriah.Waterland@Sun.COM */ 4329781SMoriah.Waterland@Sun.COM cd = strdup(path); 4339781SMoriah.Waterland@Sun.COM c = strrchr(cd, '/'); 4349781SMoriah.Waterland@Sun.COM if (c) { 4359781SMoriah.Waterland@Sun.COM /* bugid 4247895 */ 4369781SMoriah.Waterland@Sun.COM if (strcmp(cd, c) == 0) 4379781SMoriah.Waterland@Sun.COM strcpy(cd, "/"); 4389781SMoriah.Waterland@Sun.COM else 4399781SMoriah.Waterland@Sun.COM *c = NULL; 4409781SMoriah.Waterland@Sun.COM 4419781SMoriah.Waterland@Sun.COM if (chdir(cd) != 0) { 4429781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_CHDIR), cd); 4439781SMoriah.Waterland@Sun.COM return (VE_FAIL); 4449781SMoriah.Waterland@Sun.COM } 4459781SMoriah.Waterland@Sun.COM } 4469781SMoriah.Waterland@Sun.COM free(cd); 4479781SMoriah.Waterland@Sun.COM 4489781SMoriah.Waterland@Sun.COM if (retcode || (status.st_nlink < 2) || 4499781SMoriah.Waterland@Sun.COM (stat(ainfo->local, &status) < 0) || 4509781SMoriah.Waterland@Sun.COM (my_dev != status.st_dev) || (my_ino != status.st_ino)) { 4519781SMoriah.Waterland@Sun.COM if (fix) { 4529781SMoriah.Waterland@Sun.COM /* 4539781SMoriah.Waterland@Sun.COM * Don't want to do a hard link to a 4549781SMoriah.Waterland@Sun.COM * directory. 4559781SMoriah.Waterland@Sun.COM */ 4569781SMoriah.Waterland@Sun.COM if (!isdir(ainfo->local)) { 4579781SMoriah.Waterland@Sun.COM chdir(cwd); 4589781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_LINKISDIR), 4599781SMoriah.Waterland@Sun.COM ainfo->local); 4609781SMoriah.Waterland@Sun.COM return (VE_FAIL); 4619781SMoriah.Waterland@Sun.COM } 4629781SMoriah.Waterland@Sun.COM /* Now do the link. */ 4639781SMoriah.Waterland@Sun.COM if (!clear_target(path, ftype, targ_is_dir)) 4649781SMoriah.Waterland@Sun.COM return (VE_FAIL); 4659781SMoriah.Waterland@Sun.COM 4669781SMoriah.Waterland@Sun.COM if (link(ainfo->local, path)) { 4679781SMoriah.Waterland@Sun.COM chdir(cwd); 4689781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_LINKFAIL), 4699781SMoriah.Waterland@Sun.COM ainfo->local); 4709781SMoriah.Waterland@Sun.COM return (VE_FAIL); 4719781SMoriah.Waterland@Sun.COM } 4729781SMoriah.Waterland@Sun.COM retcode = 0; 4739781SMoriah.Waterland@Sun.COM } else { 4749781SMoriah.Waterland@Sun.COM /* Go back to previous working directory */ 4759781SMoriah.Waterland@Sun.COM if (chdir(cwd) != 0) 4769781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_CHDIR), cwd); 4779781SMoriah.Waterland@Sun.COM 4789781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_LINK), ainfo->local); 4799781SMoriah.Waterland@Sun.COM return (VE_CONT); 4809781SMoriah.Waterland@Sun.COM } 4819781SMoriah.Waterland@Sun.COM } 4829781SMoriah.Waterland@Sun.COM 4839781SMoriah.Waterland@Sun.COM /* Go back to previous working directory */ 4849781SMoriah.Waterland@Sun.COM if (chdir(cwd) != 0) { 4859781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_CHDIR), cwd); 4869781SMoriah.Waterland@Sun.COM return (VE_CONT); 4879781SMoriah.Waterland@Sun.COM } 4889781SMoriah.Waterland@Sun.COM 4899781SMoriah.Waterland@Sun.COM return (retcode); 4909781SMoriah.Waterland@Sun.COM } 4919781SMoriah.Waterland@Sun.COM 4929781SMoriah.Waterland@Sun.COM retcode = 0; 4939781SMoriah.Waterland@Sun.COM 494*10176Sok199659 /* If we are to process symlinks the old way then we follow the link */ 495*10176Sok199659 if (nonABI_symlinks()) { 496*10176Sok199659 if ((*ftype == 's') ? lstat(path, &status) : 497*10176Sok199659 stat(path, &status)) { 498*10176Sok199659 reperr(pkg_gt(ERR_EXIST)); 499*10176Sok199659 retcode = VE_EXIST; 500*10176Sok199659 myftype = '?'; 501*10176Sok199659 statError++; 502*10176Sok199659 } 503*10176Sok199659 /* If not then we inspect the target of the link */ 504*10176Sok199659 } else { 505*10176Sok199659 if ((n = lstat(path, &status)) == -1) { 506*10176Sok199659 reperr(pkg_gt(ERR_EXIST)); 507*10176Sok199659 retcode = VE_EXIST; 508*10176Sok199659 myftype = '?'; 509*10176Sok199659 statError++; 510*10176Sok199659 } 511*10176Sok199659 } 512*10176Sok199659 if (!statError) { 513*10176Sok199659 /* determining actual type of existing object */ 514*10176Sok199659 switch (status.st_mode & S_IFMT) { 515*10176Sok199659 case S_IFLNK: 516*10176Sok199659 myftype = 's'; 517*10176Sok199659 break; 5189781SMoriah.Waterland@Sun.COM 519*10176Sok199659 case S_IFIFO: 520*10176Sok199659 myftype = 'p'; 521*10176Sok199659 break; 522*10176Sok199659 523*10176Sok199659 case S_IFCHR: 524*10176Sok199659 myftype = 'c'; 525*10176Sok199659 break; 526*10176Sok199659 527*10176Sok199659 case S_IFDIR: 528*10176Sok199659 myftype = 'd'; 529*10176Sok199659 targ_is_dir = 1; 530*10176Sok199659 break; 5319781SMoriah.Waterland@Sun.COM 532*10176Sok199659 case S_IFBLK: 533*10176Sok199659 myftype = 'b'; 534*10176Sok199659 break; 535*10176Sok199659 536*10176Sok199659 case S_IFREG: 537*10176Sok199659 case 0: 538*10176Sok199659 myftype = 'f'; 539*10176Sok199659 break; 540*10176Sok199659 541*10176Sok199659 case S_IFDOOR: 542*10176Sok199659 myftype = 'D'; 543*10176Sok199659 break; 544*10176Sok199659 545*10176Sok199659 default: 546*10176Sok199659 reperr(pkg_gt(ERR_UNKNOWN)); 547*10176Sok199659 return (VE_FTYPE); 548*10176Sok199659 } 549*10176Sok199659 } 5509781SMoriah.Waterland@Sun.COM 5519781SMoriah.Waterland@Sun.COM if (setval) { 5529781SMoriah.Waterland@Sun.COM /* 5539781SMoriah.Waterland@Sun.COM * Check to make sure that a package or an installf that uses 5549781SMoriah.Waterland@Sun.COM * wild cards '?' to assume the ftype of an object on the 5559781SMoriah.Waterland@Sun.COM * system is not assuming a door ftype. Doors are not supported 5569781SMoriah.Waterland@Sun.COM * but should be ignored. 5579781SMoriah.Waterland@Sun.COM */ 5589781SMoriah.Waterland@Sun.COM if (myftype == 'D') { 5599781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_FTYPED), path); 5609781SMoriah.Waterland@Sun.COM retcode = VE_FTYPE; 5619781SMoriah.Waterland@Sun.COM return (VE_FTYPE); 5629781SMoriah.Waterland@Sun.COM } else { 5639781SMoriah.Waterland@Sun.COM *ftype = myftype; 5649781SMoriah.Waterland@Sun.COM } 5659781SMoriah.Waterland@Sun.COM } else if (!retcode && (*ftype != myftype) && 5669781SMoriah.Waterland@Sun.COM ((myftype != 'f') || !strchr("ilev", *ftype)) && 5679781SMoriah.Waterland@Sun.COM ((myftype != 'd') || (*ftype != 'x'))) { 5689781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_FTYPE), *ftype, myftype); 5699781SMoriah.Waterland@Sun.COM retcode = VE_FTYPE; 5709781SMoriah.Waterland@Sun.COM } 5719781SMoriah.Waterland@Sun.COM 5729781SMoriah.Waterland@Sun.COM if (!retcode && (*ftype == 's')) { 5739781SMoriah.Waterland@Sun.COM /* make sure that symbolic link is correct */ 5749781SMoriah.Waterland@Sun.COM n = readlink(path, buf, PATH_MAX); 5759781SMoriah.Waterland@Sun.COM if (n < 0) { 5769781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_SLINK), ainfo->local); 5779781SMoriah.Waterland@Sun.COM retcode = VE_CONT; 5789781SMoriah.Waterland@Sun.COM } else if (ainfo->local != NULL) { 5799781SMoriah.Waterland@Sun.COM buf[n] = '\0'; 5809781SMoriah.Waterland@Sun.COM if (strcmp(buf, ainfo->local)) { 5819781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_SLINK), ainfo->local); 5829781SMoriah.Waterland@Sun.COM retcode = VE_CONT; 5839781SMoriah.Waterland@Sun.COM } 5849781SMoriah.Waterland@Sun.COM } else if (ainfo->local == NULL) { 5859781SMoriah.Waterland@Sun.COM /* 5869781SMoriah.Waterland@Sun.COM * Since a sym link target exists, insert it 5879781SMoriah.Waterland@Sun.COM * into the ainfo structure 5889781SMoriah.Waterland@Sun.COM */ 5899781SMoriah.Waterland@Sun.COM buf[n] = '\0'; 5909781SMoriah.Waterland@Sun.COM ainfo->local = strdup(buf); 5919781SMoriah.Waterland@Sun.COM } 5929781SMoriah.Waterland@Sun.COM } 5939781SMoriah.Waterland@Sun.COM 5949781SMoriah.Waterland@Sun.COM if (retcode) { 5959781SMoriah.Waterland@Sun.COM /* The path doesn't exist or is different than it should be. */ 5969781SMoriah.Waterland@Sun.COM if (fix) { 5979781SMoriah.Waterland@Sun.COM /* 5989781SMoriah.Waterland@Sun.COM * Clear the way for the write. If it won't clear, 5999781SMoriah.Waterland@Sun.COM * there's nothing we can do. 6009781SMoriah.Waterland@Sun.COM */ 6019781SMoriah.Waterland@Sun.COM if (!clear_target(path, ftype, targ_is_dir)) 6029781SMoriah.Waterland@Sun.COM return (VE_FAIL); 6039781SMoriah.Waterland@Sun.COM 6049781SMoriah.Waterland@Sun.COM if ((*ftype == 'd') || (*ftype == 'x')) { 6059781SMoriah.Waterland@Sun.COM char *pt, *p; 6069781SMoriah.Waterland@Sun.COM 6079781SMoriah.Waterland@Sun.COM /* Try to make it the easy way */ 6089781SMoriah.Waterland@Sun.COM if (mkdir(path, ainfo->mode)) { 6099781SMoriah.Waterland@Sun.COM /* 6109781SMoriah.Waterland@Sun.COM * Failing that, walk through the 6119781SMoriah.Waterland@Sun.COM * parent directories creating 6129781SMoriah.Waterland@Sun.COM * whatever is needed. 6139781SMoriah.Waterland@Sun.COM */ 6149781SMoriah.Waterland@Sun.COM p = strdup(path); 6159781SMoriah.Waterland@Sun.COM pt = (*p == '/') ? p+1 : p; 6169781SMoriah.Waterland@Sun.COM do { 6179781SMoriah.Waterland@Sun.COM if (pt = strchr(pt, '/')) 6189781SMoriah.Waterland@Sun.COM *pt = '\0'; 6199781SMoriah.Waterland@Sun.COM if (access(p, 0) && 6209781SMoriah.Waterland@Sun.COM mkdir(p, ainfo->mode)) 6219781SMoriah.Waterland@Sun.COM break; 6229781SMoriah.Waterland@Sun.COM if (pt) 6239781SMoriah.Waterland@Sun.COM *pt++ = '/'; 6249781SMoriah.Waterland@Sun.COM } while (pt); 6259781SMoriah.Waterland@Sun.COM free(p); 6269781SMoriah.Waterland@Sun.COM } 6279781SMoriah.Waterland@Sun.COM if (stat(path, &status) < 0) { 6289781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_DIRFAIL)); 6299781SMoriah.Waterland@Sun.COM return (VE_FAIL); 6309781SMoriah.Waterland@Sun.COM } 6319781SMoriah.Waterland@Sun.COM } else if (*ftype == 's') { 6329781SMoriah.Waterland@Sun.COM if (symlink(ainfo->local, path)) { 6339781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_SLINKFAIL), 6349781SMoriah.Waterland@Sun.COM ainfo->local); 6359781SMoriah.Waterland@Sun.COM return (VE_FAIL); 6369781SMoriah.Waterland@Sun.COM } 6379781SMoriah.Waterland@Sun.COM 6389781SMoriah.Waterland@Sun.COM } else if (*ftype == 'c') { 6399781SMoriah.Waterland@Sun.COM int wilddevno = 0; 6409781SMoriah.Waterland@Sun.COM /* 6419781SMoriah.Waterland@Sun.COM * The next three if's support 2.4 and older 6429781SMoriah.Waterland@Sun.COM * packages that use "?" as device numbers. 6439781SMoriah.Waterland@Sun.COM * This should be considered for removal by 6449781SMoriah.Waterland@Sun.COM * release 2.7 or so. 6459781SMoriah.Waterland@Sun.COM */ 6469781SMoriah.Waterland@Sun.COM if (ainfo->major == BADMAJOR) { 6479781SMoriah.Waterland@Sun.COM ainfo->major = 0; 6489781SMoriah.Waterland@Sun.COM wilddevno = 1; 6499781SMoriah.Waterland@Sun.COM } 6509781SMoriah.Waterland@Sun.COM 6519781SMoriah.Waterland@Sun.COM if (ainfo->minor == BADMINOR) { 6529781SMoriah.Waterland@Sun.COM ainfo->minor = 0; 6539781SMoriah.Waterland@Sun.COM wilddevno = 1; 6549781SMoriah.Waterland@Sun.COM } 6559781SMoriah.Waterland@Sun.COM 6569781SMoriah.Waterland@Sun.COM if (wilddevno) { 6579781SMoriah.Waterland@Sun.COM wilddevno = 0; 6589781SMoriah.Waterland@Sun.COM logerr(MSG_WLDDEVNO, path, 6599781SMoriah.Waterland@Sun.COM ainfo->major, ainfo->minor); 6609781SMoriah.Waterland@Sun.COM } 6619781SMoriah.Waterland@Sun.COM 6629781SMoriah.Waterland@Sun.COM if (mknod(path, ainfo->mode | S_IFCHR, 6639781SMoriah.Waterland@Sun.COM #ifdef SUNOS41 6649781SMoriah.Waterland@Sun.COM makedev(ainfo->xmajor, ainfo->xminor)) || 6659781SMoriah.Waterland@Sun.COM #else 6669781SMoriah.Waterland@Sun.COM makedev(ainfo->major, ainfo->minor)) || 6679781SMoriah.Waterland@Sun.COM #endif 6689781SMoriah.Waterland@Sun.COM (stat(path, &status) < 0)) { 6699781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_CDEVFAIL)); 6709781SMoriah.Waterland@Sun.COM return (VE_FAIL); 6719781SMoriah.Waterland@Sun.COM } 6729781SMoriah.Waterland@Sun.COM } else if (*ftype == 'b') { 6739781SMoriah.Waterland@Sun.COM int wilddevno = 0; 6749781SMoriah.Waterland@Sun.COM /* 6759781SMoriah.Waterland@Sun.COM * The next three if's support 2.4 and older 6769781SMoriah.Waterland@Sun.COM * packages that use "?" as device numbers. 6779781SMoriah.Waterland@Sun.COM * This should be considered for removal by 6789781SMoriah.Waterland@Sun.COM * release 2.7 or so. 6799781SMoriah.Waterland@Sun.COM */ 6809781SMoriah.Waterland@Sun.COM if (ainfo->major == BADMAJOR) { 6819781SMoriah.Waterland@Sun.COM ainfo->major = 0; 6829781SMoriah.Waterland@Sun.COM wilddevno = 1; 6839781SMoriah.Waterland@Sun.COM } 6849781SMoriah.Waterland@Sun.COM 6859781SMoriah.Waterland@Sun.COM if (ainfo->minor == BADMINOR) { 6869781SMoriah.Waterland@Sun.COM ainfo->minor = 0; 6879781SMoriah.Waterland@Sun.COM wilddevno = 1; 6889781SMoriah.Waterland@Sun.COM } 6899781SMoriah.Waterland@Sun.COM 6909781SMoriah.Waterland@Sun.COM if (wilddevno) { 6919781SMoriah.Waterland@Sun.COM wilddevno = 0; 6929781SMoriah.Waterland@Sun.COM logerr(MSG_WLDDEVNO, path, 6939781SMoriah.Waterland@Sun.COM ainfo->major, ainfo->minor); 6949781SMoriah.Waterland@Sun.COM } 6959781SMoriah.Waterland@Sun.COM 6969781SMoriah.Waterland@Sun.COM if (mknod(path, ainfo->mode | S_IFBLK, 6979781SMoriah.Waterland@Sun.COM #ifdef SUNOS41 6989781SMoriah.Waterland@Sun.COM makedev(ainfo->xmajor, ainfo->xminor)) || 6999781SMoriah.Waterland@Sun.COM #else 7009781SMoriah.Waterland@Sun.COM makedev(ainfo->major, ainfo->minor)) || 7019781SMoriah.Waterland@Sun.COM #endif 7029781SMoriah.Waterland@Sun.COM (stat(path, &status) < 0)) { 7039781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_BDEVFAIL)); 7049781SMoriah.Waterland@Sun.COM return (VE_FAIL); 7059781SMoriah.Waterland@Sun.COM } 7069781SMoriah.Waterland@Sun.COM } else if (*ftype == 'p') { 7079781SMoriah.Waterland@Sun.COM if (mknod(path, ainfo->mode | S_IFIFO, NULL) || 7089781SMoriah.Waterland@Sun.COM (stat(path, &status) < 0)) { 7099781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_PIPEFAIL)); 7109781SMoriah.Waterland@Sun.COM return (VE_FAIL); 7119781SMoriah.Waterland@Sun.COM } 7129781SMoriah.Waterland@Sun.COM } else 7139781SMoriah.Waterland@Sun.COM return (retcode); 7149781SMoriah.Waterland@Sun.COM 7159781SMoriah.Waterland@Sun.COM } else 7169781SMoriah.Waterland@Sun.COM return (retcode); 7179781SMoriah.Waterland@Sun.COM } 7189781SMoriah.Waterland@Sun.COM 7199781SMoriah.Waterland@Sun.COM if (*ftype == 's') 7209781SMoriah.Waterland@Sun.COM return (0); /* don't check anything else */ 7219781SMoriah.Waterland@Sun.COM if (*ftype == 'i') 7229781SMoriah.Waterland@Sun.COM return (0); /* don't check anything else */ 7239781SMoriah.Waterland@Sun.COM 7249781SMoriah.Waterland@Sun.COM retcode = 0; 7259781SMoriah.Waterland@Sun.COM if ((myftype == 'c') || (myftype == 'b')) { 7269781SMoriah.Waterland@Sun.COM #ifdef SUNOS41 7279781SMoriah.Waterland@Sun.COM if (setval || (ainfo->xmajor < 0)) 7289781SMoriah.Waterland@Sun.COM ainfo->xmajor = ((status.st_rdev>>8)&0377); 7299781SMoriah.Waterland@Sun.COM if (setval || (ainfo->xminor < 0)) 7309781SMoriah.Waterland@Sun.COM ainfo->xminor = (status.st_rdev&0377); 7319781SMoriah.Waterland@Sun.COM /* check major & minor */ 7329781SMoriah.Waterland@Sun.COM if (status.st_rdev != makedev(ainfo->xmajor, ainfo->xminor)) { 7339781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_MAJMIN), ainfo->xmajor, 7349781SMoriah.Waterland@Sun.COM ainfo->xminor, 7359781SMoriah.Waterland@Sun.COM (status.st_rdev>>8)&0377, status.st_rdev&0377); 7369781SMoriah.Waterland@Sun.COM retcode = VE_CONT; 7379781SMoriah.Waterland@Sun.COM } 7389781SMoriah.Waterland@Sun.COM #else 7399781SMoriah.Waterland@Sun.COM if (setval || (ainfo->major == BADMAJOR)) 7409781SMoriah.Waterland@Sun.COM ainfo->major = major(status.st_rdev); 7419781SMoriah.Waterland@Sun.COM if (setval || (ainfo->minor == BADMINOR)) 7429781SMoriah.Waterland@Sun.COM ainfo->minor = minor(status.st_rdev); 7439781SMoriah.Waterland@Sun.COM /* check major & minor */ 7449781SMoriah.Waterland@Sun.COM if (status.st_rdev != makedev(ainfo->major, ainfo->minor)) { 7459781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_MAJMIN), ainfo->major, ainfo->minor, 7469781SMoriah.Waterland@Sun.COM major(status.st_rdev), minor(status.st_rdev)); 7479781SMoriah.Waterland@Sun.COM retcode = VE_CONT; 7489781SMoriah.Waterland@Sun.COM } 7499781SMoriah.Waterland@Sun.COM #endif 7509781SMoriah.Waterland@Sun.COM } 7519781SMoriah.Waterland@Sun.COM 7529781SMoriah.Waterland@Sun.COM /* compare specified mode w/ actual mode excluding sticky bit */ 7539781SMoriah.Waterland@Sun.COM if (setval || (ainfo->mode == BADMODE) || (ainfo->mode == WILDCARD)) 7549781SMoriah.Waterland@Sun.COM ainfo->mode = status.st_mode & 07777; 7559781SMoriah.Waterland@Sun.COM else if ((ainfo->mode & 06777) != (status.st_mode & 06777)) { 7569781SMoriah.Waterland@Sun.COM if (fix) { 7579781SMoriah.Waterland@Sun.COM if ((ainfo->mode == BADMODE) || 7589781SMoriah.Waterland@Sun.COM (chmod(path, ainfo->mode) < 0)) 7599781SMoriah.Waterland@Sun.COM retcode = VE_FAIL; 7609781SMoriah.Waterland@Sun.COM } else { 7619781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_PERM), ainfo->mode, 7629781SMoriah.Waterland@Sun.COM status.st_mode & 07777); 7639781SMoriah.Waterland@Sun.COM if (!retcode) 7649781SMoriah.Waterland@Sun.COM retcode = VE_ATTR; 7659781SMoriah.Waterland@Sun.COM } 7669781SMoriah.Waterland@Sun.COM } 7679781SMoriah.Waterland@Sun.COM 7689781SMoriah.Waterland@Sun.COM dochown = 0; 7699781SMoriah.Waterland@Sun.COM 7709781SMoriah.Waterland@Sun.COM /* get group entry for specified group */ 7719781SMoriah.Waterland@Sun.COM if (setval || strcmp(ainfo->group, BADGROUP) == 0) { 7729781SMoriah.Waterland@Sun.COM grp = cgrgid(status.st_gid); 7739781SMoriah.Waterland@Sun.COM if (grp) 7749781SMoriah.Waterland@Sun.COM (void) strcpy(ainfo->group, grp->gr_name); 7759781SMoriah.Waterland@Sun.COM else { 7769781SMoriah.Waterland@Sun.COM if (!retcode) 7779781SMoriah.Waterland@Sun.COM retcode = VE_ATTR; 7789781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_BADGRPID), status.st_gid); 7799781SMoriah.Waterland@Sun.COM } 7809781SMoriah.Waterland@Sun.COM gid = status.st_gid; 7819781SMoriah.Waterland@Sun.COM } else if ((grp = cgrnam(ainfo->group)) == NULL) { 7829781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_BADGRPNM), ainfo->group); 7839781SMoriah.Waterland@Sun.COM if (!retcode) 7849781SMoriah.Waterland@Sun.COM retcode = VE_ATTR; 7859781SMoriah.Waterland@Sun.COM } else if ((gid = grp->gr_gid) != status.st_gid) { 7869781SMoriah.Waterland@Sun.COM if (fix) { 7879781SMoriah.Waterland@Sun.COM /* save specified GID */ 7889781SMoriah.Waterland@Sun.COM gid = grp->gr_gid; 7899781SMoriah.Waterland@Sun.COM dochown++; 7909781SMoriah.Waterland@Sun.COM } else { 7919781SMoriah.Waterland@Sun.COM if ((grp = cgrgid((int)status.st_gid)) == 7929781SMoriah.Waterland@Sun.COM (struct group *)NULL) { 7939781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_GROUP), ainfo->group, 7949781SMoriah.Waterland@Sun.COM "(null)"); 7959781SMoriah.Waterland@Sun.COM } else { 7969781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_GROUP), ainfo->group, 7979781SMoriah.Waterland@Sun.COM grp->gr_name); 7989781SMoriah.Waterland@Sun.COM } 7999781SMoriah.Waterland@Sun.COM if (!retcode) 8009781SMoriah.Waterland@Sun.COM retcode = VE_ATTR; 8019781SMoriah.Waterland@Sun.COM } 8029781SMoriah.Waterland@Sun.COM } 8039781SMoriah.Waterland@Sun.COM 8049781SMoriah.Waterland@Sun.COM /* get password entry for specified owner */ 8059781SMoriah.Waterland@Sun.COM if (setval || strcmp(ainfo->owner, BADOWNER) == 0) { 8069781SMoriah.Waterland@Sun.COM pwd = cpwuid((int)status.st_uid); 8079781SMoriah.Waterland@Sun.COM if (pwd) 8089781SMoriah.Waterland@Sun.COM (void) strcpy(ainfo->owner, pwd->pw_name); 8099781SMoriah.Waterland@Sun.COM else { 8109781SMoriah.Waterland@Sun.COM if (!retcode) 8119781SMoriah.Waterland@Sun.COM retcode = VE_ATTR; 8129781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_BADUSRID), status.st_uid); 8139781SMoriah.Waterland@Sun.COM } 8149781SMoriah.Waterland@Sun.COM uid = status.st_uid; 8159781SMoriah.Waterland@Sun.COM } else if ((pwd = cpwnam(ainfo->owner)) == NULL) { 8169781SMoriah.Waterland@Sun.COM /* UID does not exist in password file */ 8179781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_BADUSRNM), ainfo->owner); 8189781SMoriah.Waterland@Sun.COM if (!retcode) 8199781SMoriah.Waterland@Sun.COM retcode = VE_ATTR; 8209781SMoriah.Waterland@Sun.COM } else if ((uid = pwd->pw_uid) != status.st_uid) { 8219781SMoriah.Waterland@Sun.COM /* get owner name for actual UID */ 8229781SMoriah.Waterland@Sun.COM if (fix) { 8239781SMoriah.Waterland@Sun.COM uid = pwd->pw_uid; 8249781SMoriah.Waterland@Sun.COM dochown++; 8259781SMoriah.Waterland@Sun.COM } else { 8269781SMoriah.Waterland@Sun.COM pwd = cpwuid((int)status.st_uid); 8279781SMoriah.Waterland@Sun.COM if (pwd == NULL) 8289781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_BADUSRID), 8299781SMoriah.Waterland@Sun.COM (int)status.st_uid); 8309781SMoriah.Waterland@Sun.COM else 8319781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_OWNER), ainfo->owner, 8329781SMoriah.Waterland@Sun.COM pwd->pw_name); 8339781SMoriah.Waterland@Sun.COM 8349781SMoriah.Waterland@Sun.COM if (!retcode) 8359781SMoriah.Waterland@Sun.COM retcode = VE_ATTR; 8369781SMoriah.Waterland@Sun.COM } 8379781SMoriah.Waterland@Sun.COM } 8389781SMoriah.Waterland@Sun.COM 8399781SMoriah.Waterland@Sun.COM if (statvfs(path, &vfsstatus) < 0) { 8409781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_EXIST)); 8419781SMoriah.Waterland@Sun.COM retcode = VE_FAIL; 8429781SMoriah.Waterland@Sun.COM } else { 8439781SMoriah.Waterland@Sun.COM if (dochown) { 8449781SMoriah.Waterland@Sun.COM /* pcfs doesn't support file ownership */ 8459781SMoriah.Waterland@Sun.COM if (strcmp(vfsstatus.f_basetype, "pcfs") != 0 && 8469781SMoriah.Waterland@Sun.COM chown(path, uid, gid) < 0) { 8479781SMoriah.Waterland@Sun.COM retcode = VE_FAIL; /* chown failed */ 8489781SMoriah.Waterland@Sun.COM } 8499781SMoriah.Waterland@Sun.COM } 8509781SMoriah.Waterland@Sun.COM } 8519781SMoriah.Waterland@Sun.COM 8529781SMoriah.Waterland@Sun.COM if (retcode == VE_FAIL) 8539781SMoriah.Waterland@Sun.COM reperr(pkg_gt(ERR_ATTRFAIL)); 8549781SMoriah.Waterland@Sun.COM return (retcode); 8559781SMoriah.Waterland@Sun.COM } 8569781SMoriah.Waterland@Sun.COM 8579781SMoriah.Waterland@Sun.COM /* 8589781SMoriah.Waterland@Sun.COM * This is a special fast verify which basically checks the attributes 8599781SMoriah.Waterland@Sun.COM * and then, if all is OK, checks the size and mod time using the same 8609781SMoriah.Waterland@Sun.COM * stat and statvfs structures. 8619781SMoriah.Waterland@Sun.COM */ 8629781SMoriah.Waterland@Sun.COM int 8639781SMoriah.Waterland@Sun.COM fverify(int fix, char *ftype, char *path, struct ainfo *ainfo, 8649781SMoriah.Waterland@Sun.COM struct cinfo *cinfo) 8659781SMoriah.Waterland@Sun.COM { 8669781SMoriah.Waterland@Sun.COM int retval; 8679781SMoriah.Waterland@Sun.COM 8689781SMoriah.Waterland@Sun.COM /* return success if attribute checks are disabled */ 8699781SMoriah.Waterland@Sun.COM 8709781SMoriah.Waterland@Sun.COM if (get_disable_attribute_check()) { 8719781SMoriah.Waterland@Sun.COM return (0); 8729781SMoriah.Waterland@Sun.COM } 8739781SMoriah.Waterland@Sun.COM 8749781SMoriah.Waterland@Sun.COM if ((retval = averify(fix, ftype, path, ainfo)) == 0) { 8759781SMoriah.Waterland@Sun.COM if (*ftype == 'f' || *ftype == 'i') { 8769781SMoriah.Waterland@Sun.COM if (cinfo->size != status.st_size) { 8779781SMoriah.Waterland@Sun.COM reperr(pkg_gt(WRN_QV_SIZE), path); 8789781SMoriah.Waterland@Sun.COM retval = VE_CONT; 8799781SMoriah.Waterland@Sun.COM } 8809781SMoriah.Waterland@Sun.COM /* pcfs doesn't support modification times */ 8819781SMoriah.Waterland@Sun.COM if (strcmp(vfsstatus.f_basetype, "pcfs") != 0) { 8829781SMoriah.Waterland@Sun.COM if (cinfo->modtime != status.st_mtime) { 8839781SMoriah.Waterland@Sun.COM reperr(pkg_gt(WRN_QV_MTIME), path); 8849781SMoriah.Waterland@Sun.COM retval = VE_CONT; 8859781SMoriah.Waterland@Sun.COM } 8869781SMoriah.Waterland@Sun.COM } 8879781SMoriah.Waterland@Sun.COM } 8889781SMoriah.Waterland@Sun.COM } 8899781SMoriah.Waterland@Sun.COM 8909781SMoriah.Waterland@Sun.COM return (retval); 8919781SMoriah.Waterland@Sun.COM } 8929781SMoriah.Waterland@Sun.COM 8939781SMoriah.Waterland@Sun.COM /* 8949781SMoriah.Waterland@Sun.COM * This function determines whether or not non-ABI symlinks are supported. 8959781SMoriah.Waterland@Sun.COM */ 8969781SMoriah.Waterland@Sun.COM 8979781SMoriah.Waterland@Sun.COM int 8989781SMoriah.Waterland@Sun.COM nonABI_symlinks(void) 8999781SMoriah.Waterland@Sun.COM { 9009781SMoriah.Waterland@Sun.COM return (nonabi_symlinks); 9019781SMoriah.Waterland@Sun.COM } 9029781SMoriah.Waterland@Sun.COM 9039781SMoriah.Waterland@Sun.COM void 9049781SMoriah.Waterland@Sun.COM set_nonABI_symlinks(void) 9059781SMoriah.Waterland@Sun.COM { 9069781SMoriah.Waterland@Sun.COM nonabi_symlinks = 1; 9079781SMoriah.Waterland@Sun.COM } 9089781SMoriah.Waterland@Sun.COM 9099781SMoriah.Waterland@Sun.COM /* 9109781SMoriah.Waterland@Sun.COM * Disable attribute checking. Only disable attribute checking if files 9119781SMoriah.Waterland@Sun.COM * are guaranteed to exist in the FS. 9129781SMoriah.Waterland@Sun.COM */ 9139781SMoriah.Waterland@Sun.COM void 9149781SMoriah.Waterland@Sun.COM disable_attribute_check(void) 9159781SMoriah.Waterland@Sun.COM { 9169781SMoriah.Waterland@Sun.COM disable_attributes = 1; 9179781SMoriah.Waterland@Sun.COM } 9189781SMoriah.Waterland@Sun.COM 9199781SMoriah.Waterland@Sun.COM /* 9209781SMoriah.Waterland@Sun.COM * This function determines whether or not to do attribute checking. 9219781SMoriah.Waterland@Sun.COM * Returns: 0 - Do attribute checking 9229781SMoriah.Waterland@Sun.COM * !0 - Don't do attribute checking 9239781SMoriah.Waterland@Sun.COM */ 9249781SMoriah.Waterland@Sun.COM int 9259781SMoriah.Waterland@Sun.COM get_disable_attribute_check(void) 9269781SMoriah.Waterland@Sun.COM { 9279781SMoriah.Waterland@Sun.COM return (disable_attributes); 9289781SMoriah.Waterland@Sun.COM } 9299781SMoriah.Waterland@Sun.COM 9309781SMoriah.Waterland@Sun.COM /* 9319781SMoriah.Waterland@Sun.COM * This function returns the address of the "global" error buffer that 9329781SMoriah.Waterland@Sun.COM * is populated by the various functions in this module. 9339781SMoriah.Waterland@Sun.COM */ 9349781SMoriah.Waterland@Sun.COM 9359781SMoriah.Waterland@Sun.COM char * 9369781SMoriah.Waterland@Sun.COM getErrbufAddr(void) 9379781SMoriah.Waterland@Sun.COM { 9389781SMoriah.Waterland@Sun.COM return (theErrBuf); 9399781SMoriah.Waterland@Sun.COM } 9409781SMoriah.Waterland@Sun.COM 9419781SMoriah.Waterland@Sun.COM /* 9429781SMoriah.Waterland@Sun.COM * This function returns the size of the buffer returned by getErrbufAddr() 9439781SMoriah.Waterland@Sun.COM */ 9449781SMoriah.Waterland@Sun.COM 9459781SMoriah.Waterland@Sun.COM int 9469781SMoriah.Waterland@Sun.COM getErrbufSize(void) 9479781SMoriah.Waterland@Sun.COM { 9489781SMoriah.Waterland@Sun.COM return (sizeof (theErrBuf)); 9499781SMoriah.Waterland@Sun.COM } 9509781SMoriah.Waterland@Sun.COM 9519781SMoriah.Waterland@Sun.COM /* 9529781SMoriah.Waterland@Sun.COM * This function returns the current global "error string" 9539781SMoriah.Waterland@Sun.COM */ 9549781SMoriah.Waterland@Sun.COM 9559781SMoriah.Waterland@Sun.COM char * 9569781SMoriah.Waterland@Sun.COM getErrstr(void) 9579781SMoriah.Waterland@Sun.COM { 9589781SMoriah.Waterland@Sun.COM return (theErrStr); 9599781SMoriah.Waterland@Sun.COM } 9609781SMoriah.Waterland@Sun.COM 9619781SMoriah.Waterland@Sun.COM /* 9629781SMoriah.Waterland@Sun.COM * This function sets the global "error string" 9639781SMoriah.Waterland@Sun.COM */ 9649781SMoriah.Waterland@Sun.COM 9659781SMoriah.Waterland@Sun.COM void 9669781SMoriah.Waterland@Sun.COM setErrstr(char *a_errstr) 9679781SMoriah.Waterland@Sun.COM { 9689781SMoriah.Waterland@Sun.COM theErrStr = a_errstr; 9699781SMoriah.Waterland@Sun.COM } 9709781SMoriah.Waterland@Sun.COM 9719781SMoriah.Waterland@Sun.COM /* 9729781SMoriah.Waterland@Sun.COM * This function enables checksumming 9739781SMoriah.Waterland@Sun.COM */ 9749781SMoriah.Waterland@Sun.COM 9759781SMoriah.Waterland@Sun.COM void 9769781SMoriah.Waterland@Sun.COM checksum_on(void) 9779781SMoriah.Waterland@Sun.COM { 9789781SMoriah.Waterland@Sun.COM enable_checksum = 1; 9799781SMoriah.Waterland@Sun.COM } 9809781SMoriah.Waterland@Sun.COM 9819781SMoriah.Waterland@Sun.COM /* 9829781SMoriah.Waterland@Sun.COM * This function disables checksumming 9839781SMoriah.Waterland@Sun.COM */ 9849781SMoriah.Waterland@Sun.COM 9859781SMoriah.Waterland@Sun.COM void 9869781SMoriah.Waterland@Sun.COM checksum_off(void) 9879781SMoriah.Waterland@Sun.COM { 9889781SMoriah.Waterland@Sun.COM enable_checksum = 0; 9899781SMoriah.Waterland@Sun.COM } 990