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 2008 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 #include <stdio.h> 32*5c51f124SMoriah Waterland #include <fcntl.h> 33*5c51f124SMoriah Waterland #include <sys/types.h> 34*5c51f124SMoriah Waterland #include <sys/param.h> 35*5c51f124SMoriah Waterland #include <sys/sysmacros.h> 36*5c51f124SMoriah Waterland #include <string.h> 37*5c51f124SMoriah Waterland #include <strings.h> 38*5c51f124SMoriah Waterland #include <sys/wait.h> 39*5c51f124SMoriah Waterland #include <sys/stat.h> 40*5c51f124SMoriah Waterland #include <sys/mman.h> 41*5c51f124SMoriah Waterland #include <sys/statvfs.h> 42*5c51f124SMoriah Waterland #include <signal.h> 43*5c51f124SMoriah Waterland #include <limits.h> 44*5c51f124SMoriah Waterland #include <errno.h> 45*5c51f124SMoriah Waterland #include <fcntl.h> 46*5c51f124SMoriah Waterland #include <stdlib.h> 47*5c51f124SMoriah Waterland #include <unistd.h> 48*5c51f124SMoriah Waterland #include <time.h> 49*5c51f124SMoriah Waterland #include <errno.h> 50*5c51f124SMoriah Waterland #include <pkglocs.h> 51*5c51f124SMoriah Waterland #include <locale.h> 52*5c51f124SMoriah Waterland #include <libintl.h> 53*5c51f124SMoriah Waterland #include <pkglib.h> 54*5c51f124SMoriah Waterland #include "libinst.h" 55*5c51f124SMoriah Waterland #include "libadm.h" 56*5c51f124SMoriah Waterland 57*5c51f124SMoriah Waterland #define LOCKFILE ".pkg.lock" 58*5c51f124SMoriah Waterland #define LOCKWAIT 10 /* seconds between retries */ 59*5c51f124SMoriah Waterland #define LOCKRETRY 20 /* number of retries for a DB lock */ 60*5c51f124SMoriah Waterland 61*5c51f124SMoriah Waterland #define ERR_TC_WRITE "WARNING: unable to write temp contents file <%s>" 62*5c51f124SMoriah Waterland #define ERR_NOCLOSE "WARNING: unable to close <%s>" 63*5c51f124SMoriah Waterland #define ERR_NOUNLINK_LATENT "WARNING: unable to unlink latent <%s>" 64*5c51f124SMoriah Waterland #define ERR_LINK_FAIL "link(%s, %s) failed (errno %d)" 65*5c51f124SMoriah Waterland #define ERR_NORENAME_CONTENTS "unable to establish contents file <%s> "\ 66*5c51f124SMoriah Waterland "from <%s>" 67*5c51f124SMoriah Waterland #define ERR_RENAME_FAIL "rename(%s, %s) failed (errno %d)" 68*5c51f124SMoriah Waterland #define ERR_RESTORE_FAIL "attempt to restore <%s> failed" 69*5c51f124SMoriah Waterland #define ERR_NOUNLINK "WARNING: unable to unlink <%s>" 70*5c51f124SMoriah Waterland #define ERR_FCLOSE_FAIL "fclose failed (errno %d)" 71*5c51f124SMoriah Waterland #define ERR_ERRNO "(errno %d: %s)" 72*5c51f124SMoriah Waterland #define ERR_NOTMPOPEN "unable to open temporary contents file image" 73*5c51f124SMoriah Waterland #define ERR_CFBACK "Not enough space to backup <%s>" 74*5c51f124SMoriah Waterland #define ERR_CREAT_CONT "unable to create contents file <%s>: %s" 75*5c51f124SMoriah Waterland #define ERR_ACCESS_CONT "unable to access contents file <%s>: %s" 76*5c51f124SMoriah Waterland #define ERR_CFBACK1 "Need=%llu blocks, Available=%llu blocks " \ 77*5c51f124SMoriah Waterland "(block size=%d)" 78*5c51f124SMoriah Waterland #define ERR_NOCFILE "unable to locate contents file <%s>" 79*5c51f124SMoriah Waterland #define ERR_NOROPEN "unable to open <%s> for reading" 80*5c51f124SMoriah Waterland #define ERR_NOOPEN "unable to open <%s> for writing" 81*5c51f124SMoriah Waterland #define ERR_NOSTAT "unable to stat contents file <%s>" 82*5c51f124SMoriah Waterland #define ERR_NOSTATV "statvfs(%s) failed" 83*5c51f124SMoriah Waterland #define ERR_NOUPD "unable to update contents file" 84*5c51f124SMoriah Waterland #define ERR_DRCONTCP "unable to copy contents file to <%s>" 85*5c51f124SMoriah Waterland 86*5c51f124SMoriah Waterland #define MSG_XWTING "NOTE: Waiting for exclusive access to the package " \ 87*5c51f124SMoriah Waterland "database." 88*5c51f124SMoriah Waterland #define MSG_NOLOCK "NOTE: Couldn't lock the package database." 89*5c51f124SMoriah Waterland 90*5c51f124SMoriah Waterland #define ERR_NOLOCK "Database lock failed." 91*5c51f124SMoriah Waterland #define ERR_OPLOCK "unable to open lock file <%s>." 92*5c51f124SMoriah Waterland #define ERR_MKLOCK "unable to create lock file <%s>." 93*5c51f124SMoriah Waterland #define ERR_LCKREM "unable to lock package database - remote host " \ 94*5c51f124SMoriah Waterland "unavailable." 95*5c51f124SMoriah Waterland #define ERR_BADLCK "unable to lock package database - unknown error." 96*5c51f124SMoriah Waterland #define ERR_DEADLCK "unable to lock package database - deadlock condition." 97*5c51f124SMoriah Waterland #define ERR_TMOUT "unable to lock package database - too many retries." 98*5c51f124SMoriah Waterland #define ERR_CFDIR "unable to locate contents file directory" 99*5c51f124SMoriah Waterland 100*5c51f124SMoriah Waterland static int active_lock; 101*5c51f124SMoriah Waterland static int lock_fd; /* fd of LOCKFILE. */ 102*5c51f124SMoriah Waterland static char *pkgadm_dir; 103*5c51f124SMoriah Waterland 104*5c51f124SMoriah Waterland static int pkgWlock(int verbose); 105*5c51f124SMoriah Waterland static int pkgWunlock(void); 106*5c51f124SMoriah Waterland 107*5c51f124SMoriah Waterland /* 108*5c51f124SMoriah Waterland * This VFP is used to cache the last copy of the contents file that was 109*5c51f124SMoriah Waterland * written out - upon subsequent open if the contents file has not changed 110*5c51f124SMoriah Waterland * since it was last written out, use the last cached copy that is still 111*5c51f124SMoriah Waterland * in memory to avoid re-reading the contents file again. If the contents 112*5c51f124SMoriah Waterland * file has changed since the cached copy was written out, the previous 113*5c51f124SMoriah Waterland * copy is discarded and the new contents file contents are read in. 114*5c51f124SMoriah Waterland */ 115*5c51f124SMoriah Waterland 116*5c51f124SMoriah Waterland static VFP_T *contentsVfp = {(VFP_T *)NULL}; 117*5c51f124SMoriah Waterland 118*5c51f124SMoriah Waterland /* 119*5c51f124SMoriah Waterland * This defines the maximum number of bytes that can be added to the contents 120*5c51f124SMoriah Waterland * file for a single package - this must be higher than the largest expected 121*5c51f124SMoriah Waterland * pkgmap file will ever be. This controls the amount of memory allocated for 122*5c51f124SMoriah Waterland * the contents file additions. A pkgmap file with an average line length of 123*5c51f124SMoriah Waterland * 128/256/512 bytes could add 62500/31250/15625 entries with this size. This 124*5c51f124SMoriah Waterland * allows the contents file to have a fixed allocation without having to check 125*5c51f124SMoriah Waterland * size and realloc as necessary with the attendant cost of the realloc. The 126*5c51f124SMoriah Waterland * real memory used will only be those pages that are actually touched when 127*5c51f124SMoriah Waterland * the contents file is written. 128*5c51f124SMoriah Waterland */ 129*5c51f124SMoriah Waterland 130*5c51f124SMoriah Waterland #define CONTENTS_DELTA (32*1024*1024) /* 32mb */ 131*5c51f124SMoriah Waterland 132*5c51f124SMoriah Waterland /* forward declarations */ 133*5c51f124SMoriah Waterland 134*5c51f124SMoriah Waterland int relslock(void); 135*5c51f124SMoriah Waterland 136*5c51f124SMoriah Waterland /*ARGSUSED*/ 137*5c51f124SMoriah Waterland static void 138*5c51f124SMoriah Waterland do_alarm(int n) 139*5c51f124SMoriah Waterland { 140*5c51f124SMoriah Waterland (void) signal(SIGALRM, SIG_IGN); 141*5c51f124SMoriah Waterland (void) signal(SIGALRM, do_alarm); 142*5c51f124SMoriah Waterland (void) alarm(LOCKWAIT); 143*5c51f124SMoriah Waterland } 144*5c51f124SMoriah Waterland 145*5c51f124SMoriah Waterland /* 146*5c51f124SMoriah Waterland * Point packaging to the appropriate contents file. This is primarily used 147*5c51f124SMoriah Waterland * to establish a dryrun contents file. If the malloc() doesn't work, this 148*5c51f124SMoriah Waterland * returns 99 (internal error), else 0. 149*5c51f124SMoriah Waterland */ 150*5c51f124SMoriah Waterland int 151*5c51f124SMoriah Waterland set_cfdir(char *cfdir) 152*5c51f124SMoriah Waterland { 153*5c51f124SMoriah Waterland char realcf[PATH_MAX]; 154*5c51f124SMoriah Waterland char tmpcf[PATH_MAX]; 155*5c51f124SMoriah Waterland int status; 156*5c51f124SMoriah Waterland 157*5c51f124SMoriah Waterland if (cfdir == NULL) { 158*5c51f124SMoriah Waterland pkgadm_dir = get_PKGADM(); 159*5c51f124SMoriah Waterland return (0); 160*5c51f124SMoriah Waterland } 161*5c51f124SMoriah Waterland 162*5c51f124SMoriah Waterland if ((pkgadm_dir = strdup(cfdir)) == NULL) { 163*5c51f124SMoriah Waterland return (99); 164*5c51f124SMoriah Waterland } 165*5c51f124SMoriah Waterland 166*5c51f124SMoriah Waterland (void) snprintf(tmpcf, sizeof (tmpcf), "%s/contents", pkgadm_dir); 167*5c51f124SMoriah Waterland 168*5c51f124SMoriah Waterland /* 169*5c51f124SMoriah Waterland * return if a temporary contents file already exists - 170*5c51f124SMoriah Waterland * assume it is from a prior package in this series. 171*5c51f124SMoriah Waterland */ 172*5c51f124SMoriah Waterland 173*5c51f124SMoriah Waterland if (access(tmpcf, F_OK) == 0) { 174*5c51f124SMoriah Waterland return (0); 175*5c51f124SMoriah Waterland } 176*5c51f124SMoriah Waterland 177*5c51f124SMoriah Waterland /* 178*5c51f124SMoriah Waterland * no temporary contents file exists - create one. 179*5c51f124SMoriah Waterland */ 180*5c51f124SMoriah Waterland 181*5c51f124SMoriah Waterland (void) snprintf(realcf, sizeof (realcf), "%s/contents", get_PKGADM()); 182*5c51f124SMoriah Waterland 183*5c51f124SMoriah Waterland /* 184*5c51f124SMoriah Waterland * If there's a contents file there already, copy it 185*5c51f124SMoriah Waterland * over, otherwise initialize one. 186*5c51f124SMoriah Waterland */ 187*5c51f124SMoriah Waterland 188*5c51f124SMoriah Waterland /* create new contents file if one does not already exist */ 189*5c51f124SMoriah Waterland 190*5c51f124SMoriah Waterland if (access(realcf, F_OK) != 0) { 191*5c51f124SMoriah Waterland int n; 192*5c51f124SMoriah Waterland 193*5c51f124SMoriah Waterland n = open(tmpcf, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 194*5c51f124SMoriah Waterland if (n < 0) { 195*5c51f124SMoriah Waterland progerr(gettext(ERR_CREAT_CONT), tmpcf, 196*5c51f124SMoriah Waterland strerror(errno)); 197*5c51f124SMoriah Waterland return (99); 198*5c51f124SMoriah Waterland } 199*5c51f124SMoriah Waterland (void) close(n); 200*5c51f124SMoriah Waterland } else { 201*5c51f124SMoriah Waterland 202*5c51f124SMoriah Waterland /* contents file exists, save in pkgadm-dir */ 203*5c51f124SMoriah Waterland 204*5c51f124SMoriah Waterland status = copyf(realcf, tmpcf, (time_t)0); 205*5c51f124SMoriah Waterland if (status != 0) { 206*5c51f124SMoriah Waterland progerr(gettext(ERR_DRCONTCP), tmpcf); 207*5c51f124SMoriah Waterland return (99); 208*5c51f124SMoriah Waterland } 209*5c51f124SMoriah Waterland } 210*5c51f124SMoriah Waterland 211*5c51f124SMoriah Waterland return (0); 212*5c51f124SMoriah Waterland } 213*5c51f124SMoriah Waterland 214*5c51f124SMoriah Waterland /* 215*5c51f124SMoriah Waterland * This function installs the database lock, opens the contents file for 216*5c51f124SMoriah Waterland * reading and creates and opens the temporary contents file for read/write. 217*5c51f124SMoriah Waterland * It returns 1 if successful, 0 otherwise. 218*5c51f124SMoriah Waterland */ 219*5c51f124SMoriah Waterland int 220*5c51f124SMoriah Waterland ocfile(VFP_T **r_mapvfp, VFP_T **r_tmpvfp, fsblkcnt_t map_blks) 221*5c51f124SMoriah Waterland { 222*5c51f124SMoriah Waterland struct stat64 statb; 223*5c51f124SMoriah Waterland struct statvfs64 svfsb; 224*5c51f124SMoriah Waterland fsblkcnt_t free_blocks; 225*5c51f124SMoriah Waterland fsblkcnt_t need_blocks; 226*5c51f124SMoriah Waterland VFP_T *mapvfp = (VFP_T *)NULL; 227*5c51f124SMoriah Waterland VFP_T *tmpvfp = (VFP_T *)NULL; 228*5c51f124SMoriah Waterland char contents[PATH_MAX]; 229*5c51f124SMoriah Waterland int n; 230*5c51f124SMoriah Waterland 231*5c51f124SMoriah Waterland /* reset return VFP/FILE pointers */ 232*5c51f124SMoriah Waterland 233*5c51f124SMoriah Waterland (*r_mapvfp) = (VFP_T *)NULL; 234*5c51f124SMoriah Waterland (*r_tmpvfp) = (VFP_T *)NULL; 235*5c51f124SMoriah Waterland 236*5c51f124SMoriah Waterland /* establish package administration contents directory location */ 237*5c51f124SMoriah Waterland 238*5c51f124SMoriah Waterland if (pkgadm_dir == NULL) { 239*5c51f124SMoriah Waterland if (set_cfdir(NULL) != 0) { 240*5c51f124SMoriah Waterland progerr(gettext(ERR_CFDIR)); 241*5c51f124SMoriah Waterland return (0); 242*5c51f124SMoriah Waterland } 243*5c51f124SMoriah Waterland } 244*5c51f124SMoriah Waterland 245*5c51f124SMoriah Waterland /* Lock the file for exclusive access */ 246*5c51f124SMoriah Waterland 247*5c51f124SMoriah Waterland if (!pkgWlock(1)) { 248*5c51f124SMoriah Waterland progerr(gettext(ERR_NOLOCK)); 249*5c51f124SMoriah Waterland return (0); 250*5c51f124SMoriah Waterland } 251*5c51f124SMoriah Waterland 252*5c51f124SMoriah Waterland /* determine path to the primary contents file */ 253*5c51f124SMoriah Waterland 254*5c51f124SMoriah Waterland (void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir); 255*5c51f124SMoriah Waterland 256*5c51f124SMoriah Waterland /* 257*5c51f124SMoriah Waterland * open the contents file to read only - if a previous contents file has 258*5c51f124SMoriah Waterland * been cached attempt to use that cached copy for the open, otherwise 259*5c51f124SMoriah Waterland * just open the contents file directly 260*5c51f124SMoriah Waterland */ 261*5c51f124SMoriah Waterland 262*5c51f124SMoriah Waterland n = vfpCheckpointOpen(&contentsVfp, &mapvfp, contents, "r", VFP_NONE); 263*5c51f124SMoriah Waterland 264*5c51f124SMoriah Waterland /* return error if contents file cannot be accessed */ 265*5c51f124SMoriah Waterland 266*5c51f124SMoriah Waterland if (n != 0) { 267*5c51f124SMoriah Waterland int lerrno = errno; 268*5c51f124SMoriah Waterland 269*5c51f124SMoriah Waterland if (errno == ENOENT) { 270*5c51f124SMoriah Waterland progerr(gettext(ERR_NOCFILE), contents); 271*5c51f124SMoriah Waterland } else { 272*5c51f124SMoriah Waterland progerr(gettext(ERR_NOROPEN), contents); 273*5c51f124SMoriah Waterland } 274*5c51f124SMoriah Waterland 275*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 276*5c51f124SMoriah Waterland return (0); 277*5c51f124SMoriah Waterland } 278*5c51f124SMoriah Waterland 279*5c51f124SMoriah Waterland /* 280*5c51f124SMoriah Waterland * Check and see if there is enough space for the packaging commands 281*5c51f124SMoriah Waterland * to back up the contents file, if there is not, then do not allow 282*5c51f124SMoriah Waterland * execution to continue by failing the ocfile() call. 283*5c51f124SMoriah Waterland */ 284*5c51f124SMoriah Waterland 285*5c51f124SMoriah Waterland /* Get the contents file size */ 286*5c51f124SMoriah Waterland 287*5c51f124SMoriah Waterland if (fstat64(fileno(mapvfp->_vfpFile), &statb) == -1) { 288*5c51f124SMoriah Waterland int lerrno = errno; 289*5c51f124SMoriah Waterland 290*5c51f124SMoriah Waterland progerr(gettext(ERR_NOSTAT), contents); 291*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 292*5c51f124SMoriah Waterland (void) vfpClose(&mapvfp); 293*5c51f124SMoriah Waterland return (0); 294*5c51f124SMoriah Waterland } 295*5c51f124SMoriah Waterland 296*5c51f124SMoriah Waterland /* Get the filesystem space */ 297*5c51f124SMoriah Waterland 298*5c51f124SMoriah Waterland if (fstatvfs64(fileno(mapvfp->_vfpFile), &svfsb) == -1) { 299*5c51f124SMoriah Waterland int lerrno = errno; 300*5c51f124SMoriah Waterland 301*5c51f124SMoriah Waterland progerr(gettext(ERR_NOSTATV), contents); 302*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 303*5c51f124SMoriah Waterland (void) vfpClose(&mapvfp); 304*5c51f124SMoriah Waterland return (0); 305*5c51f124SMoriah Waterland } 306*5c51f124SMoriah Waterland 307*5c51f124SMoriah Waterland free_blocks = (((fsblkcnt_t)svfsb.f_frsize > 0) ? 308*5c51f124SMoriah Waterland howmany(svfsb.f_frsize, DEV_BSIZE) : 309*5c51f124SMoriah Waterland howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree; 310*5c51f124SMoriah Waterland 311*5c51f124SMoriah Waterland if (map_blks == 0LL) { 312*5c51f124SMoriah Waterland map_blks = 10LL; 313*5c51f124SMoriah Waterland } 314*5c51f124SMoriah Waterland 315*5c51f124SMoriah Waterland /* 316*5c51f124SMoriah Waterland * Calculate the number of blocks we need to be able to operate on 317*5c51f124SMoriah Waterland * the contents file. 318*5c51f124SMoriah Waterland */ 319*5c51f124SMoriah Waterland need_blocks = map_blks + 320*5c51f124SMoriah Waterland nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize); 321*5c51f124SMoriah Waterland 322*5c51f124SMoriah Waterland if ((need_blocks + 10) > free_blocks) { 323*5c51f124SMoriah Waterland progerr(gettext(ERR_CFBACK), contents); 324*5c51f124SMoriah Waterland progerr(gettext(ERR_CFBACK1), need_blocks, free_blocks, 325*5c51f124SMoriah Waterland DEV_BSIZE); 326*5c51f124SMoriah Waterland (void) vfpClose(&mapvfp); 327*5c51f124SMoriah Waterland return (0); 328*5c51f124SMoriah Waterland } 329*5c51f124SMoriah Waterland 330*5c51f124SMoriah Waterland /* 331*5c51f124SMoriah Waterland * open the temporary contents file without a path name - this causes 332*5c51f124SMoriah Waterland * the "vfp" to be opened on in-memory storage only, the size of which 333*5c51f124SMoriah Waterland * is set following a successful return - this causes the temporary 334*5c51f124SMoriah Waterland * contents file to be maintained in memory only - if no changes are 335*5c51f124SMoriah Waterland * made as the primary contents file is processed, the in memory data 336*5c51f124SMoriah Waterland * is discarded and not written to the disk. 337*5c51f124SMoriah Waterland */ 338*5c51f124SMoriah Waterland 339*5c51f124SMoriah Waterland if (vfpOpen(&tmpvfp, (char *)NULL, "w", VFP_NONE) != 0) { 340*5c51f124SMoriah Waterland int lerrno = errno; 341*5c51f124SMoriah Waterland 342*5c51f124SMoriah Waterland progerr(gettext(ERR_NOTMPOPEN)); 343*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 344*5c51f124SMoriah Waterland (void) vfpClose(&mapvfp); 345*5c51f124SMoriah Waterland return (0); 346*5c51f124SMoriah Waterland } 347*5c51f124SMoriah Waterland 348*5c51f124SMoriah Waterland /* 349*5c51f124SMoriah Waterland * set size of allocation for temporary contents file - this sets the 350*5c51f124SMoriah Waterland * size of the in-memory buffer associated with the open vfp. 351*5c51f124SMoriah Waterland */ 352*5c51f124SMoriah Waterland 353*5c51f124SMoriah Waterland if (vfpSetSize(tmpvfp, statb.st_size + CONTENTS_DELTA) != 0) { 354*5c51f124SMoriah Waterland int lerrno = errno; 355*5c51f124SMoriah Waterland 356*5c51f124SMoriah Waterland progerr(gettext(ERR_NOTMPOPEN)); 357*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 358*5c51f124SMoriah Waterland (void) vfpClose(&tmpvfp); 359*5c51f124SMoriah Waterland (void) vfpClose(&mapvfp); 360*5c51f124SMoriah Waterland return (0); 361*5c51f124SMoriah Waterland } 362*5c51f124SMoriah Waterland 363*5c51f124SMoriah Waterland /* 364*5c51f124SMoriah Waterland * now that the temporary file is opened, advise the vm system to start 365*5c51f124SMoriah Waterland * mapping the real contents file into memory if possible 366*5c51f124SMoriah Waterland */ 367*5c51f124SMoriah Waterland 368*5c51f124SMoriah Waterland (void) vfpSetFlags(mapvfp, VFP_NEEDNOW); 369*5c51f124SMoriah Waterland 370*5c51f124SMoriah Waterland /* set return ->s to open vfps */ 371*5c51f124SMoriah Waterland 372*5c51f124SMoriah Waterland (*r_mapvfp) = mapvfp; 373*5c51f124SMoriah Waterland (*r_tmpvfp) = tmpvfp; 374*5c51f124SMoriah Waterland 375*5c51f124SMoriah Waterland return (1); /* All OK */ 376*5c51f124SMoriah Waterland } 377*5c51f124SMoriah Waterland 378*5c51f124SMoriah Waterland /* 379*5c51f124SMoriah Waterland * This is a simple open and lock of the contents file. It doesn't create a 380*5c51f124SMoriah Waterland * temporary contents file and it doesn't need to do any space checking. 381*5c51f124SMoriah Waterland * Returns 1 for OK and 0 for "didn't do it". 382*5c51f124SMoriah Waterland */ 383*5c51f124SMoriah Waterland int 384*5c51f124SMoriah Waterland socfile(VFP_T **r_mapvfp) 385*5c51f124SMoriah Waterland { 386*5c51f124SMoriah Waterland VFP_T *mapvfp = (VFP_T *)NULL; 387*5c51f124SMoriah Waterland char contents[PATH_MAX]; 388*5c51f124SMoriah Waterland int n; 389*5c51f124SMoriah Waterland 390*5c51f124SMoriah Waterland /* reset return VFP/FILE pointer */ 391*5c51f124SMoriah Waterland 392*5c51f124SMoriah Waterland (*r_mapvfp) = (VFP_T *)NULL; 393*5c51f124SMoriah Waterland 394*5c51f124SMoriah Waterland if (pkgadm_dir == NULL) { 395*5c51f124SMoriah Waterland if (set_cfdir(NULL) != 0) { 396*5c51f124SMoriah Waterland progerr(gettext(ERR_CFDIR)); 397*5c51f124SMoriah Waterland return (0); 398*5c51f124SMoriah Waterland } 399*5c51f124SMoriah Waterland } 400*5c51f124SMoriah Waterland 401*5c51f124SMoriah Waterland /* 402*5c51f124SMoriah Waterland * Lock the database for exclusive access, but don't make a fuss if 403*5c51f124SMoriah Waterland * it fails (user may not be root and the .pkg.lock file may not 404*5c51f124SMoriah Waterland * exist yet). 405*5c51f124SMoriah Waterland */ 406*5c51f124SMoriah Waterland 407*5c51f124SMoriah Waterland if (!pkgWlock(0)) { 408*5c51f124SMoriah Waterland logerr(gettext(MSG_NOLOCK)); 409*5c51f124SMoriah Waterland } 410*5c51f124SMoriah Waterland 411*5c51f124SMoriah Waterland /* open the contents file to read only */ 412*5c51f124SMoriah Waterland 413*5c51f124SMoriah Waterland (void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir); 414*5c51f124SMoriah Waterland 415*5c51f124SMoriah Waterland n = vfpCheckpointOpen(&contentsVfp, &mapvfp, contents, 416*5c51f124SMoriah Waterland "r", VFP_NEEDNOW); 417*5c51f124SMoriah Waterland if (n != 0) { 418*5c51f124SMoriah Waterland int lerrno = errno; 419*5c51f124SMoriah Waterland 420*5c51f124SMoriah Waterland if (errno == ENOENT) { 421*5c51f124SMoriah Waterland progerr(gettext(ERR_NOCFILE), contents); 422*5c51f124SMoriah Waterland } else { 423*5c51f124SMoriah Waterland progerr(gettext(ERR_NOROPEN), contents); 424*5c51f124SMoriah Waterland } 425*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 426*5c51f124SMoriah Waterland return (0); 427*5c51f124SMoriah Waterland } 428*5c51f124SMoriah Waterland 429*5c51f124SMoriah Waterland *r_mapvfp = mapvfp; 430*5c51f124SMoriah Waterland 431*5c51f124SMoriah Waterland return (1); 432*5c51f124SMoriah Waterland } 433*5c51f124SMoriah Waterland 434*5c51f124SMoriah Waterland /* 435*5c51f124SMoriah Waterland * Name: swapcfile 436*5c51f124SMoriah Waterland * Description: This function closes both the current and temporary contents 437*5c51f124SMoriah Waterland * files specified, and conditionally replaces the old transitory 438*5c51f124SMoriah Waterland * contents file with the newly updated temporary contents file. 439*5c51f124SMoriah Waterland * The "ocfile()" or "socfile()" functions must be called to re- 440*5c51f124SMoriah Waterland * open the real contents file for processing. 441*5c51f124SMoriah Waterland * Arguments: a_cfVfp - (VFP_T **) - [RW, *RW] 442*5c51f124SMoriah Waterland * This is the VFP associated with the real contents file 443*5c51f124SMoriah Waterland * that is being read from and data processed. 444*5c51f124SMoriah Waterland * a_cfTmpVfp - (VFP_T **) - [RW, *RW] 445*5c51f124SMoriah Waterland * This is the VFP associated with the temporary contents 446*5c51f124SMoriah Waterland * file that is being written to. 447*5c51f124SMoriah Waterland * pkginst - (char) - [RO, *RO] 448*5c51f124SMoriah Waterland * This is the name of the package being operated on; 449*5c51f124SMoriah Waterland * this is used to write the "last modified by xxx" 450*5c51f124SMoriah Waterland * comment at the end of the contents file. 451*5c51f124SMoriah Waterland * dbchg - (int) - [RO] 452*5c51f124SMoriah Waterland * == 0 - the temporary contents file has NOT been changed 453*5c51f124SMoriah Waterland * with respect to the real contents file; do not 454*5c51f124SMoriah Waterland * update the real contents file with the contents 455*5c51f124SMoriah Waterland * of the temporary contents file. 456*5c51f124SMoriah Waterland * != 0 - the temporary contetns file HAS been changed with 457*5c51f124SMoriah Waterland * respect to the real contents file; DO update the 458*5c51f124SMoriah Waterland * real contents file with the contents of the 459*5c51f124SMoriah Waterland * temporary contents file. 460*5c51f124SMoriah Waterland * Returns: int == RESULT_OK - successful 461*5c51f124SMoriah Waterland * == RESULT_WRN - successful with warnings 462*5c51f124SMoriah Waterland * == RESULT_ERR - failed with fatal errors - deserves an 463*5c51f124SMoriah Waterland * alarming message and a quit() 464*5c51f124SMoriah Waterland * NOTES: If dbchg != 0, the contents file is always updated. If dbchg == 0, 465*5c51f124SMoriah Waterland * the contents file is updated IF the data is modified indication 466*5c51f124SMoriah Waterland * is set on the contents file associated with a_cfTmpVfp. 467*5c51f124SMoriah Waterland */ 468*5c51f124SMoriah Waterland 469*5c51f124SMoriah Waterland int 470*5c51f124SMoriah Waterland swapcfile(VFP_T **a_cfVfp, VFP_T **a_cfTmpVfp, char *pkginst, int dbchg) 471*5c51f124SMoriah Waterland { 472*5c51f124SMoriah Waterland char *pe; 473*5c51f124SMoriah Waterland char *pl; 474*5c51f124SMoriah Waterland char *ps; 475*5c51f124SMoriah Waterland char contentsPath[PATH_MAX] = {'\0'}; 476*5c51f124SMoriah Waterland char line[256]; 477*5c51f124SMoriah Waterland char sContentsPath[PATH_MAX] = {'\0'}; 478*5c51f124SMoriah Waterland char tContentsPath[PATH_MAX] = {'\0'}; 479*5c51f124SMoriah Waterland char timeb[BUFSIZ]; 480*5c51f124SMoriah Waterland int retval = RESULT_OK; 481*5c51f124SMoriah Waterland struct tm *timep; 482*5c51f124SMoriah Waterland time_t clock; 483*5c51f124SMoriah Waterland 484*5c51f124SMoriah Waterland /* normalize pkginst so its never null */ 485*5c51f124SMoriah Waterland 486*5c51f124SMoriah Waterland if (pkginst == (char *)NULL) { 487*5c51f124SMoriah Waterland dbchg = 0; 488*5c51f124SMoriah Waterland pkginst = "<unknown>"; 489*5c51f124SMoriah Waterland } 490*5c51f124SMoriah Waterland 491*5c51f124SMoriah Waterland /* cache all paths for the associated open files */ 492*5c51f124SMoriah Waterland 493*5c51f124SMoriah Waterland (void) strlcpy(contentsPath, vfpGetPath(*a_cfVfp), 494*5c51f124SMoriah Waterland sizeof (contentsPath)); 495*5c51f124SMoriah Waterland 496*5c51f124SMoriah Waterland (void) snprintf(tContentsPath, sizeof (tContentsPath), 497*5c51f124SMoriah Waterland "%s/t.contents", pkgadm_dir); 498*5c51f124SMoriah Waterland 499*5c51f124SMoriah Waterland (void) snprintf(sContentsPath, sizeof (sContentsPath), 500*5c51f124SMoriah Waterland "%s/s.contents", pkgadm_dir); 501*5c51f124SMoriah Waterland 502*5c51f124SMoriah Waterland /* original contents file no longer needed - close */ 503*5c51f124SMoriah Waterland 504*5c51f124SMoriah Waterland if (vfpClose(a_cfVfp) != 0) { 505*5c51f124SMoriah Waterland int lerrno = errno; 506*5c51f124SMoriah Waterland 507*5c51f124SMoriah Waterland logerr(gettext(ERR_NOCLOSE), contentsPath); 508*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 509*5c51f124SMoriah Waterland retval = RESULT_WRN; 510*5c51f124SMoriah Waterland } 511*5c51f124SMoriah Waterland 512*5c51f124SMoriah Waterland /* 513*5c51f124SMoriah Waterland * If no changes were made to the database, checkpoint the temporary 514*5c51f124SMoriah Waterland * contents file - if this fails, then just close the file which causes 515*5c51f124SMoriah Waterland * the contents file to be reopened and reread if it is needed again 516*5c51f124SMoriah Waterland */ 517*5c51f124SMoriah Waterland 518*5c51f124SMoriah Waterland if ((dbchg == 0) && (vfpGetModified(*a_cfTmpVfp) == 0)) { 519*5c51f124SMoriah Waterland if (vfpCheckpointFile(&contentsVfp, a_cfTmpVfp, 520*5c51f124SMoriah Waterland contentsPath) != 0) { 521*5c51f124SMoriah Waterland vfpClose(a_cfTmpVfp); 522*5c51f124SMoriah Waterland } 523*5c51f124SMoriah Waterland (void) pkgWunlock(); /* Free the database lock. */ 524*5c51f124SMoriah Waterland return (retval); 525*5c51f124SMoriah Waterland } 526*5c51f124SMoriah Waterland 527*5c51f124SMoriah Waterland /* 528*5c51f124SMoriah Waterland * changes made to the current temporary contents file - 529*5c51f124SMoriah Waterland * remove any trailing comment lines in the temp contents file, then 530*5c51f124SMoriah Waterland * append updated modification info records to temp contents file 531*5c51f124SMoriah Waterland */ 532*5c51f124SMoriah Waterland 533*5c51f124SMoriah Waterland pe = vfpGetCurrCharPtr(*a_cfTmpVfp); /* last char in contents file */ 534*5c51f124SMoriah Waterland ps = vfpGetFirstCharPtr(*a_cfTmpVfp); /* 1st char in contents file */ 535*5c51f124SMoriah Waterland pl = pe; /* last match is last char in contents file */ 536*5c51f124SMoriah Waterland 537*5c51f124SMoriah Waterland /* skip past all trailing newlines and null bytes */ 538*5c51f124SMoriah Waterland 539*5c51f124SMoriah Waterland while ((pe > ps) && ((*pe == '\n') || (*pe == '\0'))) { 540*5c51f124SMoriah Waterland pe--; 541*5c51f124SMoriah Waterland } 542*5c51f124SMoriah Waterland 543*5c51f124SMoriah Waterland /* remove trailing comments as long as there are lines in the file */ 544*5c51f124SMoriah Waterland 545*5c51f124SMoriah Waterland while (pe > ps) { 546*5c51f124SMoriah Waterland if (*pe != '\n') { 547*5c51f124SMoriah Waterland /* curr char is not newline: backup one byte */ 548*5c51f124SMoriah Waterland pl = pe--; 549*5c51f124SMoriah Waterland } else if (*pl != '#') { 550*5c51f124SMoriah Waterland /* curr char is newline next char not comment break */ 551*5c51f124SMoriah Waterland break; 552*5c51f124SMoriah Waterland } else { 553*5c51f124SMoriah Waterland /* curr char is newline next char is comment - remove */ 554*5c51f124SMoriah Waterland *pl = '\0'; 555*5c51f124SMoriah Waterland vfpSetLastCharPtr(*a_cfTmpVfp, pl); 556*5c51f124SMoriah Waterland pe--; 557*5c51f124SMoriah Waterland } 558*5c51f124SMoriah Waterland } 559*5c51f124SMoriah Waterland 560*5c51f124SMoriah Waterland /* create two update comment lines */ 561*5c51f124SMoriah Waterland 562*5c51f124SMoriah Waterland (void) time(&clock); 563*5c51f124SMoriah Waterland timep = localtime(&clock); 564*5c51f124SMoriah Waterland 565*5c51f124SMoriah Waterland (void) strftime(timeb, sizeof (timeb), "%c\n", timep); 566*5c51f124SMoriah Waterland (void) snprintf(line, sizeof (line), 567*5c51f124SMoriah Waterland gettext("# Last modified by %s for %s package\n# %s"), 568*5c51f124SMoriah Waterland get_prog_name(), pkginst, timeb); 569*5c51f124SMoriah Waterland vfpPuts(*a_cfTmpVfp, line); 570*5c51f124SMoriah Waterland 571*5c51f124SMoriah Waterland /* commit temporary contents file bytes to storage */ 572*5c51f124SMoriah Waterland 573*5c51f124SMoriah Waterland if (vfpWriteToFile(*a_cfTmpVfp, tContentsPath) != 0) { 574*5c51f124SMoriah Waterland int lerrno = errno; 575*5c51f124SMoriah Waterland 576*5c51f124SMoriah Waterland logerr(gettext(ERR_TC_WRITE), tContentsPath); 577*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 578*5c51f124SMoriah Waterland vfpClose(a_cfTmpVfp); 579*5c51f124SMoriah Waterland (void) remove(tContentsPath); 580*5c51f124SMoriah Waterland (void) pkgWunlock(); /* Free the database lock. */ 581*5c51f124SMoriah Waterland return (RESULT_ERR); 582*5c51f124SMoriah Waterland } 583*5c51f124SMoriah Waterland 584*5c51f124SMoriah Waterland /* 585*5c51f124SMoriah Waterland * Now we want to make a copy of the old contents file as a 586*5c51f124SMoriah Waterland * fail-safe. In support of that, we create a hard link to 587*5c51f124SMoriah Waterland * s.contents. 588*5c51f124SMoriah Waterland */ 589*5c51f124SMoriah Waterland 590*5c51f124SMoriah Waterland if ((access(sContentsPath, F_OK) == 0) && remove(sContentsPath)) { 591*5c51f124SMoriah Waterland int lerrno = errno; 592*5c51f124SMoriah Waterland 593*5c51f124SMoriah Waterland logerr(gettext(ERR_NOUNLINK_LATENT), sContentsPath); 594*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 595*5c51f124SMoriah Waterland (void) remove(tContentsPath); 596*5c51f124SMoriah Waterland (void) pkgWunlock(); /* Free the database lock. */ 597*5c51f124SMoriah Waterland vfpClose(a_cfTmpVfp); 598*5c51f124SMoriah Waterland return (RESULT_ERR); 599*5c51f124SMoriah Waterland } 600*5c51f124SMoriah Waterland 601*5c51f124SMoriah Waterland if (link(contentsPath, sContentsPath) != 0) { 602*5c51f124SMoriah Waterland int lerrno = errno; 603*5c51f124SMoriah Waterland 604*5c51f124SMoriah Waterland progerr(gettext(ERR_NOUPD)); 605*5c51f124SMoriah Waterland logerr(gettext(ERR_LINK_FAIL), contentsPath, sContentsPath, 606*5c51f124SMoriah Waterland lerrno); 607*5c51f124SMoriah Waterland (void) remove(tContentsPath); 608*5c51f124SMoriah Waterland (void) pkgWunlock(); /* Free the database lock. */ 609*5c51f124SMoriah Waterland vfpClose(a_cfTmpVfp); 610*5c51f124SMoriah Waterland return (RESULT_ERR); 611*5c51f124SMoriah Waterland } 612*5c51f124SMoriah Waterland 613*5c51f124SMoriah Waterland if (rename(tContentsPath, contentsPath) != 0) { 614*5c51f124SMoriah Waterland int lerrno = errno; 615*5c51f124SMoriah Waterland 616*5c51f124SMoriah Waterland progerr(gettext(ERR_NORENAME_CONTENTS), contentsPath, 617*5c51f124SMoriah Waterland tContentsPath); 618*5c51f124SMoriah Waterland logerr(gettext(ERR_RENAME_FAIL), tContentsPath, 619*5c51f124SMoriah Waterland contentsPath, lerrno); 620*5c51f124SMoriah Waterland if (rename(sContentsPath, contentsPath)) { 621*5c51f124SMoriah Waterland lerrno = errno; 622*5c51f124SMoriah Waterland progerr(gettext(ERR_RESTORE_FAIL), contentsPath); 623*5c51f124SMoriah Waterland logerr(gettext(ERR_RENAME_FAIL), sContentsPath, 624*5c51f124SMoriah Waterland contentsPath, lerrno); 625*5c51f124SMoriah Waterland } 626*5c51f124SMoriah Waterland (void) remove(tContentsPath); 627*5c51f124SMoriah Waterland } 628*5c51f124SMoriah Waterland 629*5c51f124SMoriah Waterland if (remove(sContentsPath) != 0) { 630*5c51f124SMoriah Waterland int lerrno = errno; 631*5c51f124SMoriah Waterland 632*5c51f124SMoriah Waterland logerr(gettext(ERR_NOUNLINK), sContentsPath); 633*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 634*5c51f124SMoriah Waterland retval = RESULT_WRN; 635*5c51f124SMoriah Waterland } 636*5c51f124SMoriah Waterland 637*5c51f124SMoriah Waterland /* 638*5c51f124SMoriah Waterland * checkpoint the temporary contents file - if this fails, then 639*5c51f124SMoriah Waterland * just close the file which causes the contents file to be reopened 640*5c51f124SMoriah Waterland * and reread if it is needed again 641*5c51f124SMoriah Waterland */ 642*5c51f124SMoriah Waterland 643*5c51f124SMoriah Waterland if (vfpCheckpointFile(&contentsVfp, a_cfTmpVfp, contentsPath) != 0) { 644*5c51f124SMoriah Waterland vfpClose(a_cfTmpVfp); 645*5c51f124SMoriah Waterland } 646*5c51f124SMoriah Waterland 647*5c51f124SMoriah Waterland return (relslock() == 0 ? RESULT_ERR : retval); 648*5c51f124SMoriah Waterland } 649*5c51f124SMoriah Waterland 650*5c51f124SMoriah Waterland /* This function releases the lock on the package database. */ 651*5c51f124SMoriah Waterland int 652*5c51f124SMoriah Waterland relslock(void) 653*5c51f124SMoriah Waterland { 654*5c51f124SMoriah Waterland /* 655*5c51f124SMoriah Waterland * This closes the contents file and releases the lock. 656*5c51f124SMoriah Waterland */ 657*5c51f124SMoriah Waterland if (!pkgWunlock()) { 658*5c51f124SMoriah Waterland int lerrno = errno; 659*5c51f124SMoriah Waterland 660*5c51f124SMoriah Waterland progerr(gettext(ERR_NOUPD)); 661*5c51f124SMoriah Waterland logerr(gettext(ERR_FCLOSE_FAIL), lerrno); 662*5c51f124SMoriah Waterland return (0); 663*5c51f124SMoriah Waterland } 664*5c51f124SMoriah Waterland return (1); 665*5c51f124SMoriah Waterland } 666*5c51f124SMoriah Waterland 667*5c51f124SMoriah Waterland /* 668*5c51f124SMoriah Waterland * This function attempts to lock the package database. It returns 1 on 669*5c51f124SMoriah Waterland * success, 0 on failure. The positive logic verbose flag determines whether 670*5c51f124SMoriah Waterland * or not the function displays the error message upon failure. 671*5c51f124SMoriah Waterland */ 672*5c51f124SMoriah Waterland static int 673*5c51f124SMoriah Waterland pkgWlock(int verbose) { 674*5c51f124SMoriah Waterland int retry_cnt, retval; 675*5c51f124SMoriah Waterland char lockpath[PATH_MAX]; 676*5c51f124SMoriah Waterland 677*5c51f124SMoriah Waterland active_lock = 0; 678*5c51f124SMoriah Waterland 679*5c51f124SMoriah Waterland (void) snprintf(lockpath, sizeof (lockpath), 680*5c51f124SMoriah Waterland "%s/%s", pkgadm_dir, LOCKFILE); 681*5c51f124SMoriah Waterland 682*5c51f124SMoriah Waterland retry_cnt = LOCKRETRY; 683*5c51f124SMoriah Waterland 684*5c51f124SMoriah Waterland /* 685*5c51f124SMoriah Waterland * If the lock file is not present, create it. The mode is set to 686*5c51f124SMoriah Waterland * allow any process to lock the database, that's because pkgchk may 687*5c51f124SMoriah Waterland * be run by a non-root user. 688*5c51f124SMoriah Waterland */ 689*5c51f124SMoriah Waterland if (access(lockpath, F_OK) == -1) { 690*5c51f124SMoriah Waterland lock_fd = open(lockpath, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644); 691*5c51f124SMoriah Waterland if (lock_fd < 0) { 692*5c51f124SMoriah Waterland if (verbose) 693*5c51f124SMoriah Waterland progerr(gettext(ERR_MKLOCK), lockpath); 694*5c51f124SMoriah Waterland return (0); 695*5c51f124SMoriah Waterland } else { 696*5c51f124SMoriah Waterland (void) fchmod(lock_fd, 0644); /* force perms. */ 697*5c51f124SMoriah Waterland } 698*5c51f124SMoriah Waterland } else { 699*5c51f124SMoriah Waterland if ((lock_fd = open(lockpath, O_RDWR)) == -1) { 700*5c51f124SMoriah Waterland if (verbose) 701*5c51f124SMoriah Waterland progerr(gettext(ERR_OPLOCK), lockpath); 702*5c51f124SMoriah Waterland return (0); 703*5c51f124SMoriah Waterland } 704*5c51f124SMoriah Waterland } 705*5c51f124SMoriah Waterland 706*5c51f124SMoriah Waterland (void) signal(SIGALRM, do_alarm); 707*5c51f124SMoriah Waterland (void) alarm(LOCKWAIT); 708*5c51f124SMoriah Waterland 709*5c51f124SMoriah Waterland do { 710*5c51f124SMoriah Waterland if (lockf(lock_fd, F_LOCK, 0)) { 711*5c51f124SMoriah Waterland if (errno == EAGAIN || errno == EINTR) 712*5c51f124SMoriah Waterland logerr(gettext(MSG_XWTING)); 713*5c51f124SMoriah Waterland else if (errno == ECOMM) { 714*5c51f124SMoriah Waterland logerr(gettext(ERR_LCKREM)); 715*5c51f124SMoriah Waterland retval = 0; 716*5c51f124SMoriah Waterland break; 717*5c51f124SMoriah Waterland } else if (errno == EBADF) { 718*5c51f124SMoriah Waterland logerr(gettext(ERR_BADLCK)); 719*5c51f124SMoriah Waterland retval = 0; 720*5c51f124SMoriah Waterland break; 721*5c51f124SMoriah Waterland } else if (errno == EDEADLK) { 722*5c51f124SMoriah Waterland logerr(gettext(ERR_DEADLCK)); 723*5c51f124SMoriah Waterland retval = 0; 724*5c51f124SMoriah Waterland break; 725*5c51f124SMoriah Waterland } 726*5c51f124SMoriah Waterland } else { 727*5c51f124SMoriah Waterland active_lock = 1; 728*5c51f124SMoriah Waterland retval = 1; 729*5c51f124SMoriah Waterland break; 730*5c51f124SMoriah Waterland } 731*5c51f124SMoriah Waterland } while (retry_cnt--); 732*5c51f124SMoriah Waterland 733*5c51f124SMoriah Waterland (void) signal(SIGALRM, SIG_IGN); 734*5c51f124SMoriah Waterland 735*5c51f124SMoriah Waterland if (retval == 0) 736*5c51f124SMoriah Waterland { 737*5c51f124SMoriah Waterland if (retry_cnt == -1) { 738*5c51f124SMoriah Waterland logerr(gettext(ERR_TMOUT)); 739*5c51f124SMoriah Waterland } 740*5c51f124SMoriah Waterland 741*5c51f124SMoriah Waterland (void) pkgWunlock(); /* close the lockfile. */ 742*5c51f124SMoriah Waterland } 743*5c51f124SMoriah Waterland 744*5c51f124SMoriah Waterland return (retval); 745*5c51f124SMoriah Waterland } 746*5c51f124SMoriah Waterland 747*5c51f124SMoriah Waterland /* 748*5c51f124SMoriah Waterland * Release the lock on the package database. Returns 1 on success, 0 on 749*5c51f124SMoriah Waterland * failure. 750*5c51f124SMoriah Waterland */ 751*5c51f124SMoriah Waterland static int 752*5c51f124SMoriah Waterland pkgWunlock(void) { 753*5c51f124SMoriah Waterland if (active_lock) { 754*5c51f124SMoriah Waterland active_lock = 0; 755*5c51f124SMoriah Waterland if (close(lock_fd)) 756*5c51f124SMoriah Waterland return (0); 757*5c51f124SMoriah Waterland else 758*5c51f124SMoriah Waterland return (1); 759*5c51f124SMoriah Waterland } else 760*5c51f124SMoriah Waterland return (1); 761*5c51f124SMoriah Waterland } 762*5c51f124SMoriah Waterland 763*5c51f124SMoriah Waterland /* 764*5c51f124SMoriah Waterland * This function verifies that the contents file is in place. 765*5c51f124SMoriah Waterland * returns 1 - if it exists 766*5c51f124SMoriah Waterland * returns 0 - if it does not exist 767*5c51f124SMoriah Waterland */ 768*5c51f124SMoriah Waterland int 769*5c51f124SMoriah Waterland iscfile(void) 770*5c51f124SMoriah Waterland { 771*5c51f124SMoriah Waterland char contents[PATH_MAX]; 772*5c51f124SMoriah Waterland 773*5c51f124SMoriah Waterland (void) snprintf(contents, PATH_MAX, "%s/contents", get_PKGADM()); 774*5c51f124SMoriah Waterland 775*5c51f124SMoriah Waterland return (access(contents, F_OK) == 0 ? 1 : 0); 776*5c51f124SMoriah Waterland } 777*5c51f124SMoriah Waterland 778*5c51f124SMoriah Waterland /* 779*5c51f124SMoriah Waterland * This function verifies that the contents file is in place. If it is - no 780*5c51f124SMoriah Waterland * change. If it isn't - this creates it. 781*5c51f124SMoriah Waterland * Returns: == 0 : failure 782*5c51f124SMoriah Waterland * != 0 : success 783*5c51f124SMoriah Waterland */ 784*5c51f124SMoriah Waterland 785*5c51f124SMoriah Waterland int 786*5c51f124SMoriah Waterland vcfile(void) 787*5c51f124SMoriah Waterland { 788*5c51f124SMoriah Waterland int lerrno; 789*5c51f124SMoriah Waterland int fd; 790*5c51f124SMoriah Waterland char contents[PATH_MAX]; 791*5c51f124SMoriah Waterland 792*5c51f124SMoriah Waterland /* 793*5c51f124SMoriah Waterland * create full path to contents file 794*5c51f124SMoriah Waterland */ 795*5c51f124SMoriah Waterland 796*5c51f124SMoriah Waterland (void) snprintf(contents, sizeof (contents), 797*5c51f124SMoriah Waterland "%s/contents", get_PKGADM()); 798*5c51f124SMoriah Waterland 799*5c51f124SMoriah Waterland /* 800*5c51f124SMoriah Waterland * Attempt to create the file - will only be successful 801*5c51f124SMoriah Waterland * if the file does not currently exist. 802*5c51f124SMoriah Waterland */ 803*5c51f124SMoriah Waterland 804*5c51f124SMoriah Waterland fd = open(contents, O_WRONLY | O_CREAT | O_EXCL, 0644); 805*5c51f124SMoriah Waterland if (fd >= 0) { 806*5c51f124SMoriah Waterland /* 807*5c51f124SMoriah Waterland * Contents file wasn't there, but is now. 808*5c51f124SMoriah Waterland */ 809*5c51f124SMoriah Waterland 810*5c51f124SMoriah Waterland echo(gettext("## Software contents file initialized")); 811*5c51f124SMoriah Waterland (void) close(fd); 812*5c51f124SMoriah Waterland return (1); /* success */ 813*5c51f124SMoriah Waterland } 814*5c51f124SMoriah Waterland 815*5c51f124SMoriah Waterland /* 816*5c51f124SMoriah Waterland * Could not create the file - it may exist or there may be 817*5c51f124SMoriah Waterland * permissions issues - find out and act accordingly. 818*5c51f124SMoriah Waterland */ 819*5c51f124SMoriah Waterland 820*5c51f124SMoriah Waterland lerrno = errno; 821*5c51f124SMoriah Waterland 822*5c51f124SMoriah Waterland /* success if error is 'file exists' */ 823*5c51f124SMoriah Waterland 824*5c51f124SMoriah Waterland if (lerrno == EEXIST) { 825*5c51f124SMoriah Waterland return (1); /* success */ 826*5c51f124SMoriah Waterland } 827*5c51f124SMoriah Waterland 828*5c51f124SMoriah Waterland /* success if error is 'permission denied' but file exists */ 829*5c51f124SMoriah Waterland 830*5c51f124SMoriah Waterland if (lerrno == EACCES) { 831*5c51f124SMoriah Waterland /* 832*5c51f124SMoriah Waterland * Because O_CREAT and O_EXCL are specified in open(), 833*5c51f124SMoriah Waterland * if the contents file already exists, the open will 834*5c51f124SMoriah Waterland * fail with EACCES - determine if this is the case - 835*5c51f124SMoriah Waterland * if so return success. 836*5c51f124SMoriah Waterland */ 837*5c51f124SMoriah Waterland 838*5c51f124SMoriah Waterland if (access(contents, F_OK) == 0) { 839*5c51f124SMoriah Waterland return (1); /* success */ 840*5c51f124SMoriah Waterland } 841*5c51f124SMoriah Waterland 842*5c51f124SMoriah Waterland /* 843*5c51f124SMoriah Waterland * access() failed - if because of permissions failure this 844*5c51f124SMoriah Waterland * means the contents file exists but it cannot be accessed 845*5c51f124SMoriah Waterland * or the path to the contents file cannot be accessed - in 846*5c51f124SMoriah Waterland * either case the contents file cannot be accessed. 847*5c51f124SMoriah Waterland */ 848*5c51f124SMoriah Waterland 849*5c51f124SMoriah Waterland if (errno == EACCES) { 850*5c51f124SMoriah Waterland progerr(gettext(ERR_ACCESS_CONT), contents, 851*5c51f124SMoriah Waterland strerror(lerrno)); 852*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 853*5c51f124SMoriah Waterland return (0); /* failure */ 854*5c51f124SMoriah Waterland } 855*5c51f124SMoriah Waterland } 856*5c51f124SMoriah Waterland 857*5c51f124SMoriah Waterland /* 858*5c51f124SMoriah Waterland * the contents file does not exist and it cannot be created. 859*5c51f124SMoriah Waterland */ 860*5c51f124SMoriah Waterland 861*5c51f124SMoriah Waterland progerr(gettext(ERR_CREAT_CONT), contents, strerror(lerrno)); 862*5c51f124SMoriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 863*5c51f124SMoriah Waterland return (0); /* failure */ 864*5c51f124SMoriah Waterland } 865