xref: /titanic_53/usr/src/lib/libinstzones/common/zones_locks.c (revision f5c2e7ea56aaa46a9976476fb0cb1f02b9426f07)
15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
27*f5c2e7eaSTheo Schlossnagle /*
28*f5c2e7eaSTheo Schlossnagle  * Copyright (c) 2012 by Delphix. All rights reserved.
29*f5c2e7eaSTheo Schlossnagle  */
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland /*
325c51f124SMoriah Waterland  * Module:	zones_locks.c
335c51f124SMoriah Waterland  * Group:	libinstzones
345c51f124SMoriah Waterland  * Description:	Provide "zones" locking interfaces for install consolidation
355c51f124SMoriah Waterland  *		code
365c51f124SMoriah Waterland  *
375c51f124SMoriah Waterland  * Public Methods:
385c51f124SMoriah Waterland  *
395c51f124SMoriah Waterland  * _z_acquire_lock - acquire a lock on an object on a zone
405c51f124SMoriah Waterland  * _z_adjust_lock_object_for_rootpath - Given a lock object and a root path,
415c51f124SMoriah Waterland  *	if the root path is not
425c51f124SMoriah Waterland  * _z_lock_zone - Acquire specified locks on specified zone
435c51f124SMoriah Waterland  * _z_lock_zone_object - lock a single lock object in a specified zone
445c51f124SMoriah Waterland  * _z_release_lock - release a lock held on a zone
455c51f124SMoriah Waterland  * _z_unlock_zone - Released specified locks on specified zone
465c51f124SMoriah Waterland  * _z_unlock_zone_object - unlock a single lock object in a specified zone
475c51f124SMoriah Waterland  */
485c51f124SMoriah Waterland 
495c51f124SMoriah Waterland /*
505c51f124SMoriah Waterland  * System includes
515c51f124SMoriah Waterland  */
525c51f124SMoriah Waterland 
535c51f124SMoriah Waterland #include <stdio.h>
545c51f124SMoriah Waterland #include <stdlib.h>
555c51f124SMoriah Waterland #include <unistd.h>
565c51f124SMoriah Waterland #include <fcntl.h>
575c51f124SMoriah Waterland #include <ctype.h>
585c51f124SMoriah Waterland #include <sys/types.h>
595c51f124SMoriah Waterland #include <sys/param.h>
605c51f124SMoriah Waterland #include <string.h>
615c51f124SMoriah Waterland #include <strings.h>
625c51f124SMoriah Waterland #include <stdarg.h>
635c51f124SMoriah Waterland #include <limits.h>
645c51f124SMoriah Waterland #include <errno.h>
655c51f124SMoriah Waterland #include <time.h>
665c51f124SMoriah Waterland #include <stropts.h>
675c51f124SMoriah Waterland #include <libintl.h>
685c51f124SMoriah Waterland #include <locale.h>
695c51f124SMoriah Waterland #include <assert.h>
705c51f124SMoriah Waterland 
715c51f124SMoriah Waterland /*
725c51f124SMoriah Waterland  * local includes
735c51f124SMoriah Waterland  */
745c51f124SMoriah Waterland 
755c51f124SMoriah Waterland #include "instzones_lib.h"
765c51f124SMoriah Waterland #include "zones_strings.h"
775c51f124SMoriah Waterland 
785c51f124SMoriah Waterland /*
795c51f124SMoriah Waterland  * Private structures
805c51f124SMoriah Waterland  */
815c51f124SMoriah Waterland 
825c51f124SMoriah Waterland /*
835c51f124SMoriah Waterland  * Library Function Prototypes
845c51f124SMoriah Waterland  */
855c51f124SMoriah Waterland 
865c51f124SMoriah Waterland /*
875c51f124SMoriah Waterland  * Local Function Prototypes
885c51f124SMoriah Waterland  */
895c51f124SMoriah Waterland 
905c51f124SMoriah Waterland boolean_t	_z_adjust_lock_object_for_rootpath(char **r_result,
915c51f124SMoriah Waterland 		    char *a_lockObject);
925c51f124SMoriah Waterland boolean_t	_z_acquire_lock(char **r_lockKey, char *a_zoneName,
935c51f124SMoriah Waterland 		    char *a_lock, pid_t a_pid, boolean_t a_wait);
945c51f124SMoriah Waterland boolean_t	_z_lock_zone(zoneListElement_t *a_zlst,
955c51f124SMoriah Waterland 		    ZLOCKS_T a_lflags);
965c51f124SMoriah Waterland boolean_t	_z_lock_zone_object(char **r_objectLocks,
975c51f124SMoriah Waterland 		    char *a_zoneName, char *a_lockObject,
985c51f124SMoriah Waterland 		    pid_t a_pid, char *a_waitingMsg,
995c51f124SMoriah Waterland 		    char *a_busyMsg);
1005c51f124SMoriah Waterland boolean_t	_z_release_lock(char *a_zoneName, char *a_lock,
1015c51f124SMoriah Waterland 		    char *a_key, boolean_t a_wait);
1025c51f124SMoriah Waterland 		    boolean_t	_z_unlock_zone(zoneListElement_t *a_zlst,
1035c51f124SMoriah Waterland 		    ZLOCKS_T a_lflags);
1045c51f124SMoriah Waterland boolean_t	_z_unlock_zone_object(char **r_objectLocks,
1055c51f124SMoriah Waterland 		    char *a_zoneName, char *a_lockObject,
1065c51f124SMoriah Waterland 		    char *a_errMsg);
1075c51f124SMoriah Waterland 
1085c51f124SMoriah Waterland /*
1095c51f124SMoriah Waterland  * global internal (private) declarations
1105c51f124SMoriah Waterland  */
1115c51f124SMoriah Waterland 
1125c51f124SMoriah Waterland /*
1135c51f124SMoriah Waterland  * *****************************************************************************
1145c51f124SMoriah Waterland  * global external (public) functions
1155c51f124SMoriah Waterland  * *****************************************************************************
1165c51f124SMoriah Waterland  */
1175c51f124SMoriah Waterland 
1185c51f124SMoriah Waterland /*
1195c51f124SMoriah Waterland  * Name:	_z_acquire_lock
1205c51f124SMoriah Waterland  * Description:	acquire a lock on an object on a zone
1215c51f124SMoriah Waterland  * Arguments:	r_lockKey - [RW, *RW] - (char *)
1225c51f124SMoriah Waterland  *			Pointer to handle to string representing the lock key
1235c51f124SMoriah Waterland  *			associated with the lock object to be acquired - this
1245c51f124SMoriah Waterland  *			key is returned when the lock is acquired and must be
1255c51f124SMoriah Waterland  *			provided when releasing the lock
1265c51f124SMoriah Waterland  *			== (char *)NULL - lock not acquired
1275c51f124SMoriah Waterland  *		a_zoneName - [RO, *RO] - (char *)
1285c51f124SMoriah Waterland  *			Pointer to string representing the name of the zone to
1295c51f124SMoriah Waterland  *			acquire the specified lock on
1305c51f124SMoriah Waterland  *		a_lockObject - [RO, *RO] - (char *)
1315c51f124SMoriah Waterland  *			Pointer to string representing the lock object to
1325c51f124SMoriah Waterland  *			acquire on the specified zone
1335c51f124SMoriah Waterland  *		a_pid - [RO, *RO] - (pid_t)
1345c51f124SMoriah Waterland  *			Process i.d. to associate with this lock
1355c51f124SMoriah Waterland  *			== 0 - no process i.d. associated with the lock
1365c51f124SMoriah Waterland  *		a_wait - [RO, *RO] - (int)
1375c51f124SMoriah Waterland  *			Determines what to do if the lock cannot be acquired:
1385c51f124SMoriah Waterland  *			== B_TRUE - wait for the lock to be acquired
1395c51f124SMoriah Waterland  *			== B_FALSE - do not wait for the lock to be acquired
1405c51f124SMoriah Waterland  * Returns:	boolean_t
1415c51f124SMoriah Waterland  *			B_TRUE - lock acquired
1425c51f124SMoriah Waterland  *			B_FALSE - lock not acquired
1435c51f124SMoriah Waterland  */
1445c51f124SMoriah Waterland 
1455c51f124SMoriah Waterland boolean_t
_z_acquire_lock(char ** r_lockKey,char * a_zoneName,char * a_lockObject,pid_t a_pid,boolean_t a_wait)1465c51f124SMoriah Waterland _z_acquire_lock(char **r_lockKey, char *a_zoneName, char *a_lockObject,
1475c51f124SMoriah Waterland 	pid_t a_pid, boolean_t a_wait)
1485c51f124SMoriah Waterland {
1495c51f124SMoriah Waterland 	argArray_t	*args;
1505c51f124SMoriah Waterland 	boolean_t	b;
1515c51f124SMoriah Waterland 	char		*adjustedLockObject = (char *)NULL;
1525c51f124SMoriah Waterland 	char		*p;
1535c51f124SMoriah Waterland 	char		*results = (char *)NULL;
1545c51f124SMoriah Waterland 	int		r;
1555c51f124SMoriah Waterland 	int		status;
1565c51f124SMoriah Waterland 
1575c51f124SMoriah Waterland 	/* entry assertions */
1585c51f124SMoriah Waterland 
1595c51f124SMoriah Waterland 	assert(a_zoneName != (char *)NULL);
1605c51f124SMoriah Waterland 	assert(a_lockObject != (char *)NULL);
1615c51f124SMoriah Waterland 	assert(*a_lockObject != '\0');
1625c51f124SMoriah Waterland 	assert(r_lockKey != (char **)NULL);
1635c51f124SMoriah Waterland 
1645c51f124SMoriah Waterland 	/* entry debugging info */
1655c51f124SMoriah Waterland 
1665c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_APLK, a_zoneName, a_lockObject, a_pid);
1675c51f124SMoriah Waterland 
1685c51f124SMoriah Waterland 	/* reset returned lock key handle */
1695c51f124SMoriah Waterland 
1705c51f124SMoriah Waterland 	*r_lockKey = (char *)NULL;
1715c51f124SMoriah Waterland 
1725c51f124SMoriah Waterland 	/*
1735c51f124SMoriah Waterland 	 * Only one lock file must ever be used - the one located on the root
1745c51f124SMoriah Waterland 	 * file system of the currently running Solaris instance. To allow for
1755c51f124SMoriah Waterland 	 * alternative roots to be properly locked, adjust the lock object to
1765c51f124SMoriah Waterland 	 * take root path into account; if necessary, the root path will be
1775c51f124SMoriah Waterland 	 * prepended to the lock object.
1785c51f124SMoriah Waterland 	 */
1795c51f124SMoriah Waterland 
1805c51f124SMoriah Waterland 	b = _z_adjust_lock_object_for_rootpath(&adjustedLockObject,
1815c51f124SMoriah Waterland 	    a_lockObject);
1825c51f124SMoriah Waterland 	if (!b) {
1835c51f124SMoriah Waterland 		return (B_FALSE);
1845c51f124SMoriah Waterland 	}
1855c51f124SMoriah Waterland 
1865c51f124SMoriah Waterland 	/*
1875c51f124SMoriah Waterland 	 * construct command arguments:
1885c51f124SMoriah Waterland 	 * pkgadm lock -a -q -o adjustedLockObject [ -w -W timeout ]
1895c51f124SMoriah Waterland 	 *		[ -p a_pid -z zoneid ]
1905c51f124SMoriah Waterland 	 */
1915c51f124SMoriah Waterland 
1925c51f124SMoriah Waterland 	args = _z_new_args(20);			/* generate new arg list */
1935c51f124SMoriah Waterland 	(void) _z_add_arg(args, PKGADM_CMD);	/* pkgadm command */
1945c51f124SMoriah Waterland 	(void) _z_add_arg(args, "lock");		/* lock sub-command */
1955c51f124SMoriah Waterland 	(void) _z_add_arg(args, "-a");		/* acquire lock */
1965c51f124SMoriah Waterland 	(void) _z_add_arg(args, "-q");		/* quiet (no extra messages) */
1975c51f124SMoriah Waterland 	(void) _z_add_arg(args, "-o");		/* object to acquire */
1985c51f124SMoriah Waterland 	(void) _z_add_arg(args, "%s", adjustedLockObject);
1995c51f124SMoriah Waterland 
2005c51f124SMoriah Waterland 	/* add [ -w -W timeout ] if waiting for lock */
2015c51f124SMoriah Waterland 
2025c51f124SMoriah Waterland 	if (a_wait == B_TRUE) {
2035c51f124SMoriah Waterland 		(void) _z_add_arg(args, "-w");		/* wait */
2045c51f124SMoriah Waterland 		(void) _z_add_arg(args, "-W");		/* wait timeout */
2055c51f124SMoriah Waterland 		(void) _z_add_arg(args, "%ld",
2065c51f124SMoriah Waterland 		    (long)MAX_RETRIES*RETRY_DELAY_SECS);
2075c51f124SMoriah Waterland 	}
2085c51f124SMoriah Waterland 
2095c51f124SMoriah Waterland 	/* add process/zone i.d.s if process i.d. provided */
2105c51f124SMoriah Waterland 
2115c51f124SMoriah Waterland 	if (a_pid > 0) {
2125c51f124SMoriah Waterland 		(void) _z_add_arg(args, "-p");	/* lock valid process i.d. */
213*f5c2e7eaSTheo Schlossnagle 		(void) _z_add_arg(args, "%lld", (long long)getpid());
2145c51f124SMoriah Waterland 		(void) _z_add_arg(args, "-z");	/* lock valid zone i.d. */
215*f5c2e7eaSTheo Schlossnagle 		(void) _z_add_arg(args, "%lld", (long long)getzoneid());
2165c51f124SMoriah Waterland 	}
2175c51f124SMoriah Waterland 
2185c51f124SMoriah Waterland 	/* execute command */
2195c51f124SMoriah Waterland 
2205c51f124SMoriah Waterland 	r = _z_zone_exec(&status, &results, (char *)NULL, PKGADM_CMD,
2215c51f124SMoriah Waterland 	    _z_get_argv(args), a_zoneName, (int *)NULL);
2225c51f124SMoriah Waterland 
2235c51f124SMoriah Waterland 	/* free generated argument list */
2245c51f124SMoriah Waterland 
2255c51f124SMoriah Waterland 	_z_free_args(args);
2265c51f124SMoriah Waterland 
2275c51f124SMoriah Waterland 	/* return error if failed to acquire */
2285c51f124SMoriah Waterland 
2295c51f124SMoriah Waterland 	if ((r != 0) || (status != 0)) {
2305c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_APLK_EXIT, a_zoneName,
2315c51f124SMoriah Waterland 		    adjustedLockObject, a_pid, r, status,
2325c51f124SMoriah Waterland 		    results ? results : "");
2335c51f124SMoriah Waterland 
2345c51f124SMoriah Waterland 		/* free up results if returned */
2355c51f124SMoriah Waterland 		if (results) {
2365c51f124SMoriah Waterland 			free(results);
2375c51f124SMoriah Waterland 		}
2385c51f124SMoriah Waterland 
2395c51f124SMoriah Waterland 		/* free adjusted lock object */
2405c51f124SMoriah Waterland 		free(adjustedLockObject);
2415c51f124SMoriah Waterland 
2425c51f124SMoriah Waterland 		/* return failure */
2435c51f124SMoriah Waterland 		return (B_FALSE);
2445c51f124SMoriah Waterland 	}
2455c51f124SMoriah Waterland 
2465c51f124SMoriah Waterland 	/* return success if no results returned */
2475c51f124SMoriah Waterland 
2485c51f124SMoriah Waterland 	if (results == (char *)NULL) {
2495c51f124SMoriah Waterland 		return (B_TRUE);
2505c51f124SMoriah Waterland 	}
2515c51f124SMoriah Waterland 
2525c51f124SMoriah Waterland 	/* return the lock key */
2535c51f124SMoriah Waterland 
2545c51f124SMoriah Waterland 	p = _z_strGetToken((char *)NULL, results, 0, "\n");
2555c51f124SMoriah Waterland 	_z_strRemoveLeadingWhitespace(&p);
2565c51f124SMoriah Waterland 	*r_lockKey = p;
2575c51f124SMoriah Waterland 
2585c51f124SMoriah Waterland 	/* exit debugging info */
2595c51f124SMoriah Waterland 
2605c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_APLK_RESULTS, a_zoneName, adjustedLockObject, p,
2615c51f124SMoriah Waterland 	    results);
2625c51f124SMoriah Waterland 
2635c51f124SMoriah Waterland 	/* free up results */
2645c51f124SMoriah Waterland 
2655c51f124SMoriah Waterland 	free(results);
2665c51f124SMoriah Waterland 
2675c51f124SMoriah Waterland 	/* free adjusted lock object */
2685c51f124SMoriah Waterland 
2695c51f124SMoriah Waterland 	free(adjustedLockObject);
2705c51f124SMoriah Waterland 
2715c51f124SMoriah Waterland 	/* return success */
2725c51f124SMoriah Waterland 
2735c51f124SMoriah Waterland 	return (B_TRUE);
2745c51f124SMoriah Waterland }
2755c51f124SMoriah Waterland 
2765c51f124SMoriah Waterland /*
2775c51f124SMoriah Waterland  * Name:	_z_adjust_lock_object_for_rootpath
2785c51f124SMoriah Waterland  * Description:	Given a lock object and a root path, if the root path is not
2795c51f124SMoriah Waterland  *		the current running system root, then alter the lock object
2805c51f124SMoriah Waterland  *		to contain a reference to the root path. Only one lock file must
2815c51f124SMoriah Waterland  *		ever be used to create and maintain locks - the lock file that
2825c51f124SMoriah Waterland  *		is located in /tmp on the root file system of the currently
2835c51f124SMoriah Waterland  *		running Solaris instance. To allow for alternative roots to be
2845c51f124SMoriah Waterland  *		properly locked, if necessary adjust the lock object to take
2855c51f124SMoriah Waterland  *		root path into account. If the root path does not indicate the
2865c51f124SMoriah Waterland  *		current running Solaris instance, then the root path will be
2875c51f124SMoriah Waterland  *		prepended to the lock object.
2885c51f124SMoriah Waterland  * Arguments:	r_result - [RW, *RW] - (char **)
2895c51f124SMoriah Waterland  *			Pointer to handle to character string that will contain
2905c51f124SMoriah Waterland  *			the lock object to use.
2915c51f124SMoriah Waterland  *		a_lockObject - [RO, *RO] - (char *)
2925c51f124SMoriah Waterland  *			Pointer to string representing the lock object to adjust
2935c51f124SMoriah Waterland  * Returns:	boolean_t
2945c51f124SMoriah Waterland  *			B_TRUE - lock object adjusted and returned
2955c51f124SMoriah Waterland  *			B_FALSE - unable to adjust lock object
2965c51f124SMoriah Waterland  * NOTE:    	Any string returned is placed in new storage for the
2975c51f124SMoriah Waterland  *		calling function. The caller must use 'free' to dispose
2985c51f124SMoriah Waterland  *		of the storage once the string is no longer needed.
2995c51f124SMoriah Waterland  *
3005c51f124SMoriah Waterland  * A lock object has this form:
3015c51f124SMoriah Waterland  *
3025c51f124SMoriah Waterland  * name.value [ /name.value [ /name.value ... ] ]
3035c51f124SMoriah Waterland  *
3045c51f124SMoriah Waterland  * The "value is either a specific object or a "*", for example:
3055c51f124SMoriah Waterland  *
3065c51f124SMoriah Waterland  *     package.test
3075c51f124SMoriah Waterland  *
3085c51f124SMoriah Waterland  * This locks the package "test"
3095c51f124SMoriah Waterland  *
3105c51f124SMoriah Waterland  *     zone.* /package.*
3115c51f124SMoriah Waterland  *
3125c51f124SMoriah Waterland  * This locks all packages on all zones.
3135c51f124SMoriah Waterland  *
3145c51f124SMoriah Waterland  *     zone.* /package.SUNWluu
3155c51f124SMoriah Waterland  *
3165c51f124SMoriah Waterland  * This locks the package SUNWluu on all zones.
3175c51f124SMoriah Waterland  *
3185c51f124SMoriah Waterland  * If a -R rootpath is specified, since there is only one lock file in
3195c51f124SMoriah Waterland  * the current /tmp, the lock object is modified to include the root
3205c51f124SMoriah Waterland  * path:
3215c51f124SMoriah Waterland  *
3225c51f124SMoriah Waterland  *     rootpath.rootpath/zone.* /package.*
3235c51f124SMoriah Waterland  *
3245c51f124SMoriah Waterland  * locks all packages on all zones in the root path "?"
3255c51f124SMoriah Waterland  *
3265c51f124SMoriah Waterland  * The characters "/" and "*" and "." cannot be part of the "value"; that
3275c51f124SMoriah Waterland  * is if "-R /tmp/gmg*dir.test-path" is specified, the final object
3285c51f124SMoriah Waterland  * cannot be:
3295c51f124SMoriah Waterland  *
3305c51f124SMoriah Waterland  *     rootpath./tmp/gmg*dir.test-path/zone.* /package.*
3315c51f124SMoriah Waterland  *
3325c51f124SMoriah Waterland  * This would be parsed as:
3335c51f124SMoriah Waterland  *
3345c51f124SMoriah Waterland  *      "rootpath." "/tmp" "gmg*dir.test-path" "zone.*" "package.*"
3355c51f124SMoriah Waterland  *
3365c51f124SMoriah Waterland  * which is not correct.
3375c51f124SMoriah Waterland  *
3385c51f124SMoriah Waterland  * So the path is modified by the loop, in this case it would result in
3395c51f124SMoriah Waterland  * this lock object:
3405c51f124SMoriah Waterland  *
3415c51f124SMoriah Waterland  *     rootpath.-1tmp-1gmg-3dir-2test---path/zone.* /package.*
3425c51f124SMoriah Waterland  *
3435c51f124SMoriah Waterland  * This is parsed as:
3445c51f124SMoriah Waterland  *
3455c51f124SMoriah Waterland  *     "rootpath.-1tmp-1gmg-3dir-2test---path" "zone.*" "package.*"
3465c51f124SMoriah Waterland  *
3475c51f124SMoriah Waterland  * which is then interpreted as:
3485c51f124SMoriah Waterland  *
3495c51f124SMoriah Waterland  *     "rootpath./tmp/gmg*dir.test-path" "zone.*" "package.*"
3505c51f124SMoriah Waterland  */
3515c51f124SMoriah Waterland 
3525c51f124SMoriah Waterland boolean_t
_z_adjust_lock_object_for_rootpath(char ** r_result,char * a_lockObject)3535c51f124SMoriah Waterland _z_adjust_lock_object_for_rootpath(char **r_result, char *a_lockObject)
3545c51f124SMoriah Waterland {
3555c51f124SMoriah Waterland 	char		realRootPath[PATH_MAX] = {'\0'};
3565c51f124SMoriah Waterland 	const char	*a_rootPath;
3575c51f124SMoriah Waterland 
3585c51f124SMoriah Waterland 	/* entry assertions */
3595c51f124SMoriah Waterland 
3605c51f124SMoriah Waterland 	assert(r_result != (char **)NULL);
3615c51f124SMoriah Waterland 	assert(a_lockObject != (char *)NULL);
3625c51f124SMoriah Waterland 	assert(*a_lockObject != '\0');
3635c51f124SMoriah Waterland 
3645c51f124SMoriah Waterland 	/* reset returned lock object handle */
3655c51f124SMoriah Waterland 
3665c51f124SMoriah Waterland 	*r_result = (char *)NULL;
3675c51f124SMoriah Waterland 
3685c51f124SMoriah Waterland 	/*
3695c51f124SMoriah Waterland 	 * if root path points to "/" return a duplicate of the passed in
3705c51f124SMoriah Waterland 	 * lock objects; otherwise, resolve root path and adjust lock object by
3715c51f124SMoriah Waterland 	 * prepending the rootpath to the lock object (using LOBJ_ROOTPATH).
3725c51f124SMoriah Waterland 	 */
3735c51f124SMoriah Waterland 
3745c51f124SMoriah Waterland 	a_rootPath = _z_global_data._z_root_dir;
3755c51f124SMoriah Waterland 	if ((a_rootPath == (char *)NULL) ||
3765c51f124SMoriah Waterland 	    (*a_rootPath == '\0') ||
3775c51f124SMoriah Waterland 	    (strcmp(a_rootPath, "/") == 0)) {
3785c51f124SMoriah Waterland 
3795c51f124SMoriah Waterland 		/* root path not specified or is only "/" - no -R specified */
3805c51f124SMoriah Waterland 
3815c51f124SMoriah Waterland 		*r_result = _z_strdup(a_lockObject);
3825c51f124SMoriah Waterland 	} else {
3835c51f124SMoriah Waterland 		/*
3845c51f124SMoriah Waterland 		 * root path is not "" or "/" - -R to an alternative root has
3855c51f124SMoriah Waterland 		 * been specified; resolve all symbolic links and relative nodes
3865c51f124SMoriah Waterland 		 * of path name and determine absolute path to the root path.
3875c51f124SMoriah Waterland 		 */
3885c51f124SMoriah Waterland 
3895c51f124SMoriah Waterland 		if (realpath(a_rootPath, realRootPath) == (char *)NULL) {
3905c51f124SMoriah Waterland 			/* cannot determine absolute path; use path specified */
3915c51f124SMoriah Waterland 			(void) strlcpy(realRootPath, a_rootPath,
3925c51f124SMoriah Waterland 			    sizeof (realRootPath));
3935c51f124SMoriah Waterland 		}
3945c51f124SMoriah Waterland 
3955c51f124SMoriah Waterland 		/*
3965c51f124SMoriah Waterland 		 * if root path points to "/" duplicate existing lock object;
3975c51f124SMoriah Waterland 		 * otherwise, resolve root path and adjust lock object by
3985c51f124SMoriah Waterland 		 * prepending the rootpath to the lock object
3995c51f124SMoriah Waterland 		 */
4005c51f124SMoriah Waterland 
4015c51f124SMoriah Waterland 		if (strcmp(realRootPath, "/") == 0) {
4025c51f124SMoriah Waterland 			*r_result = _z_strdup(a_lockObject);
4035c51f124SMoriah Waterland 		} else {
4045c51f124SMoriah Waterland 			char *p1, *p2, *p3;
4055c51f124SMoriah Waterland 
4065c51f124SMoriah Waterland 			/* prefix out /.* which cannot be part of lock object */
4075c51f124SMoriah Waterland 
4085c51f124SMoriah Waterland 			p1 = _z_calloc((strlen(realRootPath)*2)+1);
4095c51f124SMoriah Waterland 			for (p3 = p1, p2 = realRootPath; *p2 != '\0'; p2++) {
4105c51f124SMoriah Waterland 				switch (*p2) {
4115c51f124SMoriah Waterland 				case '/':	/* / becomes -1 */
4125c51f124SMoriah Waterland 					*p3++ = '-';
4135c51f124SMoriah Waterland 					*p3++ = '1';
4145c51f124SMoriah Waterland 					break;
4155c51f124SMoriah Waterland 				case '.':	/* . becomes -2 */
4165c51f124SMoriah Waterland 					*p3++ = '-';
4175c51f124SMoriah Waterland 					*p3++ = '2';
4185c51f124SMoriah Waterland 					break;
4195c51f124SMoriah Waterland 				case '*':	/* * becomes -3 */
4205c51f124SMoriah Waterland 					*p3++ = '-';
4215c51f124SMoriah Waterland 					*p3++ = '3';
4225c51f124SMoriah Waterland 					break;
4235c51f124SMoriah Waterland 				case '-':	/* - becomes -- */
4245c51f124SMoriah Waterland 					*p3++ = '-';
4255c51f124SMoriah Waterland 					*p3++ = '-';
4265c51f124SMoriah Waterland 					break;
4275c51f124SMoriah Waterland 				default:	/* do not prefix out char */
4285c51f124SMoriah Waterland 					*p3++ = *p2;
4295c51f124SMoriah Waterland 					break;
4305c51f124SMoriah Waterland 				}
4315c51f124SMoriah Waterland 			}
4325c51f124SMoriah Waterland 
4335c51f124SMoriah Waterland 			/* create "realpath.%s" object */
4345c51f124SMoriah Waterland 
4355c51f124SMoriah Waterland 			p2 = _z_strPrintf(LOBJ_ROOTPATH, p1);
4365c51f124SMoriah Waterland 			free(p1);
4375c51f124SMoriah Waterland 			if (p2 == (char *)NULL) {
4385c51f124SMoriah Waterland 				_z_program_error(ERR_MALLOC, "<path>", errno,
4395c51f124SMoriah Waterland 				    strerror(errno));
4405c51f124SMoriah Waterland 				return (B_FALSE);
4415c51f124SMoriah Waterland 			}
4425c51f124SMoriah Waterland 
4435c51f124SMoriah Waterland 			/* create "realpath.%s/..." final lock object */
4445c51f124SMoriah Waterland 
4455c51f124SMoriah Waterland 			*r_result = _z_strPrintf("%s/%s", p2, a_lockObject);
4465c51f124SMoriah Waterland 			free(p2);
4475c51f124SMoriah Waterland 			if (*r_result == (char *)NULL) {
4485c51f124SMoriah Waterland 				_z_program_error(ERR_MALLOC, "<path>", errno,
4495c51f124SMoriah Waterland 				    strerror(errno));
4505c51f124SMoriah Waterland 				return (B_FALSE);
4515c51f124SMoriah Waterland 			}
4525c51f124SMoriah Waterland 		}
4535c51f124SMoriah Waterland 	}
4545c51f124SMoriah Waterland 
4555c51f124SMoriah Waterland 	/* exit debugging info */
4565c51f124SMoriah Waterland 
4575c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_ADJLCKOBJ_EXIT, a_lockObject, *r_result,
4585c51f124SMoriah Waterland 	    a_rootPath ? a_rootPath : "",
4595c51f124SMoriah Waterland 	    realRootPath ? realRootPath : "");
4605c51f124SMoriah Waterland 
4615c51f124SMoriah Waterland 	/* return success */
4625c51f124SMoriah Waterland 
4635c51f124SMoriah Waterland 	return (B_TRUE);
4645c51f124SMoriah Waterland }
4655c51f124SMoriah Waterland 
4665c51f124SMoriah Waterland /*
4675c51f124SMoriah Waterland  * Name:	_z_lock_zone
4685c51f124SMoriah Waterland  * Description:	Acquire specified locks on specified zone
4695c51f124SMoriah Waterland  * Arguments:	a_zlst - [RO, *RW] - (zoneListElement_t *)
4705c51f124SMoriah Waterland  *			Pointer to zone list structure element describing
4715c51f124SMoriah Waterland  *			the zone the lock - the structure is updated with
4725c51f124SMoriah Waterland  *			the lock objects and keys if the locks are acquired
4735c51f124SMoriah Waterland  *		a_lflags - [RO, *RO] - (ZLOCKS_T)
4745c51f124SMoriah Waterland  *			Flags indicating which locks to acquire on the zone
4755c51f124SMoriah Waterland  * Returns:	boolean_t
4765c51f124SMoriah Waterland  *			== B_TRUE - locks successfully acquired
4775c51f124SMoriah Waterland  *			== B_FALSE - failed to acquire the locks
4785c51f124SMoriah Waterland  */
4795c51f124SMoriah Waterland 
4805c51f124SMoriah Waterland boolean_t
_z_lock_zone(zoneListElement_t * a_zlst,ZLOCKS_T a_lflags)4815c51f124SMoriah Waterland _z_lock_zone(zoneListElement_t *a_zlst, ZLOCKS_T a_lflags)
4825c51f124SMoriah Waterland {
4835c51f124SMoriah Waterland 	char *scratchName;
4845c51f124SMoriah Waterland 	boolean_t	b;
4855c51f124SMoriah Waterland 
4865c51f124SMoriah Waterland 	/* entry assertions */
4875c51f124SMoriah Waterland 
4885c51f124SMoriah Waterland 	assert(a_zlst != (zoneListElement_t *)NULL);
4895c51f124SMoriah Waterland 
4905c51f124SMoriah Waterland 	/* entry debugging info */
4915c51f124SMoriah Waterland 
4925c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_LCK_ZONE, a_zlst->_zlName, a_lflags);
4935c51f124SMoriah Waterland 
4945c51f124SMoriah Waterland 	scratchName = a_zlst->_zlScratchName == NULL ? a_zlst->_zlName :
4955c51f124SMoriah Waterland 	    a_zlst->_zlScratchName;
4965c51f124SMoriah Waterland 
4975c51f124SMoriah Waterland 	/*
4985c51f124SMoriah Waterland 	 * acquire zone lock
4995c51f124SMoriah Waterland 	 */
5005c51f124SMoriah Waterland 
5015c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
5025c51f124SMoriah Waterland 		/*
5035c51f124SMoriah Waterland 		 * lock zone administration if not already locked
5045c51f124SMoriah Waterland 		 * if the lock cannot be released, stop and return an error
5055c51f124SMoriah Waterland 		 */
5065c51f124SMoriah Waterland 
5075c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_LCK_ZONE_ZONEADM, a_zlst->_zlName,
5085c51f124SMoriah Waterland 		    LOBJ_ZONEADMIN);
5095c51f124SMoriah Waterland 
5105c51f124SMoriah Waterland 		b = _z_lock_zone_object(&a_zlst->_zlLockObjects,
5115c51f124SMoriah Waterland 		    scratchName, LOBJ_ZONEADMIN, (pid_t)0,
5125c51f124SMoriah Waterland 		    MSG_ZONES_LCK_ZONE_ZONEADM,
5135c51f124SMoriah Waterland 		    ERR_ZONES_LCK_ZONE_ZONEADM);
5145c51f124SMoriah Waterland 		if (b == B_FALSE) {
5155c51f124SMoriah Waterland 			return (b);
5165c51f124SMoriah Waterland 		}
5175c51f124SMoriah Waterland 	}
5185c51f124SMoriah Waterland 
5195c51f124SMoriah Waterland 	/*
5205c51f124SMoriah Waterland 	 * acquire package lock
5215c51f124SMoriah Waterland 	 */
5225c51f124SMoriah Waterland 
5235c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_PKG_ADMIN) {
5245c51f124SMoriah Waterland 
5255c51f124SMoriah Waterland 		/*
5265c51f124SMoriah Waterland 		 * zone administration is locked; lock package administration if
5275c51f124SMoriah Waterland 		 * not already locked; if the lock cannot be released, stop,
5285c51f124SMoriah Waterland 		 * release the zone administration lock and return an error
5295c51f124SMoriah Waterland 		 */
5305c51f124SMoriah Waterland 
5315c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_LCK_ZONE_PKGADM, a_zlst->_zlName,
5325c51f124SMoriah Waterland 		    LOBJ_PKGADMIN);
5335c51f124SMoriah Waterland 
5345c51f124SMoriah Waterland 		b = _z_lock_zone_object(&a_zlst->_zlLockObjects,
5355c51f124SMoriah Waterland 		    scratchName, LOBJ_PKGADMIN, (pid_t)0,
5365c51f124SMoriah Waterland 		    MSG_ZONES_LCK_ZONE_PKGADM,
5375c51f124SMoriah Waterland 		    ERR_ZONES_LCK_ZONE_PKGADM);
5385c51f124SMoriah Waterland 		if (b == B_FALSE) {
5395c51f124SMoriah Waterland 			(void) _z_unlock_zone(a_zlst, a_lflags);
5405c51f124SMoriah Waterland 			return (b);
5415c51f124SMoriah Waterland 		}
5425c51f124SMoriah Waterland 	}
5435c51f124SMoriah Waterland 
5445c51f124SMoriah Waterland 	/*
5455c51f124SMoriah Waterland 	 * all locks have been obtained - return success!
5465c51f124SMoriah Waterland 	 */
5475c51f124SMoriah Waterland 
5485c51f124SMoriah Waterland 	return (B_TRUE);
5495c51f124SMoriah Waterland }
5505c51f124SMoriah Waterland 
5515c51f124SMoriah Waterland /*
5525c51f124SMoriah Waterland  * Name:	_z_lock_zone_object
5535c51f124SMoriah Waterland  * Description:	lock a single lock object in a specified zone
5545c51f124SMoriah Waterland  * Arguments:	r_objectLocks - [RW, *RW] - (char **)
5555c51f124SMoriah Waterland  *			Pointer to handle to character string containing a list
5565c51f124SMoriah Waterland  *			of all objects locked for this zone - this string will
5575c51f124SMoriah Waterland  *			have the key to release the specified object added to it
5585c51f124SMoriah Waterland  *			if the lock is acquired.
5595c51f124SMoriah Waterland  *		a_zoneName - [RO, *RO] - (char *)
5605c51f124SMoriah Waterland  *			Pointer to string representing the name of the zone to
5615c51f124SMoriah Waterland  *			acquire the specified lock on
5625c51f124SMoriah Waterland  *		a_lockObject - [RO, *RO] - (char *)
5635c51f124SMoriah Waterland  *			Pointer to string representing the lock object to
5645c51f124SMoriah Waterland  *			acquire on the specified zone
5655c51f124SMoriah Waterland  *		a_pid - [RO, *RO] - (pid_t)
5665c51f124SMoriah Waterland  *			Process i.d. to associate with this lock
5675c51f124SMoriah Waterland  *			== 0 - no process i.d. associated with the lock
5685c51f124SMoriah Waterland  *		a_waitingMsg - [RO, *RO] - (char *)
5695c51f124SMoriah Waterland  *			Localized message to be output if waiting for the lock
5705c51f124SMoriah Waterland  *			because the lock cannot be immediately be acquired
5715c51f124SMoriah Waterland  *		a_busyMsg - [RO, *RO] - (char *)
5725c51f124SMoriah Waterland  *			Localized message to be output if the lock cannot be
5735c51f124SMoriah Waterland  *			released
5745c51f124SMoriah Waterland  * Returns:	boolean_t
5755c51f124SMoriah Waterland  *			B_TRUE - lock released
5765c51f124SMoriah Waterland  *			B_FALSE - lock not released
5775c51f124SMoriah Waterland  */
5785c51f124SMoriah Waterland 
5795c51f124SMoriah Waterland boolean_t
_z_lock_zone_object(char ** r_objectLocks,char * a_zoneName,char * a_lockObject,pid_t a_pid,char * a_waitingMsg,char * a_busyMsg)5805c51f124SMoriah Waterland _z_lock_zone_object(char **r_objectLocks, char *a_zoneName, char *a_lockObject,
5815c51f124SMoriah Waterland 	pid_t a_pid, char *a_waitingMsg, char *a_busyMsg)
5825c51f124SMoriah Waterland {
5835c51f124SMoriah Waterland 	boolean_t	b;
5845c51f124SMoriah Waterland 	char		*p = (char *)NULL;
5855c51f124SMoriah Waterland 	char		lockItem[LOCK_OBJECT_MAXLEN+LOCK_KEY_MAXLEN+4];
5865c51f124SMoriah Waterland 	char		lockKey[LOCK_KEY_MAXLEN+2];
5875c51f124SMoriah Waterland 	char		lockObject[LOCK_OBJECT_MAXLEN+2];
5885c51f124SMoriah Waterland 	int		i;
5895c51f124SMoriah Waterland 
5905c51f124SMoriah Waterland 	/* entry assertions */
5915c51f124SMoriah Waterland 
5925c51f124SMoriah Waterland 	assert(r_objectLocks != (char **)NULL);
5935c51f124SMoriah Waterland 	assert(a_zoneName != (char *)NULL);
5945c51f124SMoriah Waterland 	assert(a_waitingMsg != (char *)NULL);
5955c51f124SMoriah Waterland 	assert(a_busyMsg != (char *)NULL);
5965c51f124SMoriah Waterland 	assert(a_lockObject != (char *)NULL);
5975c51f124SMoriah Waterland 	assert(*a_lockObject != '\0');
5985c51f124SMoriah Waterland 
5995c51f124SMoriah Waterland 	/* entry debugging info */
6005c51f124SMoriah Waterland 
6015c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_LCK_OBJ, a_lockObject, a_zoneName, a_pid,
6025c51f124SMoriah Waterland 	    *r_objectLocks ? *r_objectLocks : "");
6035c51f124SMoriah Waterland 
6045c51f124SMoriah Waterland 	/* if lock objects held search for object to lock */
6055c51f124SMoriah Waterland 
6065c51f124SMoriah Waterland 	if (*r_objectLocks != (char *)NULL) {
6075c51f124SMoriah Waterland 		for (i = 0; ; i++) {
6085c51f124SMoriah Waterland 			/* get next object locked on this zone */
6095c51f124SMoriah Waterland 			_z_strGetToken_r((char *)NULL, *r_objectLocks, i, "\n",
6105c51f124SMoriah Waterland 			    lockItem, sizeof (lockItem));
6115c51f124SMoriah Waterland 
6125c51f124SMoriah Waterland 			/* break out of loop if no more locks in list */
6135c51f124SMoriah Waterland 
6145c51f124SMoriah Waterland 			if (lockItem[0] == '\0') {
6155c51f124SMoriah Waterland 				_z_echoDebug(DBG_ZONES_LCK_OBJ_NOTHELD,
6165c51f124SMoriah Waterland 				    a_lockObject, a_zoneName);
6175c51f124SMoriah Waterland 				break;
6185c51f124SMoriah Waterland 			}
6195c51f124SMoriah Waterland 
6205c51f124SMoriah Waterland 			/* get object and key for this lock */
6215c51f124SMoriah Waterland 			_z_strGetToken_r((char *)NULL, lockItem, 0, "\t",
6225c51f124SMoriah Waterland 			    lockObject, sizeof (lockObject));
6235c51f124SMoriah Waterland 			_z_strGetToken_r((char *)NULL, lockItem, 1, "\t",
6245c51f124SMoriah Waterland 			    lockKey, sizeof (lockKey));
6255c51f124SMoriah Waterland 
6265c51f124SMoriah Waterland 			/* return success if the lock is held */
6275c51f124SMoriah Waterland 
6285c51f124SMoriah Waterland 			if (strcmp(lockObject, a_lockObject) == 0) {
6295c51f124SMoriah Waterland 				_z_echoDebug(DBG_ZONES_LCK_OBJ_FOUND,
6305c51f124SMoriah Waterland 				    lockObject, lockKey);
6315c51f124SMoriah Waterland 				return (B_TRUE);
6325c51f124SMoriah Waterland 			}
6335c51f124SMoriah Waterland 
6345c51f124SMoriah Waterland 			/* not the object to lock - scan next object */
6355c51f124SMoriah Waterland 			_z_echoDebug(DBG_ZONES_LCK_OBJ_NOTFOUND, lockObject,
6365c51f124SMoriah Waterland 			    lockKey);
6375c51f124SMoriah Waterland 		}
6385c51f124SMoriah Waterland 	}
6395c51f124SMoriah Waterland 
6405c51f124SMoriah Waterland 	/*
6415c51f124SMoriah Waterland 	 * the object to lock is not held - acquire the lock
6425c51f124SMoriah Waterland 	 */
6435c51f124SMoriah Waterland 
6445c51f124SMoriah Waterland 	/* acquire object with no wait */
6455c51f124SMoriah Waterland 	b = _z_acquire_lock(&p, a_zoneName, a_lockObject, a_pid, B_FALSE);
6465c51f124SMoriah Waterland 	if (b == B_FALSE) {
6475c51f124SMoriah Waterland 		/* failure - output message and acquire with wait */
6485c51f124SMoriah Waterland 		_z_echo(a_waitingMsg, (long)MAX_RETRIES*RETRY_DELAY_SECS,
6495c51f124SMoriah Waterland 		    a_zoneName, _z_global_data._z_root_dir);
6505c51f124SMoriah Waterland 		b = _z_acquire_lock(&p, a_zoneName, a_lockObject, a_pid,
6515c51f124SMoriah Waterland 		    B_TRUE);
6525c51f124SMoriah Waterland 	}
6535c51f124SMoriah Waterland 
6545c51f124SMoriah Waterland 	/* output error message and return failure if both acquires failed */
6555c51f124SMoriah Waterland 	if (b == B_FALSE) {
6565c51f124SMoriah Waterland 		_z_program_error(a_busyMsg, a_zoneName);
6575c51f124SMoriah Waterland 		return (b);
6585c51f124SMoriah Waterland 	}
6595c51f124SMoriah Waterland 
6605c51f124SMoriah Waterland 	/* add object/key to held locks */
6615c51f124SMoriah Waterland 
6625c51f124SMoriah Waterland 	_z_strPrintf_r(lockItem, sizeof (lockItem), "%s\t%s", a_lockObject, p);
6635c51f124SMoriah Waterland 	_z_strAddToken(r_objectLocks, lockItem, '\n');
6645c51f124SMoriah Waterland 
6655c51f124SMoriah Waterland 	free(p);
6665c51f124SMoriah Waterland 
6675c51f124SMoriah Waterland 	/* return success */
6685c51f124SMoriah Waterland 	return (B_TRUE);
6695c51f124SMoriah Waterland }
6705c51f124SMoriah Waterland 
6715c51f124SMoriah Waterland /*
6725c51f124SMoriah Waterland  * Name:	_z_release_lock
6735c51f124SMoriah Waterland  * Description:	release a lock held on a zone
6745c51f124SMoriah Waterland  * Arguments:	a_zoneName - [RO, *RO] - (char *)
6755c51f124SMoriah Waterland  *			Pointer to string representing the name of the zone to
6765c51f124SMoriah Waterland  *			release the specified lock on
6775c51f124SMoriah Waterland  *		a_lockObject - [RO, *RO] - (char *)
6785c51f124SMoriah Waterland  *			Pointer to string representing the lock object to
6795c51f124SMoriah Waterland  *			release on the specified zone
6805c51f124SMoriah Waterland  *		a_lockKey - [RO, *RO] - (char *)
6815c51f124SMoriah Waterland  *			Pointer to string representing the lock key associated
6825c51f124SMoriah Waterland  *			with the lock object to be released - this key is
6835c51f124SMoriah Waterland  *			returned when the lock is acquired and must be provided
6845c51f124SMoriah Waterland  *			when releasing the lock
6855c51f124SMoriah Waterland  *		a_wait - [RO, *RO] - (int)
6865c51f124SMoriah Waterland  *			Determines what to do if the lock cannot be released:
6875c51f124SMoriah Waterland  *			== B_TRUE - wait for the lock to be released
6885c51f124SMoriah Waterland  *			== B_FALSE - do not wait for the lock to be released
6895c51f124SMoriah Waterland  * Returns:	boolean_t
6905c51f124SMoriah Waterland  *			B_TRUE - lock released
6915c51f124SMoriah Waterland  *			B_FALSE - lock not released
6925c51f124SMoriah Waterland  */
6935c51f124SMoriah Waterland 
6945c51f124SMoriah Waterland boolean_t
_z_release_lock(char * a_zoneName,char * a_lockObject,char * a_lockKey,boolean_t a_wait)6955c51f124SMoriah Waterland _z_release_lock(char *a_zoneName, char *a_lockObject, char *a_lockKey,
6965c51f124SMoriah Waterland 	boolean_t a_wait)
6975c51f124SMoriah Waterland {
6985c51f124SMoriah Waterland 	argArray_t	*args;
6995c51f124SMoriah Waterland 	boolean_t	b;
7005c51f124SMoriah Waterland 	char		*adjustedLockObject = (char *)NULL;
7015c51f124SMoriah Waterland 	char		*results = (char *)NULL;
7025c51f124SMoriah Waterland 	int		r;
7035c51f124SMoriah Waterland 	int		status;
7045c51f124SMoriah Waterland 
7055c51f124SMoriah Waterland 	/* entry assertions */
7065c51f124SMoriah Waterland 
7075c51f124SMoriah Waterland 	assert(a_zoneName != (char *)NULL);
7085c51f124SMoriah Waterland 	assert(a_lockObject != (char *)NULL);
7095c51f124SMoriah Waterland 	assert(*a_lockObject != '\0');
7105c51f124SMoriah Waterland 	assert(a_lockKey != (char *)NULL);
7115c51f124SMoriah Waterland 	assert(*a_lockKey != '\0');
7125c51f124SMoriah Waterland 
7135c51f124SMoriah Waterland 	/* entry debugging info */
7145c51f124SMoriah Waterland 
7155c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_RELK, a_zoneName, a_lockObject,
7165c51f124SMoriah Waterland 	    a_lockKey ? a_lockKey : "");
7175c51f124SMoriah Waterland 
7185c51f124SMoriah Waterland 	/*
7195c51f124SMoriah Waterland 	 * Only one lock file must ever be used - the one located on the root
7205c51f124SMoriah Waterland 	 * file system of the currently running Solaris instance. To allow for
7215c51f124SMoriah Waterland 	 * alternative roots to be properly locked, adjust the lock object to
7225c51f124SMoriah Waterland 	 * take root path into account; if necessary, the root path will be
7235c51f124SMoriah Waterland 	 * prepended to the lock object.
7245c51f124SMoriah Waterland 	 */
7255c51f124SMoriah Waterland 
7265c51f124SMoriah Waterland 	b = _z_adjust_lock_object_for_rootpath(&adjustedLockObject,
7275c51f124SMoriah Waterland 	    a_lockObject);
7285c51f124SMoriah Waterland 	if (!b) {
7295c51f124SMoriah Waterland 		return (B_FALSE);
7305c51f124SMoriah Waterland 	}
7315c51f124SMoriah Waterland 
7325c51f124SMoriah Waterland 	/*
7335c51f124SMoriah Waterland 	 * construct command arguments:
7345c51f124SMoriah Waterland 	 * pkgadm lock -r -o adjustedLockObject -k a_lockKey [-w -W timeout]
7355c51f124SMoriah Waterland 	 */
7365c51f124SMoriah Waterland 
7375c51f124SMoriah Waterland 	args = _z_new_args(20);			/* generate new arg list */
7385c51f124SMoriah Waterland 	(void) _z_add_arg(args, PKGADM_CMD);		/* pkgadm command */
7395c51f124SMoriah Waterland 	(void) _z_add_arg(args, "lock");		/* lock sub-command */
7405c51f124SMoriah Waterland 	(void) _z_add_arg(args, "-r");			/* release lock */
7415c51f124SMoriah Waterland 	(void) _z_add_arg(args, "-o");			/* object to release */
7425c51f124SMoriah Waterland 	(void) _z_add_arg(args, "%s", adjustedLockObject);
7435c51f124SMoriah Waterland 	(void) _z_add_arg(args, "-k");			/* object's key */
7445c51f124SMoriah Waterland 	(void) _z_add_arg(args, "%s", a_lockKey);
7455c51f124SMoriah Waterland 
7465c51f124SMoriah Waterland 	/* add [ -w -W timeout ] if waiting for lock */
7475c51f124SMoriah Waterland 
7485c51f124SMoriah Waterland 	if (a_wait == B_TRUE) {
7495c51f124SMoriah Waterland 		(void) _z_add_arg(args, "-w");		/* wait */
7505c51f124SMoriah Waterland 		(void) _z_add_arg(args, "-W");		/* wait timeout */
7515c51f124SMoriah Waterland 		(void) _z_add_arg(args, "%ld",
7525c51f124SMoriah Waterland 		    (long)MAX_RETRIES*RETRY_DELAY_SECS);
7535c51f124SMoriah Waterland 	}
7545c51f124SMoriah Waterland 
7555c51f124SMoriah Waterland 	/* execute command */
7565c51f124SMoriah Waterland 
7575c51f124SMoriah Waterland 	r = _z_zone_exec(&status, &results, (char *)NULL, PKGADM_CMD,
7585c51f124SMoriah Waterland 	    _z_get_argv(args), a_zoneName, (int *)NULL);
7595c51f124SMoriah Waterland 
7605c51f124SMoriah Waterland 	/* free generated argument list */
7615c51f124SMoriah Waterland 
7625c51f124SMoriah Waterland 	_z_free_args(args);
7635c51f124SMoriah Waterland 
7645c51f124SMoriah Waterland 	/* exit debugging info */
7655c51f124SMoriah Waterland 
7665c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_RELK_EXIT, adjustedLockObject, a_lockKey,
7675c51f124SMoriah Waterland 	    a_zoneName, r, status, results ? results : "");
7685c51f124SMoriah Waterland 
7695c51f124SMoriah Waterland 	/* free adjusted lock object */
7705c51f124SMoriah Waterland 
7715c51f124SMoriah Waterland 	free(adjustedLockObject);
7725c51f124SMoriah Waterland 	free(results);
7735c51f124SMoriah Waterland 
7745c51f124SMoriah Waterland 	return (((r == 0) && (status == 0)) ? B_TRUE : B_FALSE);
7755c51f124SMoriah Waterland }
7765c51f124SMoriah Waterland 
7775c51f124SMoriah Waterland 
7785c51f124SMoriah Waterland 
7795c51f124SMoriah Waterland /*
7805c51f124SMoriah Waterland  * Name:	_z_unlock_zone
7815c51f124SMoriah Waterland  * Description:	Released specified locks on specified zone
7825c51f124SMoriah Waterland  * Arguments:	a_zlst - [RO, *RW] - (zoneListElement_t *)
7835c51f124SMoriah Waterland  *			Pointer to zone list structure element describing
7845c51f124SMoriah Waterland  *			the zone the unlock - the structure is updated by
7855c51f124SMoriah Waterland  *			removing the lock object and key if the locks are
7865c51f124SMoriah Waterland  *			successfully released
7875c51f124SMoriah Waterland  *		a_lflags - [RO, *RO] - (ZLOCKS_T)
7885c51f124SMoriah Waterland  *			Flags indicating which locks to release on the zone
7895c51f124SMoriah Waterland  * Returns:	boolean_t
7905c51f124SMoriah Waterland  *			== B_TRUE - locks successfully released
7915c51f124SMoriah Waterland  *			== B_FALSE - failed to release the locks
7925c51f124SMoriah Waterland  */
7935c51f124SMoriah Waterland 
7945c51f124SMoriah Waterland boolean_t
_z_unlock_zone(zoneListElement_t * a_zlst,ZLOCKS_T a_lflags)7955c51f124SMoriah Waterland _z_unlock_zone(zoneListElement_t *a_zlst, ZLOCKS_T a_lflags)
7965c51f124SMoriah Waterland {
7975c51f124SMoriah Waterland 	char		*scratchName;
7985c51f124SMoriah Waterland 	boolean_t	b;
7995c51f124SMoriah Waterland 	boolean_t	errors = B_FALSE;
8005c51f124SMoriah Waterland 
8015c51f124SMoriah Waterland 	/* entry assertions */
8025c51f124SMoriah Waterland 
8035c51f124SMoriah Waterland 	assert(a_zlst != (zoneListElement_t *)NULL);
8045c51f124SMoriah Waterland 
8055c51f124SMoriah Waterland 	/* entry debugging info */
8065c51f124SMoriah Waterland 
8075c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_ULK_ZONE, a_zlst->_zlName, a_lflags);
8085c51f124SMoriah Waterland 
8095c51f124SMoriah Waterland 	scratchName = a_zlst->_zlScratchName == NULL ? a_zlst->_zlName :
8105c51f124SMoriah Waterland 	    a_zlst->_zlScratchName;
8115c51f124SMoriah Waterland 
8125c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_PKG_ADMIN) {
8135c51f124SMoriah Waterland 		/*
8145c51f124SMoriah Waterland 		 * if locked, unlock package administration lock
8155c51f124SMoriah Waterland 		 * if the lock cannot be released, continue anyway
8165c51f124SMoriah Waterland 		 */
8175c51f124SMoriah Waterland 
8185c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_ULK_ZONE_PKGADM, a_zlst->_zlName,
8195c51f124SMoriah Waterland 		    LOBJ_PKGADMIN);
8205c51f124SMoriah Waterland 
8215c51f124SMoriah Waterland 		b = _z_unlock_zone_object(&a_zlst->_zlLockObjects,
8225c51f124SMoriah Waterland 		    scratchName, LOBJ_PKGADMIN,
8235c51f124SMoriah Waterland 		    WRN_ZONES_ULK_ZONE_PKGADM);
8245c51f124SMoriah Waterland 		if (b == B_FALSE) {
8255c51f124SMoriah Waterland 			errors = B_TRUE;
8265c51f124SMoriah Waterland 		}
8275c51f124SMoriah Waterland 	}
8285c51f124SMoriah Waterland 
8295c51f124SMoriah Waterland 	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
8305c51f124SMoriah Waterland 
8315c51f124SMoriah Waterland 		/*
8325c51f124SMoriah Waterland 		 * if locked, unlock zone administration lock
8335c51f124SMoriah Waterland 		 * if the lock cannot be released, continue anyway
8345c51f124SMoriah Waterland 		 */
8355c51f124SMoriah Waterland 
8365c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_ULK_ZONE_ZONEADM, a_zlst->_zlName,
8375c51f124SMoriah Waterland 		    LOBJ_ZONEADMIN);
8385c51f124SMoriah Waterland 
8395c51f124SMoriah Waterland 		b = _z_unlock_zone_object(&a_zlst->_zlLockObjects,
8405c51f124SMoriah Waterland 		    scratchName, LOBJ_ZONEADMIN,
8415c51f124SMoriah Waterland 		    WRN_ZONES_ULK_ZONE_ZONEADM);
8425c51f124SMoriah Waterland 		if (b == B_FALSE) {
8435c51f124SMoriah Waterland 			errors = B_TRUE;
8445c51f124SMoriah Waterland 		}
8455c51f124SMoriah Waterland 	}
8465c51f124SMoriah Waterland 
8475c51f124SMoriah Waterland 	return (!errors);
8485c51f124SMoriah Waterland }
8495c51f124SMoriah Waterland 
8505c51f124SMoriah Waterland /*
8515c51f124SMoriah Waterland  * Name:	_z_unlock_zone_object
8525c51f124SMoriah Waterland  * Description:	unlock a single lock object in a specified zone
8535c51f124SMoriah Waterland  * Arguments:	r_objectLocks - [RW, *RW] - (char **)
8545c51f124SMoriah Waterland  *			Pointer to handle to character string containing a list
8555c51f124SMoriah Waterland  *			of all objects locked for this zone - this string must
8565c51f124SMoriah Waterland  *			contain the key to release the specified object - if not
8575c51f124SMoriah Waterland  *			then the lock is not released - if so then the lock is
8585c51f124SMoriah Waterland  *			released and the key is removed from this list.
8595c51f124SMoriah Waterland  *		a_zoneName - [RO, *RO] - (char *)
8605c51f124SMoriah Waterland  *			Pointer to string representing the name of the zone to
8615c51f124SMoriah Waterland  *			release the specified lock on
8625c51f124SMoriah Waterland  *		a_lockObject - [RO, *RO] - (char *)
8635c51f124SMoriah Waterland  *			Pointer to string representing the lock object to
8645c51f124SMoriah Waterland  *			release on the specified zone
8655c51f124SMoriah Waterland  *		a_errMsg - [RO, *RO] - (char *)
8665c51f124SMoriah Waterland  *			Localized message to be output if the lock cannot be
8675c51f124SMoriah Waterland  *			released
8685c51f124SMoriah Waterland  * Returns:	boolean_t
8695c51f124SMoriah Waterland  *			B_TRUE - lock released
8705c51f124SMoriah Waterland  *			B_FALSE - lock not released
8715c51f124SMoriah Waterland  */
8725c51f124SMoriah Waterland 
8735c51f124SMoriah Waterland boolean_t
_z_unlock_zone_object(char ** r_objectLocks,char * a_zoneName,char * a_lockObject,char * a_errMsg)8745c51f124SMoriah Waterland _z_unlock_zone_object(char **r_objectLocks, char *a_zoneName,
8755c51f124SMoriah Waterland 	char *a_lockObject, char *a_errMsg)
8765c51f124SMoriah Waterland {
8775c51f124SMoriah Waterland 	boolean_t	b;
8785c51f124SMoriah Waterland 	char		lockItem[LOCK_OBJECT_MAXLEN+LOCK_KEY_MAXLEN+4];
8795c51f124SMoriah Waterland 	char		lockKey[LOCK_KEY_MAXLEN+2];
8805c51f124SMoriah Waterland 	char		lockObject[LOCK_OBJECT_MAXLEN+2];
8815c51f124SMoriah Waterland 	int		i;
8825c51f124SMoriah Waterland 
8835c51f124SMoriah Waterland 	/* entry assertions */
8845c51f124SMoriah Waterland 
8855c51f124SMoriah Waterland 	assert(r_objectLocks != (char **)NULL);
8865c51f124SMoriah Waterland 	assert(a_zoneName != (char *)NULL);
8875c51f124SMoriah Waterland 	assert(a_errMsg != (char *)NULL);
8885c51f124SMoriah Waterland 	assert(a_lockObject != (char *)NULL);
8895c51f124SMoriah Waterland 	assert(*a_lockObject != '\0');
8905c51f124SMoriah Waterland 
8915c51f124SMoriah Waterland 	/* entry debugging info */
8925c51f124SMoriah Waterland 
8935c51f124SMoriah Waterland 	_z_echoDebug(DBG_ZONES_ULK_OBJ, a_lockObject, a_zoneName,
8945c51f124SMoriah Waterland 	    *r_objectLocks ? *r_objectLocks : "");
8955c51f124SMoriah Waterland 
8965c51f124SMoriah Waterland 	/* return success if no objects are locked */
8975c51f124SMoriah Waterland 
8985c51f124SMoriah Waterland 	if (*r_objectLocks == (char *)NULL) {
8995c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_ULK_OBJ_NONE, a_zoneName);
9005c51f124SMoriah Waterland 		return (B_TRUE);
9015c51f124SMoriah Waterland 	}
9025c51f124SMoriah Waterland 
9035c51f124SMoriah Waterland 	/* see if the specified lock is held on this zone */
9045c51f124SMoriah Waterland 
9055c51f124SMoriah Waterland 	for (i = 0; ; i++) {
9065c51f124SMoriah Waterland 		/* get next object locked on this zone */
9075c51f124SMoriah Waterland 		_z_strGetToken_r((char *)NULL, *r_objectLocks, i, "\n",
9085c51f124SMoriah Waterland 		    lockItem, sizeof (lockItem));
9095c51f124SMoriah Waterland 
9105c51f124SMoriah Waterland 		/* return success if no more objects locked */
9115c51f124SMoriah Waterland 		if (lockItem[0] == '\0') {
9125c51f124SMoriah Waterland 			_z_echoDebug(DBG_ZONES_ULK_OBJ_NOTHELD, a_lockObject,
9135c51f124SMoriah Waterland 			    a_zoneName);
9145c51f124SMoriah Waterland 			return (B_TRUE);
9155c51f124SMoriah Waterland 		}
9165c51f124SMoriah Waterland 
9175c51f124SMoriah Waterland 		/* get object and key for this lock */
9185c51f124SMoriah Waterland 		_z_strGetToken_r((char *)NULL, lockItem, 0, "\t",
9195c51f124SMoriah Waterland 		    lockObject, sizeof (lockObject));
9205c51f124SMoriah Waterland 		_z_strGetToken_r((char *)NULL, lockItem, 1, "\t",
9215c51f124SMoriah Waterland 		    lockKey, sizeof (lockKey));
9225c51f124SMoriah Waterland 
9235c51f124SMoriah Waterland 		/* break out of loop if object is the one to unlock */
9245c51f124SMoriah Waterland 
9255c51f124SMoriah Waterland 		if (strcmp(lockObject, a_lockObject) == 0) {
9265c51f124SMoriah Waterland 			_z_echoDebug(DBG_ZONES_ULK_OBJ_FOUND, lockObject,
9275c51f124SMoriah Waterland 			    lockKey);
9285c51f124SMoriah Waterland 			break;
9295c51f124SMoriah Waterland 		}
9305c51f124SMoriah Waterland 
9315c51f124SMoriah Waterland 		/* not the object to unlock - scan next object */
9325c51f124SMoriah Waterland 		_z_echoDebug(DBG_ZONES_ULK_OBJ_NOTFOUND, lockObject, lockKey);
9335c51f124SMoriah Waterland 	}
9345c51f124SMoriah Waterland 
9355c51f124SMoriah Waterland 	/*
9365c51f124SMoriah Waterland 	 * the object to unlock is held - release the lock
9375c51f124SMoriah Waterland 	 */
9385c51f124SMoriah Waterland 
9395c51f124SMoriah Waterland 	/* release object with wait */
9405c51f124SMoriah Waterland 
9415c51f124SMoriah Waterland 	b = _z_release_lock(a_zoneName, a_lockObject, lockKey, B_TRUE);
9425c51f124SMoriah Waterland 	if (b == B_FALSE) {
9435c51f124SMoriah Waterland 		/* failure - issue error message and return failure */
9445c51f124SMoriah Waterland 		_z_program_error(a_errMsg, a_zoneName);
9455c51f124SMoriah Waterland 		return (b);
9465c51f124SMoriah Waterland 	}
9475c51f124SMoriah Waterland 
9485c51f124SMoriah Waterland 	/* remove object/key from held locks */
9495c51f124SMoriah Waterland 
9505c51f124SMoriah Waterland 	_z_strRemoveToken(r_objectLocks, lockItem, "\n", 0);
9515c51f124SMoriah Waterland 
9525c51f124SMoriah Waterland 	/* return success */
9535c51f124SMoriah Waterland 
9545c51f124SMoriah Waterland 	return (B_TRUE);
9555c51f124SMoriah Waterland }
956