1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 29 /* 30 * Module: zones_locks.c 31 * Group: libinstzones 32 * Description: Provide "zones" locking interfaces for install consolidation 33 * code 34 * 35 * Public Methods: 36 * 37 * _z_acquire_lock - acquire a lock on an object on a zone 38 * _z_adjust_lock_object_for_rootpath - Given a lock object and a root path, 39 * if the root path is not 40 * _z_lock_zone - Acquire specified locks on specified zone 41 * _z_lock_zone_object - lock a single lock object in a specified zone 42 * _z_release_lock - release a lock held on a zone 43 * _z_unlock_zone - Released specified locks on specified zone 44 * _z_unlock_zone_object - unlock a single lock object in a specified zone 45 */ 46 47 /* 48 * System includes 49 */ 50 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <unistd.h> 54 #include <fcntl.h> 55 #include <ctype.h> 56 #include <sys/types.h> 57 #include <sys/param.h> 58 #include <string.h> 59 #include <strings.h> 60 #include <stdarg.h> 61 #include <limits.h> 62 #include <errno.h> 63 #include <time.h> 64 #include <stropts.h> 65 #include <libintl.h> 66 #include <locale.h> 67 #include <assert.h> 68 69 /* 70 * local includes 71 */ 72 73 #include "instzones_lib.h" 74 #include "zones_strings.h" 75 76 /* 77 * Private structures 78 */ 79 80 /* 81 * Library Function Prototypes 82 */ 83 84 /* 85 * Local Function Prototypes 86 */ 87 88 boolean_t _z_adjust_lock_object_for_rootpath(char **r_result, 89 char *a_lockObject); 90 boolean_t _z_acquire_lock(char **r_lockKey, char *a_zoneName, 91 char *a_lock, pid_t a_pid, boolean_t a_wait); 92 boolean_t _z_lock_zone(zoneListElement_t *a_zlst, 93 ZLOCKS_T a_lflags); 94 boolean_t _z_lock_zone_object(char **r_objectLocks, 95 char *a_zoneName, char *a_lockObject, 96 pid_t a_pid, char *a_waitingMsg, 97 char *a_busyMsg); 98 boolean_t _z_release_lock(char *a_zoneName, char *a_lock, 99 char *a_key, boolean_t a_wait); 100 boolean_t _z_unlock_zone(zoneListElement_t *a_zlst, 101 ZLOCKS_T a_lflags); 102 boolean_t _z_unlock_zone_object(char **r_objectLocks, 103 char *a_zoneName, char *a_lockObject, 104 char *a_errMsg); 105 106 /* 107 * global internal (private) declarations 108 */ 109 110 /* 111 * ***************************************************************************** 112 * global external (public) functions 113 * ***************************************************************************** 114 */ 115 116 /* 117 * Name: _z_acquire_lock 118 * Description: acquire a lock on an object on a zone 119 * Arguments: r_lockKey - [RW, *RW] - (char *) 120 * Pointer to handle to string representing the lock key 121 * associated with the lock object to be acquired - this 122 * key is returned when the lock is acquired and must be 123 * provided when releasing the lock 124 * == (char *)NULL - lock not acquired 125 * a_zoneName - [RO, *RO] - (char *) 126 * Pointer to string representing the name of the zone to 127 * acquire the specified lock on 128 * a_lockObject - [RO, *RO] - (char *) 129 * Pointer to string representing the lock object to 130 * acquire on the specified zone 131 * a_pid - [RO, *RO] - (pid_t) 132 * Process i.d. to associate with this lock 133 * == 0 - no process i.d. associated with the lock 134 * a_wait - [RO, *RO] - (int) 135 * Determines what to do if the lock cannot be acquired: 136 * == B_TRUE - wait for the lock to be acquired 137 * == B_FALSE - do not wait for the lock to be acquired 138 * Returns: boolean_t 139 * B_TRUE - lock acquired 140 * B_FALSE - lock not acquired 141 */ 142 143 boolean_t 144 _z_acquire_lock(char **r_lockKey, char *a_zoneName, char *a_lockObject, 145 pid_t a_pid, boolean_t a_wait) 146 { 147 argArray_t *args; 148 boolean_t b; 149 char *adjustedLockObject = (char *)NULL; 150 char *p; 151 char *results = (char *)NULL; 152 int r; 153 int status; 154 155 /* entry assertions */ 156 157 assert(a_zoneName != (char *)NULL); 158 assert(a_lockObject != (char *)NULL); 159 assert(*a_lockObject != '\0'); 160 assert(r_lockKey != (char **)NULL); 161 162 /* entry debugging info */ 163 164 _z_echoDebug(DBG_ZONES_APLK, a_zoneName, a_lockObject, a_pid); 165 166 /* reset returned lock key handle */ 167 168 *r_lockKey = (char *)NULL; 169 170 /* 171 * Only one lock file must ever be used - the one located on the root 172 * file system of the currently running Solaris instance. To allow for 173 * alternative roots to be properly locked, adjust the lock object to 174 * take root path into account; if necessary, the root path will be 175 * prepended to the lock object. 176 */ 177 178 b = _z_adjust_lock_object_for_rootpath(&adjustedLockObject, 179 a_lockObject); 180 if (!b) { 181 return (B_FALSE); 182 } 183 184 /* 185 * construct command arguments: 186 * pkgadm lock -a -q -o adjustedLockObject [ -w -W timeout ] 187 * [ -p a_pid -z zoneid ] 188 */ 189 190 args = _z_new_args(20); /* generate new arg list */ 191 (void) _z_add_arg(args, PKGADM_CMD); /* pkgadm command */ 192 (void) _z_add_arg(args, "lock"); /* lock sub-command */ 193 (void) _z_add_arg(args, "-a"); /* acquire lock */ 194 (void) _z_add_arg(args, "-q"); /* quiet (no extra messages) */ 195 (void) _z_add_arg(args, "-o"); /* object to acquire */ 196 (void) _z_add_arg(args, "%s", adjustedLockObject); 197 198 /* add [ -w -W timeout ] if waiting for lock */ 199 200 if (a_wait == B_TRUE) { 201 (void) _z_add_arg(args, "-w"); /* wait */ 202 (void) _z_add_arg(args, "-W"); /* wait timeout */ 203 (void) _z_add_arg(args, "%ld", 204 (long)MAX_RETRIES*RETRY_DELAY_SECS); 205 } 206 207 /* add process/zone i.d.s if process i.d. provided */ 208 209 if (a_pid > 0) { 210 (void) _z_add_arg(args, "-p"); /* lock valid process i.d. */ 211 (void) _z_add_arg(args, "%ld", getpid()); 212 (void) _z_add_arg(args, "-z"); /* lock valid zone i.d. */ 213 (void) _z_add_arg(args, "%ld", getzoneid()); 214 } 215 216 /* execute command */ 217 218 r = _z_zone_exec(&status, &results, (char *)NULL, PKGADM_CMD, 219 _z_get_argv(args), a_zoneName, (int *)NULL); 220 221 /* free generated argument list */ 222 223 _z_free_args(args); 224 225 /* return error if failed to acquire */ 226 227 if ((r != 0) || (status != 0)) { 228 _z_echoDebug(DBG_ZONES_APLK_EXIT, a_zoneName, 229 adjustedLockObject, a_pid, r, status, 230 results ? results : ""); 231 232 /* free up results if returned */ 233 if (results) { 234 free(results); 235 } 236 237 /* free adjusted lock object */ 238 free(adjustedLockObject); 239 240 /* return failure */ 241 return (B_FALSE); 242 } 243 244 /* return success if no results returned */ 245 246 if (results == (char *)NULL) { 247 return (B_TRUE); 248 } 249 250 /* return the lock key */ 251 252 p = _z_strGetToken((char *)NULL, results, 0, "\n"); 253 _z_strRemoveLeadingWhitespace(&p); 254 *r_lockKey = p; 255 256 /* exit debugging info */ 257 258 _z_echoDebug(DBG_ZONES_APLK_RESULTS, a_zoneName, adjustedLockObject, p, 259 results); 260 261 /* free up results */ 262 263 free(results); 264 265 /* free adjusted lock object */ 266 267 free(adjustedLockObject); 268 269 /* return success */ 270 271 return (B_TRUE); 272 } 273 274 /* 275 * Name: _z_adjust_lock_object_for_rootpath 276 * Description: Given a lock object and a root path, if the root path is not 277 * the current running system root, then alter the lock object 278 * to contain a reference to the root path. Only one lock file must 279 * ever be used to create and maintain locks - the lock file that 280 * is located in /tmp on the root file system of the currently 281 * running Solaris instance. To allow for alternative roots to be 282 * properly locked, if necessary adjust the lock object to take 283 * root path into account. If the root path does not indicate the 284 * current running Solaris instance, then the root path will be 285 * prepended to the lock object. 286 * Arguments: r_result - [RW, *RW] - (char **) 287 * Pointer to handle to character string that will contain 288 * the lock object to use. 289 * a_lockObject - [RO, *RO] - (char *) 290 * Pointer to string representing the lock object to adjust 291 * Returns: boolean_t 292 * B_TRUE - lock object adjusted and returned 293 * B_FALSE - unable to adjust lock object 294 * NOTE: Any string returned is placed in new storage for the 295 * calling function. The caller must use 'free' to dispose 296 * of the storage once the string is no longer needed. 297 * 298 * A lock object has this form: 299 * 300 * name.value [ /name.value [ /name.value ... ] ] 301 * 302 * The "value is either a specific object or a "*", for example: 303 * 304 * package.test 305 * 306 * This locks the package "test" 307 * 308 * zone.* /package.* 309 * 310 * This locks all packages on all zones. 311 * 312 * zone.* /package.SUNWluu 313 * 314 * This locks the package SUNWluu on all zones. 315 * 316 * If a -R rootpath is specified, since there is only one lock file in 317 * the current /tmp, the lock object is modified to include the root 318 * path: 319 * 320 * rootpath.rootpath/zone.* /package.* 321 * 322 * locks all packages on all zones in the root path "?" 323 * 324 * The characters "/" and "*" and "." cannot be part of the "value"; that 325 * is if "-R /tmp/gmg*dir.test-path" is specified, the final object 326 * cannot be: 327 * 328 * rootpath./tmp/gmg*dir.test-path/zone.* /package.* 329 * 330 * This would be parsed as: 331 * 332 * "rootpath." "/tmp" "gmg*dir.test-path" "zone.*" "package.*" 333 * 334 * which is not correct. 335 * 336 * So the path is modified by the loop, in this case it would result in 337 * this lock object: 338 * 339 * rootpath.-1tmp-1gmg-3dir-2test---path/zone.* /package.* 340 * 341 * This is parsed as: 342 * 343 * "rootpath.-1tmp-1gmg-3dir-2test---path" "zone.*" "package.*" 344 * 345 * which is then interpreted as: 346 * 347 * "rootpath./tmp/gmg*dir.test-path" "zone.*" "package.*" 348 */ 349 350 boolean_t 351 _z_adjust_lock_object_for_rootpath(char **r_result, char *a_lockObject) 352 { 353 char realRootPath[PATH_MAX] = {'\0'}; 354 const char *a_rootPath; 355 356 /* entry assertions */ 357 358 assert(r_result != (char **)NULL); 359 assert(a_lockObject != (char *)NULL); 360 assert(*a_lockObject != '\0'); 361 362 /* reset returned lock object handle */ 363 364 *r_result = (char *)NULL; 365 366 /* 367 * if root path points to "/" return a duplicate of the passed in 368 * lock objects; otherwise, resolve root path and adjust lock object by 369 * prepending the rootpath to the lock object (using LOBJ_ROOTPATH). 370 */ 371 372 a_rootPath = _z_global_data._z_root_dir; 373 if ((a_rootPath == (char *)NULL) || 374 (*a_rootPath == '\0') || 375 (strcmp(a_rootPath, "/") == 0)) { 376 377 /* root path not specified or is only "/" - no -R specified */ 378 379 *r_result = _z_strdup(a_lockObject); 380 } else { 381 /* 382 * root path is not "" or "/" - -R to an alternative root has 383 * been specified; resolve all symbolic links and relative nodes 384 * of path name and determine absolute path to the root path. 385 */ 386 387 if (realpath(a_rootPath, realRootPath) == (char *)NULL) { 388 /* cannot determine absolute path; use path specified */ 389 (void) strlcpy(realRootPath, a_rootPath, 390 sizeof (realRootPath)); 391 } 392 393 /* 394 * if root path points to "/" duplicate existing lock object; 395 * otherwise, resolve root path and adjust lock object by 396 * prepending the rootpath to the lock object 397 */ 398 399 if (strcmp(realRootPath, "/") == 0) { 400 *r_result = _z_strdup(a_lockObject); 401 } else { 402 char *p1, *p2, *p3; 403 404 /* prefix out /.* which cannot be part of lock object */ 405 406 p1 = _z_calloc((strlen(realRootPath)*2)+1); 407 for (p3 = p1, p2 = realRootPath; *p2 != '\0'; p2++) { 408 switch (*p2) { 409 case '/': /* / becomes -1 */ 410 *p3++ = '-'; 411 *p3++ = '1'; 412 break; 413 case '.': /* . becomes -2 */ 414 *p3++ = '-'; 415 *p3++ = '2'; 416 break; 417 case '*': /* * becomes -3 */ 418 *p3++ = '-'; 419 *p3++ = '3'; 420 break; 421 case '-': /* - becomes -- */ 422 *p3++ = '-'; 423 *p3++ = '-'; 424 break; 425 default: /* do not prefix out char */ 426 *p3++ = *p2; 427 break; 428 } 429 } 430 431 /* create "realpath.%s" object */ 432 433 p2 = _z_strPrintf(LOBJ_ROOTPATH, p1); 434 free(p1); 435 if (p2 == (char *)NULL) { 436 _z_program_error(ERR_MALLOC, "<path>", errno, 437 strerror(errno)); 438 return (B_FALSE); 439 } 440 441 /* create "realpath.%s/..." final lock object */ 442 443 *r_result = _z_strPrintf("%s/%s", p2, a_lockObject); 444 free(p2); 445 if (*r_result == (char *)NULL) { 446 _z_program_error(ERR_MALLOC, "<path>", errno, 447 strerror(errno)); 448 return (B_FALSE); 449 } 450 } 451 } 452 453 /* exit debugging info */ 454 455 _z_echoDebug(DBG_ZONES_ADJLCKOBJ_EXIT, a_lockObject, *r_result, 456 a_rootPath ? a_rootPath : "", 457 realRootPath ? realRootPath : ""); 458 459 /* return success */ 460 461 return (B_TRUE); 462 } 463 464 /* 465 * Name: _z_lock_zone 466 * Description: Acquire specified locks on specified zone 467 * Arguments: a_zlst - [RO, *RW] - (zoneListElement_t *) 468 * Pointer to zone list structure element describing 469 * the zone the lock - the structure is updated with 470 * the lock objects and keys if the locks are acquired 471 * a_lflags - [RO, *RO] - (ZLOCKS_T) 472 * Flags indicating which locks to acquire on the zone 473 * Returns: boolean_t 474 * == B_TRUE - locks successfully acquired 475 * == B_FALSE - failed to acquire the locks 476 */ 477 478 boolean_t 479 _z_lock_zone(zoneListElement_t *a_zlst, ZLOCKS_T a_lflags) 480 { 481 char *scratchName; 482 boolean_t b; 483 484 /* entry assertions */ 485 486 assert(a_zlst != (zoneListElement_t *)NULL); 487 488 /* entry debugging info */ 489 490 _z_echoDebug(DBG_ZONES_LCK_ZONE, a_zlst->_zlName, a_lflags); 491 492 scratchName = a_zlst->_zlScratchName == NULL ? a_zlst->_zlName : 493 a_zlst->_zlScratchName; 494 495 /* 496 * acquire zone lock 497 */ 498 499 if (a_lflags & ZLOCKS_ZONE_ADMIN) { 500 /* 501 * lock zone administration if not already locked 502 * if the lock cannot be released, stop and return an error 503 */ 504 505 _z_echoDebug(DBG_ZONES_LCK_ZONE_ZONEADM, a_zlst->_zlName, 506 LOBJ_ZONEADMIN); 507 508 b = _z_lock_zone_object(&a_zlst->_zlLockObjects, 509 scratchName, LOBJ_ZONEADMIN, (pid_t)0, 510 MSG_ZONES_LCK_ZONE_ZONEADM, 511 ERR_ZONES_LCK_ZONE_ZONEADM); 512 if (b == B_FALSE) { 513 return (b); 514 } 515 } 516 517 /* 518 * acquire package lock 519 */ 520 521 if (a_lflags & ZLOCKS_PKG_ADMIN) { 522 523 /* 524 * zone administration is locked; lock package administration if 525 * not already locked; if the lock cannot be released, stop, 526 * release the zone administration lock and return an error 527 */ 528 529 _z_echoDebug(DBG_ZONES_LCK_ZONE_PKGADM, a_zlst->_zlName, 530 LOBJ_PKGADMIN); 531 532 b = _z_lock_zone_object(&a_zlst->_zlLockObjects, 533 scratchName, LOBJ_PKGADMIN, (pid_t)0, 534 MSG_ZONES_LCK_ZONE_PKGADM, 535 ERR_ZONES_LCK_ZONE_PKGADM); 536 if (b == B_FALSE) { 537 (void) _z_unlock_zone(a_zlst, a_lflags); 538 return (b); 539 } 540 } 541 542 /* 543 * acquire patch lock 544 */ 545 546 if (a_lflags & ZLOCKS_PATCH_ADMIN) { 547 548 /* 549 * zone and package administration is locked; lock patch 550 * administration; if the lock cannot be released, stop, 551 * release the other locks and return an error 552 */ 553 554 _z_echoDebug(DBG_ZONES_LCK_ZONE_PATCHADM, a_zlst->_zlName, 555 LOBJ_PATCHADMIN); 556 557 b = _z_lock_zone_object(&a_zlst->_zlLockObjects, 558 scratchName, LOBJ_PATCHADMIN, (pid_t)0, 559 MSG_ZONES_LCK_ZONE_PATCHADM, 560 ERR_ZONES_LCK_ZONE_PATCHADM); 561 if (b == B_FALSE) { 562 (void) _z_unlock_zone(a_zlst, a_lflags); 563 return (b); 564 } 565 } 566 567 /* 568 * all locks have been obtained - return success! 569 */ 570 571 return (B_TRUE); 572 } 573 574 /* 575 * Name: _z_lock_zone_object 576 * Description: lock a single lock object in a specified zone 577 * Arguments: r_objectLocks - [RW, *RW] - (char **) 578 * Pointer to handle to character string containing a list 579 * of all objects locked for this zone - this string will 580 * have the key to release the specified object added to it 581 * if the lock is acquired. 582 * a_zoneName - [RO, *RO] - (char *) 583 * Pointer to string representing the name of the zone to 584 * acquire the specified lock on 585 * a_lockObject - [RO, *RO] - (char *) 586 * Pointer to string representing the lock object to 587 * acquire on the specified zone 588 * a_pid - [RO, *RO] - (pid_t) 589 * Process i.d. to associate with this lock 590 * == 0 - no process i.d. associated with the lock 591 * a_waitingMsg - [RO, *RO] - (char *) 592 * Localized message to be output if waiting for the lock 593 * because the lock cannot be immediately be acquired 594 * a_busyMsg - [RO, *RO] - (char *) 595 * Localized message to be output if the lock cannot be 596 * released 597 * Returns: boolean_t 598 * B_TRUE - lock released 599 * B_FALSE - lock not released 600 */ 601 602 boolean_t 603 _z_lock_zone_object(char **r_objectLocks, char *a_zoneName, char *a_lockObject, 604 pid_t a_pid, char *a_waitingMsg, char *a_busyMsg) 605 { 606 boolean_t b; 607 char *p = (char *)NULL; 608 char lockItem[LOCK_OBJECT_MAXLEN+LOCK_KEY_MAXLEN+4]; 609 char lockKey[LOCK_KEY_MAXLEN+2]; 610 char lockObject[LOCK_OBJECT_MAXLEN+2]; 611 int i; 612 613 /* entry assertions */ 614 615 assert(r_objectLocks != (char **)NULL); 616 assert(a_zoneName != (char *)NULL); 617 assert(a_waitingMsg != (char *)NULL); 618 assert(a_busyMsg != (char *)NULL); 619 assert(a_lockObject != (char *)NULL); 620 assert(*a_lockObject != '\0'); 621 622 /* entry debugging info */ 623 624 _z_echoDebug(DBG_ZONES_LCK_OBJ, a_lockObject, a_zoneName, a_pid, 625 *r_objectLocks ? *r_objectLocks : ""); 626 627 /* if lock objects held search for object to lock */ 628 629 if (*r_objectLocks != (char *)NULL) { 630 for (i = 0; ; i++) { 631 /* get next object locked on this zone */ 632 _z_strGetToken_r((char *)NULL, *r_objectLocks, i, "\n", 633 lockItem, sizeof (lockItem)); 634 635 /* break out of loop if no more locks in list */ 636 637 if (lockItem[0] == '\0') { 638 _z_echoDebug(DBG_ZONES_LCK_OBJ_NOTHELD, 639 a_lockObject, a_zoneName); 640 break; 641 } 642 643 /* get object and key for this lock */ 644 _z_strGetToken_r((char *)NULL, lockItem, 0, "\t", 645 lockObject, sizeof (lockObject)); 646 _z_strGetToken_r((char *)NULL, lockItem, 1, "\t", 647 lockKey, sizeof (lockKey)); 648 649 /* return success if the lock is held */ 650 651 if (strcmp(lockObject, a_lockObject) == 0) { 652 _z_echoDebug(DBG_ZONES_LCK_OBJ_FOUND, 653 lockObject, lockKey); 654 return (B_TRUE); 655 } 656 657 /* not the object to lock - scan next object */ 658 _z_echoDebug(DBG_ZONES_LCK_OBJ_NOTFOUND, lockObject, 659 lockKey); 660 } 661 } 662 663 /* 664 * the object to lock is not held - acquire the lock 665 */ 666 667 /* acquire object with no wait */ 668 b = _z_acquire_lock(&p, a_zoneName, a_lockObject, a_pid, B_FALSE); 669 if (b == B_FALSE) { 670 /* failure - output message and acquire with wait */ 671 _z_echo(a_waitingMsg, (long)MAX_RETRIES*RETRY_DELAY_SECS, 672 a_zoneName, _z_global_data._z_root_dir); 673 b = _z_acquire_lock(&p, a_zoneName, a_lockObject, a_pid, 674 B_TRUE); 675 } 676 677 /* output error message and return failure if both acquires failed */ 678 if (b == B_FALSE) { 679 _z_program_error(a_busyMsg, a_zoneName); 680 return (b); 681 } 682 683 /* add object/key to held locks */ 684 685 _z_strPrintf_r(lockItem, sizeof (lockItem), "%s\t%s", a_lockObject, p); 686 _z_strAddToken(r_objectLocks, lockItem, '\n'); 687 688 free(p); 689 690 /* return success */ 691 return (B_TRUE); 692 } 693 694 /* 695 * Name: _z_release_lock 696 * Description: release a lock held on a zone 697 * Arguments: a_zoneName - [RO, *RO] - (char *) 698 * Pointer to string representing the name of the zone to 699 * release the specified lock on 700 * a_lockObject - [RO, *RO] - (char *) 701 * Pointer to string representing the lock object to 702 * release on the specified zone 703 * a_lockKey - [RO, *RO] - (char *) 704 * Pointer to string representing the lock key associated 705 * with the lock object to be released - this key is 706 * returned when the lock is acquired and must be provided 707 * when releasing the lock 708 * a_wait - [RO, *RO] - (int) 709 * Determines what to do if the lock cannot be released: 710 * == B_TRUE - wait for the lock to be released 711 * == B_FALSE - do not wait for the lock to be released 712 * Returns: boolean_t 713 * B_TRUE - lock released 714 * B_FALSE - lock not released 715 */ 716 717 boolean_t 718 _z_release_lock(char *a_zoneName, char *a_lockObject, char *a_lockKey, 719 boolean_t a_wait) 720 { 721 argArray_t *args; 722 boolean_t b; 723 char *adjustedLockObject = (char *)NULL; 724 char *results = (char *)NULL; 725 int r; 726 int status; 727 728 /* entry assertions */ 729 730 assert(a_zoneName != (char *)NULL); 731 assert(a_lockObject != (char *)NULL); 732 assert(*a_lockObject != '\0'); 733 assert(a_lockKey != (char *)NULL); 734 assert(*a_lockKey != '\0'); 735 736 /* entry debugging info */ 737 738 _z_echoDebug(DBG_ZONES_RELK, a_zoneName, a_lockObject, 739 a_lockKey ? a_lockKey : ""); 740 741 /* 742 * Only one lock file must ever be used - the one located on the root 743 * file system of the currently running Solaris instance. To allow for 744 * alternative roots to be properly locked, adjust the lock object to 745 * take root path into account; if necessary, the root path will be 746 * prepended to the lock object. 747 */ 748 749 b = _z_adjust_lock_object_for_rootpath(&adjustedLockObject, 750 a_lockObject); 751 if (!b) { 752 return (B_FALSE); 753 } 754 755 /* 756 * construct command arguments: 757 * pkgadm lock -r -o adjustedLockObject -k a_lockKey [-w -W timeout] 758 */ 759 760 args = _z_new_args(20); /* generate new arg list */ 761 (void) _z_add_arg(args, PKGADM_CMD); /* pkgadm command */ 762 (void) _z_add_arg(args, "lock"); /* lock sub-command */ 763 (void) _z_add_arg(args, "-r"); /* release lock */ 764 (void) _z_add_arg(args, "-o"); /* object to release */ 765 (void) _z_add_arg(args, "%s", adjustedLockObject); 766 (void) _z_add_arg(args, "-k"); /* object's key */ 767 (void) _z_add_arg(args, "%s", a_lockKey); 768 769 /* add [ -w -W timeout ] if waiting for lock */ 770 771 if (a_wait == B_TRUE) { 772 (void) _z_add_arg(args, "-w"); /* wait */ 773 (void) _z_add_arg(args, "-W"); /* wait timeout */ 774 (void) _z_add_arg(args, "%ld", 775 (long)MAX_RETRIES*RETRY_DELAY_SECS); 776 } 777 778 /* execute command */ 779 780 r = _z_zone_exec(&status, &results, (char *)NULL, PKGADM_CMD, 781 _z_get_argv(args), a_zoneName, (int *)NULL); 782 783 /* free generated argument list */ 784 785 _z_free_args(args); 786 787 /* exit debugging info */ 788 789 _z_echoDebug(DBG_ZONES_RELK_EXIT, adjustedLockObject, a_lockKey, 790 a_zoneName, r, status, results ? results : ""); 791 792 /* free adjusted lock object */ 793 794 free(adjustedLockObject); 795 free(results); 796 797 return (((r == 0) && (status == 0)) ? B_TRUE : B_FALSE); 798 } 799 800 801 802 /* 803 * Name: _z_unlock_zone 804 * Description: Released specified locks on specified zone 805 * Arguments: a_zlst - [RO, *RW] - (zoneListElement_t *) 806 * Pointer to zone list structure element describing 807 * the zone the unlock - the structure is updated by 808 * removing the lock object and key if the locks are 809 * successfully released 810 * a_lflags - [RO, *RO] - (ZLOCKS_T) 811 * Flags indicating which locks to release on the zone 812 * Returns: boolean_t 813 * == B_TRUE - locks successfully released 814 * == B_FALSE - failed to release the locks 815 */ 816 817 boolean_t 818 _z_unlock_zone(zoneListElement_t *a_zlst, ZLOCKS_T a_lflags) 819 { 820 char *scratchName; 821 boolean_t b; 822 boolean_t errors = B_FALSE; 823 824 /* entry assertions */ 825 826 assert(a_zlst != (zoneListElement_t *)NULL); 827 828 /* entry debugging info */ 829 830 _z_echoDebug(DBG_ZONES_ULK_ZONE, a_zlst->_zlName, a_lflags); 831 832 scratchName = a_zlst->_zlScratchName == NULL ? a_zlst->_zlName : 833 a_zlst->_zlScratchName; 834 835 if (a_lflags & ZLOCKS_PATCH_ADMIN) { 836 /* 837 * if locked, unlock patch administration lock 838 * if the lock cannot be released, continue anyway 839 */ 840 841 _z_echoDebug(DBG_ZONES_ULK_ZONE_PATCHADM, a_zlst->_zlName, 842 LOBJ_PATCHADMIN); 843 844 b = _z_unlock_zone_object(&a_zlst->_zlLockObjects, 845 scratchName, LOBJ_PATCHADMIN, 846 WRN_ZONES_ULK_ZONE_PATCHADM); 847 if (b == B_FALSE) { 848 errors = B_TRUE; 849 } 850 } 851 852 if (a_lflags & ZLOCKS_PKG_ADMIN) { 853 /* 854 * if locked, unlock package administration lock 855 * if the lock cannot be released, continue anyway 856 */ 857 858 _z_echoDebug(DBG_ZONES_ULK_ZONE_PKGADM, a_zlst->_zlName, 859 LOBJ_PKGADMIN); 860 861 b = _z_unlock_zone_object(&a_zlst->_zlLockObjects, 862 scratchName, LOBJ_PKGADMIN, 863 WRN_ZONES_ULK_ZONE_PKGADM); 864 if (b == B_FALSE) { 865 errors = B_TRUE; 866 } 867 } 868 869 if (a_lflags & ZLOCKS_ZONE_ADMIN) { 870 871 /* 872 * if locked, unlock zone administration lock 873 * if the lock cannot be released, continue anyway 874 */ 875 876 _z_echoDebug(DBG_ZONES_ULK_ZONE_ZONEADM, a_zlst->_zlName, 877 LOBJ_ZONEADMIN); 878 879 b = _z_unlock_zone_object(&a_zlst->_zlLockObjects, 880 scratchName, LOBJ_ZONEADMIN, 881 WRN_ZONES_ULK_ZONE_ZONEADM); 882 if (b == B_FALSE) { 883 errors = B_TRUE; 884 } 885 } 886 887 return (!errors); 888 } 889 890 /* 891 * Name: _z_unlock_zone_object 892 * Description: unlock a single lock object in a specified zone 893 * Arguments: r_objectLocks - [RW, *RW] - (char **) 894 * Pointer to handle to character string containing a list 895 * of all objects locked for this zone - this string must 896 * contain the key to release the specified object - if not 897 * then the lock is not released - if so then the lock is 898 * released and the key is removed from this list. 899 * a_zoneName - [RO, *RO] - (char *) 900 * Pointer to string representing the name of the zone to 901 * release the specified lock on 902 * a_lockObject - [RO, *RO] - (char *) 903 * Pointer to string representing the lock object to 904 * release on the specified zone 905 * a_errMsg - [RO, *RO] - (char *) 906 * Localized message to be output if the lock cannot be 907 * released 908 * Returns: boolean_t 909 * B_TRUE - lock released 910 * B_FALSE - lock not released 911 */ 912 913 boolean_t 914 _z_unlock_zone_object(char **r_objectLocks, char *a_zoneName, 915 char *a_lockObject, char *a_errMsg) 916 { 917 boolean_t b; 918 char lockItem[LOCK_OBJECT_MAXLEN+LOCK_KEY_MAXLEN+4]; 919 char lockKey[LOCK_KEY_MAXLEN+2]; 920 char lockObject[LOCK_OBJECT_MAXLEN+2]; 921 int i; 922 923 /* entry assertions */ 924 925 assert(r_objectLocks != (char **)NULL); 926 assert(a_zoneName != (char *)NULL); 927 assert(a_errMsg != (char *)NULL); 928 assert(a_lockObject != (char *)NULL); 929 assert(*a_lockObject != '\0'); 930 931 /* entry debugging info */ 932 933 _z_echoDebug(DBG_ZONES_ULK_OBJ, a_lockObject, a_zoneName, 934 *r_objectLocks ? *r_objectLocks : ""); 935 936 /* return success if no objects are locked */ 937 938 if (*r_objectLocks == (char *)NULL) { 939 _z_echoDebug(DBG_ZONES_ULK_OBJ_NONE, a_zoneName); 940 return (B_TRUE); 941 } 942 943 /* see if the specified lock is held on this zone */ 944 945 for (i = 0; ; i++) { 946 /* get next object locked on this zone */ 947 _z_strGetToken_r((char *)NULL, *r_objectLocks, i, "\n", 948 lockItem, sizeof (lockItem)); 949 950 /* return success if no more objects locked */ 951 if (lockItem[0] == '\0') { 952 _z_echoDebug(DBG_ZONES_ULK_OBJ_NOTHELD, a_lockObject, 953 a_zoneName); 954 return (B_TRUE); 955 } 956 957 /* get object and key for this lock */ 958 _z_strGetToken_r((char *)NULL, lockItem, 0, "\t", 959 lockObject, sizeof (lockObject)); 960 _z_strGetToken_r((char *)NULL, lockItem, 1, "\t", 961 lockKey, sizeof (lockKey)); 962 963 /* break out of loop if object is the one to unlock */ 964 965 if (strcmp(lockObject, a_lockObject) == 0) { 966 _z_echoDebug(DBG_ZONES_ULK_OBJ_FOUND, lockObject, 967 lockKey); 968 break; 969 } 970 971 /* not the object to unlock - scan next object */ 972 _z_echoDebug(DBG_ZONES_ULK_OBJ_NOTFOUND, lockObject, lockKey); 973 } 974 975 /* 976 * the object to unlock is held - release the lock 977 */ 978 979 /* release object with wait */ 980 981 b = _z_release_lock(a_zoneName, a_lockObject, lockKey, B_TRUE); 982 if (b == B_FALSE) { 983 /* failure - issue error message and return failure */ 984 _z_program_error(a_errMsg, a_zoneName); 985 return (b); 986 } 987 988 /* remove object/key from held locks */ 989 990 _z_strRemoveToken(r_objectLocks, lockItem, "\n", 0); 991 992 /* return success */ 993 994 return (B_TRUE); 995 } 996