5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
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 * 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 * 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 * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define LOCKWAIT 20 /* seconds between retries */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define LOCKRETRY 10 /* number of retries for a DB lock */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define LF_SIZE 128 /* size of governing lock file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define MSG_WTING "NOTE: Waiting for access to the package database."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define MSG_XWTING "NOTE: Waiting for exclusive access to the package " \
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define MSG_WTFOR "NOTE: Waiting for %s of %s to complete."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define WRN_CLRLOCK "WARNING: Stale lock installed for %s, pkg %s quit " \
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "in %s state."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_MKLOCK "unable to create governing lock file <%s>."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_NOLOCK "unable to install governing lock on <%s>."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_LCKTBL "unable to lock <%s> - lock table full."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_LCKREM "unable to lock <%s> - remote host unavailable."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_BADLCK "unable to lock <%s> - unknown error."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_DEADLCK "unable to lock <%s> - deadlock condition."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define LOCK_NAME_OLD_PKG "old version pkg command"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function writes the PID, effective utility name, package name,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * current progress of the utility and the exit state to the lockfile in
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * support of post mortem operations.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandwrlockdata(int fd, int this_pid, char *this_name,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *this_pkg, char *this_place, unsigned int this_state)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "%d %s %s %s %d\n", this_pid, this_name, this_pkg,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (write(fd, lockbuf, LF_SIZE) == LF_SIZE)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function reads the lockfile to obtain the PID and name of the lock
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * holder. Upon those rare circumstances that an older version of pkgadd
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * created the lock, this detects that zero-length file and provides the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * appropriate data. Since this data is only used if an actual lock (from
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * lockf()) is detected, a manually created .lockfile will not result in a
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (read(fd, lockbuf, LF_SIZE) != LF_SIZE) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(lock_name, LOCK_NAME_OLD_PKG,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(lock_place, LOCK_PLACE_UNKNOWN,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* LINTED format argument contains unbounded string specifier */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sscanf(lockbuf, "%ld %s %s %s %u", &lock_pid,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lock_name, lock_pkg, lock_place, &lock_state);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#endif /* lint */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This establishes a locked status file for a pkgadd, pkgrm or swmtool - any
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of the complex package processes. Since numerous packages currently use
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * installf and removef in preinstall scripts, we can't enforce a contents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file write lock throughout the install process. In 2.7 we will enforce the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * write lock and allow this lock to serve as a simple information carrier
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * which can be used by installf and removef too.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * util_name - the name of the utility that is claiming the lock
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * pkg_name - the package that is being locked (or "all package")
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * place - a string of ascii characters that defines the initial "place" where
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the current operation is - this is updated by lockupd() and is a string
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * is used fr post mortem operations if the utility should quit improperly.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns (int):
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - failure
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - success
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandlockinst(char *util_name, char *pkg_name, char *place)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* assume "initial" if no "place" during processing specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((place == (char *)NULL) || (*place == '\0')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(lockpath, sizeof (lockpath),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* If the exit file is not present, create it. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* LINTED O_CREAT without O_EXCL specified in call to open() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((fd = open(lockpath, O_RDWR | O_CREAT, 0600)) == -1) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This tries to create the lock LOCKRETRY times waiting LOCKWAIT
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * seconds between retries.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Try to read the status of the last (or current)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext(MSG_WTFOR), lock_name, lock_pkg);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else { /* This process has the lock. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland util_name : gettext("unknown"), sizeof (lock_name));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pkg_name : gettext("unknown"), sizeof (lock_pkg));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This function updates the utility progress data in the lock file. It is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * used for post mortem operations if the utility should quit improperly.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) wrlockdata(lock_fd, lock_pid, lock_name, lock_pkg, place,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This clears the governing lock and closes the lock file. If this was
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * called already, it just returns.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) wrlockdata(lock_fd, lock_pid, lock_name, lock_pkg,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If close() fails, we can't be sure the lock has been
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * removed, so we assume the worst in case this function is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * called again.