4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 2012 by Delphix. All rights reserved.
32 * Module: zones_locks.c
34 * Description: Provide "zones" locking interfaces for install consolidation
39 * _z_acquire_lock - acquire a lock on an object on a zone
40 * _z_adjust_lock_object_for_rootpath - Given a lock object and a root path,
41 * if the root path is not
42 * _z_lock_zone - Acquire specified locks on specified zone
43 * _z_lock_zone_object - lock a single lock object in a specified zone
44 * _z_release_lock - release a lock held on a zone
45 * _z_unlock_zone - Released specified locks on specified zone
46 * _z_unlock_zone_object - unlock a single lock object in a specified zone
58 #include <sys/types.h>
59 #include <sys/param.h>
75 #include "instzones_lib.h"
76 #include "zones_strings.h"
83 * Library Function Prototypes
87 * Local Function Prototypes
90 boolean_t
_z_adjust_lock_object_for_rootpath(char **r_result
,
92 boolean_t
_z_acquire_lock(char **r_lockKey
, char *a_zoneName
,
93 char *a_lock
, pid_t a_pid
, boolean_t a_wait
);
94 boolean_t
_z_lock_zone(zoneListElement_t
*a_zlst
,
96 boolean_t
_z_lock_zone_object(char **r_objectLocks
,
97 char *a_zoneName
, char *a_lockObject
,
98 pid_t a_pid
, char *a_waitingMsg
,
100 boolean_t
_z_release_lock(char *a_zoneName
, char *a_lock
,
101 char *a_key
, boolean_t a_wait
);
102 boolean_t
_z_unlock_zone(zoneListElement_t
*a_zlst
,
104 boolean_t
_z_unlock_zone_object(char **r_objectLocks
,
105 char *a_zoneName
, char *a_lockObject
,
109 * global internal (private) declarations
113 * *****************************************************************************
114 * global external (public) functions
115 * *****************************************************************************
119 * Name: _z_acquire_lock
120 * Description: acquire a lock on an object on a zone
121 * Arguments: r_lockKey - [RW, *RW] - (char *)
122 * Pointer to handle to string representing the lock key
123 * associated with the lock object to be acquired - this
124 * key is returned when the lock is acquired and must be
125 * provided when releasing the lock
126 * == (char *)NULL - lock not acquired
127 * a_zoneName - [RO, *RO] - (char *)
128 * Pointer to string representing the name of the zone to
129 * acquire the specified lock on
130 * a_lockObject - [RO, *RO] - (char *)
131 * Pointer to string representing the lock object to
132 * acquire on the specified zone
133 * a_pid - [RO, *RO] - (pid_t)
134 * Process i.d. to associate with this lock
135 * == 0 - no process i.d. associated with the lock
136 * a_wait - [RO, *RO] - (int)
137 * Determines what to do if the lock cannot be acquired:
138 * == B_TRUE - wait for the lock to be acquired
139 * == B_FALSE - do not wait for the lock to be acquired
141 * B_TRUE - lock acquired
142 * B_FALSE - lock not acquired
146 _z_acquire_lock(char **r_lockKey
, char *a_zoneName
, char *a_lockObject
,
147 pid_t a_pid
, boolean_t a_wait
)
151 char *adjustedLockObject
= (char *)NULL
;
153 char *results
= (char *)NULL
;
157 /* entry assertions */
159 assert(a_zoneName
!= (char *)NULL
);
160 assert(a_lockObject
!= (char *)NULL
);
161 assert(*a_lockObject
!= '\0');
162 assert(r_lockKey
!= (char **)NULL
);
164 /* entry debugging info */
166 _z_echoDebug(DBG_ZONES_APLK
, a_zoneName
, a_lockObject
, a_pid
);
168 /* reset returned lock key handle */
170 *r_lockKey
= (char *)NULL
;
173 * Only one lock file must ever be used - the one located on the root
174 * file system of the currently running Solaris instance. To allow for
175 * alternative roots to be properly locked, adjust the lock object to
176 * take root path into account; if necessary, the root path will be
177 * prepended to the lock object.
180 b
= _z_adjust_lock_object_for_rootpath(&adjustedLockObject
,
187 * construct command arguments:
188 * pkgadm lock -a -q -o adjustedLockObject [ -w -W timeout ]
189 * [ -p a_pid -z zoneid ]
192 args
= _z_new_args(20); /* generate new arg list */
193 (void) _z_add_arg(args
, PKGADM_CMD
); /* pkgadm command */
194 (void) _z_add_arg(args
, "lock"); /* lock sub-command */
195 (void) _z_add_arg(args
, "-a"); /* acquire lock */
196 (void) _z_add_arg(args
, "-q"); /* quiet (no extra messages) */
197 (void) _z_add_arg(args
, "-o"); /* object to acquire */
198 (void) _z_add_arg(args
, "%s", adjustedLockObject
);
200 /* add [ -w -W timeout ] if waiting for lock */
202 if (a_wait
== B_TRUE
) {
203 (void) _z_add_arg(args
, "-w"); /* wait */
204 (void) _z_add_arg(args
, "-W"); /* wait timeout */
205 (void) _z_add_arg(args
, "%ld",
206 (long)MAX_RETRIES
*RETRY_DELAY_SECS
);
209 /* add process/zone i.d.s if process i.d. provided */
212 (void) _z_add_arg(args
, "-p"); /* lock valid process i.d. */
213 (void) _z_add_arg(args
, "%lld", (long long)getpid());
214 (void) _z_add_arg(args
, "-z"); /* lock valid zone i.d. */
215 (void) _z_add_arg(args
, "%lld", (long long)getzoneid());
218 /* execute command */
220 r
= _z_zone_exec(&status
, &results
, (char *)NULL
, PKGADM_CMD
,
221 _z_get_argv(args
), a_zoneName
, (int *)NULL
);
223 /* free generated argument list */
227 /* return error if failed to acquire */
229 if ((r
!= 0) || (status
!= 0)) {
230 _z_echoDebug(DBG_ZONES_APLK_EXIT
, a_zoneName
,
231 adjustedLockObject
, a_pid
, r
, status
,
232 results
? results
: "");
234 /* free up results if returned */
239 /* free adjusted lock object */
240 free(adjustedLockObject
);
246 /* return success if no results returned */
248 if (results
== (char *)NULL
) {
252 /* return the lock key */
254 p
= _z_strGetToken((char *)NULL
, results
, 0, "\n");
255 _z_strRemoveLeadingWhitespace(&p
);
258 /* exit debugging info */
260 _z_echoDebug(DBG_ZONES_APLK_RESULTS
, a_zoneName
, adjustedLockObject
, p
,
263 /* free up results */
267 /* free adjusted lock object */
269 free(adjustedLockObject
);
277 * Name: _z_adjust_lock_object_for_rootpath
278 * Description: Given a lock object and a root path, if the root path is not
279 * the current running system root, then alter the lock object
280 * to contain a reference to the root path. Only one lock file must
281 * ever be used to create and maintain locks - the lock file that
282 * is located in /tmp on the root file system of the currently
283 * running Solaris instance. To allow for alternative roots to be
284 * properly locked, if necessary adjust the lock object to take
285 * root path into account. If the root path does not indicate the
286 * current running Solaris instance, then the root path will be
287 * prepended to the lock object.
288 * Arguments: r_result - [RW, *RW] - (char **)
289 * Pointer to handle to character string that will contain
290 * the lock object to use.
291 * a_lockObject - [RO, *RO] - (char *)
292 * Pointer to string representing the lock object to adjust
294 * B_TRUE - lock object adjusted and returned
295 * B_FALSE - unable to adjust lock object
296 * NOTE: Any string returned is placed in new storage for the
297 * calling function. The caller must use 'free' to dispose
298 * of the storage once the string is no longer needed.
300 * A lock object has this form:
302 * name.value [ /name.value [ /name.value ... ] ]
304 * The "value is either a specific object or a "*", for example:
308 * This locks the package "test"
312 * This locks all packages on all zones.
314 * zone.* /package.SUNWluu
316 * This locks the package SUNWluu on all zones.
318 * If a -R rootpath is specified, since there is only one lock file in
319 * the current /tmp, the lock object is modified to include the root
322 * rootpath.rootpath/zone.* /package.*
324 * locks all packages on all zones in the root path "?"
326 * The characters "/" and "*" and "." cannot be part of the "value"; that
327 * is if "-R /tmp/gmg*dir.test-path" is specified, the final object
330 * rootpath./tmp/gmg*dir.test-path/zone.* /package.*
332 * This would be parsed as:
334 * "rootpath." "/tmp" "gmg*dir.test-path" "zone.*" "package.*"
336 * which is not correct.
338 * So the path is modified by the loop, in this case it would result in
341 * rootpath.-1tmp-1gmg-3dir-2test---path/zone.* /package.*
345 * "rootpath.-1tmp-1gmg-3dir-2test---path" "zone.*" "package.*"
347 * which is then interpreted as:
349 * "rootpath./tmp/gmg*dir.test-path" "zone.*" "package.*"
353 _z_adjust_lock_object_for_rootpath(char **r_result
, char *a_lockObject
)
355 char realRootPath
[PATH_MAX
] = {'\0'};
356 const char *a_rootPath
;
358 /* entry assertions */
360 assert(r_result
!= (char **)NULL
);
361 assert(a_lockObject
!= (char *)NULL
);
362 assert(*a_lockObject
!= '\0');
364 /* reset returned lock object handle */
366 *r_result
= (char *)NULL
;
369 * if root path points to "/" return a duplicate of the passed in
370 * lock objects; otherwise, resolve root path and adjust lock object by
371 * prepending the rootpath to the lock object (using LOBJ_ROOTPATH).
374 a_rootPath
= _z_global_data
._z_root_dir
;
375 if ((a_rootPath
== (char *)NULL
) ||
376 (*a_rootPath
== '\0') ||
377 (strcmp(a_rootPath
, "/") == 0)) {
379 /* root path not specified or is only "/" - no -R specified */
381 *r_result
= _z_strdup(a_lockObject
);
384 * root path is not "" or "/" - -R to an alternative root has
385 * been specified; resolve all symbolic links and relative nodes
386 * of path name and determine absolute path to the root path.
389 if (realpath(a_rootPath
, realRootPath
) == (char *)NULL
) {
390 /* cannot determine absolute path; use path specified */
391 (void) strlcpy(realRootPath
, a_rootPath
,
392 sizeof (realRootPath
));
396 * if root path points to "/" duplicate existing lock object;
397 * otherwise, resolve root path and adjust lock object by
398 * prepending the rootpath to the lock object
401 if (strcmp(realRootPath
, "/") == 0) {
402 *r_result
= _z_strdup(a_lockObject
);
406 /* prefix out /.* which cannot be part of lock object */
408 p1
= _z_calloc((strlen(realRootPath
)*2)+1);
409 for (p3
= p1
, p2
= realRootPath
; *p2
!= '\0'; p2
++) {
411 case '/': /* / becomes -1 */
415 case '.': /* . becomes -2 */
419 case '*': /* * becomes -3 */
423 case '-': /* - becomes -- */
427 default: /* do not prefix out char */
433 /* create "realpath.%s" object */
435 p2
= _z_strPrintf(LOBJ_ROOTPATH
, p1
);
437 if (p2
== (char *)NULL
) {
438 _z_program_error(ERR_MALLOC
, "<path>", errno
,
443 /* create "realpath.%s/..." final lock object */
445 *r_result
= _z_strPrintf("%s/%s", p2
, a_lockObject
);
447 if (*r_result
== (char *)NULL
) {
448 _z_program_error(ERR_MALLOC
, "<path>", errno
,
455 /* exit debugging info */
457 _z_echoDebug(DBG_ZONES_ADJLCKOBJ_EXIT
, a_lockObject
, *r_result
,
458 a_rootPath
? a_rootPath
: "",
459 realRootPath
? realRootPath
: "");
468 * Description: Acquire specified locks on specified zone
469 * Arguments: a_zlst - [RO, *RW] - (zoneListElement_t *)
470 * Pointer to zone list structure element describing
471 * the zone the lock - the structure is updated with
472 * the lock objects and keys if the locks are acquired
473 * a_lflags - [RO, *RO] - (ZLOCKS_T)
474 * Flags indicating which locks to acquire on the zone
476 * == B_TRUE - locks successfully acquired
477 * == B_FALSE - failed to acquire the locks
481 _z_lock_zone(zoneListElement_t
*a_zlst
, ZLOCKS_T a_lflags
)
486 /* entry assertions */
488 assert(a_zlst
!= (zoneListElement_t
*)NULL
);
490 /* entry debugging info */
492 _z_echoDebug(DBG_ZONES_LCK_ZONE
, a_zlst
->_zlName
, a_lflags
);
494 scratchName
= a_zlst
->_zlScratchName
== NULL
? a_zlst
->_zlName
:
495 a_zlst
->_zlScratchName
;
501 if (a_lflags
& ZLOCKS_ZONE_ADMIN
) {
503 * lock zone administration if not already locked
504 * if the lock cannot be released, stop and return an error
507 _z_echoDebug(DBG_ZONES_LCK_ZONE_ZONEADM
, a_zlst
->_zlName
,
510 b
= _z_lock_zone_object(&a_zlst
->_zlLockObjects
,
511 scratchName
, LOBJ_ZONEADMIN
, (pid_t
)0,
512 MSG_ZONES_LCK_ZONE_ZONEADM
,
513 ERR_ZONES_LCK_ZONE_ZONEADM
);
520 * acquire package lock
523 if (a_lflags
& ZLOCKS_PKG_ADMIN
) {
526 * zone administration is locked; lock package administration if
527 * not already locked; if the lock cannot be released, stop,
528 * release the zone administration lock and return an error
531 _z_echoDebug(DBG_ZONES_LCK_ZONE_PKGADM
, a_zlst
->_zlName
,
534 b
= _z_lock_zone_object(&a_zlst
->_zlLockObjects
,
535 scratchName
, LOBJ_PKGADMIN
, (pid_t
)0,
536 MSG_ZONES_LCK_ZONE_PKGADM
,
537 ERR_ZONES_LCK_ZONE_PKGADM
);
539 (void) _z_unlock_zone(a_zlst
, a_lflags
);
545 * all locks have been obtained - return success!
552 * Name: _z_lock_zone_object
553 * Description: lock a single lock object in a specified zone
554 * Arguments: r_objectLocks - [RW, *RW] - (char **)
555 * Pointer to handle to character string containing a list
556 * of all objects locked for this zone - this string will
557 * have the key to release the specified object added to it
558 * if the lock is acquired.
559 * a_zoneName - [RO, *RO] - (char *)
560 * Pointer to string representing the name of the zone to
561 * acquire the specified lock on
562 * a_lockObject - [RO, *RO] - (char *)
563 * Pointer to string representing the lock object to
564 * acquire on the specified zone
565 * a_pid - [RO, *RO] - (pid_t)
566 * Process i.d. to associate with this lock
567 * == 0 - no process i.d. associated with the lock
568 * a_waitingMsg - [RO, *RO] - (char *)
569 * Localized message to be output if waiting for the lock
570 * because the lock cannot be immediately be acquired
571 * a_busyMsg - [RO, *RO] - (char *)
572 * Localized message to be output if the lock cannot be
575 * B_TRUE - lock released
576 * B_FALSE - lock not released
580 _z_lock_zone_object(char **r_objectLocks
, char *a_zoneName
, char *a_lockObject
,
581 pid_t a_pid
, char *a_waitingMsg
, char *a_busyMsg
)
584 char *p
= (char *)NULL
;
585 char lockItem
[LOCK_OBJECT_MAXLEN
+LOCK_KEY_MAXLEN
+4];
586 char lockKey
[LOCK_KEY_MAXLEN
+2];
587 char lockObject
[LOCK_OBJECT_MAXLEN
+2];
590 /* entry assertions */
592 assert(r_objectLocks
!= (char **)NULL
);
593 assert(a_zoneName
!= (char *)NULL
);
594 assert(a_waitingMsg
!= (char *)NULL
);
595 assert(a_busyMsg
!= (char *)NULL
);
596 assert(a_lockObject
!= (char *)NULL
);
597 assert(*a_lockObject
!= '\0');
599 /* entry debugging info */
601 _z_echoDebug(DBG_ZONES_LCK_OBJ
, a_lockObject
, a_zoneName
, a_pid
,
602 *r_objectLocks
? *r_objectLocks
: "");
604 /* if lock objects held search for object to lock */
606 if (*r_objectLocks
!= (char *)NULL
) {
608 /* get next object locked on this zone */
609 _z_strGetToken_r((char *)NULL
, *r_objectLocks
, i
, "\n",
610 lockItem
, sizeof (lockItem
));
612 /* break out of loop if no more locks in list */
614 if (lockItem
[0] == '\0') {
615 _z_echoDebug(DBG_ZONES_LCK_OBJ_NOTHELD
,
616 a_lockObject
, a_zoneName
);
620 /* get object and key for this lock */
621 _z_strGetToken_r((char *)NULL
, lockItem
, 0, "\t",
622 lockObject
, sizeof (lockObject
));
623 _z_strGetToken_r((char *)NULL
, lockItem
, 1, "\t",
624 lockKey
, sizeof (lockKey
));
626 /* return success if the lock is held */
628 if (strcmp(lockObject
, a_lockObject
) == 0) {
629 _z_echoDebug(DBG_ZONES_LCK_OBJ_FOUND
,
630 lockObject
, lockKey
);
634 /* not the object to lock - scan next object */
635 _z_echoDebug(DBG_ZONES_LCK_OBJ_NOTFOUND
, lockObject
,
641 * the object to lock is not held - acquire the lock
644 /* acquire object with no wait */
645 b
= _z_acquire_lock(&p
, a_zoneName
, a_lockObject
, a_pid
, B_FALSE
);
647 /* failure - output message and acquire with wait */
648 _z_echo(a_waitingMsg
, (long)MAX_RETRIES
*RETRY_DELAY_SECS
,
649 a_zoneName
, _z_global_data
._z_root_dir
);
650 b
= _z_acquire_lock(&p
, a_zoneName
, a_lockObject
, a_pid
,
654 /* output error message and return failure if both acquires failed */
656 _z_program_error(a_busyMsg
, a_zoneName
);
660 /* add object/key to held locks */
662 _z_strPrintf_r(lockItem
, sizeof (lockItem
), "%s\t%s", a_lockObject
, p
);
663 _z_strAddToken(r_objectLocks
, lockItem
, '\n');
672 * Name: _z_release_lock
673 * Description: release a lock held on a zone
674 * Arguments: a_zoneName - [RO, *RO] - (char *)
675 * Pointer to string representing the name of the zone to
676 * release the specified lock on
677 * a_lockObject - [RO, *RO] - (char *)
678 * Pointer to string representing the lock object to
679 * release on the specified zone
680 * a_lockKey - [RO, *RO] - (char *)
681 * Pointer to string representing the lock key associated
682 * with the lock object to be released - this key is
683 * returned when the lock is acquired and must be provided
684 * when releasing the lock
685 * a_wait - [RO, *RO] - (int)
686 * Determines what to do if the lock cannot be released:
687 * == B_TRUE - wait for the lock to be released
688 * == B_FALSE - do not wait for the lock to be released
690 * B_TRUE - lock released
691 * B_FALSE - lock not released
695 _z_release_lock(char *a_zoneName
, char *a_lockObject
, char *a_lockKey
,
700 char *adjustedLockObject
= (char *)NULL
;
701 char *results
= (char *)NULL
;
705 /* entry assertions */
707 assert(a_zoneName
!= (char *)NULL
);
708 assert(a_lockObject
!= (char *)NULL
);
709 assert(*a_lockObject
!= '\0');
710 assert(a_lockKey
!= (char *)NULL
);
711 assert(*a_lockKey
!= '\0');
713 /* entry debugging info */
715 _z_echoDebug(DBG_ZONES_RELK
, a_zoneName
, a_lockObject
,
716 a_lockKey
? a_lockKey
: "");
719 * Only one lock file must ever be used - the one located on the root
720 * file system of the currently running Solaris instance. To allow for
721 * alternative roots to be properly locked, adjust the lock object to
722 * take root path into account; if necessary, the root path will be
723 * prepended to the lock object.
726 b
= _z_adjust_lock_object_for_rootpath(&adjustedLockObject
,
733 * construct command arguments:
734 * pkgadm lock -r -o adjustedLockObject -k a_lockKey [-w -W timeout]
737 args
= _z_new_args(20); /* generate new arg list */
738 (void) _z_add_arg(args
, PKGADM_CMD
); /* pkgadm command */
739 (void) _z_add_arg(args
, "lock"); /* lock sub-command */
740 (void) _z_add_arg(args
, "-r"); /* release lock */
741 (void) _z_add_arg(args
, "-o"); /* object to release */
742 (void) _z_add_arg(args
, "%s", adjustedLockObject
);
743 (void) _z_add_arg(args
, "-k"); /* object's key */
744 (void) _z_add_arg(args
, "%s", a_lockKey
);
746 /* add [ -w -W timeout ] if waiting for lock */
748 if (a_wait
== B_TRUE
) {
749 (void) _z_add_arg(args
, "-w"); /* wait */
750 (void) _z_add_arg(args
, "-W"); /* wait timeout */
751 (void) _z_add_arg(args
, "%ld",
752 (long)MAX_RETRIES
*RETRY_DELAY_SECS
);
755 /* execute command */
757 r
= _z_zone_exec(&status
, &results
, (char *)NULL
, PKGADM_CMD
,
758 _z_get_argv(args
), a_zoneName
, (int *)NULL
);
760 /* free generated argument list */
764 /* exit debugging info */
766 _z_echoDebug(DBG_ZONES_RELK_EXIT
, adjustedLockObject
, a_lockKey
,
767 a_zoneName
, r
, status
, results
? results
: "");
769 /* free adjusted lock object */
771 free(adjustedLockObject
);
774 return (((r
== 0) && (status
== 0)) ? B_TRUE
: B_FALSE
);
780 * Name: _z_unlock_zone
781 * Description: Released specified locks on specified zone
782 * Arguments: a_zlst - [RO, *RW] - (zoneListElement_t *)
783 * Pointer to zone list structure element describing
784 * the zone the unlock - the structure is updated by
785 * removing the lock object and key if the locks are
786 * successfully released
787 * a_lflags - [RO, *RO] - (ZLOCKS_T)
788 * Flags indicating which locks to release on the zone
790 * == B_TRUE - locks successfully released
791 * == B_FALSE - failed to release the locks
795 _z_unlock_zone(zoneListElement_t
*a_zlst
, ZLOCKS_T a_lflags
)
799 boolean_t errors
= B_FALSE
;
801 /* entry assertions */
803 assert(a_zlst
!= (zoneListElement_t
*)NULL
);
805 /* entry debugging info */
807 _z_echoDebug(DBG_ZONES_ULK_ZONE
, a_zlst
->_zlName
, a_lflags
);
809 scratchName
= a_zlst
->_zlScratchName
== NULL
? a_zlst
->_zlName
:
810 a_zlst
->_zlScratchName
;
812 if (a_lflags
& ZLOCKS_PKG_ADMIN
) {
814 * if locked, unlock package administration lock
815 * if the lock cannot be released, continue anyway
818 _z_echoDebug(DBG_ZONES_ULK_ZONE_PKGADM
, a_zlst
->_zlName
,
821 b
= _z_unlock_zone_object(&a_zlst
->_zlLockObjects
,
822 scratchName
, LOBJ_PKGADMIN
,
823 WRN_ZONES_ULK_ZONE_PKGADM
);
829 if (a_lflags
& ZLOCKS_ZONE_ADMIN
) {
832 * if locked, unlock zone administration lock
833 * if the lock cannot be released, continue anyway
836 _z_echoDebug(DBG_ZONES_ULK_ZONE_ZONEADM
, a_zlst
->_zlName
,
839 b
= _z_unlock_zone_object(&a_zlst
->_zlLockObjects
,
840 scratchName
, LOBJ_ZONEADMIN
,
841 WRN_ZONES_ULK_ZONE_ZONEADM
);
851 * Name: _z_unlock_zone_object
852 * Description: unlock a single lock object in a specified zone
853 * Arguments: r_objectLocks - [RW, *RW] - (char **)
854 * Pointer to handle to character string containing a list
855 * of all objects locked for this zone - this string must
856 * contain the key to release the specified object - if not
857 * then the lock is not released - if so then the lock is
858 * released and the key is removed from this list.
859 * a_zoneName - [RO, *RO] - (char *)
860 * Pointer to string representing the name of the zone to
861 * release the specified lock on
862 * a_lockObject - [RO, *RO] - (char *)
863 * Pointer to string representing the lock object to
864 * release on the specified zone
865 * a_errMsg - [RO, *RO] - (char *)
866 * Localized message to be output if the lock cannot be
869 * B_TRUE - lock released
870 * B_FALSE - lock not released
874 _z_unlock_zone_object(char **r_objectLocks
, char *a_zoneName
,
875 char *a_lockObject
, char *a_errMsg
)
878 char lockItem
[LOCK_OBJECT_MAXLEN
+LOCK_KEY_MAXLEN
+4];
879 char lockKey
[LOCK_KEY_MAXLEN
+2];
880 char lockObject
[LOCK_OBJECT_MAXLEN
+2];
883 /* entry assertions */
885 assert(r_objectLocks
!= (char **)NULL
);
886 assert(a_zoneName
!= (char *)NULL
);
887 assert(a_errMsg
!= (char *)NULL
);
888 assert(a_lockObject
!= (char *)NULL
);
889 assert(*a_lockObject
!= '\0');
891 /* entry debugging info */
893 _z_echoDebug(DBG_ZONES_ULK_OBJ
, a_lockObject
, a_zoneName
,
894 *r_objectLocks
? *r_objectLocks
: "");
896 /* return success if no objects are locked */
898 if (*r_objectLocks
== (char *)NULL
) {
899 _z_echoDebug(DBG_ZONES_ULK_OBJ_NONE
, a_zoneName
);
903 /* see if the specified lock is held on this zone */
906 /* get next object locked on this zone */
907 _z_strGetToken_r((char *)NULL
, *r_objectLocks
, i
, "\n",
908 lockItem
, sizeof (lockItem
));
910 /* return success if no more objects locked */
911 if (lockItem
[0] == '\0') {
912 _z_echoDebug(DBG_ZONES_ULK_OBJ_NOTHELD
, a_lockObject
,
917 /* get object and key for this lock */
918 _z_strGetToken_r((char *)NULL
, lockItem
, 0, "\t",
919 lockObject
, sizeof (lockObject
));
920 _z_strGetToken_r((char *)NULL
, lockItem
, 1, "\t",
921 lockKey
, sizeof (lockKey
));
923 /* break out of loop if object is the one to unlock */
925 if (strcmp(lockObject
, a_lockObject
) == 0) {
926 _z_echoDebug(DBG_ZONES_ULK_OBJ_FOUND
, lockObject
,
931 /* not the object to unlock - scan next object */
932 _z_echoDebug(DBG_ZONES_ULK_OBJ_NOTFOUND
, lockObject
, lockKey
);
936 * the object to unlock is held - release the lock
939 /* release object with wait */
941 b
= _z_release_lock(a_zoneName
, a_lockObject
, lockKey
, B_TRUE
);
943 /* failure - issue error message and return failure */
944 _z_program_error(a_errMsg
, a_zoneName
);
948 /* remove object/key from held locks */
950 _z_strRemoveToken(r_objectLocks
, lockItem
, "\n", 0);