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 2009 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 #include <stdio.h> 33*5c51f124SMoriah Waterland #include <limits.h> 34*5c51f124SMoriah Waterland #include <stdlib.h> 35*5c51f124SMoriah Waterland #include <unistd.h> 36*5c51f124SMoriah Waterland #include <utime.h> 37*5c51f124SMoriah Waterland #include <sys/types.h> 38*5c51f124SMoriah Waterland #include <sys/param.h> 39*5c51f124SMoriah Waterland #include <sys/stat.h> 40*5c51f124SMoriah Waterland #include <sys/statvfs.h> 41*5c51f124SMoriah Waterland #include <grp.h> 42*5c51f124SMoriah Waterland #include <pwd.h> 43*5c51f124SMoriah Waterland #include <errno.h> 44*5c51f124SMoriah Waterland #include <string.h> 45*5c51f124SMoriah Waterland #include <stdarg.h> 46*5c51f124SMoriah Waterland #include <fcntl.h> 47*5c51f124SMoriah Waterland #include <sys/mkdev.h> 48*5c51f124SMoriah Waterland #include "pkgstrct.h" 49*5c51f124SMoriah Waterland #include "pkglib.h" 50*5c51f124SMoriah Waterland #include "pkglibmsgs.h" 51*5c51f124SMoriah Waterland #include "pkglocale.h" 52*5c51f124SMoriah Waterland 53*5c51f124SMoriah Waterland #define WDMSK 0xFFFF 54*5c51f124SMoriah Waterland #define DATEFMT "%D %r" 55*5c51f124SMoriah Waterland #define LONG_BOUNDARY ((sizeof (unsigned long))-1) 56*5c51f124SMoriah Waterland #define CHUNK 1024*1024 57*5c51f124SMoriah Waterland 58*5c51f124SMoriah Waterland static char theErrBuf[PATH_MAX+512] = {'\0'}; 59*5c51f124SMoriah Waterland static char *theErrStr = NULL; 60*5c51f124SMoriah Waterland 61*5c51f124SMoriah Waterland /* checksum disable switch */ 62*5c51f124SMoriah Waterland static int enable_checksum = 1; 63*5c51f124SMoriah Waterland 64*5c51f124SMoriah Waterland /* attribute disable flag */ 65*5c51f124SMoriah Waterland static int disable_attributes = 0; 66*5c51f124SMoriah Waterland 67*5c51f124SMoriah Waterland /* non-ABI symlinks supported */ 68*5c51f124SMoriah Waterland static int nonabi_symlinks; 69*5c51f124SMoriah Waterland 70*5c51f124SMoriah Waterland /* 71*5c51f124SMoriah Waterland * forward declarations 72*5c51f124SMoriah Waterland */ 73*5c51f124SMoriah Waterland 74*5c51f124SMoriah Waterland static int clear_target(char *path, char *ftype, int is_a_dir); 75*5c51f124SMoriah Waterland 76*5c51f124SMoriah Waterland unsigned long compute_checksum(int *r_err, char *path); 77*5c51f124SMoriah Waterland 78*5c51f124SMoriah Waterland /* union used to generate checksum */ 79*5c51f124SMoriah Waterland typedef union hilo { 80*5c51f124SMoriah Waterland struct part { 81*5c51f124SMoriah Waterland uint16_t hi; 82*5c51f124SMoriah Waterland uint16_t lo; 83*5c51f124SMoriah Waterland } hl; 84*5c51f124SMoriah Waterland uint32_t lg; 85*5c51f124SMoriah Waterland } CHECKSUM_T; 86*5c51f124SMoriah Waterland 87*5c51f124SMoriah Waterland /*PRINTFLIKE1*/ 88*5c51f124SMoriah Waterland static void 89*5c51f124SMoriah Waterland reperr(char *fmt, ...) 90*5c51f124SMoriah Waterland { 91*5c51f124SMoriah Waterland char *pt; 92*5c51f124SMoriah Waterland ssize_t ptln; 93*5c51f124SMoriah Waterland va_list ap; 94*5c51f124SMoriah Waterland int n; 95*5c51f124SMoriah Waterland 96*5c51f124SMoriah Waterland if (fmt == (char *)NULL) { 97*5c51f124SMoriah Waterland theErrBuf[0] = '\0'; 98*5c51f124SMoriah Waterland } else { 99*5c51f124SMoriah Waterland if (n = strlen(theErrBuf)) { 100*5c51f124SMoriah Waterland pt = theErrBuf + n; 101*5c51f124SMoriah Waterland *pt++ = '\n'; 102*5c51f124SMoriah Waterland *pt = '\0'; 103*5c51f124SMoriah Waterland ptln = sizeof (theErrBuf)-n; 104*5c51f124SMoriah Waterland } else { 105*5c51f124SMoriah Waterland pt = theErrBuf; 106*5c51f124SMoriah Waterland ptln = sizeof (theErrBuf); 107*5c51f124SMoriah Waterland } 108*5c51f124SMoriah Waterland va_start(ap, fmt); 109*5c51f124SMoriah Waterland /* LINTED variable format specifier to vsnprintf() */ 110*5c51f124SMoriah Waterland (void) vsnprintf(pt, ptln, fmt, ap); 111*5c51f124SMoriah Waterland va_end(ap); 112*5c51f124SMoriah Waterland } 113*5c51f124SMoriah Waterland } 114*5c51f124SMoriah Waterland 115*5c51f124SMoriah Waterland /* 116*5c51f124SMoriah Waterland * Name: cverify 117*5c51f124SMoriah Waterland * Description: This function verifies and (if fix > 0) fixes the contents 118*5c51f124SMoriah Waterland * of the file at the path provided 119*5c51f124SMoriah Waterland * Arguments: fix - 0 - do not fix entries, 1 - fix entries 120*5c51f124SMoriah Waterland * ftype - single character "type" the entry is supposed to be 121*5c51f124SMoriah Waterland * path - path to file 122*5c51f124SMoriah Waterland * cinfo - content info structure representing the contents 123*5c51f124SMoriah Waterland * the entry is supposed to contain 124*5c51f124SMoriah Waterland * allow_checksum - determine if checksumming should be disabled: 125*5c51f124SMoriah Waterland * == 0 - do not perform checksum ever - override enable_checksum. 126*5c51f124SMoriah Waterland * != 0 - use the default checksum flag "enable_checksum" to 127*5c51f124SMoriah Waterland * determine if checksumming should be done. 128*5c51f124SMoriah Waterland * NOTE: modification and creation times can be repaired; the contents 129*5c51f124SMoriah Waterland * of the file cannot be corrected if the checksum indicates that 130*5c51f124SMoriah Waterland * the contents are not correct - VE_CONT will be returned in this 131*5c51f124SMoriah Waterland * case. 132*5c51f124SMoriah Waterland * Possible return values: 133*5c51f124SMoriah Waterland * - 0 = successful 134*5c51f124SMoriah Waterland * - VE_EXIST = path name does not exist 135*5c51f124SMoriah Waterland * - VE_FTYPE = path file type is not recognized, is not supported, 136*5c51f124SMoriah Waterland * or is not what was expected 137*5c51f124SMoriah Waterland * - VE_ATTR = path mode/group/user is not what was expected 138*5c51f124SMoriah Waterland * - VE_CONT = mod time/link target/major/minor/size/file system type/current 139*5c51f124SMoriah Waterland * directory is not what was expected 140*5c51f124SMoriah Waterland * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/ 141*5c51f124SMoriah Waterland * chown failed 142*5c51f124SMoriah Waterland */ 143*5c51f124SMoriah Waterland 144*5c51f124SMoriah Waterland int 145*5c51f124SMoriah Waterland cverify(int fix, char *ftype, char *path, struct cinfo *cinfo, 146*5c51f124SMoriah Waterland int allow_checksum) 147*5c51f124SMoriah Waterland { 148*5c51f124SMoriah Waterland struct stat status; /* file status buffer */ 149*5c51f124SMoriah Waterland struct utimbuf times; 150*5c51f124SMoriah Waterland unsigned long mycksum; 151*5c51f124SMoriah Waterland int setval, retcode; 152*5c51f124SMoriah Waterland char tbuf1[512]; 153*5c51f124SMoriah Waterland char tbuf2[512]; 154*5c51f124SMoriah Waterland int cksumerr; 155*5c51f124SMoriah Waterland 156*5c51f124SMoriah Waterland setval = (*ftype == '?'); 157*5c51f124SMoriah Waterland retcode = 0; 158*5c51f124SMoriah Waterland reperr(NULL); 159*5c51f124SMoriah Waterland 160*5c51f124SMoriah Waterland if (stat(path, &status) < 0) { 161*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_EXIST)); 162*5c51f124SMoriah Waterland return (VE_EXIST); 163*5c51f124SMoriah Waterland } 164*5c51f124SMoriah Waterland 165*5c51f124SMoriah Waterland /* -1 requires modtimes to be the same */ 166*5c51f124SMoriah Waterland /* 0 reports modtime failure */ 167*5c51f124SMoriah Waterland /* 1 fixes modtimes */ 168*5c51f124SMoriah Waterland 169*5c51f124SMoriah Waterland if (setval || (cinfo->modtime == BADCONT)) { 170*5c51f124SMoriah Waterland cinfo->modtime = status.st_mtime; 171*5c51f124SMoriah Waterland } else if (status.st_mtime != cinfo->modtime) { 172*5c51f124SMoriah Waterland if (fix > 0) { 173*5c51f124SMoriah Waterland /* reset times on the file */ 174*5c51f124SMoriah Waterland times.actime = cinfo->modtime; 175*5c51f124SMoriah Waterland times.modtime = cinfo->modtime; 176*5c51f124SMoriah Waterland if (utime(path, ×)) { 177*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_MODFAIL)); 178*5c51f124SMoriah Waterland retcode = VE_FAIL; 179*5c51f124SMoriah Waterland } 180*5c51f124SMoriah Waterland } else if (fix < 0) { 181*5c51f124SMoriah Waterland /* modtimes must be the same */ 182*5c51f124SMoriah Waterland if (strftime(tbuf1, sizeof (tbuf1), DATEFMT, 183*5c51f124SMoriah Waterland localtime(&cinfo->modtime)) == 0) { 184*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_MEM)); 185*5c51f124SMoriah Waterland } 186*5c51f124SMoriah Waterland if (strftime(tbuf2, sizeof (tbuf2), DATEFMT, 187*5c51f124SMoriah Waterland localtime(&status.st_mtime)) == 0) { 188*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_MEM)); 189*5c51f124SMoriah Waterland } 190*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_MTIME), tbuf1, tbuf2); 191*5c51f124SMoriah Waterland retcode = VE_CONT; 192*5c51f124SMoriah Waterland } 193*5c51f124SMoriah Waterland } 194*5c51f124SMoriah Waterland 195*5c51f124SMoriah Waterland if (setval || (cinfo->size == (fsblkcnt_t)BADCONT)) { 196*5c51f124SMoriah Waterland cinfo->size = status.st_size; 197*5c51f124SMoriah Waterland } else if (status.st_size != cinfo->size) { 198*5c51f124SMoriah Waterland if (!retcode) { 199*5c51f124SMoriah Waterland retcode = VE_CONT; 200*5c51f124SMoriah Waterland } 201*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_SIZE), cinfo->size, status.st_size); 202*5c51f124SMoriah Waterland } 203*5c51f124SMoriah Waterland 204*5c51f124SMoriah Waterland cksumerr = 0; 205*5c51f124SMoriah Waterland 206*5c51f124SMoriah Waterland /* 207*5c51f124SMoriah Waterland * see if checksumming should be done: if checksumming is allowed, 208*5c51f124SMoriah Waterland * and checksumming is enabled, then checksum the file. 209*5c51f124SMoriah Waterland */ 210*5c51f124SMoriah Waterland 211*5c51f124SMoriah Waterland /* return if no need to compute checksum */ 212*5c51f124SMoriah Waterland 213*5c51f124SMoriah Waterland if ((allow_checksum == 0) || (enable_checksum == 0)) { 214*5c51f124SMoriah Waterland return (retcode); 215*5c51f124SMoriah Waterland } 216*5c51f124SMoriah Waterland 217*5c51f124SMoriah Waterland /* compute checksum */ 218*5c51f124SMoriah Waterland 219*5c51f124SMoriah Waterland mycksum = compute_checksum(&cksumerr, path); 220*5c51f124SMoriah Waterland 221*5c51f124SMoriah Waterland /* set value if not set or if checksum cannot be computed */ 222*5c51f124SMoriah Waterland 223*5c51f124SMoriah Waterland if (setval || (cinfo->cksum == BADCONT)) { 224*5c51f124SMoriah Waterland cinfo->cksum = mycksum; 225*5c51f124SMoriah Waterland return (retcode); 226*5c51f124SMoriah Waterland } 227*5c51f124SMoriah Waterland 228*5c51f124SMoriah Waterland /* report / return error if checksums mismatch or there is an error */ 229*5c51f124SMoriah Waterland 230*5c51f124SMoriah Waterland if ((mycksum != cinfo->cksum) || cksumerr) { 231*5c51f124SMoriah Waterland if (!retcode) { 232*5c51f124SMoriah Waterland retcode = VE_CONT; 233*5c51f124SMoriah Waterland } 234*5c51f124SMoriah Waterland if (!cksumerr) { 235*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_CKSUM), cinfo->cksum, mycksum); 236*5c51f124SMoriah Waterland } 237*5c51f124SMoriah Waterland } 238*5c51f124SMoriah Waterland 239*5c51f124SMoriah Waterland return (retcode); 240*5c51f124SMoriah Waterland } 241*5c51f124SMoriah Waterland 242*5c51f124SMoriah Waterland /* 243*5c51f124SMoriah Waterland * Name: compute_checksum 244*5c51f124SMoriah Waterland * Description: generate checksum for specified file 245*5c51f124SMoriah Waterland * Arguments: r_cksumerr (int *) [RO, *RW] 246*5c51f124SMoriah Waterland * - pointer to integer that is set on return to: 247*5c51f124SMoriah Waterland * == 0 - no error occurred 248*5c51f124SMoriah Waterland * != 0 - error occurred 249*5c51f124SMoriah Waterland * a_path (char *) [RO, *RO] 250*5c51f124SMoriah Waterland * - pointer to string representing path to file to 251*5c51f124SMoriah Waterland * generate checksum of 252*5c51f124SMoriah Waterland * Returns: unsigned long - results: 253*5c51f124SMoriah Waterland * - If *r_cksumerr == 0, checksum of specified file 254*5c51f124SMoriah Waterland * - If *r_cksumerr != 0, undefined 255*5c51f124SMoriah Waterland */ 256*5c51f124SMoriah Waterland unsigned long 257*5c51f124SMoriah Waterland compute_checksum(int *r_cksumerr, char *a_path) 258*5c51f124SMoriah Waterland { 259*5c51f124SMoriah Waterland CHECKSUM_T suma; /* to split four-bytes into 2 two-byte values */ 260*5c51f124SMoriah Waterland CHECKSUM_T tempa; 261*5c51f124SMoriah Waterland int fd; 262*5c51f124SMoriah Waterland uint32_t lg; /* running checksum value */ 263*5c51f124SMoriah Waterland uint32_t buf[CHUNK/4]; /* to read CHUNK bytes */ 264*5c51f124SMoriah Waterland uint32_t lsavhi; /* high order two-bytes of four-byte checksum */ 265*5c51f124SMoriah Waterland uint32_t lsavlo; /* low order two-bytes of four-byte checksum */ 266*5c51f124SMoriah Waterland int leap = sizeof (uint32_t); 267*5c51f124SMoriah Waterland int notyet = 0; 268*5c51f124SMoriah Waterland int nread; 269*5c51f124SMoriah Waterland struct stat64 sbuf; 270*5c51f124SMoriah Waterland 271*5c51f124SMoriah Waterland /* reset error flag */ 272*5c51f124SMoriah Waterland *r_cksumerr = 0; 273*5c51f124SMoriah Waterland 274*5c51f124SMoriah Waterland /* open file and obtain -> where file is mapped/read */ 275*5c51f124SMoriah Waterland if ((fd = open(a_path, O_RDONLY)) < 0) { 276*5c51f124SMoriah Waterland *r_cksumerr = 1; 277*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_NO_CKSUM)); 278*5c51f124SMoriah Waterland perror(ERR_NO_CKSUM); 279*5c51f124SMoriah Waterland return (0); 280*5c51f124SMoriah Waterland } 281*5c51f124SMoriah Waterland 282*5c51f124SMoriah Waterland if (fstat64(fd, &sbuf) != 0) { 283*5c51f124SMoriah Waterland *r_cksumerr = 1; 284*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_NO_CKSUM)); 285*5c51f124SMoriah Waterland perror(ERR_NO_CKSUM); 286*5c51f124SMoriah Waterland return (0); 287*5c51f124SMoriah Waterland } 288*5c51f124SMoriah Waterland 289*5c51f124SMoriah Waterland /* initialize checksum value */ 290*5c51f124SMoriah Waterland lg = 0; 291*5c51f124SMoriah Waterland 292*5c51f124SMoriah Waterland /* 293*5c51f124SMoriah Waterland * Read CHUNK bytes off the file at a time; Read size of long bytes 294*5c51f124SMoriah Waterland * from memory at a time and process them. 295*5c51f124SMoriah Waterland * If last read, then read remnant bytes and process individually. 296*5c51f124SMoriah Waterland */ 297*5c51f124SMoriah Waterland errno = 0; 298*5c51f124SMoriah Waterland while ((nread = read(fd, (void*)buf, 299*5c51f124SMoriah Waterland (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) { 300*5c51f124SMoriah Waterland uchar_t *s; 301*5c51f124SMoriah Waterland uint32_t *p = buf; 302*5c51f124SMoriah Waterland 303*5c51f124SMoriah Waterland notyet = nread % leap; 304*5c51f124SMoriah Waterland nread -= notyet; 305*5c51f124SMoriah Waterland 306*5c51f124SMoriah Waterland for (; nread > 0; nread -= leap) { 307*5c51f124SMoriah Waterland lg += ((((*p)>>24)&0xFF) & WDMSK); 308*5c51f124SMoriah Waterland lg += ((((*p)>>16)&0xFF) & WDMSK); 309*5c51f124SMoriah Waterland lg += ((((*p)>>8)&0xFF) & WDMSK); 310*5c51f124SMoriah Waterland lg += (((*p)&0xFF) & WDMSK); 311*5c51f124SMoriah Waterland p++; 312*5c51f124SMoriah Waterland } 313*5c51f124SMoriah Waterland s = (uchar_t *)p; 314*5c51f124SMoriah Waterland /* leftover bytes less than four in number */ 315*5c51f124SMoriah Waterland while (notyet--) 316*5c51f124SMoriah Waterland lg += (((uint32_t)(*s++)) & WDMSK); 317*5c51f124SMoriah Waterland } 318*5c51f124SMoriah Waterland 319*5c51f124SMoriah Waterland /* wind up */ 320*5c51f124SMoriah Waterland (void) close(fd); 321*5c51f124SMoriah Waterland 322*5c51f124SMoriah Waterland /* compute checksum components */ 323*5c51f124SMoriah Waterland suma.lg = lg; 324*5c51f124SMoriah Waterland tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK); 325*5c51f124SMoriah Waterland lsavhi = (uint32_t)tempa.hl.hi; 326*5c51f124SMoriah Waterland lsavlo = (uint32_t)tempa.hl.lo; 327*5c51f124SMoriah Waterland 328*5c51f124SMoriah Waterland /* return final checksum value */ 329*5c51f124SMoriah Waterland return (lsavhi+lsavlo); 330*5c51f124SMoriah Waterland } 331*5c51f124SMoriah Waterland 332*5c51f124SMoriah Waterland static struct stat status; /* file status buffer */ 333*5c51f124SMoriah Waterland static struct statvfs vfsstatus; /* filesystem status buffer */ 334*5c51f124SMoriah Waterland 335*5c51f124SMoriah Waterland /* 336*5c51f124SMoriah Waterland * Remove the thing that's currently in place so we can put down the package 337*5c51f124SMoriah Waterland * object. If we're replacing a directory with a directory, leave it alone. 338*5c51f124SMoriah Waterland * Returns 1 if all OK and 0 if failed. 339*5c51f124SMoriah Waterland */ 340*5c51f124SMoriah Waterland static int 341*5c51f124SMoriah Waterland clear_target(char *path, char *ftype, int is_a_dir) 342*5c51f124SMoriah Waterland { 343*5c51f124SMoriah Waterland int retcode = 1; 344*5c51f124SMoriah Waterland 345*5c51f124SMoriah Waterland if (is_a_dir) { /* if there's a directory there already ... */ 346*5c51f124SMoriah Waterland /* ... and this isn't, ... */ 347*5c51f124SMoriah Waterland if ((*ftype != 'd') && (*ftype != 'x')) { 348*5c51f124SMoriah Waterland if (rmdir(path)) { /* try to remove it. */ 349*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_RMDIR), path); 350*5c51f124SMoriah Waterland retcode = 0; 351*5c51f124SMoriah Waterland } 352*5c51f124SMoriah Waterland } 353*5c51f124SMoriah Waterland } else { 354*5c51f124SMoriah Waterland if (remove(path)) { 355*5c51f124SMoriah Waterland if (errno != ENOENT) { 356*5c51f124SMoriah Waterland retcode = 0; /* It didn't work. */ 357*5c51f124SMoriah Waterland } 358*5c51f124SMoriah Waterland } 359*5c51f124SMoriah Waterland } 360*5c51f124SMoriah Waterland 361*5c51f124SMoriah Waterland return (retcode); 362*5c51f124SMoriah Waterland } 363*5c51f124SMoriah Waterland 364*5c51f124SMoriah Waterland /* 365*5c51f124SMoriah Waterland * Name: averify 366*5c51f124SMoriah Waterland * Description: This function verifies and (if fix > 0) fixes the attributes 367*5c51f124SMoriah Waterland * of the file at the path provided. 368*5c51f124SMoriah Waterland * Arguments: fix - 0 - do not fix entries, 1 - fix entries 369*5c51f124SMoriah Waterland * ftype - single character "type" the entry is supposed to be 370*5c51f124SMoriah Waterland * path - path to file 371*5c51f124SMoriah Waterland * ainfo - attribute info structure representing the attributes 372*5c51f124SMoriah Waterland * the entry is supposed to be 373*5c51f124SMoriah Waterland * NOTE: attributes are links and permissions 374*5c51f124SMoriah Waterland * Possible return values: 375*5c51f124SMoriah Waterland * - 0 = successful 376*5c51f124SMoriah Waterland * - VE_EXIST = path name does not exist 377*5c51f124SMoriah Waterland * - VE_FTYPE = path file type is not recognized, is not supported, 378*5c51f124SMoriah Waterland * or is not what was expected 379*5c51f124SMoriah Waterland * - VE_ATTR = path mode/group/user is not what was expected 380*5c51f124SMoriah Waterland * - VE_CONT = mod time/link target/major/minor/size/file system type/current 381*5c51f124SMoriah Waterland * directory is not what was expected 382*5c51f124SMoriah Waterland * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/ 383*5c51f124SMoriah Waterland * chown failed 384*5c51f124SMoriah Waterland */ 385*5c51f124SMoriah Waterland int 386*5c51f124SMoriah Waterland averify(int fix, char *ftype, char *path, struct ainfo *ainfo) 387*5c51f124SMoriah Waterland { 388*5c51f124SMoriah Waterland struct group *grp; /* group entry buffer */ 389*5c51f124SMoriah Waterland struct passwd *pwd; 390*5c51f124SMoriah Waterland int n; 391*5c51f124SMoriah Waterland int setval; 392*5c51f124SMoriah Waterland int uid, gid; 393*5c51f124SMoriah Waterland int dochown; 394*5c51f124SMoriah Waterland int retcode; 395*5c51f124SMoriah Waterland int statError = 0; 396*5c51f124SMoriah Waterland int targ_is_dir = 0; /* replacing a directory */ 397*5c51f124SMoriah Waterland char myftype; 398*5c51f124SMoriah Waterland char buf[PATH_MAX]; 399*5c51f124SMoriah Waterland ino_t my_ino; 400*5c51f124SMoriah Waterland dev_t my_dev; 401*5c51f124SMoriah Waterland char cwd[MAXPATHLEN]; 402*5c51f124SMoriah Waterland char *cd; 403*5c51f124SMoriah Waterland char *c; 404*5c51f124SMoriah Waterland 405*5c51f124SMoriah Waterland setval = (*ftype == '?'); 406*5c51f124SMoriah Waterland retcode = 0; 407*5c51f124SMoriah Waterland reperr(NULL); 408*5c51f124SMoriah Waterland 409*5c51f124SMoriah Waterland if (get_disable_attribute_check()) { 410*5c51f124SMoriah Waterland return (0); 411*5c51f124SMoriah Waterland } 412*5c51f124SMoriah Waterland 413*5c51f124SMoriah Waterland if (*ftype == 'l') { 414*5c51f124SMoriah Waterland if (stat(path, &status) < 0) { 415*5c51f124SMoriah Waterland retcode = VE_EXIST; 416*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_EXIST)); 417*5c51f124SMoriah Waterland } 418*5c51f124SMoriah Waterland 419*5c51f124SMoriah Waterland my_ino = status.st_ino; 420*5c51f124SMoriah Waterland my_dev = status.st_dev; 421*5c51f124SMoriah Waterland 422*5c51f124SMoriah Waterland /* Get copy of the current working directory */ 423*5c51f124SMoriah Waterland if (getcwd(cwd, MAXPATHLEN) == NULL) { 424*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_GETWD), ainfo->local); 425*5c51f124SMoriah Waterland return (VE_FAIL); 426*5c51f124SMoriah Waterland } 427*5c51f124SMoriah Waterland 428*5c51f124SMoriah Waterland /* 429*5c51f124SMoriah Waterland * Change to the directory in which the hard 430*5c51f124SMoriah Waterland * link is to be created. 431*5c51f124SMoriah Waterland */ 432*5c51f124SMoriah Waterland cd = strdup(path); 433*5c51f124SMoriah Waterland c = strrchr(cd, '/'); 434*5c51f124SMoriah Waterland if (c) { 435*5c51f124SMoriah Waterland /* bugid 4247895 */ 436*5c51f124SMoriah Waterland if (strcmp(cd, c) == 0) 437*5c51f124SMoriah Waterland strcpy(cd, "/"); 438*5c51f124SMoriah Waterland else 439*5c51f124SMoriah Waterland *c = NULL; 440*5c51f124SMoriah Waterland 441*5c51f124SMoriah Waterland if (chdir(cd) != 0) { 442*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_CHDIR), cd); 443*5c51f124SMoriah Waterland return (VE_FAIL); 444*5c51f124SMoriah Waterland } 445*5c51f124SMoriah Waterland } 446*5c51f124SMoriah Waterland free(cd); 447*5c51f124SMoriah Waterland 448*5c51f124SMoriah Waterland if (retcode || (status.st_nlink < 2) || 449*5c51f124SMoriah Waterland (stat(ainfo->local, &status) < 0) || 450*5c51f124SMoriah Waterland (my_dev != status.st_dev) || (my_ino != status.st_ino)) { 451*5c51f124SMoriah Waterland if (fix) { 452*5c51f124SMoriah Waterland /* 453*5c51f124SMoriah Waterland * Don't want to do a hard link to a 454*5c51f124SMoriah Waterland * directory. 455*5c51f124SMoriah Waterland */ 456*5c51f124SMoriah Waterland if (!isdir(ainfo->local)) { 457*5c51f124SMoriah Waterland chdir(cwd); 458*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_LINKISDIR), 459*5c51f124SMoriah Waterland ainfo->local); 460*5c51f124SMoriah Waterland return (VE_FAIL); 461*5c51f124SMoriah Waterland } 462*5c51f124SMoriah Waterland /* Now do the link. */ 463*5c51f124SMoriah Waterland if (!clear_target(path, ftype, targ_is_dir)) 464*5c51f124SMoriah Waterland return (VE_FAIL); 465*5c51f124SMoriah Waterland 466*5c51f124SMoriah Waterland if (link(ainfo->local, path)) { 467*5c51f124SMoriah Waterland chdir(cwd); 468*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_LINKFAIL), 469*5c51f124SMoriah Waterland ainfo->local); 470*5c51f124SMoriah Waterland return (VE_FAIL); 471*5c51f124SMoriah Waterland } 472*5c51f124SMoriah Waterland retcode = 0; 473*5c51f124SMoriah Waterland } else { 474*5c51f124SMoriah Waterland /* Go back to previous working directory */ 475*5c51f124SMoriah Waterland if (chdir(cwd) != 0) 476*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_CHDIR), cwd); 477*5c51f124SMoriah Waterland 478*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_LINK), ainfo->local); 479*5c51f124SMoriah Waterland return (VE_CONT); 480*5c51f124SMoriah Waterland } 481*5c51f124SMoriah Waterland } 482*5c51f124SMoriah Waterland 483*5c51f124SMoriah Waterland /* Go back to previous working directory */ 484*5c51f124SMoriah Waterland if (chdir(cwd) != 0) { 485*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_CHDIR), cwd); 486*5c51f124SMoriah Waterland return (VE_CONT); 487*5c51f124SMoriah Waterland } 488*5c51f124SMoriah Waterland 489*5c51f124SMoriah Waterland return (retcode); 490*5c51f124SMoriah Waterland } 491*5c51f124SMoriah Waterland 492*5c51f124SMoriah Waterland retcode = 0; 493*5c51f124SMoriah Waterland 494*5c51f124SMoriah Waterland /* If we are to process symlinks the old way then we follow the link */ 495*5c51f124SMoriah Waterland if (nonABI_symlinks()) { 496*5c51f124SMoriah Waterland if ((*ftype == 's') ? lstat(path, &status) : 497*5c51f124SMoriah Waterland stat(path, &status)) { 498*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_EXIST)); 499*5c51f124SMoriah Waterland retcode = VE_EXIST; 500*5c51f124SMoriah Waterland myftype = '?'; 501*5c51f124SMoriah Waterland statError++; 502*5c51f124SMoriah Waterland } 503*5c51f124SMoriah Waterland /* If not then we inspect the target of the link */ 504*5c51f124SMoriah Waterland } else { 505*5c51f124SMoriah Waterland if ((n = lstat(path, &status)) == -1) { 506*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_EXIST)); 507*5c51f124SMoriah Waterland retcode = VE_EXIST; 508*5c51f124SMoriah Waterland myftype = '?'; 509*5c51f124SMoriah Waterland statError++; 510*5c51f124SMoriah Waterland } 511*5c51f124SMoriah Waterland } 512*5c51f124SMoriah Waterland if (!statError) { 513*5c51f124SMoriah Waterland /* determining actual type of existing object */ 514*5c51f124SMoriah Waterland switch (status.st_mode & S_IFMT) { 515*5c51f124SMoriah Waterland case S_IFLNK: 516*5c51f124SMoriah Waterland myftype = 's'; 517*5c51f124SMoriah Waterland break; 518*5c51f124SMoriah Waterland 519*5c51f124SMoriah Waterland case S_IFIFO: 520*5c51f124SMoriah Waterland myftype = 'p'; 521*5c51f124SMoriah Waterland break; 522*5c51f124SMoriah Waterland 523*5c51f124SMoriah Waterland case S_IFCHR: 524*5c51f124SMoriah Waterland myftype = 'c'; 525*5c51f124SMoriah Waterland break; 526*5c51f124SMoriah Waterland 527*5c51f124SMoriah Waterland case S_IFDIR: 528*5c51f124SMoriah Waterland myftype = 'd'; 529*5c51f124SMoriah Waterland targ_is_dir = 1; 530*5c51f124SMoriah Waterland break; 531*5c51f124SMoriah Waterland 532*5c51f124SMoriah Waterland case S_IFBLK: 533*5c51f124SMoriah Waterland myftype = 'b'; 534*5c51f124SMoriah Waterland break; 535*5c51f124SMoriah Waterland 536*5c51f124SMoriah Waterland case S_IFREG: 537*5c51f124SMoriah Waterland case 0: 538*5c51f124SMoriah Waterland myftype = 'f'; 539*5c51f124SMoriah Waterland break; 540*5c51f124SMoriah Waterland 541*5c51f124SMoriah Waterland case S_IFDOOR: 542*5c51f124SMoriah Waterland myftype = 'D'; 543*5c51f124SMoriah Waterland break; 544*5c51f124SMoriah Waterland 545*5c51f124SMoriah Waterland default: 546*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_UNKNOWN)); 547*5c51f124SMoriah Waterland return (VE_FTYPE); 548*5c51f124SMoriah Waterland } 549*5c51f124SMoriah Waterland } 550*5c51f124SMoriah Waterland 551*5c51f124SMoriah Waterland if (setval) { 552*5c51f124SMoriah Waterland /* 553*5c51f124SMoriah Waterland * Check to make sure that a package or an installf that uses 554*5c51f124SMoriah Waterland * wild cards '?' to assume the ftype of an object on the 555*5c51f124SMoriah Waterland * system is not assuming a door ftype. Doors are not supported 556*5c51f124SMoriah Waterland * but should be ignored. 557*5c51f124SMoriah Waterland */ 558*5c51f124SMoriah Waterland if (myftype == 'D') { 559*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_FTYPED), path); 560*5c51f124SMoriah Waterland retcode = VE_FTYPE; 561*5c51f124SMoriah Waterland return (VE_FTYPE); 562*5c51f124SMoriah Waterland } else { 563*5c51f124SMoriah Waterland *ftype = myftype; 564*5c51f124SMoriah Waterland } 565*5c51f124SMoriah Waterland } else if (!retcode && (*ftype != myftype) && 566*5c51f124SMoriah Waterland ((myftype != 'f') || !strchr("ilev", *ftype)) && 567*5c51f124SMoriah Waterland ((myftype != 'd') || (*ftype != 'x'))) { 568*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_FTYPE), *ftype, myftype); 569*5c51f124SMoriah Waterland retcode = VE_FTYPE; 570*5c51f124SMoriah Waterland } 571*5c51f124SMoriah Waterland 572*5c51f124SMoriah Waterland if (!retcode && (*ftype == 's')) { 573*5c51f124SMoriah Waterland /* make sure that symbolic link is correct */ 574*5c51f124SMoriah Waterland n = readlink(path, buf, PATH_MAX); 575*5c51f124SMoriah Waterland if (n < 0) { 576*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_SLINK), ainfo->local); 577*5c51f124SMoriah Waterland retcode = VE_CONT; 578*5c51f124SMoriah Waterland } else if (ainfo->local != NULL) { 579*5c51f124SMoriah Waterland buf[n] = '\0'; 580*5c51f124SMoriah Waterland if (strcmp(buf, ainfo->local)) { 581*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_SLINK), ainfo->local); 582*5c51f124SMoriah Waterland retcode = VE_CONT; 583*5c51f124SMoriah Waterland } 584*5c51f124SMoriah Waterland } else if (ainfo->local == NULL) { 585*5c51f124SMoriah Waterland /* 586*5c51f124SMoriah Waterland * Since a sym link target exists, insert it 587*5c51f124SMoriah Waterland * into the ainfo structure 588*5c51f124SMoriah Waterland */ 589*5c51f124SMoriah Waterland buf[n] = '\0'; 590*5c51f124SMoriah Waterland ainfo->local = strdup(buf); 591*5c51f124SMoriah Waterland } 592*5c51f124SMoriah Waterland } 593*5c51f124SMoriah Waterland 594*5c51f124SMoriah Waterland if (retcode) { 595*5c51f124SMoriah Waterland /* The path doesn't exist or is different than it should be. */ 596*5c51f124SMoriah Waterland if (fix) { 597*5c51f124SMoriah Waterland /* 598*5c51f124SMoriah Waterland * Clear the way for the write. If it won't clear, 599*5c51f124SMoriah Waterland * there's nothing we can do. 600*5c51f124SMoriah Waterland */ 601*5c51f124SMoriah Waterland if (!clear_target(path, ftype, targ_is_dir)) 602*5c51f124SMoriah Waterland return (VE_FAIL); 603*5c51f124SMoriah Waterland 604*5c51f124SMoriah Waterland if ((*ftype == 'd') || (*ftype == 'x')) { 605*5c51f124SMoriah Waterland char *pt, *p; 606*5c51f124SMoriah Waterland 607*5c51f124SMoriah Waterland /* Try to make it the easy way */ 608*5c51f124SMoriah Waterland if (mkdir(path, ainfo->mode)) { 609*5c51f124SMoriah Waterland /* 610*5c51f124SMoriah Waterland * Failing that, walk through the 611*5c51f124SMoriah Waterland * parent directories creating 612*5c51f124SMoriah Waterland * whatever is needed. 613*5c51f124SMoriah Waterland */ 614*5c51f124SMoriah Waterland p = strdup(path); 615*5c51f124SMoriah Waterland pt = (*p == '/') ? p+1 : p; 616*5c51f124SMoriah Waterland do { 617*5c51f124SMoriah Waterland if (pt = strchr(pt, '/')) 618*5c51f124SMoriah Waterland *pt = '\0'; 619*5c51f124SMoriah Waterland if (access(p, 0) && 620*5c51f124SMoriah Waterland mkdir(p, ainfo->mode)) 621*5c51f124SMoriah Waterland break; 622*5c51f124SMoriah Waterland if (pt) 623*5c51f124SMoriah Waterland *pt++ = '/'; 624*5c51f124SMoriah Waterland } while (pt); 625*5c51f124SMoriah Waterland free(p); 626*5c51f124SMoriah Waterland } 627*5c51f124SMoriah Waterland if (stat(path, &status) < 0) { 628*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_DIRFAIL)); 629*5c51f124SMoriah Waterland return (VE_FAIL); 630*5c51f124SMoriah Waterland } 631*5c51f124SMoriah Waterland } else if (*ftype == 's') { 632*5c51f124SMoriah Waterland if (symlink(ainfo->local, path)) { 633*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_SLINKFAIL), 634*5c51f124SMoriah Waterland ainfo->local); 635*5c51f124SMoriah Waterland return (VE_FAIL); 636*5c51f124SMoriah Waterland } 637*5c51f124SMoriah Waterland 638*5c51f124SMoriah Waterland } else if (*ftype == 'c') { 639*5c51f124SMoriah Waterland int wilddevno = 0; 640*5c51f124SMoriah Waterland /* 641*5c51f124SMoriah Waterland * The next three if's support 2.4 and older 642*5c51f124SMoriah Waterland * packages that use "?" as device numbers. 643*5c51f124SMoriah Waterland * This should be considered for removal by 644*5c51f124SMoriah Waterland * release 2.7 or so. 645*5c51f124SMoriah Waterland */ 646*5c51f124SMoriah Waterland if (ainfo->major == BADMAJOR) { 647*5c51f124SMoriah Waterland ainfo->major = 0; 648*5c51f124SMoriah Waterland wilddevno = 1; 649*5c51f124SMoriah Waterland } 650*5c51f124SMoriah Waterland 651*5c51f124SMoriah Waterland if (ainfo->minor == BADMINOR) { 652*5c51f124SMoriah Waterland ainfo->minor = 0; 653*5c51f124SMoriah Waterland wilddevno = 1; 654*5c51f124SMoriah Waterland } 655*5c51f124SMoriah Waterland 656*5c51f124SMoriah Waterland if (wilddevno) { 657*5c51f124SMoriah Waterland wilddevno = 0; 658*5c51f124SMoriah Waterland logerr(MSG_WLDDEVNO, path, 659*5c51f124SMoriah Waterland ainfo->major, ainfo->minor); 660*5c51f124SMoriah Waterland } 661*5c51f124SMoriah Waterland 662*5c51f124SMoriah Waterland if (mknod(path, ainfo->mode | S_IFCHR, 663*5c51f124SMoriah Waterland #ifdef SUNOS41 664*5c51f124SMoriah Waterland makedev(ainfo->xmajor, ainfo->xminor)) || 665*5c51f124SMoriah Waterland #else 666*5c51f124SMoriah Waterland makedev(ainfo->major, ainfo->minor)) || 667*5c51f124SMoriah Waterland #endif 668*5c51f124SMoriah Waterland (stat(path, &status) < 0)) { 669*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_CDEVFAIL)); 670*5c51f124SMoriah Waterland return (VE_FAIL); 671*5c51f124SMoriah Waterland } 672*5c51f124SMoriah Waterland } else if (*ftype == 'b') { 673*5c51f124SMoriah Waterland int wilddevno = 0; 674*5c51f124SMoriah Waterland /* 675*5c51f124SMoriah Waterland * The next three if's support 2.4 and older 676*5c51f124SMoriah Waterland * packages that use "?" as device numbers. 677*5c51f124SMoriah Waterland * This should be considered for removal by 678*5c51f124SMoriah Waterland * release 2.7 or so. 679*5c51f124SMoriah Waterland */ 680*5c51f124SMoriah Waterland if (ainfo->major == BADMAJOR) { 681*5c51f124SMoriah Waterland ainfo->major = 0; 682*5c51f124SMoriah Waterland wilddevno = 1; 683*5c51f124SMoriah Waterland } 684*5c51f124SMoriah Waterland 685*5c51f124SMoriah Waterland if (ainfo->minor == BADMINOR) { 686*5c51f124SMoriah Waterland ainfo->minor = 0; 687*5c51f124SMoriah Waterland wilddevno = 1; 688*5c51f124SMoriah Waterland } 689*5c51f124SMoriah Waterland 690*5c51f124SMoriah Waterland if (wilddevno) { 691*5c51f124SMoriah Waterland wilddevno = 0; 692*5c51f124SMoriah Waterland logerr(MSG_WLDDEVNO, path, 693*5c51f124SMoriah Waterland ainfo->major, ainfo->minor); 694*5c51f124SMoriah Waterland } 695*5c51f124SMoriah Waterland 696*5c51f124SMoriah Waterland if (mknod(path, ainfo->mode | S_IFBLK, 697*5c51f124SMoriah Waterland #ifdef SUNOS41 698*5c51f124SMoriah Waterland makedev(ainfo->xmajor, ainfo->xminor)) || 699*5c51f124SMoriah Waterland #else 700*5c51f124SMoriah Waterland makedev(ainfo->major, ainfo->minor)) || 701*5c51f124SMoriah Waterland #endif 702*5c51f124SMoriah Waterland (stat(path, &status) < 0)) { 703*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_BDEVFAIL)); 704*5c51f124SMoriah Waterland return (VE_FAIL); 705*5c51f124SMoriah Waterland } 706*5c51f124SMoriah Waterland } else if (*ftype == 'p') { 707*5c51f124SMoriah Waterland if (mknod(path, ainfo->mode | S_IFIFO, NULL) || 708*5c51f124SMoriah Waterland (stat(path, &status) < 0)) { 709*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_PIPEFAIL)); 710*5c51f124SMoriah Waterland return (VE_FAIL); 711*5c51f124SMoriah Waterland } 712*5c51f124SMoriah Waterland } else 713*5c51f124SMoriah Waterland return (retcode); 714*5c51f124SMoriah Waterland 715*5c51f124SMoriah Waterland } else 716*5c51f124SMoriah Waterland return (retcode); 717*5c51f124SMoriah Waterland } 718*5c51f124SMoriah Waterland 719*5c51f124SMoriah Waterland if (*ftype == 's') 720*5c51f124SMoriah Waterland return (0); /* don't check anything else */ 721*5c51f124SMoriah Waterland if (*ftype == 'i') 722*5c51f124SMoriah Waterland return (0); /* don't check anything else */ 723*5c51f124SMoriah Waterland 724*5c51f124SMoriah Waterland retcode = 0; 725*5c51f124SMoriah Waterland if ((myftype == 'c') || (myftype == 'b')) { 726*5c51f124SMoriah Waterland #ifdef SUNOS41 727*5c51f124SMoriah Waterland if (setval || (ainfo->xmajor < 0)) 728*5c51f124SMoriah Waterland ainfo->xmajor = ((status.st_rdev>>8)&0377); 729*5c51f124SMoriah Waterland if (setval || (ainfo->xminor < 0)) 730*5c51f124SMoriah Waterland ainfo->xminor = (status.st_rdev&0377); 731*5c51f124SMoriah Waterland /* check major & minor */ 732*5c51f124SMoriah Waterland if (status.st_rdev != makedev(ainfo->xmajor, ainfo->xminor)) { 733*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_MAJMIN), ainfo->xmajor, 734*5c51f124SMoriah Waterland ainfo->xminor, 735*5c51f124SMoriah Waterland (status.st_rdev>>8)&0377, status.st_rdev&0377); 736*5c51f124SMoriah Waterland retcode = VE_CONT; 737*5c51f124SMoriah Waterland } 738*5c51f124SMoriah Waterland #else 739*5c51f124SMoriah Waterland if (setval || (ainfo->major == BADMAJOR)) 740*5c51f124SMoriah Waterland ainfo->major = major(status.st_rdev); 741*5c51f124SMoriah Waterland if (setval || (ainfo->minor == BADMINOR)) 742*5c51f124SMoriah Waterland ainfo->minor = minor(status.st_rdev); 743*5c51f124SMoriah Waterland /* check major & minor */ 744*5c51f124SMoriah Waterland if (status.st_rdev != makedev(ainfo->major, ainfo->minor)) { 745*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_MAJMIN), ainfo->major, ainfo->minor, 746*5c51f124SMoriah Waterland major(status.st_rdev), minor(status.st_rdev)); 747*5c51f124SMoriah Waterland retcode = VE_CONT; 748*5c51f124SMoriah Waterland } 749*5c51f124SMoriah Waterland #endif 750*5c51f124SMoriah Waterland } 751*5c51f124SMoriah Waterland 752*5c51f124SMoriah Waterland /* compare specified mode w/ actual mode excluding sticky bit */ 753*5c51f124SMoriah Waterland if (setval || (ainfo->mode == BADMODE) || (ainfo->mode == WILDCARD)) 754*5c51f124SMoriah Waterland ainfo->mode = status.st_mode & 07777; 755*5c51f124SMoriah Waterland else if ((ainfo->mode & 06777) != (status.st_mode & 06777)) { 756*5c51f124SMoriah Waterland if (fix) { 757*5c51f124SMoriah Waterland if ((ainfo->mode == BADMODE) || 758*5c51f124SMoriah Waterland (chmod(path, ainfo->mode) < 0)) 759*5c51f124SMoriah Waterland retcode = VE_FAIL; 760*5c51f124SMoriah Waterland } else { 761*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_PERM), ainfo->mode, 762*5c51f124SMoriah Waterland status.st_mode & 07777); 763*5c51f124SMoriah Waterland if (!retcode) 764*5c51f124SMoriah Waterland retcode = VE_ATTR; 765*5c51f124SMoriah Waterland } 766*5c51f124SMoriah Waterland } 767*5c51f124SMoriah Waterland 768*5c51f124SMoriah Waterland dochown = 0; 769*5c51f124SMoriah Waterland 770*5c51f124SMoriah Waterland /* get group entry for specified group */ 771*5c51f124SMoriah Waterland if (setval || strcmp(ainfo->group, BADGROUP) == 0) { 772*5c51f124SMoriah Waterland grp = cgrgid(status.st_gid); 773*5c51f124SMoriah Waterland if (grp) 774*5c51f124SMoriah Waterland (void) strcpy(ainfo->group, grp->gr_name); 775*5c51f124SMoriah Waterland else { 776*5c51f124SMoriah Waterland if (!retcode) 777*5c51f124SMoriah Waterland retcode = VE_ATTR; 778*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_BADGRPID), status.st_gid); 779*5c51f124SMoriah Waterland } 780*5c51f124SMoriah Waterland gid = status.st_gid; 781*5c51f124SMoriah Waterland } else if ((grp = cgrnam(ainfo->group)) == NULL) { 782*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_BADGRPNM), ainfo->group); 783*5c51f124SMoriah Waterland if (!retcode) 784*5c51f124SMoriah Waterland retcode = VE_ATTR; 785*5c51f124SMoriah Waterland } else if ((gid = grp->gr_gid) != status.st_gid) { 786*5c51f124SMoriah Waterland if (fix) { 787*5c51f124SMoriah Waterland /* save specified GID */ 788*5c51f124SMoriah Waterland gid = grp->gr_gid; 789*5c51f124SMoriah Waterland dochown++; 790*5c51f124SMoriah Waterland } else { 791*5c51f124SMoriah Waterland if ((grp = cgrgid((int)status.st_gid)) == 792*5c51f124SMoriah Waterland (struct group *)NULL) { 793*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_GROUP), ainfo->group, 794*5c51f124SMoriah Waterland "(null)"); 795*5c51f124SMoriah Waterland } else { 796*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_GROUP), ainfo->group, 797*5c51f124SMoriah Waterland grp->gr_name); 798*5c51f124SMoriah Waterland } 799*5c51f124SMoriah Waterland if (!retcode) 800*5c51f124SMoriah Waterland retcode = VE_ATTR; 801*5c51f124SMoriah Waterland } 802*5c51f124SMoriah Waterland } 803*5c51f124SMoriah Waterland 804*5c51f124SMoriah Waterland /* get password entry for specified owner */ 805*5c51f124SMoriah Waterland if (setval || strcmp(ainfo->owner, BADOWNER) == 0) { 806*5c51f124SMoriah Waterland pwd = cpwuid((int)status.st_uid); 807*5c51f124SMoriah Waterland if (pwd) 808*5c51f124SMoriah Waterland (void) strcpy(ainfo->owner, pwd->pw_name); 809*5c51f124SMoriah Waterland else { 810*5c51f124SMoriah Waterland if (!retcode) 811*5c51f124SMoriah Waterland retcode = VE_ATTR; 812*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_BADUSRID), status.st_uid); 813*5c51f124SMoriah Waterland } 814*5c51f124SMoriah Waterland uid = status.st_uid; 815*5c51f124SMoriah Waterland } else if ((pwd = cpwnam(ainfo->owner)) == NULL) { 816*5c51f124SMoriah Waterland /* UID does not exist in password file */ 817*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_BADUSRNM), ainfo->owner); 818*5c51f124SMoriah Waterland if (!retcode) 819*5c51f124SMoriah Waterland retcode = VE_ATTR; 820*5c51f124SMoriah Waterland } else if ((uid = pwd->pw_uid) != status.st_uid) { 821*5c51f124SMoriah Waterland /* get owner name for actual UID */ 822*5c51f124SMoriah Waterland if (fix) { 823*5c51f124SMoriah Waterland uid = pwd->pw_uid; 824*5c51f124SMoriah Waterland dochown++; 825*5c51f124SMoriah Waterland } else { 826*5c51f124SMoriah Waterland pwd = cpwuid((int)status.st_uid); 827*5c51f124SMoriah Waterland if (pwd == NULL) 828*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_BADUSRID), 829*5c51f124SMoriah Waterland (int)status.st_uid); 830*5c51f124SMoriah Waterland else 831*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_OWNER), ainfo->owner, 832*5c51f124SMoriah Waterland pwd->pw_name); 833*5c51f124SMoriah Waterland 834*5c51f124SMoriah Waterland if (!retcode) 835*5c51f124SMoriah Waterland retcode = VE_ATTR; 836*5c51f124SMoriah Waterland } 837*5c51f124SMoriah Waterland } 838*5c51f124SMoriah Waterland 839*5c51f124SMoriah Waterland if (statvfs(path, &vfsstatus) < 0) { 840*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_EXIST)); 841*5c51f124SMoriah Waterland retcode = VE_FAIL; 842*5c51f124SMoriah Waterland } else { 843*5c51f124SMoriah Waterland if (dochown) { 844*5c51f124SMoriah Waterland /* pcfs doesn't support file ownership */ 845*5c51f124SMoriah Waterland if (strcmp(vfsstatus.f_basetype, "pcfs") != 0 && 846*5c51f124SMoriah Waterland chown(path, uid, gid) < 0) { 847*5c51f124SMoriah Waterland retcode = VE_FAIL; /* chown failed */ 848*5c51f124SMoriah Waterland } 849*5c51f124SMoriah Waterland } 850*5c51f124SMoriah Waterland } 851*5c51f124SMoriah Waterland 852*5c51f124SMoriah Waterland if (retcode == VE_FAIL) 853*5c51f124SMoriah Waterland reperr(pkg_gt(ERR_ATTRFAIL)); 854*5c51f124SMoriah Waterland return (retcode); 855*5c51f124SMoriah Waterland } 856*5c51f124SMoriah Waterland 857*5c51f124SMoriah Waterland /* 858*5c51f124SMoriah Waterland * This is a special fast verify which basically checks the attributes 859*5c51f124SMoriah Waterland * and then, if all is OK, checks the size and mod time using the same 860*5c51f124SMoriah Waterland * stat and statvfs structures. 861*5c51f124SMoriah Waterland */ 862*5c51f124SMoriah Waterland int 863*5c51f124SMoriah Waterland fverify(int fix, char *ftype, char *path, struct ainfo *ainfo, 864*5c51f124SMoriah Waterland struct cinfo *cinfo) 865*5c51f124SMoriah Waterland { 866*5c51f124SMoriah Waterland int retval; 867*5c51f124SMoriah Waterland 868*5c51f124SMoriah Waterland /* return success if attribute checks are disabled */ 869*5c51f124SMoriah Waterland 870*5c51f124SMoriah Waterland if (get_disable_attribute_check()) { 871*5c51f124SMoriah Waterland return (0); 872*5c51f124SMoriah Waterland } 873*5c51f124SMoriah Waterland 874*5c51f124SMoriah Waterland if ((retval = averify(fix, ftype, path, ainfo)) == 0) { 875*5c51f124SMoriah Waterland if (*ftype == 'f' || *ftype == 'i') { 876*5c51f124SMoriah Waterland if (cinfo->size != status.st_size) { 877*5c51f124SMoriah Waterland reperr(pkg_gt(WRN_QV_SIZE), path); 878*5c51f124SMoriah Waterland retval = VE_CONT; 879*5c51f124SMoriah Waterland } 880*5c51f124SMoriah Waterland /* pcfs doesn't support modification times */ 881*5c51f124SMoriah Waterland if (strcmp(vfsstatus.f_basetype, "pcfs") != 0) { 882*5c51f124SMoriah Waterland if (cinfo->modtime != status.st_mtime) { 883*5c51f124SMoriah Waterland reperr(pkg_gt(WRN_QV_MTIME), path); 884*5c51f124SMoriah Waterland retval = VE_CONT; 885*5c51f124SMoriah Waterland } 886*5c51f124SMoriah Waterland } 887*5c51f124SMoriah Waterland } 888*5c51f124SMoriah Waterland } 889*5c51f124SMoriah Waterland 890*5c51f124SMoriah Waterland return (retval); 891*5c51f124SMoriah Waterland } 892*5c51f124SMoriah Waterland 893*5c51f124SMoriah Waterland /* 894*5c51f124SMoriah Waterland * This function determines whether or not non-ABI symlinks are supported. 895*5c51f124SMoriah Waterland */ 896*5c51f124SMoriah Waterland 897*5c51f124SMoriah Waterland int 898*5c51f124SMoriah Waterland nonABI_symlinks(void) 899*5c51f124SMoriah Waterland { 900*5c51f124SMoriah Waterland return (nonabi_symlinks); 901*5c51f124SMoriah Waterland } 902*5c51f124SMoriah Waterland 903*5c51f124SMoriah Waterland void 904*5c51f124SMoriah Waterland set_nonABI_symlinks(void) 905*5c51f124SMoriah Waterland { 906*5c51f124SMoriah Waterland nonabi_symlinks = 1; 907*5c51f124SMoriah Waterland } 908*5c51f124SMoriah Waterland 909*5c51f124SMoriah Waterland /* 910*5c51f124SMoriah Waterland * Disable attribute checking. Only disable attribute checking if files 911*5c51f124SMoriah Waterland * are guaranteed to exist in the FS. 912*5c51f124SMoriah Waterland */ 913*5c51f124SMoriah Waterland void 914*5c51f124SMoriah Waterland disable_attribute_check(void) 915*5c51f124SMoriah Waterland { 916*5c51f124SMoriah Waterland disable_attributes = 1; 917*5c51f124SMoriah Waterland } 918*5c51f124SMoriah Waterland 919*5c51f124SMoriah Waterland /* 920*5c51f124SMoriah Waterland * This function determines whether or not to do attribute checking. 921*5c51f124SMoriah Waterland * Returns: 0 - Do attribute checking 922*5c51f124SMoriah Waterland * !0 - Don't do attribute checking 923*5c51f124SMoriah Waterland */ 924*5c51f124SMoriah Waterland int 925*5c51f124SMoriah Waterland get_disable_attribute_check(void) 926*5c51f124SMoriah Waterland { 927*5c51f124SMoriah Waterland return (disable_attributes); 928*5c51f124SMoriah Waterland } 929*5c51f124SMoriah Waterland 930*5c51f124SMoriah Waterland /* 931*5c51f124SMoriah Waterland * This function returns the address of the "global" error buffer that 932*5c51f124SMoriah Waterland * is populated by the various functions in this module. 933*5c51f124SMoriah Waterland */ 934*5c51f124SMoriah Waterland 935*5c51f124SMoriah Waterland char * 936*5c51f124SMoriah Waterland getErrbufAddr(void) 937*5c51f124SMoriah Waterland { 938*5c51f124SMoriah Waterland return (theErrBuf); 939*5c51f124SMoriah Waterland } 940*5c51f124SMoriah Waterland 941*5c51f124SMoriah Waterland /* 942*5c51f124SMoriah Waterland * This function returns the size of the buffer returned by getErrbufAddr() 943*5c51f124SMoriah Waterland */ 944*5c51f124SMoriah Waterland 945*5c51f124SMoriah Waterland int 946*5c51f124SMoriah Waterland getErrbufSize(void) 947*5c51f124SMoriah Waterland { 948*5c51f124SMoriah Waterland return (sizeof (theErrBuf)); 949*5c51f124SMoriah Waterland } 950*5c51f124SMoriah Waterland 951*5c51f124SMoriah Waterland /* 952*5c51f124SMoriah Waterland * This function returns the current global "error string" 953*5c51f124SMoriah Waterland */ 954*5c51f124SMoriah Waterland 955*5c51f124SMoriah Waterland char * 956*5c51f124SMoriah Waterland getErrstr(void) 957*5c51f124SMoriah Waterland { 958*5c51f124SMoriah Waterland return (theErrStr); 959*5c51f124SMoriah Waterland } 960*5c51f124SMoriah Waterland 961*5c51f124SMoriah Waterland /* 962*5c51f124SMoriah Waterland * This function sets the global "error string" 963*5c51f124SMoriah Waterland */ 964*5c51f124SMoriah Waterland 965*5c51f124SMoriah Waterland void 966*5c51f124SMoriah Waterland setErrstr(char *a_errstr) 967*5c51f124SMoriah Waterland { 968*5c51f124SMoriah Waterland theErrStr = a_errstr; 969*5c51f124SMoriah Waterland } 970*5c51f124SMoriah Waterland 971*5c51f124SMoriah Waterland /* 972*5c51f124SMoriah Waterland * This function enables checksumming 973*5c51f124SMoriah Waterland */ 974*5c51f124SMoriah Waterland 975*5c51f124SMoriah Waterland void 976*5c51f124SMoriah Waterland checksum_on(void) 977*5c51f124SMoriah Waterland { 978*5c51f124SMoriah Waterland enable_checksum = 1; 979*5c51f124SMoriah Waterland } 980*5c51f124SMoriah Waterland 981*5c51f124SMoriah Waterland /* 982*5c51f124SMoriah Waterland * This function disables checksumming 983*5c51f124SMoriah Waterland */ 984*5c51f124SMoriah Waterland 985*5c51f124SMoriah Waterland void 986*5c51f124SMoriah Waterland checksum_off(void) 987*5c51f124SMoriah Waterland { 988*5c51f124SMoriah Waterland enable_checksum = 0; 989*5c51f124SMoriah Waterland } 990