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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #include <stdio.h> 32 #include <fcntl.h> 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/sysmacros.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <sys/wait.h> 39 #include <sys/stat.h> 40 #include <sys/mman.h> 41 #include <sys/statvfs.h> 42 #include <signal.h> 43 #include <limits.h> 44 #include <errno.h> 45 #include <fcntl.h> 46 #include <stdlib.h> 47 #include <unistd.h> 48 #include <time.h> 49 #include <errno.h> 50 #include <pkglocs.h> 51 #include <locale.h> 52 #include <libintl.h> 53 #include <pkglib.h> 54 #include "libinst.h" 55 #include "libadm.h" 56 57 #define LOCKFILE ".pkg.lock" 58 #define LOCKWAIT 10 /* seconds between retries */ 59 #define LOCKRETRY 20 /* number of retries for a DB lock */ 60 61 #define ERR_TC_WRITE "WARNING: unable to write temp contents file <%s>" 62 #define ERR_NOCLOSE "WARNING: unable to close <%s>" 63 #define ERR_NOUNLINK_LATENT "WARNING: unable to unlink latent <%s>" 64 #define ERR_LINK_FAIL "link(%s, %s) failed (errno %d)" 65 #define ERR_NORENAME_CONTENTS "unable to establish contents file <%s> "\ 66 "from <%s>" 67 #define ERR_RENAME_FAIL "rename(%s, %s) failed (errno %d)" 68 #define ERR_RESTORE_FAIL "attempt to restore <%s> failed" 69 #define ERR_NOUNLINK "WARNING: unable to unlink <%s>" 70 #define ERR_FCLOSE_FAIL "fclose failed (errno %d)" 71 #define ERR_ERRNO "(errno %d: %s)" 72 #define ERR_NOTMPOPEN "unable to open temporary contents file image" 73 #define ERR_CFBACK "Not enough space to backup <%s>" 74 #define ERR_CREAT_CONT "unable to create contents file <%s>: %s" 75 #define ERR_ACCESS_CONT "unable to access contents file <%s>: %s" 76 #define ERR_CFBACK1 "Need=%llu blocks, Available=%llu blocks " \ 77 "(block size=%d)" 78 #define ERR_NOCFILE "unable to locate contents file <%s>" 79 #define ERR_NOROPEN "unable to open <%s> for reading" 80 #define ERR_NOOPEN "unable to open <%s> for writing" 81 #define ERR_NOSTAT "unable to stat contents file <%s>" 82 #define ERR_NOSTATV "statvfs(%s) failed" 83 #define ERR_NOUPD "unable to update contents file" 84 #define ERR_DRCONTCP "unable to copy contents file to <%s>" 85 86 #define MSG_XWTING "NOTE: Waiting for exclusive access to the package " \ 87 "database." 88 #define MSG_NOLOCK "NOTE: Couldn't lock the package database." 89 90 #define ERR_NOLOCK "Database lock failed." 91 #define ERR_OPLOCK "unable to open lock file <%s>." 92 #define ERR_MKLOCK "unable to create lock file <%s>." 93 #define ERR_LCKREM "unable to lock package database - remote host " \ 94 "unavailable." 95 #define ERR_BADLCK "unable to lock package database - unknown error." 96 #define ERR_DEADLCK "unable to lock package database - deadlock condition." 97 #define ERR_TMOUT "unable to lock package database - too many retries." 98 #define ERR_CFDIR "unable to locate contents file directory" 99 100 static int active_lock; 101 static int lock_fd; /* fd of LOCKFILE. */ 102 static char *pkgadm_dir; 103 104 static int pkgWlock(int verbose); 105 static int pkgWunlock(void); 106 107 /* 108 * This VFP is used to cache the last copy of the contents file that was 109 * written out - upon subsequent open if the contents file has not changed 110 * since it was last written out, use the last cached copy that is still 111 * in memory to avoid re-reading the contents file again. If the contents 112 * file has changed since the cached copy was written out, the previous 113 * copy is discarded and the new contents file contents are read in. 114 */ 115 116 static VFP_T *contentsVfp = {(VFP_T *)NULL}; 117 118 /* 119 * This defines the maximum number of bytes that can be added to the contents 120 * file for a single package - this must be higher than the largest expected 121 * pkgmap file will ever be. This controls the amount of memory allocated for 122 * the contents file additions. A pkgmap file with an average line length of 123 * 128/256/512 bytes could add 62500/31250/15625 entries with this size. This 124 * allows the contents file to have a fixed allocation without having to check 125 * size and realloc as necessary with the attendant cost of the realloc. The 126 * real memory used will only be those pages that are actually touched when 127 * the contents file is written. 128 */ 129 130 #define CONTENTS_DELTA (32*1024*1024) /* 32mb */ 131 132 /* forward declarations */ 133 134 int relslock(void); 135 136 /*ARGSUSED*/ 137 static void 138 do_alarm(int n) 139 { 140 (void) signal(SIGALRM, SIG_IGN); 141 (void) signal(SIGALRM, do_alarm); 142 (void) alarm(LOCKWAIT); 143 } 144 145 /* 146 * Point packaging to the appropriate contents file. This is primarily used 147 * to establish a dryrun contents file. If the malloc() doesn't work, this 148 * returns 99 (internal error), else 0. 149 */ 150 int 151 set_cfdir(char *cfdir) 152 { 153 char realcf[PATH_MAX]; 154 char tmpcf[PATH_MAX]; 155 int status; 156 157 if (cfdir == NULL) { 158 pkgadm_dir = get_PKGADM(); 159 return (0); 160 } 161 162 if ((pkgadm_dir = strdup(cfdir)) == NULL) { 163 return (99); 164 } 165 166 (void) snprintf(tmpcf, sizeof (tmpcf), "%s/contents", pkgadm_dir); 167 168 /* 169 * return if a temporary contents file already exists - 170 * assume it is from a prior package in this series. 171 */ 172 173 if (access(tmpcf, F_OK) == 0) { 174 return (0); 175 } 176 177 /* 178 * no temporary contents file exists - create one. 179 */ 180 181 (void) snprintf(realcf, sizeof (realcf), "%s/contents", get_PKGADM()); 182 183 /* 184 * If there's a contents file there already, copy it 185 * over, otherwise initialize one. 186 */ 187 188 /* create new contents file if one does not already exist */ 189 190 if (access(realcf, F_OK) != 0) { 191 int n; 192 193 n = open(tmpcf, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 194 if (n < 0) { 195 progerr(gettext(ERR_CREAT_CONT), tmpcf, 196 strerror(errno)); 197 return (99); 198 } 199 (void) close(n); 200 } else { 201 202 /* contents file exists, save in pkgadm-dir */ 203 204 status = copyf(realcf, tmpcf, (time_t)0); 205 if (status != 0) { 206 progerr(gettext(ERR_DRCONTCP), tmpcf); 207 return (99); 208 } 209 } 210 211 return (0); 212 } 213 214 /* 215 * This function installs the database lock, opens the contents file for 216 * reading and creates and opens the temporary contents file for read/write. 217 * It returns 1 if successful, 0 otherwise. 218 */ 219 int 220 ocfile(VFP_T **r_mapvfp, VFP_T **r_tmpvfp, fsblkcnt_t map_blks) 221 { 222 struct stat64 statb; 223 struct statvfs64 svfsb; 224 fsblkcnt_t free_blocks; 225 fsblkcnt_t need_blocks; 226 VFP_T *mapvfp = (VFP_T *)NULL; 227 VFP_T *tmpvfp = (VFP_T *)NULL; 228 char contents[PATH_MAX]; 229 int n; 230 231 /* reset return VFP/FILE pointers */ 232 233 (*r_mapvfp) = (VFP_T *)NULL; 234 (*r_tmpvfp) = (VFP_T *)NULL; 235 236 /* establish package administration contents directory location */ 237 238 if (pkgadm_dir == NULL) { 239 if (set_cfdir(NULL) != 0) { 240 progerr(gettext(ERR_CFDIR)); 241 return (0); 242 } 243 } 244 245 /* Lock the file for exclusive access */ 246 247 if (!pkgWlock(1)) { 248 progerr(gettext(ERR_NOLOCK)); 249 return (0); 250 } 251 252 /* determine path to the primary contents file */ 253 254 (void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir); 255 256 /* 257 * open the contents file to read only - if a previous contents file has 258 * been cached attempt to use that cached copy for the open, otherwise 259 * just open the contents file directly 260 */ 261 262 n = vfpCheckpointOpen(&contentsVfp, &mapvfp, contents, "r", VFP_NONE); 263 264 /* return error if contents file cannot be accessed */ 265 266 if (n != 0) { 267 int lerrno = errno; 268 269 if (errno == ENOENT) { 270 progerr(gettext(ERR_NOCFILE), contents); 271 } else { 272 progerr(gettext(ERR_NOROPEN), contents); 273 } 274 275 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 276 return (0); 277 } 278 279 /* 280 * Check and see if there is enough space for the packaging commands 281 * to back up the contents file, if there is not, then do not allow 282 * execution to continue by failing the ocfile() call. 283 */ 284 285 /* Get the contents file size */ 286 287 if (fstat64(fileno(mapvfp->_vfpFile), &statb) == -1) { 288 int lerrno = errno; 289 290 progerr(gettext(ERR_NOSTAT), contents); 291 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 292 (void) vfpClose(&mapvfp); 293 return (0); 294 } 295 296 /* Get the filesystem space */ 297 298 if (fstatvfs64(fileno(mapvfp->_vfpFile), &svfsb) == -1) { 299 int lerrno = errno; 300 301 progerr(gettext(ERR_NOSTATV), contents); 302 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 303 (void) vfpClose(&mapvfp); 304 return (0); 305 } 306 307 free_blocks = (((fsblkcnt_t)svfsb.f_frsize > 0) ? 308 howmany(svfsb.f_frsize, DEV_BSIZE) : 309 howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree; 310 311 if (map_blks == 0LL) { 312 map_blks = 10LL; 313 } 314 315 /* 316 * Calculate the number of blocks we need to be able to operate on 317 * the contents file. 318 */ 319 need_blocks = map_blks + 320 nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize); 321 322 if ((need_blocks + 10) > free_blocks) { 323 progerr(gettext(ERR_CFBACK), contents); 324 progerr(gettext(ERR_CFBACK1), need_blocks, free_blocks, 325 DEV_BSIZE); 326 (void) vfpClose(&mapvfp); 327 return (0); 328 } 329 330 /* 331 * open the temporary contents file without a path name - this causes 332 * the "vfp" to be opened on in-memory storage only, the size of which 333 * is set following a successful return - this causes the temporary 334 * contents file to be maintained in memory only - if no changes are 335 * made as the primary contents file is processed, the in memory data 336 * is discarded and not written to the disk. 337 */ 338 339 if (vfpOpen(&tmpvfp, (char *)NULL, "w", VFP_NONE) != 0) { 340 int lerrno = errno; 341 342 progerr(gettext(ERR_NOTMPOPEN)); 343 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 344 (void) vfpClose(&mapvfp); 345 return (0); 346 } 347 348 /* 349 * set size of allocation for temporary contents file - this sets the 350 * size of the in-memory buffer associated with the open vfp. 351 */ 352 353 if (vfpSetSize(tmpvfp, statb.st_size + CONTENTS_DELTA) != 0) { 354 int lerrno = errno; 355 356 progerr(gettext(ERR_NOTMPOPEN)); 357 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 358 (void) vfpClose(&tmpvfp); 359 (void) vfpClose(&mapvfp); 360 return (0); 361 } 362 363 /* 364 * now that the temporary file is opened, advise the vm system to start 365 * mapping the real contents file into memory if possible 366 */ 367 368 (void) vfpSetFlags(mapvfp, VFP_NEEDNOW); 369 370 /* set return ->s to open vfps */ 371 372 (*r_mapvfp) = mapvfp; 373 (*r_tmpvfp) = tmpvfp; 374 375 return (1); /* All OK */ 376 } 377 378 /* 379 * This is a simple open and lock of the contents file. It doesn't create a 380 * temporary contents file and it doesn't need to do any space checking. 381 * Returns 1 for OK and 0 for "didn't do it". 382 */ 383 int 384 socfile(VFP_T **r_mapvfp) 385 { 386 VFP_T *mapvfp = (VFP_T *)NULL; 387 char contents[PATH_MAX]; 388 int n; 389 390 /* reset return VFP/FILE pointer */ 391 392 (*r_mapvfp) = (VFP_T *)NULL; 393 394 if (pkgadm_dir == NULL) { 395 if (set_cfdir(NULL) != 0) { 396 progerr(gettext(ERR_CFDIR)); 397 return (0); 398 } 399 } 400 401 /* 402 * Lock the database for exclusive access, but don't make a fuss if 403 * it fails (user may not be root and the .pkg.lock file may not 404 * exist yet). 405 */ 406 407 if (!pkgWlock(0)) { 408 logerr(gettext(MSG_NOLOCK)); 409 } 410 411 /* open the contents file to read only */ 412 413 (void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir); 414 415 n = vfpCheckpointOpen(&contentsVfp, &mapvfp, contents, 416 "r", VFP_NEEDNOW); 417 if (n != 0) { 418 int lerrno = errno; 419 420 if (errno == ENOENT) { 421 progerr(gettext(ERR_NOCFILE), contents); 422 } else { 423 progerr(gettext(ERR_NOROPEN), contents); 424 } 425 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 426 return (0); 427 } 428 429 *r_mapvfp = mapvfp; 430 431 return (1); 432 } 433 434 /* 435 * Name: swapcfile 436 * Description: This function closes both the current and temporary contents 437 * files specified, and conditionally replaces the old transitory 438 * contents file with the newly updated temporary contents file. 439 * The "ocfile()" or "socfile()" functions must be called to re- 440 * open the real contents file for processing. 441 * Arguments: a_cfVfp - (VFP_T **) - [RW, *RW] 442 * This is the VFP associated with the real contents file 443 * that is being read from and data processed. 444 * a_cfTmpVfp - (VFP_T **) - [RW, *RW] 445 * This is the VFP associated with the temporary contents 446 * file that is being written to. 447 * pkginst - (char) - [RO, *RO] 448 * This is the name of the package being operated on; 449 * this is used to write the "last modified by xxx" 450 * comment at the end of the contents file. 451 * dbchg - (int) - [RO] 452 * == 0 - the temporary contents file has NOT been changed 453 * with respect to the real contents file; do not 454 * update the real contents file with the contents 455 * of the temporary contents file. 456 * != 0 - the temporary contetns file HAS been changed with 457 * respect to the real contents file; DO update the 458 * real contents file with the contents of the 459 * temporary contents file. 460 * Returns: int == RESULT_OK - successful 461 * == RESULT_WRN - successful with warnings 462 * == RESULT_ERR - failed with fatal errors - deserves an 463 * alarming message and a quit() 464 * NOTES: If dbchg != 0, the contents file is always updated. If dbchg == 0, 465 * the contents file is updated IF the data is modified indication 466 * is set on the contents file associated with a_cfTmpVfp. 467 */ 468 469 int 470 swapcfile(VFP_T **a_cfVfp, VFP_T **a_cfTmpVfp, char *pkginst, int dbchg) 471 { 472 char *pe; 473 char *pl; 474 char *ps; 475 char contentsPath[PATH_MAX] = {'\0'}; 476 char line[256]; 477 char sContentsPath[PATH_MAX] = {'\0'}; 478 char tContentsPath[PATH_MAX] = {'\0'}; 479 char timeb[BUFSIZ]; 480 int retval = RESULT_OK; 481 struct tm *timep; 482 time_t clock; 483 484 /* normalize pkginst so its never null */ 485 486 if (pkginst == (char *)NULL) { 487 dbchg = 0; 488 pkginst = "<unknown>"; 489 } 490 491 /* cache all paths for the associated open files */ 492 493 (void) strlcpy(contentsPath, vfpGetPath(*a_cfVfp), 494 sizeof (contentsPath)); 495 496 (void) snprintf(tContentsPath, sizeof (tContentsPath), 497 "%s/t.contents", pkgadm_dir); 498 499 (void) snprintf(sContentsPath, sizeof (sContentsPath), 500 "%s/s.contents", pkgadm_dir); 501 502 /* original contents file no longer needed - close */ 503 504 if (vfpClose(a_cfVfp) != 0) { 505 int lerrno = errno; 506 507 logerr(gettext(ERR_NOCLOSE), contentsPath); 508 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 509 retval = RESULT_WRN; 510 } 511 512 /* 513 * If no changes were made to the database, checkpoint the temporary 514 * contents file - if this fails, then just close the file which causes 515 * the contents file to be reopened and reread if it is needed again 516 */ 517 518 if ((dbchg == 0) && (vfpGetModified(*a_cfTmpVfp) == 0)) { 519 if (vfpCheckpointFile(&contentsVfp, a_cfTmpVfp, 520 contentsPath) != 0) { 521 vfpClose(a_cfTmpVfp); 522 } 523 (void) pkgWunlock(); /* Free the database lock. */ 524 return (retval); 525 } 526 527 /* 528 * changes made to the current temporary contents file - 529 * remove any trailing comment lines in the temp contents file, then 530 * append updated modification info records to temp contents file 531 */ 532 533 pe = vfpGetCurrCharPtr(*a_cfTmpVfp); /* last char in contents file */ 534 ps = vfpGetFirstCharPtr(*a_cfTmpVfp); /* 1st char in contents file */ 535 pl = pe; /* last match is last char in contents file */ 536 537 /* skip past all trailing newlines and null bytes */ 538 539 while ((pe > ps) && ((*pe == '\n') || (*pe == '\0'))) { 540 pe--; 541 } 542 543 /* remove trailing comments as long as there are lines in the file */ 544 545 while (pe > ps) { 546 if (*pe != '\n') { 547 /* curr char is not newline: backup one byte */ 548 pl = pe--; 549 } else if (*pl != '#') { 550 /* curr char is newline next char not comment break */ 551 break; 552 } else { 553 /* curr char is newline next char is comment - remove */ 554 *pl = '\0'; 555 vfpSetLastCharPtr(*a_cfTmpVfp, pl); 556 pe--; 557 } 558 } 559 560 /* create two update comment lines */ 561 562 (void) time(&clock); 563 timep = localtime(&clock); 564 565 (void) strftime(timeb, sizeof (timeb), "%c\n", timep); 566 (void) snprintf(line, sizeof (line), 567 gettext("# Last modified by %s for %s package\n# %s"), 568 get_prog_name(), pkginst, timeb); 569 vfpPuts(*a_cfTmpVfp, line); 570 571 /* commit temporary contents file bytes to storage */ 572 573 if (vfpWriteToFile(*a_cfTmpVfp, tContentsPath) != 0) { 574 int lerrno = errno; 575 576 logerr(gettext(ERR_TC_WRITE), tContentsPath); 577 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 578 vfpClose(a_cfTmpVfp); 579 (void) remove(tContentsPath); 580 (void) pkgWunlock(); /* Free the database lock. */ 581 return (RESULT_ERR); 582 } 583 584 /* 585 * Now we want to make a copy of the old contents file as a 586 * fail-safe. In support of that, we create a hard link to 587 * s.contents. 588 */ 589 590 if ((access(sContentsPath, F_OK) == 0) && remove(sContentsPath)) { 591 int lerrno = errno; 592 593 logerr(gettext(ERR_NOUNLINK_LATENT), sContentsPath); 594 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 595 (void) remove(tContentsPath); 596 (void) pkgWunlock(); /* Free the database lock. */ 597 vfpClose(a_cfTmpVfp); 598 return (RESULT_ERR); 599 } 600 601 if (link(contentsPath, sContentsPath) != 0) { 602 int lerrno = errno; 603 604 progerr(gettext(ERR_NOUPD)); 605 logerr(gettext(ERR_LINK_FAIL), contentsPath, sContentsPath, 606 lerrno); 607 (void) remove(tContentsPath); 608 (void) pkgWunlock(); /* Free the database lock. */ 609 vfpClose(a_cfTmpVfp); 610 return (RESULT_ERR); 611 } 612 613 if (rename(tContentsPath, contentsPath) != 0) { 614 int lerrno = errno; 615 616 progerr(gettext(ERR_NORENAME_CONTENTS), contentsPath, 617 tContentsPath); 618 logerr(gettext(ERR_RENAME_FAIL), tContentsPath, 619 contentsPath, lerrno); 620 if (rename(sContentsPath, contentsPath)) { 621 lerrno = errno; 622 progerr(gettext(ERR_RESTORE_FAIL), contentsPath); 623 logerr(gettext(ERR_RENAME_FAIL), sContentsPath, 624 contentsPath, lerrno); 625 } 626 (void) remove(tContentsPath); 627 } 628 629 if (remove(sContentsPath) != 0) { 630 int lerrno = errno; 631 632 logerr(gettext(ERR_NOUNLINK), sContentsPath); 633 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 634 retval = RESULT_WRN; 635 } 636 637 /* 638 * checkpoint the temporary contents file - if this fails, then 639 * just close the file which causes the contents file to be reopened 640 * and reread if it is needed again 641 */ 642 643 if (vfpCheckpointFile(&contentsVfp, a_cfTmpVfp, contentsPath) != 0) { 644 vfpClose(a_cfTmpVfp); 645 } 646 647 return (relslock() == 0 ? RESULT_ERR : retval); 648 } 649 650 /* This function releases the lock on the package database. */ 651 int 652 relslock(void) 653 { 654 /* 655 * This closes the contents file and releases the lock. 656 */ 657 if (!pkgWunlock()) { 658 int lerrno = errno; 659 660 progerr(gettext(ERR_NOUPD)); 661 logerr(gettext(ERR_FCLOSE_FAIL), lerrno); 662 return (0); 663 } 664 return (1); 665 } 666 667 /* 668 * This function attempts to lock the package database. It returns 1 on 669 * success, 0 on failure. The positive logic verbose flag determines whether 670 * or not the function displays the error message upon failure. 671 */ 672 static int 673 pkgWlock(int verbose) { 674 int retry_cnt, retval; 675 char lockpath[PATH_MAX]; 676 677 active_lock = 0; 678 679 (void) snprintf(lockpath, sizeof (lockpath), 680 "%s/%s", pkgadm_dir, LOCKFILE); 681 682 retry_cnt = LOCKRETRY; 683 684 /* 685 * If the lock file is not present, create it. The mode is set to 686 * allow any process to lock the database, that's because pkgchk may 687 * be run by a non-root user. 688 */ 689 if (access(lockpath, F_OK) == -1) { 690 lock_fd = open(lockpath, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644); 691 if (lock_fd < 0) { 692 if (verbose) 693 progerr(gettext(ERR_MKLOCK), lockpath); 694 return (0); 695 } else { 696 (void) fchmod(lock_fd, 0644); /* force perms. */ 697 } 698 } else { 699 if ((lock_fd = open(lockpath, O_RDWR)) == -1) { 700 if (verbose) 701 progerr(gettext(ERR_OPLOCK), lockpath); 702 return (0); 703 } 704 } 705 706 (void) signal(SIGALRM, do_alarm); 707 (void) alarm(LOCKWAIT); 708 709 do { 710 if (lockf(lock_fd, F_LOCK, 0)) { 711 if (errno == EAGAIN || errno == EINTR) 712 logerr(gettext(MSG_XWTING)); 713 else if (errno == ECOMM) { 714 logerr(gettext(ERR_LCKREM)); 715 retval = 0; 716 break; 717 } else if (errno == EBADF) { 718 logerr(gettext(ERR_BADLCK)); 719 retval = 0; 720 break; 721 } else if (errno == EDEADLK) { 722 logerr(gettext(ERR_DEADLCK)); 723 retval = 0; 724 break; 725 } 726 } else { 727 active_lock = 1; 728 retval = 1; 729 break; 730 } 731 } while (retry_cnt--); 732 733 (void) signal(SIGALRM, SIG_IGN); 734 735 if (retval == 0) 736 { 737 if (retry_cnt == -1) { 738 logerr(gettext(ERR_TMOUT)); 739 } 740 741 (void) pkgWunlock(); /* close the lockfile. */ 742 } 743 744 return (retval); 745 } 746 747 /* 748 * Release the lock on the package database. Returns 1 on success, 0 on 749 * failure. 750 */ 751 static int 752 pkgWunlock(void) { 753 if (active_lock) { 754 active_lock = 0; 755 if (close(lock_fd)) 756 return (0); 757 else 758 return (1); 759 } else 760 return (1); 761 } 762 763 /* 764 * This function verifies that the contents file is in place. 765 * returns 1 - if it exists 766 * returns 0 - if it does not exist 767 */ 768 int 769 iscfile(void) 770 { 771 char contents[PATH_MAX]; 772 773 (void) snprintf(contents, PATH_MAX, "%s/contents", get_PKGADM()); 774 775 return (access(contents, F_OK) == 0 ? 1 : 0); 776 } 777 778 /* 779 * This function verifies that the contents file is in place. If it is - no 780 * change. If it isn't - this creates it. 781 * Returns: == 0 : failure 782 * != 0 : success 783 */ 784 785 int 786 vcfile(void) 787 { 788 int lerrno; 789 int fd; 790 char contents[PATH_MAX]; 791 792 /* 793 * create full path to contents file 794 */ 795 796 (void) snprintf(contents, sizeof (contents), 797 "%s/contents", get_PKGADM()); 798 799 /* 800 * Attempt to create the file - will only be successful 801 * if the file does not currently exist. 802 */ 803 804 fd = open(contents, O_WRONLY | O_CREAT | O_EXCL, 0644); 805 if (fd >= 0) { 806 /* 807 * Contents file wasn't there, but is now. 808 */ 809 810 echo(gettext("## Software contents file initialized")); 811 (void) close(fd); 812 return (1); /* success */ 813 } 814 815 /* 816 * Could not create the file - it may exist or there may be 817 * permissions issues - find out and act accordingly. 818 */ 819 820 lerrno = errno; 821 822 /* success if error is 'file exists' */ 823 824 if (lerrno == EEXIST) { 825 return (1); /* success */ 826 } 827 828 /* success if error is 'permission denied' but file exists */ 829 830 if (lerrno == EACCES) { 831 /* 832 * Because O_CREAT and O_EXCL are specified in open(), 833 * if the contents file already exists, the open will 834 * fail with EACCES - determine if this is the case - 835 * if so return success. 836 */ 837 838 if (access(contents, F_OK) == 0) { 839 return (1); /* success */ 840 } 841 842 /* 843 * access() failed - if because of permissions failure this 844 * means the contents file exists but it cannot be accessed 845 * or the path to the contents file cannot be accessed - in 846 * either case the contents file cannot be accessed. 847 */ 848 849 if (errno == EACCES) { 850 progerr(gettext(ERR_ACCESS_CONT), contents, 851 strerror(lerrno)); 852 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 853 return (0); /* failure */ 854 } 855 } 856 857 /* 858 * the contents file does not exist and it cannot be created. 859 */ 860 861 progerr(gettext(ERR_CREAT_CONT), contents, strerror(lerrno)); 862 logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); 863 return (0); /* failure */ 864 } 865