5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdio.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <fcntl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/types.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/param.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/sysmacros.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <string.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <strings.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/wait.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/stat.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/mman.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/statvfs.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <signal.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <limits.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <fcntl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdlib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <unistd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <time.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <pkglocs.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <locale.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <libintl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <pkglib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "libinst.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "libadm.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik#define LOCKFILE ".pkg.lock.client"
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik#define LOCKFILESERV ".pkg.lock"
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define LOCKWAIT 10 /* seconds between retries */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define LOCKRETRY 20 /* number of retries for a DB lock */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik#define ERR_COMMIT "WARNING: unable to commit contents database update"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOCLOSE "WARNING: unable to close <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOUNLINK_LATENT "WARNING: unable to unlink latent <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_LINK_FAIL "link(%s, %s) failed (errno %d)"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NORENAME_CONTENTS "unable to establish contents file <%s> "\
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "from <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_RENAME_FAIL "rename(%s, %s) failed (errno %d)"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_RESTORE_FAIL "attempt to restore <%s> failed"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOUNLINK "WARNING: unable to unlink <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_FCLOSE_FAIL "fclose failed (errno %d)"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_ERRNO "(errno %d: %s)"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOTMPOPEN "unable to open temporary contents file image"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_CFBACK "Not enough space to backup <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_CREAT_CONT "unable to create contents file <%s>: %s"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_ACCESS_CONT "unable to access contents file <%s>: %s"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_CFBACK1 "Need=%llu blocks, Available=%llu blocks " \
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "(block size=%d)"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOCFILE "unable to locate contents file <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOROPEN "unable to open <%s> for reading"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOOPEN "unable to open <%s> for writing"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOSTAT "unable to stat contents file <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOSTATV "statvfs(%s) failed"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOUPD "unable to update contents file"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_DRCONTCP "unable to copy contents file to <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define MSG_XWTING "NOTE: Waiting for exclusive access to the package " \
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "database."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define MSG_NOLOCK "NOTE: Couldn't lock the package database."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOLOCK "Database lock failed."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_OPLOCK "unable to open lock file <%s>."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_MKLOCK "unable to create lock file <%s>."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_LCKREM "unable to lock package database - remote host " \
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "unavailable."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_BADLCK "unable to lock package database - unknown error."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_DEADLCK "unable to lock package database - deadlock condition."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_TMOUT "unable to lock package database - too many retries."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_CFDIR "unable to locate contents file directory"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int active_lock;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int lock_fd; /* fd of LOCKFILE. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char *pkgadm_dir;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dikint pkgWlock(int verbose);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int pkgWunlock(void);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* forward declarations */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint relslock(void);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*ARGSUSED*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlanddo_alarm(int n)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) signal(SIGALRM, SIG_IGN);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) signal(SIGALRM, do_alarm);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) alarm(LOCKWAIT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Point packaging to the appropriate contents file. This is primarily used
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to establish a dryrun contents file. If the malloc() doesn't work, this
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * returns 99 (internal error), else 0.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandset_cfdir(char *cfdir)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char realcf[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char tmpcf[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int status;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (cfdir == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pkgadm_dir = get_PKGADM();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((pkgadm_dir = strdup(cfdir)) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (99);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(tmpcf, sizeof (tmpcf), "%s/contents", pkgadm_dir);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * return if a temporary contents file already exists -
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * assume it is from a prior package in this series.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (access(tmpcf, F_OK) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * no temporary contents file exists - create one.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(realcf, sizeof (realcf), "%s/contents", get_PKGADM());
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If there's a contents file there already, copy it
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * over, otherwise initialize one. Make sure that the
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * server, if running, flushes the contents file.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (void) pkgsync(NULL, get_PKGADM(), B_FALSE);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* create new contents file if one does not already exist */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (access(realcf, F_OK) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int n;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = open(tmpcf, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CREAT_CONT), tmpcf,
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik strerror(errno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (99);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(n);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* contents file exists, save in pkgadm-dir */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland status = copyf(realcf, tmpcf, (time_t)0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (status != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_DRCONTCP), tmpcf);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (99);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function installs the database lock, opens the contents file for
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * reading and creates and opens the temporary contents file for read/write.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * It returns 1 if successful, 0 otherwise.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dikocfile(PKGserver *server, VFP_T **r_tmpvfp, fsblkcnt_t map_blks)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik struct stat64 statb, statl;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct statvfs64 svfsb;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fsblkcnt_t free_blocks;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fsblkcnt_t need_blocks;
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik fsblkcnt_t log_blocks;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFP_T *tmpvfp = (VFP_T *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char contents[PATH_MAX];
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik char logfile[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int n;
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik off_t cdiff_alloc;
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik PKGserver newserver;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* establish package administration contents directory location */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pkgadm_dir == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (set_cfdir(NULL) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CFDIR));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Lock the file for exclusive access */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!pkgWlock(1)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_NOLOCK));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (*server != NULL) {
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik vfpTruncate(*r_tmpvfp);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (void) vfpClearModified(*r_tmpvfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik return (1);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik newserver = pkgopenserver(NULL, pkgadm_dir, B_FALSE);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* The error has been reported. */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (newserver == NULL)
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* reset return VFP/FILE pointers */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (*r_tmpvfp) = (VFP_T *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* determine path to the primary contents file */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik (void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Check and see if there is enough space for the packaging commands
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to back up the contents file, if there is not, then do not allow
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * execution to continue by failing the ocfile() call.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Get the contents file size */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (stat64(contents, &statb) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik progerr(gettext(ERR_NOCFILE), contents);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik pkgcloseserver(newserver);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Get the filesystem space */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (statvfs64(contents, &svfsb) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_NOSTATV), contents);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik pkgcloseserver(newserver);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free_blocks = (((fsblkcnt_t)svfsb.f_frsize > 0) ?
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik howmany(svfsb.f_frsize, DEV_BSIZE) :
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik /* determine blocks used by the logfile */
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik (void) snprintf(logfile, sizeof (logfile), "%s/" PKGLOG, pkgadm_dir);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik if (stat64(logfile, &statl) == -1)
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik log_blocks = 0;
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik else
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik log_blocks = nblk(statl.st_size, svfsb.f_bsize, svfsb.f_frsize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Calculate the number of blocks we need to be able to operate on
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * the contents file and the log file.
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * When adding a package (map_blks > 0), we add the size of the
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * pkgmap file times 1.5 as the pkgmap is a bit smaller then the
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * lines added to the contents file. That data is written both to
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * the new contents file and the log file (2 * 1.5 * map_blks).
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * The new contents file is limited by the size of the current
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * contents file and the increased log file.
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * If we're removing a package, then the log might grow to the size
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * of the full contents file but then the new contents file would
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik * be zero and so we only need to add the size of the contents file.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik need_blocks = map_blks * 3 +
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik /* Current log file */
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik log_blocks +
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik /* Current contents file */
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((need_blocks + 10) > free_blocks) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CFBACK), contents);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CFBACK1), need_blocks, free_blocks,
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik DEV_BSIZE);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik pkgcloseserver(newserver);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * open the temporary contents file without a path name - this causes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the "vfp" to be opened on in-memory storage only, the size of which
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is set following a successful return - this causes the temporary
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * contents file to be maintained in memory only - if no changes are
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * made as the primary contents file is processed, the in memory data
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is discarded and not written to the disk.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfpOpen(&tmpvfp, (char *)NULL, "w", VFP_NONE) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_NOTMPOPEN));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik pkgcloseserver(newserver);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * set size of allocation for temporary contents file - this sets the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * size of the in-memory buffer associated with the open vfp.
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * We only store the new and changed entries.
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * We allocate memory depending on the size of the pkgmap; it's not
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * completely right but <some value + * 1.5 * map_blks * DEV_BSIZE>
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * seems fine (an install adds the size if the name of the package.)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik cdiff_alloc = map_blks * DEV_BSIZE;
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik cdiff_alloc += cdiff_alloc/2;
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (cdiff_alloc < 1000000)
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik cdiff_alloc += 1000000;
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (vfpSetSize(tmpvfp, cdiff_alloc) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_NOTMPOPEN));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpClose(&tmpvfp);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik pkgcloseserver(newserver);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik /* set return ->s to open server/vfps */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*r_tmpvfp) = tmpvfp;
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik *server = newserver;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1); /* All OK */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is a simple open and lock of the contents file. It doesn't create a
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * temporary contents file and it doesn't need to do any space checking.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns 1 for OK and 0 for "didn't do it".
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Diksocfile(PKGserver *server, boolean_t quiet)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik char contents[PATH_MAX];
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik boolean_t readonly = B_FALSE;
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik PKGserver newserver;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pkgadm_dir == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (set_cfdir(NULL) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CFDIR));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Lock the database for exclusive access, but don't make a fuss if
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * it fails (user may not be root and the .pkg.lock file may not
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * exist yet).
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!pkgWlock(0)) {
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (!quiet)
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik logerr(gettext(MSG_NOLOCK));
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik readonly = B_TRUE;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik newserver = pkgopenserver(NULL, pkgadm_dir, readonly);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (newserver == NULL)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik *server = newserver;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: swapcfile
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: This function closes both the current and temporary contents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * files specified, and conditionally replaces the old transitory
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * contents file with the newly updated temporary contents file.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The "ocfile()" or "socfile()" functions must be called to re-
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * open the real contents file for processing.
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * Arguments: PKGserver - handle to the package database
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_cfTmpVfp - (VFP_T **) - [RW, *RW]
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * This is the VFP associated which contains all the
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik * modifications to be written back to the database.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file that is being written to.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * pkginst - (char) - [RO, *RO]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This is the name of the package being operated on;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * this is used to write the "last modified by xxx"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * comment at the end of the contents file.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * dbchg - (int) - [RO]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - the temporary contents file has NOT been changed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * with respect to the real contents file; do not
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * update the real contents file with the contents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of the temporary contents file.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - the temporary contetns file HAS been changed with
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * respect to the real contents file; DO update the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * real contents file with the contents of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * temporary contents file.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == RESULT_OK - successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == RESULT_WRN - successful with warnings
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == RESULT_ERR - failed with fatal errors - deserves an
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * alarming message and a quit()
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTES: If dbchg != 0, the contents file is always updated. If dbchg == 0,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the contents file is updated IF the data is modified indication
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is set on the contents file associated with a_cfTmpVfp.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dikswapcfile(PKGserver server, VFP_T **a_cfTmpVfp, char *pkginst, int dbchg)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *pe;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *pl;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *ps;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char line[256];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char timeb[BUFSIZ];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int retval = RESULT_OK;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct tm *timep;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland time_t clock;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* normalize pkginst so its never null */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pkginst == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland dbchg = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pkginst = "<unknown>";
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If no changes were made to the database, checkpoint the temporary
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * contents file - if this fails, then just close the file which causes
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the contents file to be reopened and reread if it is needed again
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((dbchg == 0) && (vfpGetModified(*a_cfTmpVfp) == 0)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) pkgWunlock(); /* Free the database lock. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (retval);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * changes made to the current temporary contents file -
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * remove any trailing comment lines in the temp contents file, then
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * append updated modification info records to temp contents file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pe = vfpGetCurrCharPtr(*a_cfTmpVfp); /* last char in contents file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ps = vfpGetFirstCharPtr(*a_cfTmpVfp); /* 1st char in contents file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pl = pe; /* last match is last char in contents file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* skip past all trailing newlines and null bytes */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while ((pe > ps) && ((*pe == '\n') || (*pe == '\0'))) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pe--;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* remove trailing comments as long as there are lines in the file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (pe > ps) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (*pe != '\n') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* curr char is not newline: backup one byte */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pl = pe--;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (*pl != '#') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* curr char is newline next char not comment break */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* curr char is newline next char is comment - remove */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *pl = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfpSetLastCharPtr(*a_cfTmpVfp, pl);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pe--;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* create two update comment lines */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) time(&clock);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland timep = localtime(&clock);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strftime(timeb, sizeof (timeb), "%c\n", timep);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(line, sizeof (line),
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik gettext("# Last modified by %s for %s package\n# %s"),
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik get_prog_name(), pkginst, timeb);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfpPuts(*a_cfTmpVfp, line);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* commit temporary contents file bytes to storage */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik if (pkgservercommitfile(*a_cfTmpVfp, server) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik logerr(gettext(ERR_COMMIT));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfpClose(a_cfTmpVfp);
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dik pkgcloseserver(server);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) pkgWunlock(); /* Free the database lock. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (RESULT_ERR);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (relslock() == 0 ? RESULT_ERR : retval);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* This function releases the lock on the package database. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandrelslock(void)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This closes the contents file and releases the lock.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!pkgWunlock()) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_NOUPD));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_FCLOSE_FAIL), lerrno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function attempts to lock the package database. It returns 1 on
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * success, 0 on failure. The positive logic verbose flag determines whether
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or not the function displays the error message upon failure.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
62224350e5355e6834f7deb9d8a7d062a50cb7c2Casper H.S. Dikint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandpkgWlock(int verbose) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int retry_cnt, retval;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char lockpath[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland active_lock = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(lockpath, sizeof (lockpath),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "%s/%s", pkgadm_dir, LOCKFILE);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland retry_cnt = LOCKRETRY;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If the lock file is not present, create it. The mode is set to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * allow any process to lock the database, that's because pkgchk may
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * be run by a non-root user.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (access(lockpath, F_OK) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lock_fd = open(lockpath, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (lock_fd < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (verbose)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_MKLOCK), lockpath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fchmod(lock_fd, 0644); /* force perms. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((lock_fd = open(lockpath, O_RDWR)) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (verbose)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_OPLOCK), lockpath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) signal(SIGALRM, do_alarm);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) alarm(LOCKWAIT);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland do {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (lockf(lock_fd, F_LOCK, 0)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EAGAIN || errno == EINTR)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(MSG_XWTING));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland else if (errno == ECOMM) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_LCKREM));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland retval = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (errno == EBADF) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_BADLCK));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland retval = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (errno == EDEADLK) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_DEADLCK));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland retval = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland active_lock = 1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland retval = 1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } while (retry_cnt--);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) signal(SIGALRM, SIG_IGN);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (retval == 0)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (retry_cnt == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_TMOUT));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) pkgWunlock(); /* close the lockfile. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (retval);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Release the lock on the package database. Returns 1 on success, 0 on
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * failure.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandpkgWunlock(void) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (active_lock) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland active_lock = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (close(lock_fd))
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland else
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function verifies that the contents file is in place.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * returns 1 - if it exists
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * returns 0 - if it does not exist
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandiscfile(void)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char contents[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(contents, PATH_MAX, "%s/contents", get_PKGADM());
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (access(contents, F_OK) == 0 ? 1 : 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function verifies that the contents file is in place. If it is - no
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * change. If it isn't - this creates it.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: == 0 : failure
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 : success
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandvcfile(void)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int fd;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char contents[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * create full path to contents file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(contents, sizeof (contents),
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik "%s/contents", get_PKGADM());
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Attempt to create the file - will only be successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if the file does not currently exist.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fd = open(contents, O_WRONLY | O_CREAT | O_EXCL, 0644);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fd >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Contents file wasn't there, but is now.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland echo(gettext("## Software contents file initialized"));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1); /* success */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Could not create the file - it may exist or there may be
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * permissions issues - find out and act accordingly.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* success if error is 'file exists' */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (lerrno == EEXIST) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1); /* success */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* success if error is 'permission denied' but file exists */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (lerrno == EACCES) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Because O_CREAT and O_EXCL are specified in open(),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if the contents file already exists, the open will
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fail with EACCES - determine if this is the case -
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if so return success.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (access(contents, F_OK) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (1); /* success */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * access() failed - if because of permissions failure this
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * means the contents file exists but it cannot be accessed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or the path to the contents file cannot be accessed - in
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * either case the contents file cannot be accessed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EACCES) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_ACCESS_CONT), contents,
214c21966e601d9d9946efda70b0d87b019d10dcCasper H.S. Dik strerror(lerrno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0); /* failure */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the contents file does not exist and it cannot be created.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CREAT_CONT), contents, strerror(lerrno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0); /* failure */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}